From c3ea1a394acbfa1726a0c8732e0fab4383c70130 Mon Sep 17 00:00:00 2001 From: MARCROCK22 Date: Sat, 3 Aug 2024 23:58:55 +0000 Subject: [PATCH] feat: endcode & decode cache adapters option --- src/cache/adapters/default.ts | 34 +++++++++++++++++++++++++--------- src/cache/adapters/limited.ts | 35 +++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/cache/adapters/default.ts b/src/cache/adapters/default.ts index 0da75bb..e5217f8 100644 --- a/src/cache/adapters/default.ts +++ b/src/cache/adapters/default.ts @@ -1,11 +1,27 @@ import type { Adapter } from './types'; -export class MemoryAdapter implements Adapter { +export interface MemoryAdapterOptions { + encode(data: any): T; + decode(data: T): unknown; +} + +export class MemoryAdapter implements Adapter { isAsync = false; - readonly storage = new Map(); + readonly storage = new Map(); readonly relationships = new Map(); + constructor( + public options: MemoryAdapterOptions = { + encode(data) { + return JSON.stringify(data) as T; + }, + decode(data) { + return JSON.parse(data as string); + }, + }, + ) {} + scan(query: string, keys?: false): any[]; scan(query: string, keys: true): string[]; scan(query: string, keys = false) { @@ -13,7 +29,7 @@ export class MemoryAdapter implements Adapter { const sq = query.split('.'); for (const [key, value] of this.storage.entries()) { if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) { - values.push(keys ? key : JSON.parse(value)); + values.push(keys ? key : this.options.decode(value)); } } @@ -24,24 +40,24 @@ export class MemoryAdapter implements Adapter { return keys .map(x => { const data = this.storage.get(x); - return data ? JSON.parse(data) : null; + return data ? this.options.decode(data) : null; }) .filter(x => x); } get(keys: string) { const data = this.storage.get(keys); - return data ? JSON.parse(data) : null; + return data ? this.options.decode(data) : null; } bulkSet(keys: [string, any][]) { for (const [key, value] of keys) { - this.storage.set(key, JSON.stringify(value)); + this.storage.set(key, this.options.encode(value)); } } set(key: string, data: any) { - this.storage.set(key, JSON.stringify(data)); + this.storage.set(key, this.options.encode(data)); } bulkPatch(updateOnly: boolean, keys: [string, any][]) { @@ -52,7 +68,7 @@ export class MemoryAdapter implements Adapter { } this.storage.set( key, - Array.isArray(value) ? JSON.stringify(value) : JSON.stringify({ ...(oldData ?? {}), ...value }), + Array.isArray(value) ? this.options.encode(value) : this.options.encode({ ...(oldData ?? {}), ...value }), ); } } @@ -64,7 +80,7 @@ export class MemoryAdapter implements Adapter { } this.storage.set( keys, - Array.isArray(data) ? JSON.stringify(data) : JSON.stringify({ ...(oldData ?? {}), ...data }), + Array.isArray(data) ? this.options.encode(data) : this.options.encode({ ...(oldData ?? {}), ...data }), ); } diff --git a/src/cache/adapters/limited.ts b/src/cache/adapters/limited.ts index 420b93b..86c6365 100644 --- a/src/cache/adapters/limited.ts +++ b/src/cache/adapters/limited.ts @@ -7,7 +7,7 @@ export interface ResourceLimitedMemoryAdapter { limit?: number; } -export interface LimitedMemoryAdapterOptions { +export interface LimitedMemoryAdapterOptions { default?: ResourceLimitedMemoryAdapter; guild?: ResourceLimitedMemoryAdapter; @@ -26,24 +26,33 @@ export interface LimitedMemoryAdapterOptions { thread?: ResourceLimitedMemoryAdapter; overwrite?: ResourceLimitedMemoryAdapter; message?: ResourceLimitedMemoryAdapter; + + encode(data: any): T; + decode(data: T): unknown; } -export class LimitedMemoryAdapter implements Adapter { +export class LimitedMemoryAdapter implements Adapter { isAsync = false; - readonly storage = new Map>(); + readonly storage = new Map>(); readonly relationships = new Map>(); - options: MakeRequired; + options: MakeRequired, 'default'>; - constructor(options: LimitedMemoryAdapterOptions) { + constructor(options: LimitedMemoryAdapterOptions) { this.options = MergeOptions( { default: { expire: undefined, limit: Number.POSITIVE_INFINITY, }, - } satisfies LimitedMemoryAdapterOptions, + encode(data) { + return JSON.stringify(data) as T; + }, + decode(data) { + return JSON.parse(data as string); + }, + } satisfies LimitedMemoryAdapterOptions, options, ); } @@ -56,7 +65,7 @@ export class LimitedMemoryAdapter implements Adapter { for (const iterator of [...this.storage.values()].flatMap(x => x.entries())) for (const [key, value] of iterator) { if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) { - values.push(keys ? key : JSON.parse(value.value)); + values.push(keys ? key : this.options.decode(value.value)); } } @@ -68,14 +77,14 @@ export class LimitedMemoryAdapter implements Adapter { return keys .map(key => { const data = iterator.find(x => x.has(key))?.get(key); - return data ? JSON.parse(data) : null; + return data ? this.options.decode(data) : null; }) .filter(x => x); } get(keys: string) { const data = [...this.storage.values()].find(x => x.has(keys))?.get(keys); - return data ? JSON.parse(data) : null; + return data ? this.options.decode(data) : null; } private __set(key: string, data: any) { @@ -87,9 +96,11 @@ export class LimitedMemoryAdapter implements Adapter { namespace, new LimitedCollection({ expire: - this.options[key.split('.')[0] as keyof LimitedMemoryAdapterOptions]?.expire ?? this.options.default.expire, + this.options[key.split('.')[0] as Exclude, 'decode' | 'encode'>] + ?.expire ?? this.options.default.expire, limit: - this.options[key.split('.')[0] as keyof LimitedMemoryAdapterOptions]?.limit ?? this.options.default.limit, + this.options[key.split('.')[0] as Exclude, 'decode' | 'encode'>] + ?.limit ?? this.options.default.limit, resetOnDemand: true, onDelete(k) { const relationshipNamespace = key.split('.')[0]; @@ -126,7 +137,7 @@ export class LimitedMemoryAdapter implements Adapter { ); } - this.storage.get(namespace)!.set(key, JSON.stringify(data)); + this.storage.get(namespace)!.set(key, this.options.encode(data)); } bulkSet(keys: [string, any][]) {