{"version":3,"sources":["../../../packages/core/shared/shared-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAM,MAAM,MAAM,CAAC;AAGtC,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB,CAAC,MAAM;IACxC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;GAMG;AAEH,8BAAsB,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO;IAehD,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,YAAY,CAAC;IACrB,OAAO,CAAC,OAAO,CAAC;IApBpB,OAAO,CAAC,KAAK,CAAqC;IAElD;;;;;;;;;;OAUG;gBAES,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,EACvC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EACvC,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,EAC3C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC,MAAM,CAAC,EACtD,OAAO,CAAC,EAAE,kBAAkB;IAExC;;OAEG;IACH,IAAW,EAAE,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED;;;OAGG;IACI,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO;IAgB5C;;;OAGG;IACI,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IASvE;;;OAGG;IACI,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAQzE;;;;;OAKG;IACI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQhD;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAepC;;;;;OAKG;IACI,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC;IAUlE,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,MAAM;IAcd,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,WAAW;IAsBnB,OAAO,KAAK,QAAQ,GAGnB;CACJ","file":"shared-cache.d.ts","sourcesContent":["/* eslint-disable unused-imports/no-unused-vars */\r\nimport { Observable, of } from 'rxjs';\r\nimport { map } from 'rxjs/operators';\r\n\r\nexport interface SharedCacheOptions {\r\n    /**\r\n     * The expiration time by milliseconds.\r\n     */\r\n    expiration?: number;\r\n\r\n    /**\r\n     * Flag to force the cache to refresh.\r\n     */\r\n    forceRefresh?: boolean;\r\n}\r\n\r\nexport interface SharedCacheContainer<TClass> {\r\n    /**\r\n     * The last timestamp for the instance collected.\r\n     */\r\n    timestamp: number;\r\n\r\n    /**\r\n     * The instance of the data class.\r\n     */\r\n    instance: TClass;\r\n}\r\n\r\ninterface SharedCacheCollection<TClass> {\r\n    [instanceId: string]: SharedCacheContainer<TClass>;\r\n}\r\n\r\n/**\r\n * Abstract class of SharedCache by using session storage.\r\n *\r\n * TClass: the caching data class type.\r\n * TData: the caching data interface type.\r\n * TParams: the data query parameters type.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\nexport abstract class SharedCache<TClass, TData, TParams> {\r\n    private cache: SharedCacheCollection<TClass> = {};\r\n\r\n    /**\r\n     * Initializes a new instance of the SharedCache class.\r\n     *\r\n     * @param uniqueId the unique identity of the collection of data.\r\n     * @param uniqueVersion the unique version of data. (Should increment any data format or query change)\r\n     * @param instanceId the instance id generator.\r\n     * @param serialize the data serialization.\r\n     * @param deserialize the data deserialization.\r\n     * @param getDataQuery the query observable.\r\n     * @param options the shared cache options.\r\n     */\r\n    constructor(\r\n        private uniqueId: string,\r\n        private uniqueVersion: number,\r\n        private instanceId: (params: TParams) => string,\r\n        private serialize: (instance: TClass) => string,\r\n        private deserialize: (serialized: string) => TClass,\r\n        private getDataQuery?: (params: TParams) => Observable<TClass>,\r\n        private options?: SharedCacheOptions) { }\r\n\r\n    /**\r\n     * Gets the id of the collection of data.\r\n     */\r\n    public get id(): string {\r\n        return this.uniqueId;\r\n    }\r\n\r\n    /**\r\n     * Gets the version of the cache for format and query.\r\n     */\r\n    public get version(): number {\r\n        return this.uniqueVersion;\r\n    }\r\n\r\n    /**\r\n     * Check if the Cache has unexpired data available for the instance id.\r\n     * @param params the parameter to check for the data.\r\n     */\r\n    public isAvailable(params: TParams): boolean {\r\n        const instanceId = this.instanceId(params);\r\n        if (this.cache[instanceId] && !this.expired(this.cache[instanceId])) {\r\n            return true;\r\n        }\r\n\r\n        if (MsftSme.SessionStorageHandler.getSessionStorage()?.[this.cacheKey]) {\r\n            this.sessionRestore();\r\n            if (this.cache[instanceId] && !this.expired(this.cache[instanceId])) {\r\n                return true;\r\n            }\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     * Query to find the data.\r\n     * @param params the parameter to query the data.\r\n     */\r\n    public query(params: TParams): Observable<SharedCacheContainer<TClass>> {\r\n        if (this.isAvailable(params)) {\r\n            const instanceId = this.instanceId(params);\r\n            return of(this.cache[instanceId]);\r\n        }\r\n\r\n        return this.update(params);\r\n    }\r\n\r\n    /**\r\n     * Refresh the data.\r\n     * @param params the parameter to query the data.\r\n     */\r\n    public refresh(params: TParams): Observable<SharedCacheContainer<TClass>> {\r\n        if (MsftSme.SessionStorageHandler.getSessionStorage()?.[this.cacheKey]) {\r\n            this.sessionRestore();\r\n        }\r\n\r\n        return this.update(params);\r\n    }\r\n\r\n    /**\r\n     * Save an instance data to session storage.\r\n     *\r\n     * @param params the parameter to query the data.\r\n     * @param data the data object to store.\r\n     */\r\n    public save(params: TParams, data: TClass): void {\r\n        if (MsftSme.SessionStorageHandler.getSessionStorage()?.[this.cacheKey]) {\r\n            this.sessionRestore();\r\n        }\r\n\r\n        this.sessionSave(params, data);\r\n    }\r\n\r\n    /**\r\n     * Clear the cache.\r\n     *\r\n     * @param params the parameter to query the data (optional to delete an instance)\r\n     */\r\n    public clear(params?: TParams): void {\r\n        if (params) {\r\n            if (MsftSme.SessionStorageHandler.getSessionStorage()?.[this.cacheKey]) {\r\n                this.sessionRestore();\r\n            }\r\n\r\n            this.sessionSave(params);\r\n        } else {\r\n            this.cache = {};\r\n            if (MsftSme.SessionStorageHandler.getSessionStorage()) {\r\n                MsftSme.SessionStorageHandler.getSessionStorage()[this.cacheKey] = JSON.stringify(this.cache);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Force restore whole data and return the data for the params specified.\r\n     *\r\n     * @param params the parameter to query the data.\r\n     * @return SharedCacheContainer<TClass> the data for the params specified.\r\n     */\r\n    public forceRestore(params: TParams): SharedCacheContainer<TClass> {\r\n        if (MsftSme.SessionStorageHandler.getSessionStorage()?.[this.cacheKey]) {\r\n            const instanceId = this.instanceId(params);\r\n            this.sessionRestore();\r\n            return this.cache[instanceId];\r\n        }\r\n\r\n        return null;\r\n    }\r\n\r\n    private expired(data: SharedCacheContainer<TClass>): boolean {\r\n        if (this.options && this.options.forceRefresh) {\r\n            return true;\r\n        }\r\n\r\n        if (!this.options || !this.options.expiration) {\r\n            return false;\r\n        }\r\n\r\n        return (Date.now() - data.timestamp) > this.options.expiration;\r\n    }\r\n\r\n    private update(params: TParams): Observable<SharedCacheContainer<TClass>> {\r\n        if (this.getDataQuery) {\r\n            const instanceId = this.instanceId(params);\r\n            return this.getDataQuery(params)\r\n                .pipe(\r\n                    map(data => {\r\n                        this.sessionSave(params, data);\r\n                        return this.cache[instanceId];\r\n                    }));\r\n        } else {\r\n            return of(null);\r\n        }\r\n    }\r\n\r\n    private sessionRestore(): void {\r\n        const preProcessed: SharedCacheCollection<string> = JSON.parse(sessionStorage[this.cacheKey]);\r\n        const cache: SharedCacheCollection<TClass> = {};\r\n        const keys = Object.keys(preProcessed);\r\n        keys.forEach(key => {\r\n            cache[key] = <SharedCacheContainer<TClass>>{\r\n                timestamp: preProcessed[key].timestamp,\r\n                instance: this.deserialize(preProcessed[key].instance)\r\n            };\r\n        });\r\n        this.cache = cache;\r\n    }\r\n\r\n    private sessionSave(params: TParams, data?: TClass): void {\r\n        const instanceId = this.instanceId(params);\r\n        if (data) {\r\n            this.cache[instanceId] = { timestamp: Date.now(), instance: data };\r\n        } else {\r\n            delete this.cache[instanceId];\r\n        }\r\n\r\n        const preProcessed: SharedCacheCollection<string> = {};\r\n        const keys = Object.keys(this.cache);\r\n        keys.forEach(key => {\r\n            preProcessed[key] = <SharedCacheContainer<string>>{\r\n                timestamp: this.cache[key].timestamp,\r\n                instance: this.serialize(this.cache[key].instance)\r\n            };\r\n        });\r\n\r\n        if (MsftSme.SessionStorageHandler.getSessionStorage()) {\r\n            MsftSme.SessionStorageHandler.getSessionStorage()[this.cacheKey] = JSON.stringify(preProcessed);\r\n        }\r\n    }\r\n\r\n    private get cacheKey(): string {\r\n        // used as sessionStorage key name.\r\n        return 'shared-cache:{0}.{1}'.format(this.id, this.version);\r\n    }\r\n}\r\n"]}