@ngx-pwa/local-storage 21.0.0 → 22.0.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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2016-2025 Cyrille Tuzi
3
+ Copyright (c) 2016-2026 Cyrille Tuzi
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, NgModule, inject, Injectable, PLATFORM_ID } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, NgModule, inject, Service, assertInInjectionContext, PLATFORM_ID, Injectable } from '@angular/core';
3
3
  import { of, throwError, Observable, asyncScheduler, from, ReplaySubject, fromEvent, race } from 'rxjs';
4
4
  import { observeOn, mergeMap, map, first, takeWhile, tap, catchError } from 'rxjs/operators';
5
5
  import { isPlatformBrowser } from '@angular/common';
@@ -175,11 +175,11 @@ class StorageModule {
175
175
  ],
176
176
  };
177
177
  }
178
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: StorageModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
179
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.0", ngImport: i0, type: StorageModule });
180
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: StorageModule });
178
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: StorageModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
179
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.0", ngImport: i0, type: StorageModule });
180
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: StorageModule });
181
181
  }
182
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: StorageModule, decorators: [{
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: StorageModule, decorators: [{
183
183
  type: NgModule
184
184
  }] });
185
185
 
@@ -241,6 +241,7 @@ class LocalStorageDatabase {
241
241
  * @returns A RxJS `Observable` to wait the end of the operation
242
242
  */
243
243
  set(key, data) {
244
+ // eslint-disable-next-line no-useless-assignment
244
245
  let serializedData = null;
245
246
  /* Check if data can be serialized */
246
247
  const dataPrototype = Object.getPrototypeOf(data);
@@ -346,14 +347,11 @@ class LocalStorageDatabase {
346
347
  prefixKey(key) {
347
348
  return `${this.prefix}${key}`;
348
349
  }
349
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LocalStorageDatabase, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
350
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LocalStorageDatabase, providedIn: "root" });
350
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LocalStorageDatabase, deps: [], target: i0.ɵɵFactoryTarget.Service });
351
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: LocalStorageDatabase });
351
352
  }
352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LocalStorageDatabase, decorators: [{
353
- type: Injectable,
354
- args: [{
355
- providedIn: "root"
356
- }]
353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LocalStorageDatabase, decorators: [{
354
+ type: Service
357
355
  }], ctorParameters: () => [] });
358
356
 
359
357
  class MemoryDatabase {
@@ -424,14 +422,11 @@ class MemoryDatabase {
424
422
  /* Wrap in a RxJS `Observable` to be consistent with other storages */
425
423
  return of(this.memoryStorage.has(key));
426
424
  }
427
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: MemoryDatabase, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
428
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: MemoryDatabase, providedIn: "root" });
425
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: MemoryDatabase, deps: [], target: i0.ɵɵFactoryTarget.Service });
426
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: MemoryDatabase });
429
427
  }
430
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: MemoryDatabase, decorators: [{
431
- type: Injectable,
432
- args: [{
433
- providedIn: "root"
434
- }]
428
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: MemoryDatabase, decorators: [{
429
+ type: Service
435
430
  }] });
436
431
 
437
432
  /**
@@ -439,6 +434,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
439
434
  * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/BROWSERS_SUPPORT.md}
440
435
  */
441
436
  function localDatabaseFactory() {
437
+ assertInInjectionContext(localDatabaseFactory);
442
438
  const platformId = inject(PLATFORM_ID);
443
439
  /* When storage is fully disabled in browser (via the "Block all cookies" option),
444
440
  * just trying to check `indexedDB` or `localStorage` variables causes a security exception.
@@ -471,9 +467,7 @@ function localDatabaseFactory() {
471
467
  return new LocalStorageDatabase();
472
468
  }
473
469
  }
474
- catch {
475
- // Nothing to do
476
- }
470
+ catch { }
477
471
  /* Will be the case for:
478
472
  * - In browsers if storage has been fully disabled (via the "Block all cookies" option)
479
473
  * - Server-side rendering
@@ -482,14 +476,13 @@ function localDatabaseFactory() {
482
476
  return new MemoryDatabase();
483
477
  }
484
478
  class LocalDatabase {
485
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LocalDatabase, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
486
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LocalDatabase, providedIn: "root", useFactory: localDatabaseFactory });
479
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LocalDatabase, deps: [], target: i0.ɵɵFactoryTarget.Service });
480
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: LocalDatabase, factory: localDatabaseFactory });
487
481
  }
488
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LocalDatabase, decorators: [{
489
- type: Injectable,
482
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: LocalDatabase, decorators: [{
483
+ type: Service,
490
484
  args: [{
491
- providedIn: "root",
492
- useFactory: localDatabaseFactory,
485
+ factory: localDatabaseFactory,
493
486
  }]
494
487
  }] });
495
488
 
@@ -736,6 +729,7 @@ class IndexedDBDatabase {
736
729
  * Create store on first use of `indexedDB`
737
730
  * @param request `indexedDB` database opening request
738
731
  */
732
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
739
733
  createStore(request) {
740
734
  /* Listen to the event fired on first connection */
741
735
  fromEvent(request, "upgradeneeded")
@@ -781,6 +775,7 @@ class IndexedDBDatabase {
781
775
  * @param transactionOrRequest `indexedDb` transaction or request to listen
782
776
  * @returns An `Observable` listening to errors
783
777
  */
778
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
784
779
  listenError(transactionOrRequest) {
785
780
  return fromEvent(transactionOrRequest, "error").pipe(
786
781
  /* Throw on error to be able to catch errors in RxJS way.
@@ -794,6 +789,7 @@ class IndexedDBDatabase {
794
789
  * @param transaction Transaction to listen
795
790
  * @returns An `Observable` listening to transaction `complete` and `error` events
796
791
  */
792
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
797
793
  listenTransactionEvents(transaction) {
798
794
  /* Listen to the `complete` event */
799
795
  const complete$ = fromEvent(transaction, "complete");
@@ -802,14 +798,11 @@ class IndexedDBDatabase {
802
798
  /* Choose the first event to occur */
803
799
  return race([complete$, error$]);
804
800
  }
805
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: IndexedDBDatabase, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
806
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: IndexedDBDatabase, providedIn: "root" });
801
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: IndexedDBDatabase, deps: [], target: i0.ɵɵFactoryTarget.Service });
802
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: IndexedDBDatabase });
807
803
  }
808
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: IndexedDBDatabase, decorators: [{
809
- type: Injectable,
810
- args: [{
811
- providedIn: "root"
812
- }]
804
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: IndexedDBDatabase, decorators: [{
805
+ type: Service
813
806
  }], ctorParameters: () => [] });
814
807
 
815
808
  class JSONValidator {
@@ -865,9 +858,7 @@ class JSONValidator {
865
858
  return false;
866
859
  }
867
860
  }
868
- catch {
869
- // Nothing to do
870
- }
861
+ catch { }
871
862
  }
872
863
  return true;
873
864
  }
@@ -1047,14 +1038,11 @@ class JSONValidator {
1047
1038
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1048
1039
  return (schema.enum.includes(data));
1049
1040
  }
1050
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: JSONValidator, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1051
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: JSONValidator, providedIn: "root" });
1041
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: JSONValidator, deps: [], target: i0.ɵɵFactoryTarget.Service });
1042
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: JSONValidator });
1052
1043
  }
1053
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: JSONValidator, decorators: [{
1054
- type: Injectable,
1055
- args: [{
1056
- providedIn: "root"
1057
- }]
1044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: JSONValidator, decorators: [{
1045
+ type: Service
1058
1046
  }] });
1059
1047
 
1060
1048
  class StorageMap {
@@ -1066,7 +1054,7 @@ class StorageMap {
1066
1054
  * @param database Storage to use
1067
1055
  */
1068
1056
  constructor(
1069
- // eslint-disable-next-line @angular-eslint/prefer-inject -- Used in tests
1057
+ // eslint-disable-next-line @angular-eslint/prefer-inject, @typescript-eslint/prefer-readonly-parameter-types -- Used in tests for inject, wanted as writeable for readonly
1070
1058
  database) {
1071
1059
  this.#database = database;
1072
1060
  this.#jsonValidator = new JSONValidator();
@@ -1313,10 +1301,7 @@ class StorageMap {
1313
1301
  },
1314
1302
  });
1315
1303
  /* Only the public API of the Observable should be returned */
1316
- return (schema ?
1317
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1318
- notifier.asObservable() :
1319
- notifier.asObservable());
1304
+ return notifier.asObservable();
1320
1305
  }
1321
1306
  /**
1322
1307
  * Notify when a value changes
@@ -1379,10 +1364,10 @@ class StorageMap {
1379
1364
  ɵinternalGetDatabase() {
1380
1365
  return this.#database;
1381
1366
  }
1382
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: StorageMap, deps: [{ token: LocalDatabase }], target: i0.ɵɵFactoryTarget.Injectable });
1383
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: StorageMap, providedIn: "root" });
1367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: StorageMap, deps: [{ token: LocalDatabase }], target: i0.ɵɵFactoryTarget.Injectable });
1368
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: StorageMap, providedIn: "root" });
1384
1369
  }
1385
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: StorageMap, decorators: [{
1370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: StorageMap, decorators: [{
1386
1371
  type: Injectable,
1387
1372
  args: [{
1388
1373
  providedIn: "root"
@@ -1 +1 @@
1
- {"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":";;;;;;AAAA;;AAEG;AACI,MAAM,gBAAgB,GAAG,0BAA0B;AAE1D;;AAEG;AACG,MAAO,cAAe,SAAQ,KAAK,CAAA;IAC9B,OAAO,GAAW,gBAAgB;AAC5C;AAED;;AAEG;AACI,MAAM,mBAAmB,GAAG,CAAA;;AAGnC;;AAEG;AACG,MAAO,kBAAmB,SAAQ,KAAK,CAAA;IAClC,OAAO,GAAW,mBAAmB;AAC/C;;ACrBD;;AAEG;AACI,MAAM,SAAS,GAA2B,IAAI,cAAc,CAAS,oBAAoB,EAAE;AAChG,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAc;AACxB,CAAA,CAAC;AAEF;;AAEG;AACI,MAAM,mBAAmB,GAAG,WAAW;AAE9C;;AAEG;AACI,MAAM,WAAW,GAA2B,IAAI,cAAc,CAAS,uBAAuB,EAAE;AACrG,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAc;AACxB,CAAA,CAAC;AAEF;;AAEG;AACI,MAAM,sBAAsB,GAAG,CAAC;AAEvC;;;AAGG;AACI,MAAM,cAAc,GAA2B,IAAI,cAAc,CAAS,0BAA0B,EAAE;AAC3G,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAc;AACxB,CAAA,CAAC;AAEF;;AAEG;AACI,MAAM,sBAAsB,GAAG,cAAc;AAEpD;;;AAGG;AACI,MAAM,cAAc,GAA2B,IAAI,cAAc,CAAS,0BAA0B,EAAE;AAC3G,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAc;AACxB,CAAA,CAAC;AAEF;;;AAGG;AACI,MAAM,mBAAmB,GAAG,IAAI;AAEvC;;;;;AAKG;AACI,MAAM,WAAW,GAA4B,IAAI,cAAc,CAAU,qBAAqB,EAAE;AACrG,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAe;AACzB,CAAA,CAAC;;AC/DF;;;;;;;;;;;AAWG;AACG,SAAU,yBAAyB,CAAC,MAAc,EAAA;AAEtD,IAAA,OAAO,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAE7E;AAEA;;;;;;;;;;;AAWG;AACG,SAAU,4BAA4B,CAAC,IAAY,EAAA;AAEvD,IAAA,OAAO,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAE7E;AAEA;;;;;;;;;;;;;;AAcG;AACG,SAAU,+BAA+B,CAAC,OAAe,EAAA;AAE7D,IAAA,OAAO,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAEnF;AAEA;;;;;;;;;;;AAWG;AACG,SAAU,yBAAyB,CAAC,IAAY,EAAA;AAEpD,IAAA,OAAO,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAEhF;;ACzEA;;;;AAIG;MAEU,aAAa,CAAA;AAExB;;;;AAIG;IACH,OAAO,OAAO,CAAC,MAAqB,EAAA;QAClC,OAAO;AACL,YAAA,QAAQ,EAAE,aAAa;AACvB,YAAA,SAAS,EAAE;;gBAET,MAAM,CAAC,QAAQ,KAAK,SAAS,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE;;gBAEtF,MAAM,CAAC,SAAS,KAAK,SAAS,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE;;gBAE1F,MAAM,CAAC,YAAY,KAAK,SAAS,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,YAAY,EAAE,GAAG,EAAE;;gBAEnG,MAAM,CAAC,YAAY,KAAK,SAAS,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,YAAY,EAAE,GAAG,EAAE;gBACnG,CAAC,MAAM,CAAC,SAAS,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE;AACzF,aAAA;SACF;IACH;uGAtBW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA;wGAAb,aAAa,EAAA,CAAA;wGAAb,aAAa,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBADzB;;;ACRD;;AAEG;AACI,MAAM,gBAAgB,GAAG,CAAA;;AAGhC;;AAEG;AACG,MAAO,eAAgB,SAAQ,KAAK,CAAA;IAC/B,OAAO,GAAW,gBAAgB;AAC5C;;MCDY,oBAAoB,CAAA;AAE/B;;AAEG;AACM,IAAA,MAAM;AAEf,IAAA,WAAA,GAAA;;AAGE,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAEjC;AAEA;;AAEG;AACH,IAAA,IAAI,IAAI,GAAA;;AAGN,QAAA,OAAO,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;IAEhC;AAEA;;;;AAIG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;;AAGb,QAAA,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;;AAG9D,QAAA,IAAI,YAAY,KAAK,IAAI,EAAE;;AAGzB,YAAA,IAAI;gBAEF,MAAM,UAAU,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;;AAGpD,gBAAA,OAAO,EAAE,CAAC,UAAU,CAAC;YAEvB;YAAE,OAAO,KAAK,EAAE;;AAEd,gBAAA,OAAO,UAAU,CAAC,MAAM,KAAoB,CAAC;YAC/C;QAEF;AAEA,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;;;AAKG;IACH,GAAG,CAAC,GAAW,EAAE,IAAY,EAAA;QAE3B,IAAI,cAAc,GAAmC,IAAI;;QAGzD,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC;AACjD,QAAA,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;AACpD,YAAA,EAAE,CAAC,aAAa,KAAK,MAAM,CAAC,SAAS,MAAM,aAAa,KAAK,IAAI,CAAC,CAAC,EAAE;YACrE,OAAO,UAAU,CAAC,MAAM,IAAI,kBAAkB,EAAE,CAAC;QACnD;;AAGA,QAAA,IAAI;AACF,YAAA,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACrC,YAAA,IAAI,cAAc,KAAK,SAAS,EAAE;gBAChC,MAAM,IAAI,KAAK,EAAE;YACnB;QACF;QAAE,OAAO,KAAK,EAAE;;AAEd,YAAA,OAAO,UAAU,CAAC,MAAM,KAAkB,CAAC;QAC7C;;AAGA,QAAA,IAAI;AACF,YAAA,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC;QAC3D;QAAE,OAAO,KAAK,EAAE;;AAEd,YAAA,OAAO,UAAU,CAAC,MAAM,KAAqB,CAAC;QAChD;;AAGA,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;;AAIG;AACH,IAAA,MAAM,CAAC,GAAW,EAAA;QAEhB,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;;AAG5C,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;AAGG;IACH,KAAK,GAAA;QAEH,YAAY,CAAC,KAAK,EAAE;;AAGpB,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;;AAIG;IACH,IAAI,GAAA;;AAGF,QAAA,OAAO,IAAI,UAAU,CAAS,CAAC,UAAU,KAAI;;AAG3C,YAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE;;;gBAI3D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAE,CAAC;YAEhD;YAEA,UAAU,CAAC,QAAQ,EAAE;QAEvB,CAAC,CAAC,CAAC,IAAI;;AAEL,QAAA,SAAS,CAAC,cAAc,CAAC,CAC1B;IAEH;AAEA;;;;AAIG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;;AAGb,QAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE;YAE3D,IAAI,GAAG,KAAK,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE;;AAGxC,gBAAA,OAAO,EAAE,CAAC,IAAI,CAAC;YAEjB;QAEF;;AAGA,QAAA,OAAO,EAAE,CAAC,KAAK,CAAC;IAElB;AAEA;;;;AAIG;AACK,IAAA,gBAAgB,CAAC,KAAa,EAAA;;QAGpC,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAE3C,QAAA,IAAI,WAAW,KAAK,IAAI,EAAE;;YAGxB,OAAO,IAAI,CAAC,MAAM,KAAK,EAAE,GAAG,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAErF;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;AAIG;AACK,IAAA,SAAS,CAAC,GAAW,EAAA;AAE3B,QAAA,OAAO,GAAG,IAAI,CAAC,MAAM,CAAA,EAAG,GAAG,EAAE;IAE/B;uGA9MW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAApB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,oBAAoB,cAFnB,MAAM,EAAA,CAAA;;2FAEP,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAHhC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;MCFY,cAAc,CAAA;AAEzB;;AAEG;AACc,IAAA,aAAa,GAAG,IAAI,GAAG,EAAmB;AAE3D;;AAEG;AACH,IAAA,IAAI,IAAI,GAAA;;QAGN,OAAO,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;IAEpC;AAEA;;;;AAIG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;;QAGb,OAAO,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC;AAEA;;;;;AAKG;IACH,GAAG,CAAC,GAAW,EAAE,IAAa,EAAA;QAE5B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;;AAGjC,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;;AAIG;AACH,IAAA,MAAM,CAAC,GAAW,EAAA;AAEhB,QAAA,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC;;AAG9B,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;AAGG;IACH,KAAK,GAAA;AAEH,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;;AAG1B,QAAA,OAAO,EAAE,CAAC,SAAS,CAAC;IAEtB;AAEA;;;AAGG;IACH,IAAI,GAAA;;QAGF,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IAExC;AAEA;;;;AAIG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;;QAGb,OAAO,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExC;uGA5FW,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAd,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,cAAc,cAFb,MAAM,EAAA,CAAA;;2FAEP,cAAc,EAAA,UAAA,EAAA,CAAA;kBAH1B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACCD;;;AAGG;SACa,oBAAoB,GAAA;AAElC,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;AAEtC;;;AAGG;AACH,IAAA,IAAI;;;QAIF,IAAI,iBAAiB,CAAC,UAAU,CAAC,KAAK,SAAS,KAAK,SAAS,CAAC,KAAK,SAAS,KAAK,IAAI,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC,EAAE;AAE/G;;;;;;AAMmH;YACnH,OAAO,IAAI,iBAAiB,EAAE;QAEhC;aAAO,IAAI,iBAAiB,CAAC,UAAU;;AAElC,gBAAC,YAAY,KAAK,SAAS,CAAC,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,SAAS,IAAI,YAAY,CAAC,EAAE;AAE3F;;;;;;;AAOE;YACF,OAAO,IAAI,oBAAoB,EAAE;QAEnC;IAEF;AAAE,IAAA,MAAM;;IAER;AAEA;;;;AAIG;IACH,OAAO,IAAI,cAAc,EAAE;AAE7B;MAMsB,aAAa,CAAA;uGAAb,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAb,aAAa,EAAA,UAAA,EAHrB,MAAM,EAAA,UAAA,EACN,oBAAoB,EAAA,CAAA;;2FAEZ,aAAa,EAAA,UAAA,EAAA,CAAA;kBAJlC,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AAClB,oBAAA,UAAU,EAAE,oBAAoB;AACjC,iBAAA;;;MCxDY,iBAAiB,CAAA;AAE5B;;AAEG;AACc,IAAA,MAAM;AAEvB;;AAEG;AACc,IAAA,SAAS;AAE1B;;AAEG;AACc,IAAA,SAAS;AAE1B;;;AAGG;AACc,IAAA,QAAQ,GAAG,IAAI,aAAa,CAAc,CAAC,CAAC;AAE7D;;AAEG;AACc,IAAA,MAAM;AAEvB;;AAEG;IACc,SAAS,GAAG,OAAO;AAEpC,IAAA,WAAA,GAAA;AAEE,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;AACjC,QAAA,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC;AACvC,QAAA,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC;AACvC,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;;QAGjC,IAAI,CAAC,OAAO,EAAE;IAEhB;AAEA;;;AAGG;AACH,IAAA,IAAI,YAAY,GAAA;QAEd,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,MAAM;YACrB,KAAK,EAAE,IAAI,CAAC,SAAS;YACrB,OAAO,EAAE,IAAI,CAAC,SAAS;SACxB;IAEH;AAEA;;AAEG;AACH,IAAA,IAAI,IAAI,GAAA;;AAGN,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,IAAI,CACtC,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe;;AAGzC,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE;;AAG7B,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;AAE/C,QAAA,CAAC,CAAC;;QAEF,KAAK,EAAE,CACR;IAEH;AAEA;;;;AAIG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;;AAGb,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,IAAI,CACtC,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe;;YAGzC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;;AAG9B,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAc;AAEnC,gBAAA,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,MAAM,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE;;oBAG/D,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;;yBAE3F,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,EAAE;;wBAG7F,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;oBAEvC;yBAAO;;wBAGL,OAAO,OAAO,CAAC,MAAM;oBAEvB;gBAEF;;AAGA,gBAAA,OAAO,SAAS;YAElB,CAAC,CAAC,CAAC;AAEL,QAAA,CAAC,CAAC;;QAEF,KAAK,EAAE,CACR;IAEH;AAEA;;;;;AAKG;IACH,GAAG,CAAC,GAAW,EAAE,IAAa,EAAA;;AAG5B,QAAA,IAAI,IAAI,KAAK,SAAS,EAAE;AACtB,YAAA,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;QACzB;;AAGA,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CACvC,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe;;YAGzC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE;;AAGnE,YAAA,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC;;AAG3B,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC;AAE1C,QAAA,CAAC,CAAC;;QAEF,KAAK,EAAE,CACR;IAEH;AAEA;;;;AAIG;AACH,IAAA,MAAM,CAAC,GAAW,EAAA;;AAGhB,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CACvC,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe;;AAGzC,YAAA,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;;AAGjB,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC;AAE1C,QAAA,CAAC,CAAC;;QAEF,KAAK,EAAE,CACR;IAEH;AAEA;;;AAGG;IACH,KAAK,GAAA;;AAGH,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CACvC,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe;;YAGzC,KAAK,CAAC,KAAK,EAAE;;AAGb,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC;AAE1C,QAAA,CAAC,CAAC;;QAEF,KAAK,EAAE,CACR;IAEH;AAEA;;;AAGG;IACH,IAAI,GAAA;;AAGF,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,IAAI;AACtC;;AAE2F;AAC3F,QAAA,KAAK,EAAE,EACP,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe;AAEjC;AAC4F;AAC5F,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,EAAE;;YAGrC,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI;;;YAGjD,SAAS,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;AAC1C;AAC2E;;AAE3E,YAAA,GAAG,CAAC,MAAM,OAAO,CAAC,MAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;;;AAGzC,YAAA,GAAG,CAAC,MAAK,EAAG,OAAO,CAAC,MAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAC3C;;YAGD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;;YAGxC,OAAO,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAEjC,CAAC,CAAC,CACH;IAEH;AAEA;;;AAGG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;;AAGb,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,IAAI,CACtC,QAAQ,CAAC,CAAC,eAAe,KAAI;AAE3B,YAAA,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe;AAEzC;;AAEG;YACH,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;;YAGjC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC;AAE9E,QAAA,CAAC,CAAC;;QAEF,KAAK,EAAE,CACR;IAEH;AAEA;;AAEG;IACK,OAAO,GAAA;AAEb,QAAA,IAAI,OAAyB;AAE7B;;AAEuF;AACvF,QAAA,IAAI;;AAGF,YAAA,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QAEvD;AAAE,QAAA,MAAM;YAEN,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;YAEzC;QAEF;;AAGA,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;;QAGzB,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;;AAGxC,QAAA,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC;;aAEpB,IAAI,CAAC,KAAK,EAAE;AACZ,aAAA,SAAS,CAAC;YACT,IAAI,EAAE,MAAK;;gBAET,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACpC,CAAC;YACD,KAAK,EAAE,MAAK;AACV;;AAEuF;gBACvF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;YAC3C,CAAC;AACF,SAAA,CAAC;IAEN;AAEA;;;AAGG;AACK,IAAA,WAAW,CAAC,OAAyB,EAAA;;AAG3C,QAAA,SAAS,CAAC,OAAO,EAAE,eAAe;;aAE/B,IAAI,CAAC,KAAK,EAAE;AACZ,aAAA,SAAS,CAAC;YACT,IAAI,EAAE,MAAK;;AAGT,gBAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;;oBAG7D,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC;gBAElD;YAEF;AACD,SAAA,CAAC;IAEN;AAEA;;;;AAIG;AACK,IAAA,WAAW,CAAC,IAAwB,EAAA;;QAM1C,OAAO,IAAI,CAAC;AACT,aAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,QAAQ,KAAI;AAE1B,YAAA,IAAI,WAA2B;AAE/B,YAAA,IAAI;AAEF,gBAAA,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC;YAE5D;YAAE,OAAO,KAAK,EAAE;;;AAId,gBAAA,OAAO,UAAU,CAAC,MAAM,KAAqB,CAAC;YAEhD;;YAGA,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC;;YAGrD,MAAM,MAAM,GAAG,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC;YAExD,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAE9B,CAAC,CAAC,CAAC;IAEP;AAEA;;;;AAIG;AACK,IAAA,WAAW,CAAC,oBAAiD,EAAA;AAEnE,QAAA,OAAO,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,IAAI;AAClD;;AAEuF;;AAEvF,QAAA,QAAQ,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,MAAO,KAAK,CAAC,MAA6C,EAAE,KAAK,CAAC,CAAC,CACnG;IAEH;AAEA;;;;AAIG;AACK,IAAA,uBAAuB,CAAC,WAA2B,EAAA;;QAGzD,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC;;QAGpD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;;QAG5C,OAAO,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAElC;uGAvbW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cAFhB,MAAM,EAAA,CAAA;;2FAEP,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAH7B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;MCKY,aAAa,CAAA;AAExB;;;;;;;AAOG;IACH,QAAQ,CAAC,IAAa,EAAE,MAAkB,EAAA;AAExC,QAAA,QAAQ,MAAM,CAAC,IAAI;AAEjB,YAAA,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC;AAC1C,YAAA,KAAK,QAAQ;AACb,YAAA,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC;AAC1C,YAAA,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC;AAC3C,YAAA,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC;AACzC,YAAA,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC;;IAI9C;AAEA;;;;;AAKG;IACK,cAAc,CAAC,IAAa,EAAE,MAAwB,EAAA;AAE5D,QAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AAC5B,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AACrC,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,MAAM,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,EAAE;AACxE,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,MAAM,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,EAAE;AACxE,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE;AAEhC,YAAA,IAAI;gBACF,MAAM,iBAAiB,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;gBAEpD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACjC,oBAAA,OAAO,KAAK;gBACd;YACF;AAAE,YAAA,MAAM;;YAER;QAEF;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;;AAKG;IACK,cAAc,CAAC,IAAa,EAAE,MAA4C,EAAA;AAEhF,QAAA,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AAC5B,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;AAC1D,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AACrC,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AACpC,YAAA,OAAO,KAAK;QACd;;AAGA,QAAA,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE;AACnJ,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE;AAC7D,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,KAAK,SAAS,MAAM,IAAI,IAAI,MAAM,CAAC,gBAAgB,CAAC,EAAE;AAChF,YAAA,OAAO,KAAK;QAEd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE;AAC7D,YAAA,OAAO,KAAK;QAEd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,gBAAgB,KAAK,SAAS,MAAM,IAAI,IAAI,MAAM,CAAC,gBAAgB,CAAC,EAAE;AAChF,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;;AAKG;IACK,eAAe,CAAC,IAAa,EAAE,MAAyB,EAAA;AAE9D,QAAA,IAAI,OAAO,IAAI,KAAK,SAAS,EAAE;AAC7B,YAAA,OAAO,KAAK;QACd;QAEA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AACrC,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;;AAKG;IACK,aAAa,CAAC,IAAa,EAAE,MAAyC,EAAA;QAE5E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AACxB,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,MAAM,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE;AACtE,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,MAAM,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE;AACtE,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,EAAE;;AAG/B,YAAA,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC;YAE7B,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE;AAChC,gBAAA,OAAO,KAAK;YACd;QAEF;;AAGA,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE;;;YAI7D,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,KAAiC,CAAC;QAE3E;;AAGA,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE;;;;AAKxB,YAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAmB,CAAC,EAAE;AACrD,gBAAA,OAAO,KAAK;YACd;QAEF;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;;AAKG;IACK,aAAa,CAAC,IAAe,EAAE,OAAiC,EAAA;AAEtE,QAAA,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC;;AAGlD,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE;AAEjC,YAAA,OAAO,KAAK;QAEd;QAEA,IAAI,OAAO,EAAE;AAEX,YAAA,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE;AAE/C,gBAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAAE;AACvC,oBAAA,OAAO,KAAK;gBACd;YAEF;QAEF;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;;AAKG;IACK,cAAc,CAAC,IAAa,EAAE,MAAwB,EAAA;;AAG5D,QAAA,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,MAAM,IAAI,KAAK,IAAI,CAAC,EAAE;AACjD,YAAA,OAAO,KAAK;QACd;AAEA;;AAEG;QACH,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;AACpE,YAAA,OAAO,KAAK;QACd;;AAGA,QAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;AAEnB,YAAA,KAAK,MAAM,YAAY,IAAI,MAAM,CAAC,QAAQ,EAAE;gBAE1C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE;AACtC,oBAAA,OAAO,KAAK;gBACd;YAEF;QAEF;;AAGA,QAAA,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE;;YAGxC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;;AAG/E,gBAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAE,IAAgC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAE,CAAC,EAAE;AAC7F,oBAAA,OAAO,KAAK;gBACd;YAEF;QAEF;AAEA,QAAA,OAAO,IAAI;IAEb;AAEA;;;;;AAKG;IACK,aAAa,CAAC,IAAa,EAAE,MAAmF,EAAA;AAEtH,QAAA,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE;AAC9B,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,QAAQ,IAAI,KAAK,MAAM,CAAC,KAAK;IAE/B;AAEA;;;;;AAKG;IACK,YAAY,CAAC,IAAa,EAAE,MAA+D,EAAA;AAEjG,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;AAChB,YAAA,OAAO,IAAI;QACb;;;QAIA,QAAS,MAAM,CAAC,IAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC;IAEnD;uGAhUW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAb,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,aAAa,cAFZ,MAAM,EAAA,CAAA;;2FAEP,aAAa,EAAA,UAAA,EAAA,CAAA;kBAHzB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;MCOY,UAAU,CAAA;AAErB,IAAA,SAAS;AACA,IAAA,cAAc;AACd,IAAA,UAAU,GAAG,IAAI,GAAG,EAAkC;AAE/D;;;AAGG;AACH,IAAA,WAAA;;IAEE,QAAuB,EAAA;AAEvB,QAAA,IAAI,CAAC,SAAS,GAAG,QAAQ;AACzB,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI,aAAa,EAAE;IAC3C;AAEA;;;;;;;;;AASG;AACH,IAAA,IAAI,IAAI,GAAA;AAEN,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC;;AAEnB,aAAA,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAE1D;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH,IAAA,IAAI,aAAa,GAAA;AAEf,QAAA,IAAI,IAAI,CAAC,SAAS,YAAY,iBAAiB,EAAE;AAE/C,YAAA,OAAO,WAAW;QAEpB;AAAO,aAAA,IAAI,IAAI,CAAC,SAAS,YAAY,oBAAoB,EAAE;AAEzD,YAAA,OAAO,cAAc;QAEvB;AAAO,aAAA,IAAI,IAAI,CAAC,SAAS,YAAY,cAAc,EAAE;AAEnD,YAAA,OAAO,QAAQ;QAEjB;aAAO;AAEL,YAAA,OAAO,SAAS;QAElB;IAEF;AAEA;;;;;;;;;;;;;;AAcG;AACH,IAAA,IAAI,YAAY,GAAA;QAEd,OAAO,CAAC,IAAI,CAAC,SAAS,YAAY,iBAAiB;AACjD,YAAA,IAAI,CAAC,SAAS,CAAC,YAAY;AAC3B,YAAA,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;IAE3C;AAEA;;;;;;;;;;;;;;AAcG;AACH,IAAA,IAAI,oBAAoB,GAAA;QAEtB,OAAO,CAAC,IAAI,CAAC,SAAS,YAAY,oBAAoB;YACpD,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;AACjC,YAAA,EAAE,MAAM,EAAE,EAAE,EAAE;IAElB;IAqDA,GAAG,CAAc,GAAW,EAAE,MAAmB,EAAA;;QAG/C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI;;QAEjC,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EACnD,QAAQ,CAAC,CAAC,IAAI,KAAI;;AAGhB,YAAA,IAAI,CAAC,IAAI,KAAK,SAAS,MAAM,IAAI,KAAK,IAAI,CAAC,EAAE;AAE3C,gBAAA,OAAO,EAAE,CAAC,SAAS,CAAC;YAEtB;iBAAO,IAAI,MAAM,EAAE;;AAGjB,gBAAA,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;oBAC/C,OAAO,UAAU,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC;gBAChD;;;AAIA,gBAAA,OAAO,EAAE,CAAC,IAAqB,CAAC;YAElC;;AAGA,YAAA,OAAO,EAAE,CAAC,IAAI,CAAC;QAEjB,CAAC,CAAC,CACH;IAEH;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACH,IAAA,GAAG,CAAC,GAAW,EAAE,IAAa,EAAE,MAAmB,EAAA;AAEjD;AACwE;AACxE,QAAA,IAAI,CAAC,IAAI,KAAK,SAAS,MAAM,IAAI,KAAK,IAAI,CAAC,EAAE;AAC3C,YAAA,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;QACzB;;AAGA,QAAA,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;YACzD,OAAO,UAAU,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC;QAChD;QAEA,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI;;AAEvC,QAAA,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;;AAEzD,QAAA,GAAG,CAAC,MAAK,EAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CACxC;IACH;AAEA;;;;;;;;;;;;AAYG;AACH,IAAA,MAAM,CAAC,GAAW,EAAA;QAEhB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI;;AAEpC,QAAA,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;;AAEtD,QAAA,GAAG,CAAC,MAAK,EAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAC7C;IAEH;AAEA;;;;;;;;;;;AAWG;IACH,KAAK,GAAA;AAEH,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI;;AAEhC,QAAA,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;;QAElD,GAAG,CAAC,MAAK;YACP,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE;AACxC,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC;YAC9B;QACF,CAAC,CAAC,CACH;IAEH;AAEA;;;;;;;;;;;;;;;;AAgBG;IACH,IAAI,GAAA;AAEF,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI;;AAEvB,aAAA,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAE5D;AAEA;;;;;;;;;;;AAWG;AACH,IAAA,GAAG,CAAC,GAAW,EAAA;AAEb,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG;;AAE1B,aAAA,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAE9D;IA4CA,KAAK,CAAc,GAAW,EAAE,MAAmB,EAAA;;QAGjD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;AAC7B,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC;QAChD;;;QAIA,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAE;;QAG1C,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAI,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC;AAC5D,YAAA,IAAI,EAAE,CAAC,MAAM,KAAI;AACf,gBAAA,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YACvB,CAAC;AACD,YAAA,KAAK,EAAE,CAAC,KAAK,KAAI;AACf,gBAAA,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;YACvB,CAAC;AACF,SAAA,CAAC;;QAGF,QAAQ,MAAM;;AAEZ,YAAA,QAAQ,CAAC,YAAY,EAA+B;AACpD,YAAA,QAAQ,CAAC,YAAY,EAAE;IAG3B;AAEA;;;;AAIG;IACH,OAAO,CAAC,GAAW,EAAE,KAAc,EAAA;QAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;QAEzC,IAAI,QAAQ,EAAE;AACZ,YAAA,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;QACtB;IAEF;AAEA;;;AAGG;AACH,IAAA,eAAe,CAAI,iBAAsC,EAAA;AAEvD,QAAA,OAAO,UAAU,CAAC,CAAC,KAAK,KAAI;;YAG1B,IAAI,CAAC,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,IAAI;oBACtC,OAAO,KAAK,KAAK,QAAQ,CAAC,KAAK,SAAS,IAAI,KAAK;;AAElD,oBAAC,KAAK,CAAC,OAAO,KAAK,gBAAgB,CAAC,EAAE;AAEzC;;;AAGG;AACH,gBAAA,IAAI;AAEF,oBAAA,IAAI,SAAS,IAAI,YAAY,EAAE;;AAG7B,wBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,oBAAoB,EAAE;oBAE7C;yBAAO;;AAGL,wBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,cAAc,EAAE;oBAEvC;gBAEF;AAAE,gBAAA,MAAM;;AAGN,oBAAA,IAAI,CAAC,SAAS,GAAG,IAAI,cAAc,EAAE;gBAEvC;;gBAGA,OAAO,iBAAiB,EAAE;YAE5B;iBAAO;;;AAIL,gBAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;YAEhC;AAEF,QAAA,CAAC,CAAC;IAEJ;AAEA;;;;;AAKG;;;IAGK,oBAAoB,GAAA;QAE1B,OAAO,IAAI,CAAC,SAAS;IAEvB;uGA9eW,UAAU,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAAA,aAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAV,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAU,cAFT,MAAM,EAAA,CAAA;;2FAEP,UAAU,EAAA,UAAA,EAAA,CAAA;kBAHtB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE;AACb,iBAAA;;;ACnBD;;AAEG;;ACFH;;AAEG;;;;"}
1
+ {"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 readonly LSPrefix?: string;\n\n /**\n * @deprecated Use `provideIndexedDBDataBaseName()` method instead\n */\n readonly IDBDBName?: string;\n\n /**\n * @deprecated Use `provideIndexedDBStoreName()` method instead\n */\n readonly IDBStoreName?: string;\n\n /**\n * @deprecated Use `provideIndexedDBDataBaseVersion()` method instead\n */\n readonly 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 readonly 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 { Service, 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@Service()\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 // eslint-disable-next-line no-useless-assignment\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 { Service } from \"@angular/core\";\nimport { Observable, from, of } from \"rxjs\";\nimport { LocalDatabase } from \"./local-database\";\n\n@Service()\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 { assertInInjectionContext, inject, PLATFORM_ID, Service } 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 assertInInjectionContext(localDatabaseFactory);\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\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@Service({\n factory: 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 { Service, 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@Service()\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 // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\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 readonly store: IDBObjectStore;\n readonly 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 // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\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 // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\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 { Service } 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@Service()\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\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: readonly unknown[], schemas: readonly 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, @typescript-eslint/prefer-readonly-parameter-types -- Used in tests for inject, wanted as writeable for readonly\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 notifier.asObservable();\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngx-pwa/local-storage",
3
- "version": "21.0.0",
3
+ "version": "22.0.0",
4
4
  "funding": {
5
5
  "type": "github",
6
6
  "url": "https://github.com/sponsors/cyrilletuzi"
@@ -20,8 +20,8 @@
20
20
  "tslib": "^2.5.0"
21
21
  },
22
22
  "peerDependencies": {
23
- "@angular/common": "^21.0.0",
24
- "@angular/core": "^21.0.0",
23
+ "@angular/common": "^22.0.0",
24
+ "@angular/core": "^22.0.0",
25
25
  "rxjs": "^7.6.0"
26
26
  },
27
27
  "schematics": "./schematics/collection.json",
@@ -39,5 +39,6 @@
39
39
  "types": "./types/ngx-pwa-local-storage.d.ts",
40
40
  "default": "./fesm2022/ngx-pwa-local-storage.mjs"
41
41
  }
42
- }
42
+ },
43
+ "type": "module"
43
44
  }
@@ -9,10 +9,10 @@ function default_1() {
9
9
  /* Get config */
10
10
  const angularMajorVersion = (0, config_1.getDependencyMajorVersion)("@angular/core", host);
11
11
  if (angularMajorVersion === undefined) {
12
- context.logger.warn(`Not able to detect @angular/core version. Be aware that Angular versions <= 18 are no longer supported.`);
12
+ context.logger.warn(`Not able to detect @angular/core version. Be aware that Angular versions <= 19 are no longer supported.`);
13
13
  }
14
- if (angularMajorVersion !== undefined && (angularMajorVersion <= 18)) {
15
- throw new schematics_1.SchematicsException("Angular versions <= 18 are no longer supported.");
14
+ if (angularMajorVersion !== undefined && (angularMajorVersion <= 19)) {
15
+ throw new schematics_1.SchematicsException("Angular versions <= 19 are no longer supported.");
16
16
  }
17
17
  const rxjsMajorVersion = (0, config_1.getDependencyMajorVersion)("rxjs", host);
18
18
  if (rxjsMajorVersion === undefined) {
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updateModule = updateModule;
4
4
  exports.updateModuleToV9 = updateModuleToV9;
5
5
  const schematics_1 = require("@angular-devkit/schematics");
6
- const typescript_1 = require("@schematics/angular/third_party/github.com/Microsoft/TypeScript/lib/typescript");
7
6
  const ast_utils_1 = require("@schematics/angular/utility/ast-utils");
8
7
  const ng_ast_utils_1 = require("@schematics/angular/utility/ng-ast-utils");
8
+ const typescript_1 = require("typescript");
9
9
  const config_1 = require("./config");
10
10
  /**
11
11
  * @param mainPath Path of the project `main.ts` file
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../../../lib/schematics/utility/module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../../../lib/schematics/utility/module.ts"],"names":[],"mappings":"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"}
@@ -78,19 +78,19 @@ interface StorageConfig {
78
78
  /**
79
79
  * @deprecated Use `provideLocalStoragePrefix()` method instead
80
80
  */
81
- LSPrefix?: string;
81
+ readonly LSPrefix?: string;
82
82
  /**
83
83
  * @deprecated Use `provideIndexedDBDataBaseName()` method instead
84
84
  */
85
- IDBDBName?: string;
85
+ readonly IDBDBName?: string;
86
86
  /**
87
87
  * @deprecated Use `provideIndexedDBStoreName()` method instead
88
88
  */
89
- IDBStoreName?: string;
89
+ readonly IDBStoreName?: string;
90
90
  /**
91
91
  * @deprecated Use `provideIndexedDBDataBaseVersion()` method instead
92
92
  */
93
- IDBDBVersion?: number;
93
+ readonly IDBDBVersion?: number;
94
94
  /**
95
95
  * Allows interoperability with native `indexedDB` and other storage libs,
96
96
  * by changing how values are stored in `indexedDB` database.
@@ -99,7 +99,7 @@ interface StorageConfig {
99
99
  *
100
100
  * **DO NOT CHANGE THIS BEHAVIOR ONCE IN PRODUCTION**, as it would break with existing data.
101
101
  */
102
- IDBNoWrap?: boolean;
102
+ readonly IDBNoWrap?: boolean;
103
103
  }
104
104
 
105
105
  /**
@@ -149,11 +149,11 @@ interface JSONSchemaBoolean {
149
149
  /**
150
150
  * Type for a boolean value.
151
151
  */
152
- type: "boolean";
152
+ readonly type: "boolean";
153
153
  /**
154
154
  * Checks if a value is strictly equal to this.
155
155
  */
156
- const?: boolean;
156
+ readonly const?: boolean;
157
157
  }
158
158
  /**
159
159
  * JSON Schema to describe a number value.
@@ -162,36 +162,36 @@ interface JSONSchemaNumber {
162
162
  /**
163
163
  * Type for a numeric value.
164
164
  */
165
- type: "number";
165
+ readonly type: "number";
166
166
  /**
167
167
  * Checks if a value is strictly equal to this.
168
168
  */
169
- const?: number;
169
+ readonly const?: number;
170
170
  /**
171
171
  * Checks if a value is strictly equal to one of the value of enum.
172
172
  */
173
- enum?: readonly number[];
173
+ readonly enum?: readonly number[];
174
174
  /**
175
175
  * Check if a number is a multiple of x.
176
176
  * Must be strictly greater than 0.
177
177
  */
178
- multipleOf?: number;
178
+ readonly multipleOf?: number;
179
179
  /**
180
180
  * Check if a number is lower or equal than this maximum.
181
181
  */
182
- maximum?: number;
182
+ readonly maximum?: number;
183
183
  /**
184
184
  * Check if a number is strictly lower than this maximum.
185
185
  */
186
- exclusiveMaximum?: number;
186
+ readonly exclusiveMaximum?: number;
187
187
  /**
188
188
  * Check if a number is greater or equal than this minimum.
189
189
  */
190
- minimum?: number;
190
+ readonly minimum?: number;
191
191
  /**
192
192
  * Check if a number is strictly greater than this minimum.
193
193
  */
194
- exclusiveMinimum?: number;
194
+ readonly exclusiveMinimum?: number;
195
195
  }
196
196
  /**
197
197
  * JSON Schema to describe an integer value.
@@ -200,36 +200,36 @@ interface JSONSchemaInteger {
200
200
  /**
201
201
  * Type for an integer value.
202
202
  */
203
- type: "integer";
203
+ readonly type: "integer";
204
204
  /**
205
205
  * Checks if a value is strictly equal to this.
206
206
  */
207
- const?: number;
207
+ readonly const?: number;
208
208
  /**
209
209
  * Checks if a value is strictly equal to one of the value of enum.
210
210
  */
211
- enum?: readonly number[];
211
+ readonly enum?: readonly number[];
212
212
  /**
213
213
  * Check if a number is a multiple of x.
214
214
  * Must be strictly greater than 0.
215
215
  */
216
- multipleOf?: number;
216
+ readonly multipleOf?: number;
217
217
  /**
218
218
  * Check if a number is lower or equal than this maximum.
219
219
  */
220
- maximum?: number;
220
+ readonly maximum?: number;
221
221
  /**
222
222
  * Check if a number is strictly lower than this maximum.
223
223
  */
224
- exclusiveMaximum?: number;
224
+ readonly exclusiveMaximum?: number;
225
225
  /**
226
226
  * Check if a number is greater or equal than this minimum.
227
227
  */
228
- minimum?: number;
228
+ readonly minimum?: number;
229
229
  /**
230
230
  * Check if a number is strictly greater than this minimum.
231
231
  */
232
- exclusiveMinimum?: number;
232
+ readonly exclusiveMinimum?: number;
233
233
  }
234
234
  /**
235
235
  * JSON Schema to describe a string value.
@@ -238,30 +238,30 @@ interface JSONSchemaString {
238
238
  /**
239
239
  * Type for a string value.
240
240
  */
241
- type: "string";
241
+ readonly type: "string";
242
242
  /**
243
243
  * Checks if a value is strictly equal to this.
244
244
  */
245
- const?: string;
245
+ readonly const?: string;
246
246
  /**
247
247
  * Checks if a value is strictly equal to one of the value of enum.
248
248
  */
249
- enum?: readonly string[];
249
+ readonly enum?: readonly string[];
250
250
  /**
251
251
  * Maxium length for a string.
252
252
  * Must be a non-negative integer.
253
253
  */
254
- maxLength?: number;
254
+ readonly maxLength?: number;
255
255
  /**
256
256
  * Minimum length for a string.
257
257
  * Must be a non-negative integer.
258
258
  */
259
- minLength?: number;
259
+ readonly minLength?: number;
260
260
  /**
261
261
  * Pattern to match for a string.
262
262
  * Must be a valid regular expression, *without* the `/` delimiters.
263
263
  */
264
- pattern?: string;
264
+ readonly pattern?: string;
265
265
  }
266
266
  /**
267
267
  * JSON schema to describe an array of values.
@@ -270,25 +270,25 @@ interface JSONSchemaArray {
270
270
  /**
271
271
  * Type for an array of values.
272
272
  */
273
- type: "array";
273
+ readonly type: "array";
274
274
  /**
275
275
  * Schema for the values of the array.
276
276
  */
277
- items: JSONSchema;
277
+ readonly items: JSONSchema;
278
278
  /**
279
279
  * Check if an array length is lower or equal to this value.
280
280
  * Must be a non negative integer.
281
281
  */
282
- maxItems?: number;
282
+ readonly maxItems?: number;
283
283
  /**
284
284
  * Check if an array length is greater or equal to this value.
285
285
  * Must be a non negative integer.
286
286
  */
287
- minItems?: number;
287
+ readonly minItems?: number;
288
288
  /**
289
289
  * Check if an array only have unique values.
290
290
  */
291
- uniqueItems?: boolean;
291
+ readonly uniqueItems?: boolean;
292
292
  }
293
293
  /**
294
294
  * JSON Schema to describe an array of primitive values:
@@ -301,25 +301,25 @@ interface JSONSchemaArrayOf<T extends JSONSchemaBoolean | JSONSchemaNumber | JSO
301
301
  /**
302
302
  * Type for an array of values.
303
303
  */
304
- type: "array";
304
+ readonly type: "array";
305
305
  /**
306
306
  * Schema for the values of an array.
307
307
  */
308
- items: T;
308
+ readonly items: T;
309
309
  /**
310
310
  * Check if an array length is lower or equal to this value.
311
311
  * Must be a non negative integer.
312
312
  */
313
- maxItems?: number;
313
+ readonly maxItems?: number;
314
314
  /**
315
315
  * Check if an array length is greater or equal to this value.
316
316
  * Must be a non negative integer.
317
317
  */
318
- minItems?: number;
318
+ readonly minItems?: number;
319
319
  /**
320
320
  * Check if an array only have unique values.
321
321
  */
322
- uniqueItems?: boolean;
322
+ readonly uniqueItems?: boolean;
323
323
  }
324
324
  /**
325
325
  * JSON schema to describe a tuple.
@@ -328,25 +328,25 @@ interface JSONSchemaTuple {
328
328
  /**
329
329
  * Type for an array of values.
330
330
  */
331
- type: "array";
331
+ readonly type: "array";
332
332
  /**
333
333
  * Schema for the values of the tuple.
334
334
  */
335
- items?: readonly JSONSchema[];
335
+ readonly items?: readonly JSONSchema[];
336
336
  /**
337
337
  * Check if an array length is lower or equal to this value.
338
338
  * Must be a non negative integer.
339
339
  */
340
- maxItems?: number;
340
+ readonly maxItems?: number;
341
341
  /**
342
342
  * Check if an array length is greater or equal to this value.
343
343
  * Must be a non negative integer.
344
344
  */
345
- minItems?: number;
345
+ readonly minItems?: number;
346
346
  /**
347
347
  * Check if an array only have unique values.
348
348
  */
349
- uniqueItems?: boolean;
349
+ readonly uniqueItems?: boolean;
350
350
  }
351
351
  /**
352
352
  * JSON schema to describe an object.
@@ -355,16 +355,16 @@ interface JSONSchemaObject {
355
355
  /**
356
356
  * Type for an object.
357
357
  */
358
- type: "object";
358
+ readonly type: "object";
359
359
  /**
360
360
  * List of properties of the object and their associated JSON schemas.
361
361
  */
362
- properties: Record<string, JSONSchema>;
362
+ readonly properties: Readonly<Record<string, JSONSchema>>;
363
363
  /**
364
364
  * Array of names of the required properties for an object.
365
365
  * Properties set as required should be present in `properties` too.
366
366
  */
367
- required?: readonly string[];
367
+ readonly required?: readonly string[];
368
368
  }
369
369
  /**
370
370
  * Subset of the JSON Schema standard.