{"version":3,"file":"ngx-pwa-local-storage.mjs","sources":["../../../lib/src/lib/databases/exceptions.ts","../../../lib/src/lib/tokens.ts","../../../lib/src/lib/providers.ts","../../../lib/src/lib/storage.module.ts","../../../lib/src/lib/storages/exceptions.ts","../../../lib/src/lib/databases/localstorage-database.ts","../../../lib/src/lib/databases/memory-database.ts","../../../lib/src/lib/databases/local-database.ts","../../../lib/src/lib/databases/indexeddb-database.ts","../../../lib/src/lib/validation/json-validator.ts","../../../lib/src/lib/storages/storage-map.ts","../../../lib/src/public-api.ts","../../../lib/src/ngx-pwa-local-storage.ts"],"sourcesContent":["/**\n * Exception message when `indexedDB` is not working\n */\nexport const IDB_BROKEN_ERROR = \"indexedDB is not working\";\n\n/**\n * Exception raised when `indexedDB` is not working\n */\nexport class IDBBrokenError extends Error {\n  override message: string = IDB_BROKEN_ERROR;\n}\n\n/**\n * Exception message when a value cannot be serialized for `localStorage`\n */\nexport const SERIALIZATION_ERROR = `The storage is currently localStorage,\nwhere data must be serialized, and the provided data can't be serialized.`;\n\n/**\n * Exception throwned when a value cannot be serialized for `localStorage`\n */\nexport class SerializationError extends Error {\n  override message: string = SERIALIZATION_ERROR;\n}\n","import { InjectionToken } from \"@angular/core\";\n\n/**\n * Token to provide a prefix to `localStorage` keys.\n */\nexport const LS_PREFIX: InjectionToken<string> = new InjectionToken<string>(\"localStoragePrefix\", {\n  providedIn: \"root\",\n  factory: (): string => \"\"\n});\n\n/**\n * Default name used for `indexedDB` database.\n */\nexport const DEFAULT_IDB_DB_NAME = \"ngStorage\";\n\n/**\n * Token to provide `indexedDB` database name.\n */\nexport const IDB_DB_NAME: InjectionToken<string> = new InjectionToken<string>(\"localStorageIDBDBName\", {\n  providedIn: \"root\",\n  factory: (): string => DEFAULT_IDB_DB_NAME\n});\n\n/**\n * Default version used for `indexedDB` database.\n */\nexport const DEFAULT_IDB_DB_VERSION = 1;\n\n/**\n * Token to provide `indexedDB` database version.\n * Must be an unsigned **integer**.\n */\nexport const IDB_DB_VERSION: InjectionToken<number> = new InjectionToken<number>(\"localStorageIDBDBVersion\", {\n  providedIn: \"root\",\n  factory: (): number => DEFAULT_IDB_DB_VERSION\n});\n\n/**\n * Default name used for `indexedDB` object store.\n */\nexport const DEFAULT_IDB_STORE_NAME = \"localStorage\";\n\n/**\n * Token to provide `indexedDB` store name.\n * For backward compatibility, the default can't be set now, `IndexedDBDatabase` will do it at runtime.\n */\nexport const IDB_STORE_NAME: InjectionToken<string> = new InjectionToken<string>(\"localStorageIDBStoreName\", {\n  providedIn: \"root\",\n  factory: (): string => DEFAULT_IDB_STORE_NAME\n});\n\n/**\n * Default value for interoperability with native `indexedDB` and other storage libs,\n * by changing how values are stored in `indexedDB` database.\n */\nexport const DEFAULT_IDB_NO_WRAP = true;\n\n/**\n * Token to allow interoperability with native `indexedDB` and other storage libs,\n * by changing how values are stored in `indexedDB` database.\n * Defaults to `true`. Change to `false` for backward compatiblity in existing applications.\n * **DO NOT CHANGE THIS BEHAVIOR ONCE IN PRODUCTION**, as it would break with existing data.\n */\nexport const IDB_NO_WRAP: InjectionToken<boolean> = new InjectionToken<boolean>(\"localStorageIDBWrap\", {\n  providedIn: \"root\",\n  factory: (): boolean => DEFAULT_IDB_NO_WRAP\n});\n\n/**\n * This interface is only here for backward compatibility, **do not add it by yourself**\n * \n * @ignore\n */\nexport interface StorageConfig {\n\n  /**\n   * @deprecated Use `provideLocalStoragePrefix()` method instead\n   */\n  LSPrefix?: string;\n\n  /**\n   * @deprecated Use `provideIndexedDBDataBaseName()` method instead\n   */\n  IDBDBName?: string;\n\n  /**\n   * @deprecated Use `provideIndexedDBStoreName()` method instead\n   */\n  IDBStoreName?: string;\n\n  /**\n   * @deprecated Use `provideIndexedDBDataBaseVersion()` method instead\n   */\n  IDBDBVersion?: number;\n\n  /**\n   * Allows interoperability with native `indexedDB` and other storage libs,\n   * by changing how values are stored in `indexedDB` database.\n   * \n   * Defaults to `true`. Change to `false` for backward compatiblity in existing applications.\n   * \n   * **DO NOT CHANGE THIS BEHAVIOR ONCE IN PRODUCTION**, as it would break with existing data.\n   */\n  IDBNoWrap?: boolean;\n\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from \"@angular/core\";\nimport { IDB_DB_NAME, IDB_DB_VERSION, IDB_STORE_NAME, LS_PREFIX } from \"./tokens\";\n\n/**\n * Allows to add a prefix before `localStorage` keys.\n * \n * *Use only* for interoperability with other APIs or to avoid collision for multiple applications on the same subdomain.\n * \n * **WARNING: do not change this option in an application already deployed in production, as previously stored data would be lost.**\n *\n * @example\n * export const appConfig: ApplicationConfig = {\n *   providers: [provideLocalStoragePrefix('custom_')]\n * };\n */\nexport function provideLocalStoragePrefix(prefix: string): EnvironmentProviders {\n\n  return makeEnvironmentProviders([{ provide: LS_PREFIX, useValue: prefix }]);\n\n}\n\n/**\n * Allows to change the name used for `indexedDB` database.\n * \n * *Use only* for interoperability with other APIs or to avoid collision for multiple applications on the same subdomain.\n * \n * **WARNING: do not change this option in an application already deployed in production, as previously stored data would be lost.**\n *\n * @example\n * export const appConfig: ApplicationConfig = {\n *   providers: [provideIndexedDBDataBaseName('custom')]\n * };\n */\nexport function provideIndexedDBDataBaseName(name: string): EnvironmentProviders {\n\n  return makeEnvironmentProviders([{ provide: IDB_DB_NAME, useValue: name }]);\n\n}\n\n/**\n * Allows to change the database version used for `indexedDB` database.\n * Must be an unsigned **integer**.\n * \n * **Use with caution as the creation of the store depends on the version.**\n * \n * *Use only* for interoperability with other APIs or to avoid collision for multiple applications on the same subdomain.\n * \n * **WARNING: do not change this option in an applicattion already deployed in production, as previously stored data would be lost.**\n *\n * @example\n * export const appConfig: ApplicationConfig = {\n *   providers: [provideIndexedDBDataBaseVersion(2)]\n * };\n */\nexport function provideIndexedDBDataBaseVersion(version: number): EnvironmentProviders {\n\n  return makeEnvironmentProviders([{ provide: IDB_DB_VERSION, useValue: version }]);\n\n}\n\n/**\n * Allows to change the name used for `indexedDB` object store.\n * \n * *Use only* for interoperability with other APIs.\n * \n * **WARNING: do not change this option in an application already deployed in production, as previously stored data would be lost.**\n *\n * @example\n * export const appConfig: ApplicationConfig = {\n *   providers: [provideIndexedDBStoreName('custom')]\n * };\n */\nexport function provideIndexedDBStoreName(name: string): EnvironmentProviders {\n\n  return makeEnvironmentProviders([{ provide: IDB_STORE_NAME, useValue: name }]);\n\n}\n","import { NgModule, type ModuleWithProviders } from \"@angular/core\";\nimport { IDB_DB_NAME, IDB_DB_VERSION, IDB_NO_WRAP, IDB_STORE_NAME, LS_PREFIX, type StorageConfig } from \"./tokens\";\n\n/**\n * This module is only here for backward compatibility, **do not add it by yourself**\n * \n * @ignore\n */\n@NgModule()\nexport class StorageModule {\n\n  /**\n   * Only useful to provide options, otherwise it does nothing.\n   * \n   * **Must be used at initialization, ie. in `AppModule`, and must not be loaded again in another module.**\n   */\n  static forRoot(config: StorageConfig): ModuleWithProviders<StorageModule> {\n    return {\n      ngModule: StorageModule,\n      providers: [\n        // eslint-disable-next-line @typescript-eslint/no-deprecated\n        config.LSPrefix !== undefined ? { provide: LS_PREFIX, useValue: config.LSPrefix } : [],\n        // eslint-disable-next-line @typescript-eslint/no-deprecated\n        config.IDBDBName !== undefined ? { provide: IDB_DB_NAME, useValue: config.IDBDBName } : [],\n        // eslint-disable-next-line @typescript-eslint/no-deprecated\n        config.IDBStoreName !== undefined ? { provide: IDB_STORE_NAME, useValue: config.IDBStoreName } : [],\n        // eslint-disable-next-line @typescript-eslint/no-deprecated\n        config.IDBDBVersion !== undefined ? { provide: IDB_DB_VERSION, useValue: config.IDBDBVersion } : [],\n        (config.IDBNoWrap === false) ? { provide: IDB_NO_WRAP, useValue: config.IDBNoWrap } : [],\n      ],\n    };\n  }\n\n}\n","/**\n * Exception message when a value is not valid against the JSON schema\n */\nexport const VALIDATION_ERROR = `Data stored is not valid against the provided JSON schema.\nCheck your JSON schema, otherwise it means data has been corrupted.`;\n\n/**\n * Exception throwned when a value is not valid against the JSON schema\n */\nexport class ValidationError extends Error {\n  override message: string = VALIDATION_ERROR;\n}\n","import { Injectable, inject } from \"@angular/core\";\nimport { Observable, asyncScheduler, of, throwError } from \"rxjs\";\nimport { observeOn } from \"rxjs/operators\";\nimport { LS_PREFIX } from \"../tokens\";\nimport { SerializationError } from \"./exceptions\";\nimport { LocalDatabase } from \"./local-database\";\n\n@Injectable({\n  providedIn: \"root\"\n})\nexport class LocalStorageDatabase implements LocalDatabase {\n\n  /**\n   * Optional user prefix to avoid collision for multiple apps on the same subdomain\n   */\n  readonly prefix: string;\n\n  constructor() {\n\n    /* Prefix if asked, or no prefix otherwise */\n    this.prefix = inject(LS_PREFIX);\n\n  }\n\n  /**\n   * Number of items in `localStorage`\n   */\n  get size(): Observable<number> {\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(localStorage.length);\n\n  }\n\n  /**\n   * Gets an item value in `localStorage`\n   * @param key The item's key\n   * @returns The item's value if the key exists, `undefined` otherwise, wrapped in a RxJS `Observable`\n   */\n  get(key: string): Observable<unknown> {\n\n    /* Get raw data */\n    const unparsedData = localStorage.getItem(this.prefixKey(key));\n\n    /* No need to parse if data is `null` or `undefined` */\n    if (unparsedData !== null) {\n\n      /* Try to parse */\n      try {\n\n        const parsedData: unknown = JSON.parse(unparsedData);\n\n        /* Wrap in a RxJS `Observable` to be consistent with other storages */\n        return of(parsedData);\n\n      } catch (error) {\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n        return throwError(() => error as SyntaxError);\n      }\n\n    }\n\n    return of(undefined);\n\n  }\n\n  /**\n   * Store an item in `localStorage`\n   * @param key The item's key\n   * @param data The item's value\n   * @returns A RxJS `Observable` to wait the end of the operation\n   */\n  set(key: string, data: object): Observable<undefined> {\n\n    let serializedData: StringifyResult<object> | null = null;\n\n    /* Check if data can be serialized */\n    const dataPrototype = Object.getPrototypeOf(data);\n    if ((typeof data === \"object\") && !Array.isArray(data) &&\n      !((dataPrototype === Object.prototype) || (dataPrototype === null))) {\n      return throwError(() => new SerializationError());\n    }\n\n    /* Try to stringify (can fail on circular references) */\n    try {\n      serializedData = JSON.stringify(data);\n      if (serializedData === undefined) {\n        throw new Error();\n      }\n    } catch (error) {\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n      return throwError(() => error as TypeError);\n    }\n\n    /* Can fail if storage quota is exceeded */\n    try {\n      localStorage.setItem(this.prefixKey(key), serializedData);\n    } catch (error) {\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n      return throwError(() => error as DOMException);\n    }\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(undefined);\n\n  }\n\n  /**\n   * Deletes an item in `localStorage`\n   * @param key The item's key\n   * @returns A RxJS `Observable` to wait the end of the operation\n   */\n  delete(key: string): Observable<undefined> {\n\n    localStorage.removeItem(this.prefixKey(key));\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(undefined);\n\n  }\n\n  /**\n   * Deletes all items in `localStorage`\n   * @returns A RxJS `Observable` to wait the end of the operation\n   */\n  clear(): Observable<undefined> {\n\n    localStorage.clear();\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(undefined);\n\n  }\n\n  /**\n   * Get all keys in `localStorage`\n   * Note the order of the keys may be inconsistent in Firefox\n   * @returns A RxJS `Observable` iterating on keys\n   */\n  keys(): Observable<string> {\n\n    /* Create an `Observable` from keys */\n    return new Observable<string>((subscriber) => {\n\n      /* Iteretate over all the indexes */\n      for (let index = 0; index < localStorage.length; index += 1) {\n\n        /* Cast as we are sure in this case the key is not `null` */\n        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Ensured by the logic\n        subscriber.next(this.getUnprefixedKey(index)!);\n\n      }\n\n      subscriber.complete();\n\n    }).pipe(\n      /* Required to work like other databases which are asynchronous */\n      observeOn(asyncScheduler),\n    );\n\n  }\n\n  /**\n   * Check if a key exists in `localStorage`\n   * @param key The item's key\n   * @returns A RxJS `Observable` telling if the key exists or not\n   */\n  has(key: string): Observable<boolean> {\n\n    /* Itérate over all indexes in storage */\n    for (let index = 0; index < localStorage.length; index += 1) {\n\n      if (key === this.getUnprefixedKey(index)) {\n\n        /* Wrap in a RxJS `Observable` to be consistent with other storages */\n        return of(true);\n\n      }\n\n    }\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(false);\n\n  }\n\n  /**\n   * Get an unprefixed key\n   * @param index Index of the key\n   * @returns The unprefixed key name if exists, `null` otherwise\n   */\n  private getUnprefixedKey(index: number): string | null {\n\n    /* Get the key in storage: may have a prefix */\n    const prefixedKey = localStorage.key(index);\n\n    if (prefixedKey !== null) {\n\n      /* If no prefix, the key is already good, otherwrite strip the prefix */\n      return this.prefix === \"\" ? prefixedKey : prefixedKey.substring(this.prefix.length);\n\n    }\n\n    return null;\n\n  }\n\n  /**\n   * Add the prefix to a key\n   * @param key The key name\n   * @returns The prefixed key name\n   */\n  private prefixKey(key: string): string {\n\n    return `${this.prefix}${key}`;\n\n  }\n\n}\n","import { Injectable } from \"@angular/core\";\nimport { Observable, from, of } from \"rxjs\";\nimport { LocalDatabase } from \"./local-database\";\n\n@Injectable({\n  providedIn: \"root\"\n})\nexport class MemoryDatabase implements LocalDatabase {\n\n  /**\n   * Memory storage\n   */\n  private readonly memoryStorage = new Map<string, unknown>();\n\n  /**\n   * Number of items in memory\n   */\n  get size(): Observable<number> {\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(this.memoryStorage.size);\n\n  }\n\n  /**\n   * Gets an item value in memory\n   * @param key The item's key\n   * @returns The item's value if the key exists, `undefined` otherwise, wrapped in a RxJS `Observable`\n   */\n  get(key: string): Observable<unknown> {\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(this.memoryStorage.get(key));\n\n  }\n\n  /**\n   * Sets an item in memory\n   * @param key The item's key\n   * @param data The item's value\n   * @returns A RxJS `Observable` to wait the end of the operation\n   */\n  set(key: string, data: unknown): Observable<undefined> {\n\n    this.memoryStorage.set(key, data);\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(undefined);\n\n  }\n\n  /**\n   * Deletes an item in memory\n   * @param key The item's key\n   * @returns A RxJS `Observable` to wait the end of the operation\n   */\n  delete(key: string): Observable<undefined> {\n\n    this.memoryStorage.delete(key);\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(undefined);\n\n  }\n\n  /**\n   * Deletes all items in memory\n   * @returns A RxJS `Observable` to wait the end of the operation\n   */\n  clear(): Observable<undefined> {\n\n    this.memoryStorage.clear();\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(undefined);\n\n  }\n\n  /**\n   * Get all keys in memory\n   * @returns A RxJS `Observable` iterating on keys\n   */\n  keys(): Observable<string> {\n\n    /* Create an `Observable` from keys */\n    return from(this.memoryStorage.keys());\n\n  }\n\n  /**\n   * Check if a key exists in memory\n   * @param key Key name\n   * @returns a RxJS `Observable` telling if the key exists or not\n   */\n  has(key: string): Observable<boolean> {\n\n    /* Wrap in a RxJS `Observable` to be consistent with other storages */\n    return of(this.memoryStorage.has(key));\n\n  }\n\n}\n","import { isPlatformBrowser } from \"@angular/common\";\nimport { inject, Injectable, PLATFORM_ID } from \"@angular/core\";\nimport { Observable } from \"rxjs\";\nimport { IndexedDBDatabase } from \"./indexeddb-database\";\nimport { LocalStorageDatabase } from \"./localstorage-database\";\nimport { MemoryDatabase } from \"./memory-database\";\n\n/**\n * Factory to create a storage according to browser support\n * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/BROWSERS_SUPPORT.md}\n */\nexport function localDatabaseFactory(): LocalDatabase {\n\n  const platformId = inject(PLATFORM_ID);\n\n  /* When storage is fully disabled in browser (via the \"Block all cookies\" option),\n   * just trying to check `indexedDB` or `localStorage` variables causes a security exception.\n   * Prevents https://github.com/cyrilletuzi/angular-async-local-storage/issues/118\n   */\n  try {\n\n    // Do not explicit `window` here, as the global object is not the same in web workers\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- They can be undefined in some browsers scenarios\n    if (isPlatformBrowser(platformId) && (indexedDB !== undefined) && (indexedDB !== null) && (\"open\" in indexedDB)) {\n\n      /* Check:\n      * - if we are in a browser context (issue: server-side rendering)\n      * - it could exist but be `undefined` or `null`\n      * - it could exists but not having a working API\n      * Will be the case for:\n      * - All other browsers in normal mode\n      * - Chromium / Safari / Firefox private mode, but in this case, data will be swiped when the user leaves the app */\n      return new IndexedDBDatabase();\n\n    } else if (isPlatformBrowser(platformId)\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- They can be undefined in some browsers scenarios\n      && (localStorage !== undefined) && (localStorage !== null) && (\"getItem\" in localStorage)) {\n\n      /* Check:\n      * - if we are in a browser context (issue: server-side rendering)\n      * - if `localStorage` exists (to be sure)\n      * - it could exists but not having a working API\n      * Will be the case for:\n      * - Safari cross-origin iframes, detected later in `IndexedDBDatabase.connect()`\n      * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/issues/42}\n      */\n      return new LocalStorageDatabase();\n\n    }\n\n  } catch {\n    // Nothing to do\n  }\n\n  /* Will be the case for:\n   * - In browsers if storage has been fully disabled (via the \"Block all cookies\" option)\n   * - Server-side rendering\n   * - All other non-browser context\n   */\n  return new MemoryDatabase();\n\n}\n\n@Injectable({\n  providedIn: \"root\",\n  useFactory: localDatabaseFactory,\n})\nexport abstract class LocalDatabase {\n\n  abstract readonly size: Observable<number>;\n\n  abstract get(key: string): Observable<unknown>;\n  abstract set(key: string, data: unknown): Observable<undefined>;\n  abstract delete(key: string): Observable<undefined>;\n  abstract clear(): Observable<undefined>;\n  abstract keys(): Observable<string>;\n  abstract has(key: string): Observable<boolean>;\n\n}\n","import { Injectable, inject } from \"@angular/core\";\nimport { Observable, ReplaySubject, fromEvent, of, race, throwError } from \"rxjs\";\nimport { first, map, mergeMap, takeWhile, tap } from \"rxjs/operators\";\nimport { IDB_DB_NAME, IDB_DB_VERSION, IDB_NO_WRAP, IDB_STORE_NAME } from \"../tokens\";\nimport { IDBBrokenError } from \"./exceptions\";\nimport { LocalDatabase } from \"./local-database\";\n\n@Injectable({\n  providedIn: \"root\"\n})\nexport class IndexedDBDatabase implements LocalDatabase {\n\n  /**\n   * `indexedDB` database name\n   */\n  private readonly dbName: string;\n\n  /**\n   * `indexedDB` object store name\n   */\n  private readonly storeName: string;\n\n  /**\n   * `indexedDB` database version. Must be an unsigned **integer**\n   */\n  private readonly dbVersion: number;\n\n  /**\n   * `indexedDB` database connection, wrapped in a RxJS `ReplaySubject` to be able to access the connection\n   * even after the connection success event happened\n   */\n  private readonly database = new ReplaySubject<IDBDatabase>(1);\n\n  /**\n   * Flag to not wrap `indexedDB` values for interoperability or to wrap for backward compatibility.\n   */\n  private readonly noWrap: boolean;\n\n  /**\n   * Index used when wrapping value. *For backward compatibility only.*\n   */\n  private readonly wrapIndex = \"value\";\n\n  constructor() {\n\n    this.dbName = inject(IDB_DB_NAME);\n    this.storeName = inject(IDB_STORE_NAME);\n    this.dbVersion = inject(IDB_DB_VERSION);\n    this.noWrap = inject(IDB_NO_WRAP);\n\n    /* Connect to `indexedDB`, with prefix if provided by the user */\n    this.connect();\n\n  }\n\n  /**\n   * Information about `indexedDB` connection. *Only useful for interoperability.*\n   * @returns `indexedDB` database name, store name and database version\n   */\n  get backingStore(): { database: string, store: string, version: number; } {\n\n    return {\n      database: this.dbName,\n      store: this.storeName,\n      version: this.dbVersion,\n    };\n\n  }\n\n  /**\n   * Number of items in our `indexedDB` database and object store\n   */\n  get size(): Observable<number> {\n\n    /* Open a transaction in read-only mode */\n    return this.transaction(\"readonly\").pipe(\n      mergeMap((transactionData) => {\n\n        const { store, events } = transactionData;\n\n        /* Request to know the number of items */\n        const request = store.count();\n\n        /* Return the result */\n        return events.pipe(map(() => request.result));\n\n      }),\n      /* The observable will complete after the first value */\n      first(),\n    );\n\n  }\n\n  /**\n   * Gets an item value in our `indexedDB` store\n   * @param key The item's key\n   * @returns The item's value if the key exists, `undefined` otherwise, wrapped in an RxJS `Observable`\n   */\n  get(key: string): Observable<unknown> {\n\n    /* Open a transaction in read-only mode */\n    return this.transaction(\"readonly\").pipe(\n      mergeMap((transactionData) => {\n\n        const { store, events } = transactionData;\n\n        /* Request the value with the key provided by the user */\n        const request = store.get(key);\n\n        /* Listen events and return the result */\n        return events.pipe(map((): unknown => {\n\n          if ((request.result !== undefined) && (request.result !== null)) {\n\n            /* Prior to v8, the value was wrapped in an `{ value: ...}` object */\n            if (!this.noWrap && (typeof request.result === \"object\") && (this.wrapIndex in request.result) &&\n              // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Required by indexedDb behavior\n              (request.result[this.wrapIndex] !== undefined) && (request.result[this.wrapIndex] !== null)) {\n\n              // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Required by indexedDb behavior\n              return request.result[this.wrapIndex];\n\n            } else {\n\n              /* Cast to the wanted type */\n              return request.result;\n\n            }\n\n          }\n\n          /* Return `undefined` if the value is empty */\n          return undefined;\n\n        }));\n\n      }),\n      /* The observable will complete after the first value */\n      first(),\n    );\n\n  }\n\n  /**\n   * Sets an item in our `indexedDB` store\n   * @param key The item's key\n   * @param data The item's value\n   * @returns An RxJS `Observable` to wait the end of the operation\n   */\n  set(key: string, data: unknown): Observable<undefined> {\n\n    /* Storing `undefined` in `indexedDb` can cause issues in some browsers so removing item instead */\n    if (data === undefined) {\n      return this.delete(key);\n    }\n\n    /* Open a transaction in write mode */\n    return this.transaction(\"readwrite\").pipe(\n      mergeMap((transactionData) => {\n\n        const { store, events } = transactionData;\n\n        /* Prior to v8, data was wrapped in a `{ value: ... }` object */\n        const dataToStore = this.noWrap ? data : { [this.wrapIndex]: data };\n\n        /* Add if the item is not existing yet, or update otherwise */\n        store.put(dataToStore, key);\n\n        /* Listen to events and return `undefined` as no value is expected */\n        return events.pipe(map(() => undefined));\n\n      }),\n      /* The observable will complete after the first value */\n      first(),\n    );\n\n  }\n\n  /**\n   * Deletes an item in our `indexedDB` store\n   * @param key The item's key\n   * @returns An RxJS `Observable` to wait the end of the operation\n   */\n  delete(key: string): Observable<undefined> {\n\n    /* Open a transaction in write mode */\n    return this.transaction(\"readwrite\").pipe(\n      mergeMap((transactionData) => {\n\n        const { store, events } = transactionData;\n\n        /* Delete the item in store */\n        store.delete(key);\n\n        /* Listen to events and return `undefined` as no data is expected here */\n        return events.pipe(map(() => undefined));\n\n      }),\n      /* The observable will complete after the first value */\n      first(),\n    );\n\n  }\n\n  /**\n   * Deletes all items from our `indexedDB` objet store\n   * @returns An RxJS `Observable` to wait the end of the operation\n   */\n  clear(): Observable<undefined> {\n\n    /* Open a transaction in write mode */\n    return this.transaction(\"readwrite\").pipe(\n      mergeMap((transactionData) => {\n\n        const { store, events } = transactionData;\n\n        /* Delete all items in object store */\n        store.clear();\n\n        /* Listen to events and return `undefined` as no data is expected here */\n        return events.pipe(map(() => undefined));\n\n      }),\n      /* The observable will complete */\n      first(),\n    );\n\n  }\n\n  /**\n   * Get all the keys in our `indexedDB` store\n   * @returns An RxJS `Observable` iterating on each key\n   */\n  keys(): Observable<string> {\n\n    /* Open a transaction in read-only mode */\n    return this.transaction(\"readonly\").pipe(\n      /* `first()` is used as the final operator in other methods to complete the `Observable`\n       * (as it all starts from a `ReplaySubject` which never ends),\n       * but as this method is iterating over multiple values, `first()` **must** be used here */\n      first(),\n      mergeMap((transactionData) => {\n\n        const { store } = transactionData;\n\n        /* Open a cursor on the store\n         * Avoid issues like https://github.com/cyrilletuzi/angular-async-local-storage/issues/69 */\n        const request = store.openKeyCursor();\n\n        /* Listen to success event */\n        const success$ = fromEvent(request, \"success\").pipe(\n          /* Stop the `Observable` when the cursor is `null` */\n          // // eslint-disable-next-line rxjs/no-ignored-takewhile-value -- Required by indexedDb behavior, getting the result from the event does not always work\n          takeWhile(() => (request.result !== null)),\n          /* This lib only allows string keys, but user could have added other types of keys from outside\n           * It's OK to cast as the cursor as been tested in the previous operator */\n          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-base-to-string -- Required by indexedDb behavior, and strings are enforced by the lib\n          map(() => request.result!.key.toString()),\n          /* Iterate on the cursor */\n          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Required by indexedDb behavior\n          tap(() => { request.result!.continue(); }),\n        );\n\n        /* Listen to error event and if so, throw an error */\n        const error$ = this.listenError(request);\n\n        /* Choose the first event to occur */\n        return race([success$, error$]);\n\n      }),\n    );\n\n  }\n\n  /**\n   * Check if a key exists in our `indexedDB` store\n   * @returns An RxJS `Observable` telling if the key exists or not\n   */\n  has(key: string): Observable<boolean> {\n\n    /* Open a transaction in read-only mode */\n    return this.transaction(\"readonly\").pipe(\n      mergeMap((transactionData) => {\n\n        const { store, events } = transactionData;\n\n        /* Check if the key exists in the store\n         * Fixes https://github.com/cyrilletuzi/angular-async-local-storage/issues/69\n         */\n        const request = store.getKey(key);\n\n        /* Listen to events and return `true` or `false` */\n        return events.pipe(map(() => (request.result !== undefined) ? true : false));\n\n      }),\n      /* The observable will complete */\n      first(),\n    );\n\n  }\n\n  /**\n   * Connects to `indexedDB` and creates the object store on first time\n   */\n  private connect(): void {\n\n    let request: IDBOpenDBRequest;\n\n    /* Connect to `indexedDB`\n     * Will fail in Safari cross-origin iframes\n     * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/issues/42} */\n    try {\n\n      /* Do NOT explicit `window` here, as `indexedDB` could be used from a web worker too */\n      request = indexedDB.open(this.dbName, this.dbVersion);\n\n    } catch {\n\n      this.database.error(new IDBBrokenError());\n\n      return;\n\n    }\n\n    /* Create store on first connection */\n    this.createStore(request);\n\n    /* Listen to success and error events */\n    const success$ = fromEvent(request, \"success\");\n    const error$ = this.listenError(request);\n\n    /* Choose the first to occur */\n    race([success$, error$])\n      /* The observable will complete */\n      .pipe(first())\n      .subscribe({\n        next: () => {\n          /* Register the database connection in the `ReplaySubject` for further access */\n          this.database.next(request.result);\n        },\n        error: () => {\n          /* Keeping this error management for safety, but it should not happen anymore.\n           * It was for Firefox private mode issue in Firefox versions < 115\n           * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/issues/26} */\n          this.database.error(new IDBBrokenError());\n        },\n      });\n\n  }\n\n  /**\n   * Create store on first use of `indexedDB`\n   * @param request `indexedDB` database opening request\n   */\n  private createStore(request: IDBOpenDBRequest): void {\n\n    /* Listen to the event fired on first connection */\n    fromEvent(request, \"upgradeneeded\")\n      /* The observable will complete */\n      .pipe(first())\n      .subscribe({\n        next: () => {\n\n          /* Check if the store already exists, to avoid error */\n          if (!request.result.objectStoreNames.contains(this.storeName)) {\n\n            /* Create the object store */\n            request.result.createObjectStore(this.storeName);\n\n          }\n\n        }\n      });\n\n  }\n\n  /**\n   * Open an `indexedDB` transaction and get our store\n   * @param mode `readonly` or `readwrite`\n   * @returns An `indexedDB` transaction store and events, wrapped in an RxJS `Observable`\n   */\n  private transaction(mode: IDBTransactionMode): Observable<{\n    store: IDBObjectStore;\n    events: Observable<Event>;\n  }> {\n\n    /* From the `indexedDB` connection, open a transaction and get the store */\n    return this.database\n      .pipe(mergeMap((database) => {\n\n        let transaction: IDBTransaction;\n\n        try {\n\n          transaction = database.transaction([this.storeName], mode);\n\n        } catch (error) {\n\n          /* The store could have been deleted from outside */\n          // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n          return throwError(() => error as DOMException);\n\n        }\n\n        /* Get the store from the transaction */\n        const store = transaction.objectStore(this.storeName);\n\n        /* Listen transaction `complete` and `error` events */\n        const events = this.listenTransactionEvents(transaction);\n\n        return of({ store, events });\n\n      }));\n\n  }\n\n  /**\n   * Listen errors on a transaction or request, and throw if trigerred\n   * @param transactionOrRequest `indexedDb` transaction or request to listen\n   * @returns An `Observable` listening to errors\n   */\n  private listenError(transactionOrRequest: IDBTransaction | IDBRequest): Observable<never> {\n\n    return fromEvent(transactionOrRequest, \"error\").pipe(\n      /* Throw on error to be able to catch errors in RxJS way.\n       * Here `event.target` must be used, as `transactionOrRequest.error` will be `null`\n       * if we are on the request and the error is only triggered later by the transaction */\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n      mergeMap((event) => throwError(() => (event.target as IDBTransaction | IDBRequest | null)?.error)),\n    );\n\n  }\n\n  /**\n   * Listen transaction `complete` and `error` events\n   * @param transaction Transaction to listen\n   * @returns An `Observable` listening to transaction `complete` and `error` events\n   */\n  private listenTransactionEvents(transaction: IDBTransaction): Observable<Event> {\n\n    /* Listen to the `complete` event */\n    const complete$ = fromEvent(transaction, \"complete\");\n\n    /* Listen to the `error` event */\n    const error$ = this.listenError(transaction);\n\n    /* Choose the first event to occur */\n    return race([complete$, error$]);\n\n  }\n\n}\n","import { Injectable } from \"@angular/core\";\nimport type {\n  JSONSchema,\n  JSONSchemaArray,\n  JSONSchemaBoolean,\n  JSONSchemaInteger, JSONSchemaNumber,\n  JSONSchemaObject,\n  JSONSchemaString,\n  JSONSchemaTuple\n} from \"./json-schema\";\n\n@Injectable({\n  providedIn: \"root\"\n})\nexport class JSONValidator {\n\n  /**\n   * Validate a JSON data against a Jsubset of the JSON Schema standard.\n   * Types are enforced to validate everything: each schema must\n   * @param data JSON data to validate\n   * @param schema Subset of JSON Schema. Must have a `type`.\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/VALIDATION.md}\n   */\n  validate(data: unknown, schema: JSONSchema): boolean {\n\n    switch (schema.type) {\n\n      case \"string\":\n        return this.validateString(data, schema);\n      case \"number\":\n      case \"integer\":\n        return this.validateNumber(data, schema);\n      case \"boolean\":\n        return this.validateBoolean(data, schema);\n      case \"array\":\n        return this.validateArray(data, schema);\n      case \"object\":\n        return this.validateObject(data, schema);\n\n    }\n\n  }\n\n  /**\n   * Validate a string\n   * @param data Data to validate\n   * @param schema Schema describing the string\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateString(data: unknown, schema: JSONSchemaString): boolean {\n\n    if (typeof data !== \"string\") {\n      return false;\n    }\n\n    if (!this.validateConst(data, schema)) {\n      return false;\n    }\n\n    if (!this.validateEnum(data, schema)) {\n      return false;\n    }\n\n    if ((schema.maxLength !== undefined) && (data.length > schema.maxLength)) {\n      return false;\n    }\n\n    if ((schema.minLength !== undefined) && (data.length < schema.minLength)) {\n      return false;\n    }\n\n    if (schema.pattern !== undefined) {\n\n      try {\n        const regularExpression = new RegExp(schema.pattern);\n\n        if (!regularExpression.test(data)) {\n          return false;\n        }\n      } catch {\n        // Nothing to do\n      }\n\n    }\n\n    return true;\n\n  }\n\n  /**\n   * Validate a number or an integer\n   * @param data Data to validate\n   * @param schema Schema describing the number or integer\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateNumber(data: unknown, schema: JSONSchemaNumber | JSONSchemaInteger): boolean {\n\n    if (typeof data !== \"number\") {\n      return false;\n    }\n\n    if ((schema.type === \"integer\") && !Number.isInteger(data)) {\n      return false;\n    }\n\n    if (!this.validateConst(data, schema)) {\n      return false;\n    }\n\n    if (!this.validateEnum(data, schema)) {\n      return false;\n    }\n\n    /* Test is done this way to not divide by 0 */\n    if (schema.multipleOf !== undefined && schema.multipleOf !== 0 && Number.isFinite(schema.multipleOf) && !Number.isInteger(data / schema.multipleOf)) {\n      return false;\n    }\n\n    if ((schema.maximum !== undefined) && (data > schema.maximum)) {\n      return false;\n    }\n\n    if ((schema.exclusiveMaximum !== undefined) && (data >= schema.exclusiveMaximum)) {\n      return false;\n\n    }\n\n    if ((schema.minimum !== undefined) && (data < schema.minimum)) {\n      return false;\n\n    }\n\n    if ((schema.exclusiveMinimum !== undefined) && (data <= schema.exclusiveMinimum)) {\n      return false;\n    }\n\n    return true;\n\n  }\n\n  /**\n   * Validate a boolean\n   * @param data Data to validate\n   * @param schema Schema describing the boolean\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateBoolean(data: unknown, schema: JSONSchemaBoolean): boolean {\n\n    if (typeof data !== \"boolean\") {\n      return false;\n    }\n\n    if (!this.validateConst(data, schema)) {\n      return false;\n    }\n\n    return true;\n\n  }\n\n  /**\n   * Validate an array\n   * @param data Data to validate\n   * @param schema Schema describing the array\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateArray(data: unknown, schema: JSONSchemaArray | JSONSchemaTuple): boolean {\n\n    if (!Array.isArray(data)) {\n      return false;\n    }\n\n    if ((schema.maxItems !== undefined) && (data.length > schema.maxItems)) {\n      return false;\n    }\n\n    if ((schema.minItems !== undefined) && (data.length < schema.minItems)) {\n      return false;\n    }\n\n    if (schema.uniqueItems === true) {\n\n      /* Create a set to eliminate values with multiple occurences */\n      const dataSet = new Set(data);\n\n      if (data.length !== dataSet.size) {\n        return false;\n      }\n\n    }\n\n    /* Specific test for tuples */\n    if (Array.isArray(schema.items) || schema.items === undefined) {\n\n      // TODO: cast should not be needed here\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n      return this.validateTuple(data, schema.items as JSONSchema[] | undefined);\n\n    }\n\n    /* Validate all the values in array */\n    for (const value of data) {\n\n      // TODO: remove when TypeScript 4.1 is available\n      // (currently the narrowed type from `Array.isArray()` is lost on readonly arrays)\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n      if (!this.validate(value, schema.items as JSONSchema)) {\n        return false;\n      }\n\n    }\n\n    return true;\n\n  }\n\n  /**\n   * Validate a tuple (array with fixed length and multiple types)\n   * @param data Data to validate\n   * @param schemas Schemas describing the tuple\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateTuple(data: unknown[], schemas: JSONSchema[] | undefined): boolean {\n\n    const lengthToCheck = schemas ? schemas.length : 0;\n\n    /* Tuples have a fixed length */\n    if (data.length !== lengthToCheck) {\n\n      return false;\n\n    }\n\n    if (schemas) {\n\n      for (const [index, schema] of schemas.entries()) {\n\n        if (!this.validate(data[index], schema)) {\n          return false;\n        }\n\n      }\n\n    }\n\n    return true;\n\n  }\n\n  /**\n   * Validate an object\n   * @param data Data to validate\n   * @param schema JSON schema describing the object\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateObject(data: unknown, schema: JSONSchemaObject): boolean {\n\n    /* Check the type and if not `null` as `null` also have the type `object` in old browsers */\n    if ((typeof data !== \"object\") || (data === null)) {\n      return false;\n    }\n\n    /* Check if the object doesn't have more properties than expected\n     * Equivalent of `additionalProperties: false`\n     */\n    if (Object.keys(schema.properties).length < Object.keys(data).length) {\n      return false;\n    }\n\n    /* Validate required properties */\n    if (schema.required) {\n\n      for (const requiredProp of schema.required) {\n\n        if (!Object.hasOwn(data, requiredProp)) {\n          return false;\n        }\n\n      }\n\n    }\n\n    /* Recursively validate all properties */\n    for (const property in schema.properties) {\n\n      /* Filter to keep only real properties (no internal JS stuff) and check if the data has the property too */\n      if (Object.hasOwn(schema.properties, property) && Object.hasOwn(data, property)) {\n\n        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-type-assertion -- Ensured by the logic\n        if (!this.validate((data as Record<string, unknown>)[property], schema.properties[property]!)) {\n          return false;\n        }\n\n      }\n\n    }\n\n    return true;\n\n  }\n\n  /**\n   * Validate a constant\n   * @param data Data ta validate\n   * @param schema JSON schema describing the constant\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateConst(data: unknown, schema: JSONSchemaBoolean | JSONSchemaInteger | JSONSchemaNumber | JSONSchemaString): boolean {\n\n    if (schema.const === undefined) {\n      return true;\n    }\n\n    return (data === schema.const);\n\n  }\n\n  /**\n   * Validate an enum\n   * @param data Data ta validate\n   * @param schema JSON schema describing the enum\n   * @returns If data is valid: `true`, if it is invalid: `false`\n   */\n  private validateEnum(data: unknown, schema: JSONSchemaInteger | JSONSchemaNumber | JSONSchemaString): boolean {\n\n    if (!schema.enum) {\n      return true;\n    }\n\n    /* Cast as the data can be of multiple types, and so TypeScript is lost */\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n    return ((schema.enum as unknown[]).includes(data));\n\n  }\n\n}\n","import { Injectable } from \"@angular/core\";\nimport { Observable, ReplaySubject, of, throwError, type OperatorFunction } from \"rxjs\";\nimport { catchError, mergeMap, tap } from \"rxjs/operators\";\nimport { IDB_BROKEN_ERROR } from \"../databases/exceptions\";\nimport { IndexedDBDatabase } from \"../databases/indexeddb-database\";\nimport { LocalDatabase } from \"../databases/local-database\";\nimport { LocalStorageDatabase } from \"../databases/localstorage-database\";\nimport { MemoryDatabase } from \"../databases/memory-database\";\nimport type {\n  JSONSchema,\n  JSONSchemaArrayOf,\n  JSONSchemaBoolean, JSONSchemaInteger,\n  JSONSchemaNumber, JSONSchemaString\n} from \"../validation/json-schema\";\nimport { JSONValidator } from \"../validation/json-validator\";\nimport { ValidationError } from \"./exceptions\";\n\n@Injectable({\n  providedIn: \"root\"\n})\nexport class StorageMap {\n\n  #database: LocalDatabase;\n  readonly #jsonValidator: JSONValidator;\n  readonly #notifiers = new Map<string, ReplaySubject<unknown>>();\n\n  /**\n   * Constructor params are provided by Angular (but can also be passed manually in tests)\n   * @param database Storage to use\n   */\n  constructor(\n    // eslint-disable-next-line @angular-eslint/prefer-inject -- Used in tests\n    database: LocalDatabase,\n  ) {\n    this.#database = database;\n    this.#jsonValidator = new JSONValidator();\n  }\n\n  /**\n   * **Number of items** in storage, wrapped in an Observable.\n   * \n   * Note you do *not* need to unsubscribe (it is a self-completing Observable).\n   *\n   * @example\n   * this.storageMap.size.subscribe((size) => {\n   *   console.log(size);\n   * });\n   */\n  get size(): Observable<number> {\n\n    return this.#database.size\n      /* Catch if `indexedDb` is broken */\n      .pipe(this.#catchIDBBroken(() => this.#database.size));\n\n  }\n\n  /**\n   * Tells you which storage engine is used.\n   * \n   * *Only useful for interoperability.*\n   * \n   * Note that due to some browsers issues in some special contexts\n   * (like Safari cross-origin iframes),\n   * **this information may be wrong at initialization,**\n   * as the storage could fallback from `indexedDB` to `localStorage`\n   * only after a first read or write operation.\n   * @returns Storage engine used\n   *\n   * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/INTEROPERABILITY.md}\n   *\n   * @example\n   * if (this.storageMap.backingEngine === 'indexedDB') {}\n   */\n  get backingEngine(): \"indexedDB\" | \"localStorage\" | \"memory\" | \"unknown\" {\n\n    if (this.#database instanceof IndexedDBDatabase) {\n\n      return \"indexedDB\";\n\n    } else if (this.#database instanceof LocalStorageDatabase) {\n\n      return \"localStorage\";\n\n    } else if (this.#database instanceof MemoryDatabase) {\n\n      return \"memory\";\n\n    } else {\n\n      return \"unknown\";\n\n    }\n\n  }\n\n  /**\n   * Information about `indexedDB` database.\n   * \n   * *Only useful for interoperability.*\n   * \n   * @returns `indexedDB` database name, store name and database version.\n   * **Values will be empty if the storage is not `indexedDB`, so it should be used after an engine check**.\n   *\n   * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/INTEROPERABILITY.md}\n   *\n   * @example\n   * if (this.storageMap.backingEngine === 'indexedDB') {\n   *   const { database, store, version } = this.storageMap.backingStore;\n   * }\n   */\n  get backingStore(): { database: string, store: string, version: number; } {\n\n    return (this.#database instanceof IndexedDBDatabase) ?\n      this.#database.backingStore :\n      { database: \"\", store: \"\", version: 0 };\n\n  }\n\n  /**\n   * Information about `localStorage` fallback storage.\n   * \n   * *Only useful for interoperability.*\n   * \n   * @returns `localStorage` prefix.\n   * **Values will be empty if the storage is not `localStorage`, so it should be used after an engine check**.\n   *\n   * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/INTEROPERABILITY.md}\n   *\n   * @example\n   * if (this.storageMap.backingEngine === 'localStorage') {\n   *   const { prefix } = this.storageMap.fallbackBackingStore;\n   * }\n   */\n  get fallbackBackingStore(): { prefix: string; } {\n\n    return (this.#database instanceof LocalStorageDatabase) ?\n      { prefix: this.#database.prefix } :\n      { prefix: \"\" };\n\n  }\n\n  /**\n   * Get an item value in storage.\n   * \n   * Note that:\n   * * not finding an item is not an error, it succeeds but returns `undefined`,\n   * * you do *not* need to unsubscribe (it is a self-completing Observable),\n   * * you will only get *one* value: the Observable is here for asynchrony but is *not* meant to emit again when the stored data is changed. If you need to watch the value, see the `watch` method.\n   * \n   * Do not forget it is client-side storage: **always check the data**, as it could have been forged.\n   * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/VALIDATION.md}\n   * \n   * @param key The item's key\n   * @param schema Optional but recommended JSON schema to validate the data\n   * @returns The item's value if the key exists, `undefined` otherwise, wrapped in a RxJS Observable\n   *\n   * @example\n   * this.storageMap.get('key', { type: 'string' }).subscribe((result) => {\n   *   result; // string or undefined\n   * });\n   *\n   * @example\n   * interface User {\n   *   firstName: string;\n   *   lastName?: string;\n   * }\n   *\n   * const schema = {\n   *   type: 'object',\n   *   properties: {\n   *     firstName: { type: 'string' },\n   *     lastName: { type: 'string' },\n   *   },\n   *   required: ['firstName'],\n   * } satisfies JSONSchema;\n   *\n   * this.storageMap.get<User>('user', schema).subscribe((user) => {\n   *   if (user) {\n   *     user.firstName;\n   *   }\n   * });\n   */\n  get(key: string): Observable<unknown>;\n  get<T extends string = string>(key: string, schema: JSONSchemaString): Observable<T | undefined>;\n  get<T extends number = number>(key: string, schema: JSONSchemaInteger | JSONSchemaNumber): Observable<T | undefined>;\n  get<T extends boolean = boolean>(key: string, schema: JSONSchemaBoolean): Observable<T | undefined>;\n  get<T extends readonly string[] = string[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaString>): Observable<T | undefined>;\n  // eslint-disable-next-line @typescript-eslint/unified-signatures -- Better for documentation\n  get<T extends readonly number[] = number[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaInteger | JSONSchemaNumber>): Observable<T | undefined>;\n  // eslint-disable-next-line @typescript-eslint/unified-signatures -- Better for documentation\n  get<T extends readonly boolean[] = boolean[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaBoolean>): Observable<T | undefined>;\n  get<T>(key: string, schema: JSONSchema): Observable<T | undefined>;\n  get<T = unknown>(key: string, schema?: JSONSchema): Observable<unknown> {\n\n    /* Get the data in storage */\n    return this.#database.get(key).pipe(\n      /* Check if `indexedDb` is broken */\n      this.#catchIDBBroken(() => this.#database.get(key)),\n      mergeMap((data) => {\n\n        /* No need to validate if the data is empty */\n        if ((data === undefined) || (data === null)) {\n\n          return of(undefined);\n\n        } else if (schema) {\n\n          /* Validate data against a JSON schema if provided */\n          if (!this.#jsonValidator.validate(data, schema)) {\n            return throwError(() => new ValidationError());\n          }\n\n          /* Data have been checked, so it's OK to cast */\n          // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n          return of(data as T | undefined);\n\n        }\n\n        /* Cast to unknown as the data wasn't checked */\n        return of(data);\n\n      }),\n    );\n\n  }\n\n  /**\n   * Store an item in storage.\n   * \n   * Note that:\n   * * you *do* need to subscribe, even if you do not have something specific to do after writing in storage, otherwise nothing happens (because it is how RxJS Observables work),\n   * * but you do *not* need to unsubscribe (it is a self-completing Observable),\n   * * setting `null` or `undefined` will remove the item to avoid some browsers issues,\n   * * you should stick to serializable JSON data, meaning primitive types, arrays and literal objects. Date, Map, Set, Blob and other special structures can cause issues in some scenarios.\n   * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/SERIALIZATION.md}\n   * \n   * @param key The item's key\n   * @param data The item's value\n   * @param schema Optional JSON schema to validate the data\n   * @returns A RxJS Observable to wait the end of the operation\n   *\n   * @example\n   * this.storageMap.set('key', 'value').subscribe(() => {});\n   */\n  set(key: string, data: unknown, schema?: JSONSchema): Observable<undefined> {\n\n    /* Storing `undefined` or `null` is useless and can cause issues in `indexedDb` in some browsers,\n     * so removing item instead for all storages to have a consistent API */\n    if ((data === undefined) || (data === null)) {\n      return this.delete(key);\n    }\n\n    /* Validate data against a JSON schema if provided */\n    if (schema && !this.#jsonValidator.validate(data, schema)) {\n      return throwError(() => new ValidationError());\n    }\n\n    return this.#database.set(key, data).pipe(\n      /* Catch if `indexedDb` is broken */\n      this.#catchIDBBroken(() => this.#database.set(key, data)),\n      /* Notify watchers (must be last because it should only happen if the operation succeeds) */\n      tap(() => { this.#notify(key, data); }),\n    );\n  }\n\n  /**\n   * Delete an item in storage.\n   * \n   * Note that:\n   * * you *do* need to subscribe, even if you do not have something specific to do after deleting, otherwise nothing happens (because it is how RxJS Observables work),\n   * * but you do *not* need to unsubscribe (it is a self-completing Observable).\n   * \n   * @param key The item's key\n   * @returns A RxJS Observable to wait the end of the operation\n   *\n   * @example\n   * this.storageMap.delete('key').subscribe(() => {});\n   */\n  delete(key: string): Observable<undefined> {\n\n    return this.#database.delete(key).pipe(\n      /* Catch if `indexedDb` is broken */\n      this.#catchIDBBroken(() => this.#database.delete(key)),\n      /* Notify watchers (must be last because it should only happen if the operation succeeds) */\n      tap(() => { this.#notify(key, undefined); }),\n    );\n\n  }\n\n  /**\n   * Delete all items in storage.\n   * \n   * Note that:\n   * * you *do* need to subscribe, even if you do not have something specific to do after clearing, otherwise nothing happens (because it is how RxJS Observables work),\n   * * but you do *not* need to unsubscribe (it is a self-completing Observable).\n   * \n   * @returns A RxJS Observable to wait the end of the operation\n   *\n   * @example\n   * this.storageMap.clear().subscribe(() => {});\n   */\n  clear(): Observable<undefined> {\n\n    return this.#database.clear().pipe(\n      /* Catch if `indexedDb` is broken */\n      this.#catchIDBBroken(() => this.#database.clear()),\n      /* Notify watchers (must be last because it should only happen if the operation succeeds) */\n      tap(() => {\n        for (const key of this.#notifiers.keys()) {\n          this.#notify(key, undefined);\n        }\n      }),\n    );\n\n  }\n\n  /**\n   * Get all keys stored in storage.\n   * \n   * Note **this is an *iterating* Observable**:\n   * * if there is no key, the `next` callback will not be invoked,\n   * * if you need to wait the whole operation to end, be sure to act in the `complete` callback,\n   * as this Observable can emit several values and so will invoke the `next` callback several times,\n   * * you do *not* need to unsubscribe (it is a self-completing Observable).\n   * \n   * @returns A list of the keys wrapped in a RxJS Observable\n   *\n   * @example\n   * this.storageMap.keys().subscribe({\n   *   next: (key) => { console.log(key); },\n   *   complete: () => { console.log('Done'); },\n   * });\n   */\n  keys(): Observable<string> {\n\n    return this.#database.keys()\n      /* Catch if `indexedDb` is broken */\n      .pipe(this.#catchIDBBroken(() => this.#database.keys()));\n\n  }\n\n  /**\n   * Tells if a key exists in storage.\n   * \n   * Note you do *not* need to unsubscribe (it is a self-completing Observable).\n   * \n   * @returns A RxJS Observable telling if the key exists\n   *\n   * @example\n   * this.storageMap.has('key').subscribe((hasKey) => {\n   *   if (hasKey) {}\n   * });\n   */\n  has(key: string): Observable<boolean> {\n\n    return this.#database.has(key)\n      /* Catch if `indexedDb` is broken */\n      .pipe(this.#catchIDBBroken(() => this.#database.has(key)));\n\n  }\n\n  /**\n   * Watch an item value in storage.\n   * \n   * Note that:\n   * * it is an infinite Observable, do not forget to unsubscribe,\n   * * only changes done via this library will be watched, external changes in storage cannot be detected.\n   * \n   * The signature has many overloads due to validation, **please refer to the documentation.**\n   * @see https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/VALIDATION.md\n   * \n   * @param key The item's key to watch\n   * @param schema Optional JSON schema to validate the initial value\n   * @returns An infinite Observable giving the current value\n   * \n   * @example\n   * Component()\n   * export class MyComponent implements OnInit, OnDestroy {\n   * \n   *   private storageSubscription?: Subscription;\n   * \n   *   ngOnInit(): void {\n   *     this.storageSubscription = this.storageMap.watch('key', { type: 'string' }).subscribe((result) => {\n   *       result; // string or undefined\n   *     });\n   *   }\n   * \n   *   ngOnDestroy(): void {\n   *     this.storageSubscription?.unsubscribe();\n   *   }\n   * \n   * }\n   */\n  watch(key: string): Observable<unknown>;\n  watch<T extends string = string>(key: string, schema: JSONSchemaString): Observable<T | undefined>;\n  watch<T extends number = number>(key: string, schema: JSONSchemaInteger | JSONSchemaNumber): Observable<T | undefined>;\n  watch<T extends boolean = boolean>(key: string, schema: JSONSchemaBoolean): Observable<T | undefined>;\n  watch<T extends readonly string[] = string[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaString>): Observable<T | undefined>;\n  // eslint-disable-next-line @typescript-eslint/unified-signatures -- Better for documentation\n  watch<T extends readonly number[] = number[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaInteger | JSONSchemaNumber>): Observable<T | undefined>;\n  // eslint-disable-next-line @typescript-eslint/unified-signatures -- Better for documentation\n  watch<T extends readonly boolean[] = boolean[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaBoolean>): Observable<T | undefined>;\n  watch<T>(key: string, schema: JSONSchema): Observable<T | undefined>;\n  watch<T = unknown>(key: string, schema?: JSONSchema): Observable<unknown> {\n\n    /* Check if there is already a notifier */\n    if (!this.#notifiers.has(key)) {\n      this.#notifiers.set(key, new ReplaySubject(1));\n    }\n\n    /* Non-null assertion is required because TypeScript doesn't narrow `.has()` yet */\n    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Ensured by the logic\n    const notifier = this.#notifiers.get(key)!;\n\n    /* Get the current item value */\n    (schema ? this.get<T>(key, schema) : this.get(key)).subscribe({\n      next: (result) => {\n        notifier.next(result);\n      },\n      error: (error) => {\n        notifier.error(error);\n      },\n    });\n\n    /* Only the public API of the Observable should be returned */\n    return (schema ?\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n      notifier.asObservable() as Observable<T | undefined> :\n      notifier.asObservable()\n    );\n\n  }\n\n  /**\n   * Notify when a value changes\n   * @param key The item's key\n   * @param data The new value\n   */\n  #notify(key: string, value: unknown): void {\n\n    const notifier = this.#notifiers.get(key);\n\n    if (notifier) {\n      notifier.next(value);\n    }\n\n  }\n\n  /**\n   * RxJS operator to catch if `indexedDB` is broken\n   * @param operationCallback Callback with the operation to redo\n   */\n  #catchIDBBroken<T>(operationCallback: () => Observable<T>): OperatorFunction<T, T> {\n\n    return catchError((error) => {\n\n      /* Check if `indexedDB` is broken based on error message (the specific error class seems to be lost in the process) */\n      if ((error !== undefined) && (error !== null)\n        && (typeof error === \"object\") && (\"message\" in error)\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Required because TypeScript narrowing is not working here\n        && (error.message === IDB_BROKEN_ERROR)) {\n\n        /* When storage is fully disabled in browser (via the \"Block all cookies\" option),\n         * just trying to check `localStorage` variable causes a security exception.\n         * Prevents https://github.com/cyrilletuzi/angular-async-local-storage/issues/118\n         */\n        try {\n\n          if (\"getItem\" in localStorage) {\n\n            /* Fallback to `localStorage` if available */\n            this.#database = new LocalStorageDatabase();\n\n          } else {\n\n            /* Fallback to memory storage otherwise */\n            this.#database = new MemoryDatabase();\n\n          }\n\n        } catch {\n\n          /* Fallback to memory storage otherwise */\n          this.#database = new MemoryDatabase();\n\n        }\n\n        /* Redo the operation */\n        return operationCallback();\n\n      } else {\n\n        /* Otherwise, rethrow the error */\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n        return throwError(() => error);\n\n      }\n\n    });\n\n  }\n\n  /**\n   * THIS METHOD IS FOR INTERNAL PURPOSE ONLY AND MUST NOT BE USED,\n   * IT CAN BE REMOVED AT ANY TIME AND MESSING WITH IT CAN CAUSE ISSUES\n   * @private\n   * @ignore\n   */\n  // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- Silence the not used error, it is used in tests\n  // @ts-ignore\n  private ɵinternalGetDatabase(): LocalDatabase {\n\n    return this.#database;\n\n  }\n\n}\n","/*\n * Public API Surface of local-storage\n */\n\nexport { SERIALIZATION_ERROR, SerializationError } from \"./lib/databases/exceptions\";\nexport {\n  provideIndexedDBDataBaseName, provideIndexedDBDataBaseVersion,\n  provideIndexedDBStoreName, provideLocalStoragePrefix\n} from \"./lib/providers\";\nexport { StorageModule } from \"./lib/storage.module\";\nexport { VALIDATION_ERROR, ValidationError } from \"./lib/storages/exceptions\";\nexport { StorageMap } from \"./lib/storages/storage-map\";\nexport type { StorageConfig } from \"./lib/tokens\";\nexport type { JSONSchema } from \"./lib/validation/json-schema\";\n\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.LocalDatabase"],"mappings":"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"}