mastercache
Version:
Multi-tier cache module for Node.js. Redis, Upstash, CloudfareKV, File, in-memory and others drivers
108 lines (89 loc) • 2.83 kB
text/typescript
import type { DbResult, DefaultColumnTypes, DefaultSchemaConfig } from 'orchid-orm';
import { DatabaseDriver } from '../database';
import type { CreateDriverResult, DatabaseAdapter, OrchidConfig } from '../../../types/main';
/**
* Orchid adapter for the DatabaseDriver
*/
export class OrchidAdapter implements DatabaseAdapter {
#connection: DbResult<DefaultColumnTypes<DefaultSchemaConfig>>;
#tableName!: string;
constructor(config: OrchidConfig) {
this.#connection = config.connection;
}
private getTable() {
return this.#connection(this.#tableName, (t) => ({
key: t.varchar().primaryKey(),
value: t.varchar(),
expires_at: t
.timestampNoTZ()
.encode((value: Date) => value)
.parse((v: any): number => (v ? new Date(v).valueOf() : v))
.nullable(),
}));
}
setTableName(tableName: string): void {
this.#tableName = tableName;
}
async get(key: string): Promise<{ value: string; expiresAt: number | null } | undefined> {
const result = await this.getTable().findByOptional({ key }).select('value', 'expires_at');
if (!result) return;
return { value: result.value, expiresAt: result.expires_at };
}
async delete(key: string): Promise<boolean> {
const count = await this.getTable().where({ key }).delete();
return count > 0;
}
async deleteMany(keys: string[]): Promise<number> {
return await this.getTable().whereIn('key', keys).delete();
}
async disconnect(): Promise<void> {
await this.#connection.close();
}
async createTableIfNotExists(): Promise<void> {
await this.#connection.adapter.pool.query(`
CREATE TABLE IF NOT EXISTS "public"."${this.#tableName}" (
"key" varchar NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp,
PRIMARY KEY ("key")
);
`);
}
async pruneExpiredEntries(): Promise<void> {
await this.getTable()
.where({ expires_at: { lt: new Date() } })
.delete();
}
async clear(prefix: string): Promise<void> {
await this.getTable()
.where({ key: { startsWith: prefix } })
.delete();
}
async set(row: { key: string; value: any; expiresAt: Date | null }): Promise<void> {
await this.getTable()
.findBy({ key: row.key })
.upsert({
create: {
key: row.key,
value: row.value,
expires_at: row.expiresAt,
},
update: {
value: row.value,
expires_at: row.expiresAt,
},
});
}
}
/**
* Create a orchid driver
*/
export function orchidDriver(options: OrchidConfig): CreateDriverResult<DatabaseDriver> {
return {
options,
factory: (config: OrchidConfig) => {
const adapter = new OrchidAdapter(config);
return new DatabaseDriver(adapter, config);
},
};
}