unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
99 lines • 3.47 kB
JavaScript
import { NotFoundError } from '../../error/index.js';
import { DB_TIME } from '../../metric-events.js';
import metricsHelper from '../../util/metrics-helper.js';
import { defaultFromRow, defaultToRow } from './default-mappings.js';
/**
* This abstract class defines the basic operations for a CRUD store.
*
* It accepts one model as input and one model as output that generally includes auto-generated properties such as the id or createdAt.
*
* Provides default types for:
* - OutputRowModel turning the properties of OutputModel from camelCase to snake_case
* - InputRowModel turning the properties of InputModel from camelCase to snake_case
* - IdType assumming it's a number
*
* These types can be overridden to suit different needs.
*
* Default implementations of toRow and fromRow are provided, but can be overridden.
*/
export class CRUDStore {
constructor(tableName, db, { eventBus }, options) {
this.tableName = tableName;
this.db = db;
this.timer = (action) => metricsHelper.wrapTimer(eventBus, DB_TIME, {
store: tableName,
action,
});
this.toRow = options?.toRow ?? (defaultToRow);
this.fromRow =
options?.fromRow ?? (defaultFromRow);
}
async getAll(query) {
const endTimer = this.timer('getAll');
let allQuery = this.db(this.tableName);
if (query) {
allQuery = allQuery.where(this.toRow(query));
}
const items = await allQuery;
endTimer();
return items.map(this.fromRow);
}
async insert(item) {
const rows = await this.db(this.tableName)
.insert(this.toRow(item))
.returning('*');
return this.fromRow(rows[0]);
}
async bulkInsert(items) {
if (!items || items.length === 0) {
return [];
}
const endTimer = this.timer('bulkInsert');
const rows = await this.db(this.tableName)
.insert(items.map(this.toRow))
.returning('*');
endTimer();
return rows.map(this.fromRow);
}
async update(id, item) {
const rows = await this.db(this.tableName)
.where({ id })
.update(this.toRow(item))
.returning('*');
return this.fromRow(rows[0]);
}
async delete(id) {
return this.db(this.tableName).where({ id }).delete();
}
async deleteAll() {
return this.db(this.tableName).delete();
}
destroy() { }
async exists(id) {
const endTimer = this.timer('exists');
const result = await this.db.raw(`SELECT EXISTS(SELECT 1 FROM ${this.tableName} WHERE id = ?) AS present`, [id]);
const { present } = result.rows[0];
endTimer();
return present;
}
async count(query) {
const endTimer = this.timer('count');
let countQuery = this.db(this.tableName).count('*');
if (query) {
countQuery = countQuery.where(this.toRow(query));
}
const { count } = (await countQuery.first()) ?? { count: 0 };
endTimer();
return Number(count);
}
async get(id) {
const endTimer = this.timer('get');
const row = await this.db(this.tableName).where({ id }).first();
endTimer();
if (!row) {
throw new NotFoundError(`No item with id ${id}`);
}
return this.fromRow(row);
}
}
//# sourceMappingURL=crud-store.js.map