@cachemap/core
Version:
The Cachemap core module.
1 lines • 40.3 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../core/src//main/index.ts","../core/src//constants.ts"],"sourcesContent":["import { instance } from '@cachemap/controller';\nimport { MapStore } from '@cachemap/map';\nimport { type DehydratedMetadata, type Metadata, type Store, type Tag } from '@cachemap/types';\nimport {\n ArgsError,\n GroupedError,\n PositionError,\n ValueFormat,\n constants,\n dehydrateMetadata,\n isJsonValue,\n prepareGetEntry,\n prepareSetEntry,\n rehydrateMetadata,\n sizeOf,\n} from '@cachemap/utils';\nimport { Cacheability } from 'cacheability';\nimport { EventEmitter } from 'eventemitter3';\nimport { castArray, get, isArray, isFunction, isNumber, isPlainObject, isString, isUndefined } from 'lodash-es';\nimport { Md5 } from 'ts-md5';\nimport { type JsonValue } from 'type-fest';\nimport { DEFAULT_BACKUP_INTERVAL, DEFAULT_MAX_HEAP_SIZE } from '../constants.ts';\nimport {\n type ConstructorOptions,\n type ControllerEvent,\n type ExportOptions,\n type ExportResult,\n type ImportOptions,\n type MethodName,\n type Reaper,\n type ReaperInit,\n type RequestQueue,\n type SetOptions,\n} from '../types.ts';\n\nexport class Core {\n public events = {\n ENTRY_DELETED: 'ENTRY_DELETED',\n };\n\n private static _sortComparator = (a: Metadata, b: Metadata): number => {\n let index;\n\n if (a.accessedCount > b.accessedCount) {\n index = -1;\n } else if (a.accessedCount < b.accessedCount) {\n index = 1;\n } else if (a.lastAccessed > b.lastAccessed) {\n index = -1;\n } else if (a.lastAccessed < b.lastAccessed) {\n index = 1;\n } else if (a.lastUpdated > b.lastUpdated) {\n index = -1;\n } else if (a.lastUpdated < b.lastUpdated) {\n index = 1;\n } else if (a.added > b.added) {\n index = -1;\n } else if (a.added < b.added) {\n index = 1;\n } else if (a.size < b.size) {\n index = -1;\n } else if (a.size > b.size) {\n index = 1;\n } else {\n index = 0;\n }\n\n return index;\n };\n\n private _handleClearEvent = ({ name, type }: ControllerEvent): void => {\n if ((isString(name) && name === this._name) || (isString(type) && type === this._type)) {\n void this._clear();\n }\n };\n\n private _handleStartReaperEvent = ({ name, type }: ControllerEvent): void => {\n if ((isString(name) && name === this._name) || (isString(type) && type === this._type)) {\n this._reaper?.start();\n }\n };\n\n private _handleStopReaperEvent = ({ name, type }: ControllerEvent): void => {\n if ((isString(name) && name === this._name) || (isString(type) && type === this._type)) {\n this._reaper?.stop();\n }\n };\n\n private _handleStartBackupEvent = ({ name, type }: ControllerEvent): void => {\n if ((isString(name) && name === this._name) || (isString(type) && type === this._type)) {\n this._startBackup();\n }\n };\n\n private _handleStopBackupEvent = ({ name, type }: ControllerEvent): void => {\n if ((isString(name) && name === this._name) || (isString(type) && type === this._type)) {\n this._stopBackup();\n }\n };\n\n private _backupInterval: number = DEFAULT_BACKUP_INTERVAL;\n private _backupIntervalID?: NodeJS.Timeout;\n private _backupStore?: Store;\n private readonly _disableCacheInvalidation: boolean;\n private _emitter: EventEmitter = new EventEmitter();\n private readonly _encryptionSecret: string | undefined;\n private _maxHeapSize: number = DEFAULT_MAX_HEAP_SIZE;\n private _metadata: Metadata[] = [];\n private readonly _name: string;\n private _persistedStore = true;\n private _processing: string[] = [];\n private _ready = false;\n private readonly _reaper?: Reaper;\n private _requestQueue: RequestQueue = [];\n private readonly _sharedCache: boolean;\n private _store?: Store;\n private readonly _type: string;\n private _usedHeapSize = 0;\n private readonly _valueFormatting: ValueFormat = ValueFormat.String;\n\n constructor(options: ConstructorOptions) {\n const errors: ArgsError[] = [];\n\n if (!isPlainObject(options)) {\n errors.push(new ArgsError('@cachemap/core expected options to be a plain object.'));\n }\n\n if (!isString(options.name)) {\n errors.push(new ArgsError('@cachemap/core expected options.name to be a string.'));\n }\n\n if (!isFunction(options.store)) {\n errors.push(new ArgsError('@cachemap/core expected options.store to be a function.'));\n }\n\n if (!isString(options.type)) {\n errors.push(new ArgsError('@cachemap/core expected options.type to be a string.'));\n }\n\n if (options.valueFormatting === ValueFormat.Ecrypt && !options.encryptionSecret) {\n errors.push(\n new ArgsError('@cachemap/core expected encryptionSecret to be set when valueFormatting is \"encrypt\"'),\n );\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core constructor argument validation errors.', errors);\n }\n\n const {\n backupInterval,\n backupStore,\n disableCacheInvalidation = false,\n encryptionSecret,\n name,\n reaper,\n sharedCache = false,\n sortComparator,\n startBackup,\n store: storeInit,\n type,\n valueFormatting,\n } = options;\n\n this._disableCacheInvalidation = disableCacheInvalidation;\n\n if (valueFormatting) {\n this._valueFormatting = valueFormatting;\n }\n\n if (isString(encryptionSecret)) {\n this._encryptionSecret = encryptionSecret;\n }\n\n this._name = name;\n\n if (isFunction(reaper)) {\n this._reaper = this._initializeReaper(reaper);\n }\n\n this._sharedCache = sharedCache;\n\n if (isFunction(sortComparator)) {\n Core._sortComparator = sortComparator;\n }\n\n this._type = type;\n this._addControllerEventListeners();\n\n void Promise.resolve(storeInit({ name })).then(async store => {\n this._maxHeapSize = store.maxHeapSize;\n\n if (backupStore) {\n if (store.type === 'map') {\n throw new ArgsError(\"@cachemap/core expected store.type not to be 'map' when backupStore is true.\");\n }\n\n if (isNumber(backupInterval)) {\n this._backupInterval = backupInterval;\n }\n\n this._backupStore = store;\n this._persistedStore = true;\n this._store = new MapStore({ maxHeapSize: store.maxHeapSize, name });\n await this._backupStoreEntriesToStore();\n this._ready = true;\n void this._releaseQueuedRequests();\n\n if (startBackup) {\n this._startBackup();\n }\n } else {\n this._persistedStore = store.type !== 'map';\n this._store = store;\n await this._retreiveMetadataFromStore();\n this._ready = true;\n void this._releaseQueuedRequests();\n }\n });\n }\n\n public async clear(): Promise<void> {\n return this._clear();\n }\n\n public async delete(key: string, options: { hashKey?: boolean } = {}): Promise<boolean> {\n const errors: ArgsError[] = [];\n\n if (!isString(key)) {\n errors.push(new ArgsError('@cachemap/core expected key to be a string.'));\n }\n\n if (!isPlainObject(options)) {\n errors.push(new ArgsError('@cachemap/core expected options to be a plain object.'));\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core delete argument validation errors.', errors);\n }\n\n return this._delete(key, options);\n }\n\n get emitter(): EventEmitter {\n return this._emitter;\n }\n\n public async entries<T>(keys?: string[]): Promise<[string, T][]> {\n if (keys && !isArray(keys)) {\n throw new ArgsError('@cachemap/core expected keys to be an array.');\n }\n\n const entries = await this._entries<T>(keys);\n\n return entries.sort(([a], [b]) => {\n if (a < b) {\n return -1;\n }\n\n if (a > b) {\n return 1;\n }\n\n return 0;\n });\n }\n\n public async export<T>(options: ExportOptions = {}): Promise<ExportResult<T>> {\n const errors: ArgsError[] = [];\n\n if (!isPlainObject(options)) {\n errors.push(new ArgsError('@cachemap/core expected options to be an plain object.'));\n }\n\n if (options.keys && !isArray(options.keys)) {\n errors.push(new ArgsError('@cachemap/core expected options.keys to be an array.'));\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core export argument validation errors.', errors);\n }\n\n const { entries, metadata } = await this._export<T>(options);\n\n return {\n entries: entries.sort(([a], [b]) => {\n if (a < b) {\n return -1;\n }\n\n if (a > b) {\n return 1;\n }\n\n return 0;\n }),\n metadata: metadata.sort((a, b) => {\n if (a.key < b.key) {\n return -1;\n }\n\n if (a.key > b.key) {\n return 1;\n }\n\n return 0;\n }),\n };\n }\n\n public async get<T>(key: string, options: { hashKey?: boolean } = {}): Promise<T | undefined> {\n const errors: ArgsError[] = [];\n\n if (!isString(key)) {\n errors.push(new ArgsError('@cachemap/core expected key to be a string.'));\n }\n\n if (!isPlainObject(options)) {\n errors.push(new ArgsError('@cachemap/core expected options to be a plain object.'));\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core get argument validation errors.', errors);\n }\n\n return this._get<T>(key, options);\n }\n\n public getMetadataEntry(rawkey: string, options: { hashKey?: boolean } = {}): Metadata | undefined {\n const key = options.hashKey ? Md5.hashStr(rawkey) : rawkey;\n return this._getMetadataEntry(key);\n }\n\n public async has(\n key: string,\n options: { deleteExpired?: boolean; hashKey?: boolean } = {},\n ): Promise<false | Cacheability> {\n const errors: ArgsError[] = [];\n\n if (!isString(key)) {\n errors.push(new ArgsError('@cachemap/core expected key to be a string.'));\n }\n\n if (!isPlainObject(options)) {\n errors.push(new ArgsError('@cachemap/core expected opts to be a plain object.'));\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core has argument validation errors.', errors);\n }\n\n return this._has(key, options);\n }\n\n public async import(options: ImportOptions): Promise<void> {\n if (!isPlainObject(options)) {\n throw new ArgsError('@cachemap/core expected options to be a plain object.');\n }\n\n const { entries, metadata } = options;\n const errors: ArgsError[] = [];\n\n if (!isArray(entries)) {\n errors.push(new ArgsError('@cachemap/core expected entries to be an array.'));\n }\n\n if (!isArray(metadata)) {\n errors.push(new ArgsError('@cachemap/core expected metadata to be an array.'));\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core has argument validation errors.', errors);\n }\n\n return this._import(options);\n }\n\n get metadata(): Metadata[] {\n return this._metadata;\n }\n\n get name(): string {\n return this._name;\n }\n\n get reaper(): Reaper | undefined {\n return this._reaper;\n }\n\n public async set(key: string, value: unknown, options: SetOptions = {}): Promise<void> {\n const errors: ArgsError[] = [];\n\n if (!isString(key)) {\n errors.push(new ArgsError('@cachemap/core expected key to be a string.'));\n }\n\n if (!isPlainObject(options)) {\n errors.push(new ArgsError('@cachemap/core expected options to be a plain object.'));\n }\n\n if (!isJsonValue(value)) {\n errors.push(new ArgsError('@cachemap/core expected value to be JSON serializable.'));\n }\n\n if (errors.length > 0) {\n throw new GroupedError('@cachemap/core set argument validation errors.', errors);\n }\n\n // typescript not deriving value is JsonValue from above type guard.\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return this._set(key, value as JsonValue, options);\n }\n\n public async size(): Promise<number> {\n return this._size();\n }\n\n public startBackup(): void {\n this._startBackup();\n }\n\n public stopBackup(): void {\n this._stopBackup();\n }\n\n get storeType(): string {\n return this._store?.type ?? 'none';\n }\n\n get type(): string {\n return this._type;\n }\n\n get usedHeapSize(): number {\n return this._usedHeapSize;\n }\n\n private _addControllerEventListeners(): void {\n instance.on(constants.CLEAR, this._handleClearEvent);\n instance.on(constants.START_REAPER, this._handleStartReaperEvent);\n instance.on(constants.STOP_REAPER, this._handleStopReaperEvent);\n instance.on(constants.START_BACKUP, this._handleStartBackupEvent);\n instance.on(constants.STOP_BACKUP, this._handleStopBackupEvent);\n }\n\n private async _addMetadata(\n key: string,\n size: number,\n cacheability: Cacheability,\n tag?: Tag,\n extensions?: Record<string, unknown>,\n ): Promise<void> {\n this._metadata.push({\n accessedCount: 0,\n added: Date.now(),\n cacheability,\n extensions,\n key,\n lastAccessed: Date.now(),\n lastUpdated: Date.now(),\n size,\n tags: tag ? [tag] : [],\n updatedCount: 0,\n });\n\n this._sortMetadata();\n this._updateHeapSize();\n return this._backupMetadata();\n }\n\n private _addRequestToQueue<T>(methodName: MethodName, ...payload: unknown[]): Promise<T> {\n return new Promise((resolve: (value: T) => void) => {\n this._requestQueue.push([resolve, methodName, payload]);\n });\n }\n\n private async _backupMetadata(): Promise<void> {\n if (!this._store || !this._persistedStore) {\n return;\n }\n\n const store = this._backupStore ?? this._store;\n\n return store.set(\n constants.METADATA,\n // metadata is serializable as JSON.\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n prepareSetEntry(dehydrateMetadata(this._metadata) as JsonValue, this._valueFormatting, this._encryptionSecret),\n );\n }\n\n private async _backupStoreEntriesToStore(): Promise<void> {\n if (!(this._backupStore && this._store)) {\n throw new PositionError(\n '@cachemap/core expected backupStoreEntriesToStore to be called after setting the backupStore and store.',\n );\n }\n\n this._metadata = [];\n const backupMetadata = await this._backupStore.get(constants.METADATA);\n\n if (backupMetadata) {\n const metadata = prepareGetEntry<DehydratedMetadata[]>(\n backupMetadata,\n this._valueFormatting,\n this._encryptionSecret,\n );\n\n if (metadata.length > 0) {\n const keys = metadata.map(entry => entry.key);\n await this._store.import(await this._backupStore.entries(keys));\n this._metadata = rehydrateMetadata(metadata);\n }\n }\n }\n\n private _calcReductionChunk(): number | undefined {\n const reductionSize = Math.round(this._maxHeapSize * 0.2);\n let chunkSize = 0;\n let chunk: number | undefined;\n\n for (let index = this._metadata.length - 1; index >= 0; index -= 1) {\n // Based on surrounding code context, this cannot be undefined.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n chunkSize += this._metadata[index]!.size;\n\n if (chunkSize > reductionSize) {\n chunk = index;\n break;\n }\n }\n\n return chunk;\n }\n\n private _cleanupTag(tag: string | number): void {\n for (const entry of this._metadata) {\n if (entry.tags.includes(tag)) {\n entry.tags = entry.tags.filter(t => t !== tag);\n }\n }\n }\n\n private async _clear(): Promise<void> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.CLEAR);\n }\n\n await this._store.clear();\n this._metadata = [];\n this._processing = [];\n this._updateHeapSize();\n return this._backupMetadata();\n }\n\n private async _delete(key: string, options: { hashKey?: boolean } = {}): Promise<boolean> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.DELETE, key, options);\n }\n\n const deleteKey = options.hashKey ? Md5.hashStr(key) : key;\n const deleted = await this._store.delete(deleteKey);\n\n if (!deleted) {\n return false;\n }\n\n await this._deleteMetadata(deleteKey);\n return true;\n }\n\n private async _deleteMetadata(key: string): Promise<void> {\n const index = this._metadata.findIndex(metadata => metadata.key === key);\n\n if (index === -1) {\n return;\n }\n\n this._metadata.splice(index, 1);\n this._sortMetadata();\n this._updateHeapSize();\n return this._backupMetadata();\n }\n\n private async _entries<T>(keys?: string[]): Promise<[string, T][]> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.ENTRIES, keys);\n }\n\n const entryKeys = keys ?? this._metadata.map(metadata => metadata.key);\n const entries = await this._store.entries(entryKeys);\n return entries.map(([key, data]) => [key, prepareGetEntry(data, this._valueFormatting, this._encryptionSecret)]);\n }\n\n private async _export<T>({ cleanupTag, filterByValue, keys, tag }: ExportOptions): Promise<ExportResult<T>> {\n let exportKeys: string[] | undefined;\n let metadata = [...this._metadata];\n\n if (tag) {\n metadata = this._metadata.filter(meta => meta.tags.includes(tag));\n exportKeys = metadata.map(meta => meta.key);\n\n if (cleanupTag) {\n this._cleanupTag(tag);\n }\n } else if (keys) {\n metadata = this._metadata.filter(meta => keys.includes(meta.key));\n exportKeys = keys;\n }\n\n let entries = await this._entries<T>(exportKeys);\n\n if (filterByValue) {\n const castFilterByValue = castArray(filterByValue);\n\n entries = entries.filter(([, data]) =>\n castFilterByValue.every(({ comparator, keyChain }) => get(data, keyChain) === comparator),\n );\n\n metadata = metadata.filter(meta => entries.some(([key]) => key === meta.key));\n }\n\n return { entries, metadata };\n }\n\n private async _get<T>(key: string, options: { deleteExpired?: boolean; hashKey?: boolean }): Promise<T | undefined> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.GET, key, options);\n }\n\n const getKey = options.hashKey ? Md5.hashStr(key) : key;\n const hasExpired = this._hasCacheEntryExpired(getKey);\n\n if (hasExpired) {\n if (options.deleteExpired) {\n await this._delete(getKey);\n }\n\n return;\n }\n\n const value = await this._store.get(getKey);\n\n if (!value) {\n return;\n }\n\n await this._updateMetadata(getKey);\n return prepareGetEntry(value, this._valueFormatting, this._encryptionSecret);\n }\n\n private _getCacheability(key: string): Cacheability | undefined {\n const metadata = this._getMetadataEntry(key);\n return metadata ? metadata.cacheability : undefined;\n }\n\n private _getMetadataEntry(key: string): Metadata | undefined {\n return this._metadata.find(metadata => metadata.key === key);\n }\n\n private async _has(\n key: string,\n options: { deleteExpired?: boolean; hashKey?: boolean },\n ): Promise<false | Cacheability> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.HAS, key, options);\n }\n\n const hasKey = options.hashKey ? Md5.hashStr(key) : key;\n const hasExpired = this._hasCacheEntryExpired(hasKey);\n\n if (hasExpired) {\n if (options.deleteExpired) {\n await this._delete(hasKey);\n }\n\n return false;\n }\n\n const exists = await this._store.has(hasKey);\n\n if (!exists) {\n return false;\n }\n\n return this._getCacheability(hasKey) ?? false;\n }\n\n private _hasCacheEntryExpired(key: string): boolean {\n if (this._disableCacheInvalidation) {\n return false;\n }\n\n const cacheability = this._getCacheability(key);\n return cacheability ? !cacheability.checkTTL() : false;\n }\n\n private async _import(options: ImportOptions): Promise<void> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.IMPORT, options);\n }\n\n let filtered: Metadata[] = [];\n\n if (this._metadata.length > 0) {\n filtered = this._metadata.filter(metadata => {\n return !options.metadata.some(optionsMetadata => metadata.key === optionsMetadata.key);\n });\n }\n\n const entries = options.entries.map(\n // typescript is not seeing this as a string tuple.\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n ([key, data]) => [key, prepareSetEntry(data, this._valueFormatting, this._encryptionSecret)] as [string, string],\n );\n\n await this._store.import(entries);\n this._metadata = rehydrateMetadata([...filtered, ...options.metadata]);\n this._sortMetadata();\n await this._backupMetadata();\n this._updateHeapSize();\n }\n\n private _initializeReaper(reaperInit: ReaperInit): Reaper {\n return reaperInit({\n deleteCallback: async (key: string, tags?: Tag[]) => {\n this.emitter.emit(this.events.ENTRY_DELETED, { deleted: await this._delete(key), key, tags });\n },\n metadataCallback: () => this._metadata,\n });\n }\n\n private _processed(key: string): void {\n this._processing = this._processing.filter(value => value !== key);\n }\n\n private _reduceHeapSize(): void {\n const index = this._calcReductionChunk();\n\n if (!index || !this._reaper) {\n return;\n }\n\n void this._reaper.cull(this._metadata.slice(index));\n }\n\n private async _releaseQueuedRequests(): Promise<void> {\n for (const [resolve, methodName, payload] of this._requestQueue) {\n // @ts-expect-error complicated\n resolve(await this[methodName](...payload));\n }\n\n this._requestQueue = [];\n }\n\n private async _retreiveMetadataFromStore(): Promise<void> {\n if (!this._store || !this._persistedStore) {\n return;\n }\n\n const metadata = await this._store.get(constants.METADATA);\n\n if (metadata) {\n this._metadata = rehydrateMetadata(prepareGetEntry(metadata, this._valueFormatting, this._encryptionSecret));\n }\n }\n\n private async _set(key: string, value: JsonValue, options: SetOptions): Promise<void> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.SET, key, value, options);\n }\n\n const cacheability = new Cacheability(options.cacheOptions);\n const { cacheControl } = cacheability.metadata;\n\n if (cacheControl.noStore || (this._sharedCache && cacheControl.private)) {\n return;\n }\n\n const setKey = options.hashKey ? Md5.hashStr(key) : key;\n const processing = this._processing.includes(setKey);\n\n if (!processing) {\n this._processing.push(setKey);\n }\n\n try {\n const exists = (await this._store.has(setKey)) || processing;\n const preparedSetValue = prepareSetEntry(value, this._valueFormatting, this._encryptionSecret);\n await this._store.set(setKey, preparedSetValue);\n\n await (exists\n ? this._updateMetadata(setKey, sizeOf(preparedSetValue), cacheability, options.tag, options.extensions)\n : this._addMetadata(setKey, sizeOf(preparedSetValue), cacheability, options.tag, options.extensions));\n\n this._processed(setKey);\n } catch (error) {\n this._processed(setKey);\n throw error;\n }\n }\n\n private async _size(): Promise<number> {\n if (!this._ready || !this._store) {\n return this._addRequestToQueue(constants.SIZE);\n }\n\n return this._store.size();\n }\n\n private _sortMetadata(): void {\n this._metadata.sort(Core._sortComparator);\n }\n\n private _startBackup(): void {\n this._backupIntervalID = setInterval(() => {\n void this._storeEntriesToBackupStore();\n }, this._backupInterval);\n }\n\n private _stopBackup(): void {\n if (this._backupIntervalID) {\n clearInterval(this._backupIntervalID);\n }\n }\n\n private async _storeEntriesToBackupStore(): Promise<void> {\n if (!(this._backupStore && this._store)) {\n return;\n }\n\n const keys = this._metadata.map(entry => entry.key);\n void this._backupStore.import(await this._store.entries(keys));\n }\n\n private _updateHeapSize(): void {\n this._usedHeapSize = this._metadata.reduce((acc, value) => acc + value.size, 0);\n\n if (!this._disableCacheInvalidation && this._usedHeapSize > this._maxHeapSize) {\n this._reduceHeapSize();\n }\n }\n\n private async _updateMetadata(\n key: string,\n size?: number,\n cacheability?: Cacheability,\n tag?: Tag,\n extensions?: Record<string, unknown>,\n ): Promise<void> {\n const entry = this._getMetadataEntry(key);\n\n if (!entry) {\n return;\n }\n\n if (size) {\n entry.size = size;\n entry.lastUpdated = Date.now();\n entry.updatedCount += 1;\n } else {\n entry.accessedCount += 1;\n entry.lastAccessed = Date.now();\n }\n\n if (cacheability) {\n entry.cacheability = cacheability;\n }\n\n if (!isUndefined(tag)) {\n entry.tags.push(tag);\n }\n\n if (extensions) {\n entry.extensions = Object.assign(entry.extensions ?? {}, extensions);\n }\n\n this._sortMetadata();\n this._updateHeapSize();\n return this._backupMetadata();\n }\n}\n","export const DEFAULT_MAX_HEAP_SIZE = 4_194_304;\nexport const DEFAULT_BACKUP_INTERVAL = 10_000;\n"],"names":["Core","_sortComparator","a","b","index","accessedCount","lastAccessed","lastUpdated","added","size","constructor","options","events","ENTRY_DELETED","_handleClearEvent","name","type","isString","this","_name","_type","_clear","_handleStartReaperEvent","_reaper","start","_handleStopReaperEvent","stop","_handleStartBackupEvent","_startBackup","_handleStopBackupEvent","_stopBackup","_backupInterval","_emitter","EventEmitter","_maxHeapSize","_metadata","_persistedStore","_processing","_ready","_requestQueue","_usedHeapSize","_valueFormatting","ValueFormat","String","errors","isPlainObject","push","ArgsError","isFunction","store","valueFormatting","Ecrypt","encryptionSecret","length","GroupedError","backupInterval","backupStore","disableCacheInvalidation","reaper","sharedCache","sortComparator","startBackup","storeInit","_disableCacheInvalidation","_encryptionSecret","_initializeReaper","_sharedCache","_addControllerEventListeners","Promise","resolve","then","async","maxHeapSize","isNumber","_backupStore","_store","MapStore","_backupStoreEntriesToStore","_releaseQueuedRequests","_retreiveMetadataFromStore","clear","delete","key","_delete","emitter","entries","keys","isArray","_entries","sort","export","metadata","_export","get","_get","getMetadataEntry","rawkey","hashKey","Md5","hashStr","_getMetadataEntry","has","_has","import","_import","set","value","isJsonValue","_set","_size","stopBackup","storeType","usedHeapSize","instance","on","constants","CLEAR","START_REAPER","STOP_REAPER","START_BACKUP","STOP_BACKUP","_addMetadata","cacheability","tag","extensions","Date","now","tags","updatedCount","_sortMetadata","_updateHeapSize","_backupMetadata","_addRequestToQueue","methodName","payload","METADATA","prepareSetEntry","dehydrateMetadata","PositionError","backupMetadata","prepareGetEntry","map","entry","rehydrateMetadata","_calcReductionChunk","reductionSize","Math","round","chunk","chunkSize","_cleanupTag","includes","filter","t","DELETE","deleteKey","_deleteMetadata","findIndex","splice","ENTRIES","entryKeys","data","cleanupTag","filterByValue","exportKeys","meta","castFilterByValue","castArray","every","comparator","keyChain","some","GET","getKey","_hasCacheEntryExpired","deleteExpired","_updateMetadata","_getCacheability","undefined","find","HAS","hasKey","checkTTL","IMPORT","filtered","optionsMetadata","reaperInit","deleteCallback","emit","deleted","metadataCallback","_processed","_reduceHeapSize","cull","slice","SET","Cacheability","cacheOptions","cacheControl","noStore","private","setKey","processing","exists","preparedSetValue","sizeOf","error","SIZE","_backupIntervalID","setInterval","_storeEntriesToBackupStore","clearInterval","reduce","acc","isUndefined","Object","assign"],"mappings":"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"}