Files
bs-manager/src/main/models/json-cache.class.ts
T
2024-07-28 16:41:16 +02:00

85 lines
2.3 KiB
TypeScript

import { pathExistsSync, readFileSync, writeFileSync } from "fs-extra";
import { tryit } from "shared/helpers/error.helpers";
import log from "electron-log";
import { Subject, debounceTime } from "rxjs";
export class JsonCache<T = unknown> {
private _cache: Record<string, T> = {};
private readonly setEvent: Subject<void> = new Subject<void>();
public constructor(
private readonly jsonPath: string,
private readonly options: JsonCacheOptions = { autoSave: true, saveDebounce: 1000}
){
this.load();
if(this.options.autoSave){
this.setEvent = new Subject<void>();
this.setEvent.pipe(debounceTime(this.options.saveDebounce ?? 1000)).subscribe(() => this.save());
}
}
private load(): void {
try {
if(pathExistsSync(this.jsonPath)){
this._cache = JSON.parse(readFileSync(this.jsonPath).toString());
} else {
log.warn("File cache not exist yet", this.jsonPath);
}
} catch (error) {
log.warn("Failed to load cache file", this.jsonPath, error);
} finally {
this._cache ??= {};
}
}
public save(): void {
const res = tryit(() => writeFileSync(this.jsonPath, JSON.stringify(this._cache), { flush: true }));
if(res.error){
log.error("Failed to save cache", this.jsonPath, res.error);
}
}
public get(key: string): T {
return this._cache[key];
}
public set(key: string, value: T): void {
this._cache[key] = value;
this.setEvent?.next();
}
public delete(key: string): void {
delete this._cache[key];
this.setEvent?.next();
}
public clear(): void {
this._cache = {};
this.setEvent?.next();
}
public get cache(): Record<string, T> {
return this._cache;
}
}
export type JsonCacheOptions = {
/**
* Load the cache immediately after creating the instance
* @default true
*/
loadImmediately?: boolean;
/**
* Auto save the cache after a change
* @default true
*/
autoSave?: boolean;
/**
* Time in ms to wait before saving the cache after a change
* @default 1000
*/
saveDebounce?: number;
};