import * as i0 from '@angular/core';
import { EnvironmentProviders, ModuleWithProviders } from '@angular/core';
import { Observable } from 'rxjs';

/**
 * Exception message when a value cannot be serialized for `localStorage`
 */
declare const SERIALIZATION_ERROR = "The storage is currently localStorage,\nwhere data must be serialized, and the provided data can't be serialized.";
/**
 * Exception throwned when a value cannot be serialized for `localStorage`
 */
declare class SerializationError extends Error {
    message: string;
}

/**
 * Allows to add a prefix before `localStorage` keys.
 *
 * *Use only* for interoperability with other APIs or to avoid collision for multiple applications on the same subdomain.
 *
 * **WARNING: do not change this option in an application already deployed in production, as previously stored data would be lost.**
 *
 * @example
 * export const appConfig: ApplicationConfig = {
 *   providers: [provideLocalStoragePrefix('custom_')]
 * };
 */
declare function provideLocalStoragePrefix(prefix: string): EnvironmentProviders;
/**
 * Allows to change the name used for `indexedDB` database.
 *
 * *Use only* for interoperability with other APIs or to avoid collision for multiple applications on the same subdomain.
 *
 * **WARNING: do not change this option in an application already deployed in production, as previously stored data would be lost.**
 *
 * @example
 * export const appConfig: ApplicationConfig = {
 *   providers: [provideIndexedDBDataBaseName('custom')]
 * };
 */
declare function provideIndexedDBDataBaseName(name: string): EnvironmentProviders;
/**
 * Allows to change the database version used for `indexedDB` database.
 * Must be an unsigned **integer**.
 *
 * **Use with caution as the creation of the store depends on the version.**
 *
 * *Use only* for interoperability with other APIs or to avoid collision for multiple applications on the same subdomain.
 *
 * **WARNING: do not change this option in an applicattion already deployed in production, as previously stored data would be lost.**
 *
 * @example
 * export const appConfig: ApplicationConfig = {
 *   providers: [provideIndexedDBDataBaseVersion(2)]
 * };
 */
declare function provideIndexedDBDataBaseVersion(version: number): EnvironmentProviders;
/**
 * Allows to change the name used for `indexedDB` object store.
 *
 * *Use only* for interoperability with other APIs.
 *
 * **WARNING: do not change this option in an application already deployed in production, as previously stored data would be lost.**
 *
 * @example
 * export const appConfig: ApplicationConfig = {
 *   providers: [provideIndexedDBStoreName('custom')]
 * };
 */
declare function provideIndexedDBStoreName(name: string): EnvironmentProviders;

/**
 * This interface is only here for backward compatibility, **do not add it by yourself**
 *
 * @ignore
 */
interface StorageConfig {
    /**
     * @deprecated Use `provideLocalStoragePrefix()` method instead
     */
    LSPrefix?: string;
    /**
     * @deprecated Use `provideIndexedDBDataBaseName()` method instead
     */
    IDBDBName?: string;
    /**
     * @deprecated Use `provideIndexedDBStoreName()` method instead
     */
    IDBStoreName?: string;
    /**
     * @deprecated Use `provideIndexedDBDataBaseVersion()` method instead
     */
    IDBDBVersion?: number;
    /**
     * Allows interoperability with native `indexedDB` and other storage libs,
     * by changing how values are stored in `indexedDB` database.
     *
     * Defaults to `true`. Change to `false` for backward compatiblity in existing applications.
     *
     * **DO NOT CHANGE THIS BEHAVIOR ONCE IN PRODUCTION**, as it would break with existing data.
     */
    IDBNoWrap?: boolean;
}

/**
 * This module is only here for backward compatibility, **do not add it by yourself**
 *
 * @ignore
 */
declare class StorageModule {
    /**
     * Only useful to provide options, otherwise it does nothing.
     *
     * **Must be used at initialization, ie. in `AppModule`, and must not be loaded again in another module.**
     */
    static forRoot(config: StorageConfig): ModuleWithProviders<StorageModule>;
    static ɵfac: i0.ɵɵFactoryDeclaration<StorageModule, never>;
    static ɵmod: i0.ɵɵNgModuleDeclaration<StorageModule, never, never, never>;
    static ɵinj: i0.ɵɵInjectorDeclaration<StorageModule>;
}

/**
 * Exception message when a value is not valid against the JSON schema
 */
declare const VALIDATION_ERROR = "Data stored is not valid against the provided JSON schema.\nCheck your JSON schema, otherwise it means data has been corrupted.";
/**
 * Exception throwned when a value is not valid against the JSON schema
 */
declare class ValidationError extends Error {
    message: string;
}

declare abstract class LocalDatabase {
    abstract readonly size: Observable<number>;
    abstract get(key: string): Observable<unknown>;
    abstract set(key: string, data: unknown): Observable<undefined>;
    abstract delete(key: string): Observable<undefined>;
    abstract clear(): Observable<undefined>;
    abstract keys(): Observable<string>;
    abstract has(key: string): Observable<boolean>;
    static ɵfac: i0.ɵɵFactoryDeclaration<LocalDatabase, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<LocalDatabase>;
}

/**
 * JSON Schema to describe a boolean value.
 */
interface JSONSchemaBoolean {
    /**
     * Type for a boolean value.
     */
    type: "boolean";
    /**
     * Checks if a value is strictly equal to this.
     */
    const?: boolean;
}
/**
 * JSON Schema to describe a number value.
 */
interface JSONSchemaNumber {
    /**
     * Type for a numeric value.
     */
    type: "number";
    /**
     * Checks if a value is strictly equal to this.
     */
    const?: number;
    /**
     * Checks if a value is strictly equal to one of the value of enum.
     */
    enum?: readonly number[];
    /**
     * Check if a number is a multiple of x.
     * Must be strictly greater than 0.
     */
    multipleOf?: number;
    /**
     * Check if a number is lower or equal than this maximum.
     */
    maximum?: number;
    /**
     * Check if a number is strictly lower than this maximum.
     */
    exclusiveMaximum?: number;
    /**
     * Check if a number is greater or equal than this minimum.
     */
    minimum?: number;
    /**
     * Check if a number is strictly greater than this minimum.
     */
    exclusiveMinimum?: number;
}
/**
 * JSON Schema to describe an integer value.
 */
interface JSONSchemaInteger {
    /**
     * Type for an integer value.
     */
    type: "integer";
    /**
     * Checks if a value is strictly equal to this.
     */
    const?: number;
    /**
     * Checks if a value is strictly equal to one of the value of enum.
     */
    enum?: readonly number[];
    /**
     * Check if a number is a multiple of x.
     * Must be strictly greater than 0.
     */
    multipleOf?: number;
    /**
     * Check if a number is lower or equal than this maximum.
     */
    maximum?: number;
    /**
     * Check if a number is strictly lower than this maximum.
     */
    exclusiveMaximum?: number;
    /**
     * Check if a number is greater or equal than this minimum.
     */
    minimum?: number;
    /**
     * Check if a number is strictly greater than this minimum.
     */
    exclusiveMinimum?: number;
}
/**
 * JSON Schema to describe a string value.
 */
interface JSONSchemaString {
    /**
     * Type for a string value.
     */
    type: "string";
    /**
     * Checks if a value is strictly equal to this.
     */
    const?: string;
    /**
     * Checks if a value is strictly equal to one of the value of enum.
     */
    enum?: readonly string[];
    /**
     * Maxium length for a string.
     * Must be a non-negative integer.
     */
    maxLength?: number;
    /**
     * Minimum length for a string.
     * Must be a non-negative integer.
     */
    minLength?: number;
    /**
     * Pattern to match for a string.
     * Must be a valid regular expression, *without* the `/` delimiters.
     */
    pattern?: string;
}
/**
 * JSON schema to describe an array of values.
 */
interface JSONSchemaArray {
    /**
     * Type for an array of values.
     */
    type: "array";
    /**
     * Schema for the values of the array.
     */
    items: JSONSchema;
    /**
     * Check if an array length is lower or equal to this value.
     * Must be a non negative integer.
     */
    maxItems?: number;
    /**
     * Check if an array length is greater or equal to this value.
     * Must be a non negative integer.
     */
    minItems?: number;
    /**
     * Check if an array only have unique values.
     */
    uniqueItems?: boolean;
}
/**
 * JSON Schema to describe an array of primitive values:
 * - array of booleans: `JSONSchemaArrayOf<JSONSchemaBoolean>`,
 * - array of numbers: `JSONSchemaArrayOf<JSONSchemaNumber>`,
 * - array of integers: `JSONSchemaArrayOf<JSONSchemaInteger>`,
 * - array of strings: `JSONSchemaArrayOf<JSONSchemaString>`.
 */
interface JSONSchemaArrayOf<T extends JSONSchemaBoolean | JSONSchemaNumber | JSONSchemaInteger | JSONSchemaString> {
    /**
     * Type for an array of values.
     */
    type: "array";
    /**
     * Schema for the values of an array.
     */
    items: T;
    /**
     * Check if an array length is lower or equal to this value.
     * Must be a non negative integer.
     */
    maxItems?: number;
    /**
     * Check if an array length is greater or equal to this value.
     * Must be a non negative integer.
     */
    minItems?: number;
    /**
     * Check if an array only have unique values.
     */
    uniqueItems?: boolean;
}
/**
 * JSON schema to describe a tuple.
 */
interface JSONSchemaTuple {
    /**
     * Type for an array of values.
     */
    type: "array";
    /**
     * Schema for the values of the tuple.
     */
    items?: readonly JSONSchema[];
    /**
     * Check if an array length is lower or equal to this value.
     * Must be a non negative integer.
     */
    maxItems?: number;
    /**
     * Check if an array length is greater or equal to this value.
     * Must be a non negative integer.
     */
    minItems?: number;
    /**
     * Check if an array only have unique values.
     */
    uniqueItems?: boolean;
}
/**
 * JSON schema to describe an object.
 */
interface JSONSchemaObject {
    /**
     * Type for an object.
     */
    type: "object";
    /**
     * List of properties of the object and their associated JSON schemas.
     */
    properties: Record<string, JSONSchema>;
    /**
     * Array of names of the required properties for an object.
     * Properties set as required should be present in `properties` too.
     */
    required?: readonly string[];
}
/**
 * Subset of the JSON Schema standard.
 *
 * Types are enforced to validate everything: each value **must** have a `type`.
 *
 * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/VALIDATION.md}
 *
 * @example
 * const schema = { type: 'string' } satisfies JSONSchema;
 *
 * @example
 * const schema = { type: 'number' } satisfies JSONSchema;
 *
 * @example
 * const schema = { type: 'integer' } satisfies JSONSchema;
 *
 * @example
 * const schema = { type: 'boolean' } satisfies JSONSchema;
 *
 * @example
 * const schema = {
 *   type: 'array',
 *   items: { type: 'string' },
 * } satisfies JSONSchema;
 *
 * @example
 * const schema = {
 *   type: 'object',
 *   properties: {
 *     firstName: { type: 'string' },
 *     lastName: { type: 'string' },
 *   },
 *   required: ['firstName'],
 * } satisfies JSONSchema;
 */
type JSONSchema = JSONSchemaString | JSONSchemaNumber | JSONSchemaInteger | JSONSchemaBoolean | JSONSchemaArray | JSONSchemaTuple | JSONSchemaObject;

declare class StorageMap {
    #private;
    /**
     * Constructor params are provided by Angular (but can also be passed manually in tests)
     * @param database Storage to use
     */
    constructor(database: LocalDatabase);
    /**
     * **Number of items** in storage, wrapped in an Observable.
     *
     * Note you do *not* need to unsubscribe (it is a self-completing Observable).
     *
     * @example
     * this.storageMap.size.subscribe((size) => {
     *   console.log(size);
     * });
     */
    get size(): Observable<number>;
    /**
     * Tells you which storage engine is used.
     *
     * *Only useful for interoperability.*
     *
     * Note that due to some browsers issues in some special contexts
     * (like Safari cross-origin iframes),
     * **this information may be wrong at initialization,**
     * as the storage could fallback from `indexedDB` to `localStorage`
     * only after a first read or write operation.
     * @returns Storage engine used
     *
     * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/INTEROPERABILITY.md}
     *
     * @example
     * if (this.storageMap.backingEngine === 'indexedDB') {}
     */
    get backingEngine(): "indexedDB" | "localStorage" | "memory" | "unknown";
    /**
     * Information about `indexedDB` database.
     *
     * *Only useful for interoperability.*
     *
     * @returns `indexedDB` database name, store name and database version.
     * **Values will be empty if the storage is not `indexedDB`, so it should be used after an engine check**.
     *
     * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/INTEROPERABILITY.md}
     *
     * @example
     * if (this.storageMap.backingEngine === 'indexedDB') {
     *   const { database, store, version } = this.storageMap.backingStore;
     * }
     */
    get backingStore(): {
        database: string;
        store: string;
        version: number;
    };
    /**
     * Information about `localStorage` fallback storage.
     *
     * *Only useful for interoperability.*
     *
     * @returns `localStorage` prefix.
     * **Values will be empty if the storage is not `localStorage`, so it should be used after an engine check**.
     *
     * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/INTEROPERABILITY.md}
     *
     * @example
     * if (this.storageMap.backingEngine === 'localStorage') {
     *   const { prefix } = this.storageMap.fallbackBackingStore;
     * }
     */
    get fallbackBackingStore(): {
        prefix: string;
    };
    /**
     * Get an item value in storage.
     *
     * Note that:
     * * not finding an item is not an error, it succeeds but returns `undefined`,
     * * you do *not* need to unsubscribe (it is a self-completing Observable),
     * * 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.
     *
     * Do not forget it is client-side storage: **always check the data**, as it could have been forged.
     * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/VALIDATION.md}
     *
     * @param key The item's key
     * @param schema Optional but recommended JSON schema to validate the data
     * @returns The item's value if the key exists, `undefined` otherwise, wrapped in a RxJS Observable
     *
     * @example
     * this.storageMap.get('key', { type: 'string' }).subscribe((result) => {
     *   result; // string or undefined
     * });
     *
     * @example
     * interface User {
     *   firstName: string;
     *   lastName?: string;
     * }
     *
     * const schema = {
     *   type: 'object',
     *   properties: {
     *     firstName: { type: 'string' },
     *     lastName: { type: 'string' },
     *   },
     *   required: ['firstName'],
     * } satisfies JSONSchema;
     *
     * this.storageMap.get<User>('user', schema).subscribe((user) => {
     *   if (user) {
     *     user.firstName;
     *   }
     * });
     */
    get(key: string): Observable<unknown>;
    get<T extends string = string>(key: string, schema: JSONSchemaString): Observable<T | undefined>;
    get<T extends number = number>(key: string, schema: JSONSchemaInteger | JSONSchemaNumber): Observable<T | undefined>;
    get<T extends boolean = boolean>(key: string, schema: JSONSchemaBoolean): Observable<T | undefined>;
    get<T extends readonly string[] = string[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaString>): Observable<T | undefined>;
    get<T extends readonly number[] = number[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaInteger | JSONSchemaNumber>): Observable<T | undefined>;
    get<T extends readonly boolean[] = boolean[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaBoolean>): Observable<T | undefined>;
    get<T>(key: string, schema: JSONSchema): Observable<T | undefined>;
    /**
     * Store an item in storage.
     *
     * Note that:
     * * 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),
     * * but you do *not* need to unsubscribe (it is a self-completing Observable),
     * * setting `null` or `undefined` will remove the item to avoid some browsers issues,
     * * 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.
     * @see {@link https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/SERIALIZATION.md}
     *
     * @param key The item's key
     * @param data The item's value
     * @param schema Optional JSON schema to validate the data
     * @returns A RxJS Observable to wait the end of the operation
     *
     * @example
     * this.storageMap.set('key', 'value').subscribe(() => {});
     */
    set(key: string, data: unknown, schema?: JSONSchema): Observable<undefined>;
    /**
     * Delete an item in storage.
     *
     * Note that:
     * * 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),
     * * but you do *not* need to unsubscribe (it is a self-completing Observable).
     *
     * @param key The item's key
     * @returns A RxJS Observable to wait the end of the operation
     *
     * @example
     * this.storageMap.delete('key').subscribe(() => {});
     */
    delete(key: string): Observable<undefined>;
    /**
     * Delete all items in storage.
     *
     * Note that:
     * * 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),
     * * but you do *not* need to unsubscribe (it is a self-completing Observable).
     *
     * @returns A RxJS Observable to wait the end of the operation
     *
     * @example
     * this.storageMap.clear().subscribe(() => {});
     */
    clear(): Observable<undefined>;
    /**
     * Get all keys stored in storage.
     *
     * Note **this is an *iterating* Observable**:
     * * if there is no key, the `next` callback will not be invoked,
     * * if you need to wait the whole operation to end, be sure to act in the `complete` callback,
     * as this Observable can emit several values and so will invoke the `next` callback several times,
     * * you do *not* need to unsubscribe (it is a self-completing Observable).
     *
     * @returns A list of the keys wrapped in a RxJS Observable
     *
     * @example
     * this.storageMap.keys().subscribe({
     *   next: (key) => { console.log(key); },
     *   complete: () => { console.log('Done'); },
     * });
     */
    keys(): Observable<string>;
    /**
     * Tells if a key exists in storage.
     *
     * Note you do *not* need to unsubscribe (it is a self-completing Observable).
     *
     * @returns A RxJS Observable telling if the key exists
     *
     * @example
     * this.storageMap.has('key').subscribe((hasKey) => {
     *   if (hasKey) {}
     * });
     */
    has(key: string): Observable<boolean>;
    /**
     * Watch an item value in storage.
     *
     * Note that:
     * * it is an infinite Observable, do not forget to unsubscribe,
     * * only changes done via this library will be watched, external changes in storage cannot be detected.
     *
     * The signature has many overloads due to validation, **please refer to the documentation.**
     * @see https://github.com/cyrilletuzi/angular-async-local-storage/blob/main/docs/VALIDATION.md
     *
     * @param key The item's key to watch
     * @param schema Optional JSON schema to validate the initial value
     * @returns An infinite Observable giving the current value
     *
     * @example
     * Component()
     * export class MyComponent implements OnInit, OnDestroy {
     *
     *   private storageSubscription?: Subscription;
     *
     *   ngOnInit(): void {
     *     this.storageSubscription = this.storageMap.watch('key', { type: 'string' }).subscribe((result) => {
     *       result; // string or undefined
     *     });
     *   }
     *
     *   ngOnDestroy(): void {
     *     this.storageSubscription?.unsubscribe();
     *   }
     *
     * }
     */
    watch(key: string): Observable<unknown>;
    watch<T extends string = string>(key: string, schema: JSONSchemaString): Observable<T | undefined>;
    watch<T extends number = number>(key: string, schema: JSONSchemaInteger | JSONSchemaNumber): Observable<T | undefined>;
    watch<T extends boolean = boolean>(key: string, schema: JSONSchemaBoolean): Observable<T | undefined>;
    watch<T extends readonly string[] = string[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaString>): Observable<T | undefined>;
    watch<T extends readonly number[] = number[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaInteger | JSONSchemaNumber>): Observable<T | undefined>;
    watch<T extends readonly boolean[] = boolean[]>(key: string, schema: JSONSchemaArrayOf<JSONSchemaBoolean>): Observable<T | undefined>;
    watch<T>(key: string, schema: JSONSchema): Observable<T | undefined>;
    /**
     * THIS METHOD IS FOR INTERNAL PURPOSE ONLY AND MUST NOT BE USED,
     * IT CAN BE REMOVED AT ANY TIME AND MESSING WITH IT CAN CAUSE ISSUES
     * @private
     * @ignore
     */
    private ɵinternalGetDatabase;
    static ɵfac: i0.ɵɵFactoryDeclaration<StorageMap, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<StorageMap>;
}

export { SERIALIZATION_ERROR, SerializationError, StorageMap, StorageModule, VALIDATION_ERROR, ValidationError, provideIndexedDBDataBaseName, provideIndexedDBDataBaseVersion, provideIndexedDBStoreName, provideLocalStoragePrefix };
export type { JSONSchema, StorageConfig };
