unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
138 lines • 5.88 kB
JavaScript
import { ulid } from 'ulidx';
import { CRUDStore } from '../../db/crud/crud-store.js';
import { NotFoundError } from '../../error/index.js';
const TABLE = 'release_plan_definitions';
const fromRow = (row) => {
return {
id: row.id,
name: row.name,
createdAt: row.created_at,
description: row.description,
discriminator: row.discriminator,
createdByUserId: row.created_by_user_id,
};
};
export class ReleasePlanTemplateStore extends CRUDStore {
constructor(db, config) {
super(TABLE, db, config);
}
async getAll() {
const endTimer = this.timer('getAll');
const templates = await this.db(TABLE)
.where('discriminator', 'template')
.where('archived_at', null)
.orderBy('created_at');
endTimer();
return templates.map(({ milestones, ...template }) => fromRow(template));
}
async count(query) {
let countQuery = this.db(this.tableName)
.where('discriminator', 'template')
.whereNull('archived_at')
.count('*');
if (query) {
countQuery = countQuery.where(this.toRow(query));
}
const { count } = (await countQuery.first()) ?? { count: 0 };
return Number(count);
}
async checkNameAlreadyExists(name, id) {
const exists = await this.db(TABLE)
.where('discriminator', 'template')
.where({ name })
.modify((qb) => {
if (id) {
qb.whereNot('id', id);
}
})
.first()
.select('id');
return Boolean(exists);
}
processReleasePlanTemplateRows(templateRows) {
return {
id: templateRows[0].templateId,
discriminator: templateRows[0].templateDiscriminator,
name: templateRows[0].templateName,
description: templateRows[0].templateDescription,
createdByUserId: templateRows[0].templateCreatedByUserId,
createdAt: templateRows[0].templateCreatedAt,
milestones: templateRows.reduce((acc, row) => {
if (!row.milestoneId) {
return acc;
}
let milestone = acc.find((m) => m.id === row.milestoneId);
if (!milestone) {
milestone = {
id: row.milestoneId,
name: row.milestoneName,
sortOrder: row.milestoneSortOrder,
strategies: [],
releasePlanDefinitionId: row.templateId,
};
acc.push(milestone);
}
if (!row.strategyId) {
return acc;
}
let strategy = milestone.strategies?.find((s) => s.id === row.strategyId);
if (!strategy) {
strategy = {
id: row.strategyId,
milestoneId: row.milestoneId,
sortOrder: row.strategySortOrder,
title: row.strategyTitle,
strategyName: row.strategyName,
parameters: row.strategyParameters ?? {},
constraints: row.strategyConstraints,
variants: row.strategyVariants ?? [],
segments: [],
};
milestone.strategies = [
...(milestone.strategies || []),
strategy,
];
}
if (row.segmentId) {
strategy.segments = [
...(strategy.segments || []),
row.segmentId,
];
}
return acc;
}, []),
archivedAt: templateRows[0].templateArchivedAt,
};
}
async getById(id) {
const endTimer = this.timer('getById');
const templateRows = await this.db(`${TABLE} AS rpd`)
.where('rpd.id', id)
.leftJoin('milestones AS mi', 'mi.release_plan_definition_id', 'rpd.id')
.leftJoin('milestone_strategies AS ms', 'ms.milestone_id', 'mi.id')
.leftJoin('milestone_strategy_segments AS mss', 'mss.milestone_strategy_id', 'ms.id')
.orderBy('mi.sort_order', 'asc')
.orderBy('ms.sort_order', 'asc')
.select('rpd.id AS templateId', 'rpd.discriminator AS templateDiscriminator', 'rpd.name AS templateName', 'rpd.description as templateDescription', 'rpd.created_by_user_id as templateCreatedByUserId', 'rpd.created_at as templateCreatedAt', 'rpd.archived_at AS templateArchivedAt', 'mi.id AS milestoneId', 'mi.name AS milestoneName', 'mi.sort_order AS milestoneSortOrder', 'ms.id AS strategyId', 'ms.sort_order AS strategySortOrder', 'ms.title AS strategyTitle', 'ms.strategy_name AS strategyName', 'ms.parameters AS strategyParameters', 'ms.constraints AS strategyConstraints', 'ms.variants AS strategyVariants', 'mss.segment_id AS segmentId');
endTimer();
if (!templateRows.length) {
throw new NotFoundError(`Could not find template with id ${id}`);
}
return this.processReleasePlanTemplateRows(templateRows);
}
async insert(item) {
const endTimer = this.timer('insert');
const row = this.toRow(item);
row.id = ulid();
await this.db(TABLE).insert(row);
endTimer();
return fromRow(row);
}
async archive(id) {
const endTimer = this.timer('archive');
const now = new Date();
await this.db(TABLE).where('id', id).update({ archived_at: now });
endTimer();
}
}
//# sourceMappingURL=release-plan-template-store.js.map