Move more core logic to new folder

This commit is contained in:
schroda
2024-10-05 23:22:42 +02:00
parent babda1ea57
commit e7e1fbbc4e
71 changed files with 77 additions and 72 deletions

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// eslint-disable-next-line max-classes-per-file
export class Storage {
constructor(private readonly storage: typeof window.localStorage) {}
parseValue<T>(value: string | null, defaultValue: T): T {
if (value === null) {
return defaultValue;
}
return JSON.parse(value);
}
getItem(key: string): string | null {
return this.storage.getItem(key);
}
getItemParsed<T>(key: string, defaultValue: T): T {
return this.parseValue(this.getItem(key), defaultValue);
}
setItem(key: string, value: unknown, emitEvent: boolean = true): void {
const fireEvent = (valueToStore: string | undefined) => {
if (!emitEvent) {
return;
}
window.dispatchEvent(
new StorageEvent('storage', {
key,
oldValue: this.getItem(key),
newValue: valueToStore,
}),
);
};
if (value === undefined) {
this.storage.removeItem(key);
fireEvent(undefined);
return;
}
const valueToStore = JSON.stringify(value);
this.storage.setItem(key, valueToStore);
fireEvent(valueToStore);
}
}
export class AppStorage {
static readonly local: Storage = new Storage(window.localStorage);
static readonly session: Storage = new Storage(window.sessionStorage);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
export class CustomCache {
private keyToResponseMap = new Map<string, unknown>();
private keyToFetchTimestampMap = new Map<string, number>();
public readonly createKeyFn = (endpoint: string, data: unknown): string => `${endpoint}_${JSON.stringify(data)}`;
constructor(createKeyFn?: (endpoint: string, data: unknown) => string) {
this.createKeyFn = createKeyFn ?? this.createKeyFn;
}
public getKeyFor(key: string, data: unknown): string {
return this.createKeyFn(key, data);
}
public cacheResponse(endpoint: string, data: unknown, response: unknown) {
const createdKey = this.getKeyFor(endpoint, data);
this.keyToFetchTimestampMap.set(createdKey, Date.now());
this.keyToResponseMap.set(createdKey, response);
}
public getFetchTimestampFor(endpoint: string, data: unknown): number | undefined {
const key = this.getKeyFor(endpoint, data);
return this.keyToFetchTimestampMap.get(key);
}
public getResponseFor<Response = any>(endpoint: string, data: unknown, ttl?: number): Response | undefined {
const key = this.getKeyFor(endpoint, data);
const isTtlReached = ttl && Date.now() - (this.getFetchTimestampFor(endpoint, data) ?? 0) >= ttl;
if (isTtlReached) {
this.keyToResponseMap.delete(key);
}
return this.keyToResponseMap.get(key) as Response;
}
public getAllKeys(): string[] {
return [...this.keyToResponseMap.keys()];
}
public getMatchingKeys(regex: RegExp): string[] {
return this.getAllKeys().filter((key) => !!regex.exec(key));
}
public clearFor(...keys: string[]) {
keys.forEach((key) => {
this.keyToResponseMap.delete(key);
this.keyToFetchTimestampMap.delete(key);
});
}
public clear(): void {
this.keyToResponseMap.clear();
this.keyToFetchTimestampMap.clear();
}
}