import { Db } from '../../db/db'; import { IDependentFeaturesStore } from './dependent-features-store-type'; import { FeatureDependency, FeatureDependencyId } from './dependent-features'; type SerializableFeatureDependency = Omit & { variants?: string; }; export class DependentFeaturesStore implements IDependentFeaturesStore { private db: Db; constructor(db: Db) { this.db = db; } async upsert(featureDependency: FeatureDependency): Promise { const serializableFeatureDependency: SerializableFeatureDependency = { parent: featureDependency.parent, child: featureDependency.child, enabled: featureDependency.enabled, }; if ('variants' in featureDependency) { serializableFeatureDependency.variants = JSON.stringify( featureDependency.variants, ); } await this.db('dependent_features') .insert(serializableFeatureDependency) .onConflict(['parent', 'child']) .merge(); } async getChildren(parent: string): Promise { const rows = await this.db('dependent_features').where( 'parent', parent, ); return rows.map((row) => row.child); } async getParentOptions(child: string): Promise { const result = await this.db('features as f') .where('f.name', child) .select('f.project'); if (result.length === 0) { return []; } const rows = await this.db('features as f') .leftJoin('dependent_features as df', 'f.name', 'df.child') .where('f.project', result[0].project) .andWhere('f.name', '!=', child) .andWhere('df.child', null) .select('f.name'); return rows.map((item) => item.name); } async delete(dependency: FeatureDependencyId): Promise { await this.db('dependent_features') .where('parent', dependency.parent) .andWhere('child', dependency.child) .del(); } async deleteAll(feature: string): Promise { await this.db('dependent_features').andWhere('child', feature).del(); } }