1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-11-01 19:07:38 +01:00
unleash.unleash/src/lib/db/strategy-store.ts
andreas-unleash 2da279b7fb
feat: add title to strategy (#3510)
<!-- Thanks for creating a PR! To make it easier for reviewers and
everyone else to understand what your changes relate to, please add some
relevant content to the headings below. Feel free to ignore or delete
sections that you don't think are relevant. Thank you! ❤️ -->
Adds title column to strategies, feature_strategies and features_view in
the db
Updates model/schemas
## About the changes
<!-- Describe the changes introduced. What are they and why are they
being introduced? Feel free to also add screenshots or steps to view the
changes if they're visual. -->

<!-- Does it close an issue? Multiple? -->
Closes #
[1-855](https://linear.app/unleash/issue/1-855/allow-for-title-on-strategy-backend)

<!-- (For internal contributors): Does it relate to an issue on public
roadmap? -->
<!--
Relates to [roadmap](https://github.com/orgs/Unleash/projects/10) item:
#
-->

### Important files
<!-- PRs can contain a lot of changes, but not all changes are equally
important. Where should a reviewer start looking to get an overview of
the changes? Are any files particularly important? -->


## Discussion points
<!-- Anything about the PR you'd like to discuss before it gets merged?
Got any questions or doubts? -->

---------

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
2023-04-18 08:59:02 +02:00

187 lines
5.2 KiB
TypeScript

import { Logger, LogProvider } from '../logger';
import NotFoundError from '../error/notfound-error';
import {
IEditableStrategy,
IMinimalStrategyRow,
IStrategy,
IStrategyImport,
IStrategyStore,
} from '../types/stores/strategy-store';
import { Db } from './db';
const STRATEGY_COLUMNS = [
'title',
'name',
'description',
'parameters',
'built_in',
'deprecated',
'display_name',
];
const TABLE = 'strategies';
interface IStrategyRow {
title: string;
name: string;
built_in: number;
description: string;
parameters: object[];
deprecated: boolean;
display_name: string;
}
export default class StrategyStore implements IStrategyStore {
private db: Db;
private logger: Logger;
constructor(db: Db, getLogger: LogProvider) {
this.db = db;
this.logger = getLogger('strategy-store.ts');
}
async getAll(): Promise<IStrategy[]> {
const rows = await this.db
.select(STRATEGY_COLUMNS)
.from(TABLE)
.orderBy('sort_order', 'asc')
.orderBy('name', 'asc');
return rows.map(this.rowToStrategy);
}
async getEditableStrategies(): Promise<IEditableStrategy[]> {
const rows = await this.db
.select(STRATEGY_COLUMNS)
.from(TABLE)
.where({ built_in: 0 }) // eslint-disable-line
.orderBy('sort_order', 'asc')
.orderBy('name', 'asc');
return rows.map(this.rowToEditableStrategy);
}
async getStrategy(name: string): Promise<IStrategy> {
return this.db
.first(STRATEGY_COLUMNS)
.from(TABLE)
.where({ name })
.then(this.rowToStrategy);
}
async delete(name: string): Promise<void> {
await this.db(TABLE).where({ name }).del();
}
async deleteAll(): Promise<void> {
await this.db(TABLE).del();
}
async count(): Promise<number> {
return this.db
.from(TABLE)
.count('*')
.then((res) => Number(res[0].count));
}
destroy(): void {}
async exists(name: string): Promise<boolean> {
const result = await this.db.raw(
`SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE name = ?) AS present`,
[name],
);
const { present } = result.rows[0];
return present;
}
async get(name: string): Promise<IStrategy> {
const row = await this.db(TABLE).where({ name }).first();
return this.rowToStrategy(row);
}
rowToStrategy(row: IStrategyRow): IStrategy {
if (!row) {
throw new NotFoundError('No strategy found');
}
return {
displayName: row.display_name,
name: row.name,
editable: row.built_in !== 1,
description: row.description,
parameters: row.parameters,
deprecated: row.deprecated,
title: row.title,
};
}
rowToEditableStrategy(row: IStrategyRow): IEditableStrategy {
if (!row) {
throw new NotFoundError('No strategy found');
}
return {
name: row.name,
description: row.description,
parameters: row.parameters,
deprecated: row.deprecated,
title: row.title,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
eventDataToRow(data): IMinimalStrategyRow {
return {
name: data.name,
description: data.description,
parameters: JSON.stringify(data.parameters),
title: data.title,
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
async createStrategy(data): Promise<void> {
await this.db(TABLE).insert(this.eventDataToRow(data));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
async updateStrategy(data): Promise<void> {
await this.db(TABLE)
.where({ name: data.name })
.update(this.eventDataToRow(data));
}
async deprecateStrategy({ name }: Pick<IStrategy, 'name'>): Promise<void> {
await this.db(TABLE).where({ name }).update({ deprecated: true });
}
async reactivateStrategy({ name }: Pick<IStrategy, 'name'>): Promise<void> {
await this.db(TABLE).where({ name }).update({ deprecated: false });
}
async deleteStrategy({ name }: Pick<IStrategy, 'name'>): Promise<void> {
await this.db(TABLE).where({ name }).del();
}
async importStrategy(data: IStrategyImport): Promise<void> {
const rowData = {
name: data.name,
description: data.description,
deprecated: data.deprecated || false,
parameters: JSON.stringify(data.parameters || []),
built_in: data.builtIn ? 1 : 0,
sort_order: data.sortOrder || 9999,
display_name: data.displayName,
title: data.title,
};
await this.db(TABLE).insert(rowData).onConflict(['name']).merge();
}
async dropCustomStrategies(): Promise<void> {
await this.db(TABLE)
.where({ built_in: 0 }) // eslint-disable-line
.delete();
}
}
module.exports = StrategyStore;