mirror of https://github.com/boxyhq/jackson.git
84 lines
2.5 KiB
TypeScript
84 lines
2.5 KiB
TypeScript
import { DatabaseDriver, DatabaseOption, Encrypted, EncryptionKey, Index, Storable } from '../typings';
|
|
import * as encrypter from './encrypter';
|
|
import mem from './mem';
|
|
import mongo from './mongo';
|
|
import redis from './redis';
|
|
import sql from './sql/sql';
|
|
import store from './store';
|
|
|
|
const decrypt = (res: Encrypted, encryptionKey: EncryptionKey): unknown => {
|
|
if (res.iv && res.tag) {
|
|
return JSON.parse(encrypter.decrypt(res.value, res.iv, res.tag, encryptionKey));
|
|
}
|
|
|
|
return JSON.parse(res.value);
|
|
};
|
|
|
|
class DB implements DatabaseDriver {
|
|
private db: DatabaseDriver;
|
|
private encryptionKey: EncryptionKey;
|
|
|
|
constructor(db: DatabaseDriver, encryptionKey: EncryptionKey) {
|
|
this.db = db;
|
|
this.encryptionKey = encryptionKey;
|
|
}
|
|
|
|
async get(namespace: string, key: string): Promise<unknown> {
|
|
const res = await this.db.get(namespace, key);
|
|
|
|
if (!res) {
|
|
return null;
|
|
}
|
|
|
|
return decrypt(res, this.encryptionKey);
|
|
}
|
|
|
|
async getByIndex(namespace: string, idx: Index): Promise<unknown[]> {
|
|
const res = await this.db.getByIndex(namespace, idx);
|
|
const encryptionKey = this.encryptionKey;
|
|
return res.map((r) => {
|
|
return decrypt(r, encryptionKey);
|
|
});
|
|
}
|
|
|
|
// ttl is in seconds
|
|
async put(namespace: string, key: string, val: unknown, ttl = 0, ...indexes: Index[]): Promise<unknown> {
|
|
if (ttl > 0 && indexes && indexes.length > 0) {
|
|
throw new Error('secondary indexes not allow on a store with ttl');
|
|
}
|
|
|
|
const dbVal = this.encryptionKey
|
|
? encrypter.encrypt(JSON.stringify(val), this.encryptionKey)
|
|
: { value: JSON.stringify(val) };
|
|
|
|
return await this.db.put(namespace, key, dbVal, ttl, ...indexes);
|
|
}
|
|
|
|
async delete(namespace: string, key: string): Promise<unknown> {
|
|
return await this.db.delete(namespace, key);
|
|
}
|
|
|
|
store(namespace: string, ttl = 0): Storable {
|
|
return store.new(namespace, this, ttl);
|
|
}
|
|
}
|
|
|
|
export default {
|
|
new: async (options: DatabaseOption) => {
|
|
const encryptionKey = options.encryptionKey ? Buffer.from(options.encryptionKey, 'latin1') : null;
|
|
|
|
switch (options.engine) {
|
|
case 'redis':
|
|
return new DB(await redis.new(options), encryptionKey);
|
|
case 'sql':
|
|
return new DB(await sql.new(options), encryptionKey);
|
|
case 'mongo':
|
|
return new DB(await mongo.new(options), encryptionKey);
|
|
case 'mem':
|
|
return new DB(await mem.new(options), encryptionKey);
|
|
default:
|
|
throw new Error('unsupported db engine: ' + options.engine);
|
|
}
|
|
},
|
|
};
|