diff --git a/README.md b/README.md index d4c25dc..37bcce8 100644 --- a/README.md +++ b/README.md @@ -20,22 +20,37 @@ yarn add @BolajiOlajide/now-playing ## Usage ```ts -import { NowPlaying, Providers } from '@BolajiOlajide/now-playing' +import { NowPlaying, Providers, type IStorer } from '@BolajiOlajide/now-playing' + +let myCustomStorer: IStorer const np = new NowPlaying(Providers.SPOTIFY, { - useCache: false, // default is true - cacheDuration: 30000, // in milliseconds + useCache: false, // (optional) default is true + cacheDuration: 30000, // (optional) in milliseconds streamerArgs: { clientId: 'foo', clientSecret: 'bar', refreshToken: 'baz', }, + storer: myCustomStorer, // (optional) custom storage implementation }) ``` ### Storage -Data is stored in memory. This is to reduce overhead. We plan to expose the `IStorer` interface later to allow you to use your own storage mechanism. +We default to inmemory storage for saving information gotten via the API, (e.g Access tokens, Song data e.t.c). +However you can pass in your own custom storage object, provided it satisfies the `IStorer` interface. + +```ts +interface IStorer { + set(key: string, value: T, duration: number): void + get(key: string): T | undefined + delete(key: string): boolean + has(key: string): boolean + clear(): void + pruneExpiredEntries(): void +} +``` ### Providers diff --git a/src/index.ts b/src/index.ts index 2e30f56..f9200ac 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,3 @@ export { NowPlaying } from './main' export { Providers } from './schema' +export { type IStorer } from './storage' diff --git a/src/main.ts b/src/main.ts index f155da6..d546b97 100644 --- a/src/main.ts +++ b/src/main.ts @@ -46,7 +46,7 @@ export class NowPlaying { // We only support in memory storage for now, if there's a need we can // support more storage mechanism. - this.storer = this.getStorer() + this.storer = args.storer || this.getStorer() this.streamer = this.getStreamer() } catch (err: unknown) { if (err instanceof ZodError) { diff --git a/src/schema.ts b/src/schema.ts index 23bc8a1..4bc4299 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1,4 +1,5 @@ import { z } from 'zod' +import type { IStorer } from './storage' export enum Providers { SPOTIFY = 'SPOTIFY', @@ -10,6 +11,25 @@ export const providerSchema = z.nativeEnum(Providers) export const BaseNowPlayingArgsSchema = z.object({ useCache: z.boolean().optional(), cacheDuration: z.number().optional(), + storer: z + .custom( + (data: unknown): data is IStorer => { + return ( + typeof data === 'object' && + data !== null && + typeof (data as IStorer).set === 'function' && + typeof (data as IStorer).get === 'function' && + typeof (data as IStorer).delete === 'function' && + typeof (data as IStorer).has === 'function' && + typeof (data as IStorer).clear === 'function' && + typeof (data as IStorer).pruneExpiredEntries === 'function' + ) + }, + { + message: 'Object does not implement IStorer interface', + } + ) + .optional(), }) export type BaseNowPlayingArgs = z.infer