UNPKG

unleash-server

Version:

Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.

137 lines 5.7 kB
import { ensureStringValue, mapValues } from '../../util/index.js'; import FeatureToggleStore from '../feature-toggle/feature-toggle-store.js'; import metricsHelper from '../../util/metrics-helper.js'; import { DB_TIME } from '../../metric-events.js'; export default class ClientFeatureToggleReadModel { constructor(db, eventBus) { this.db = db; this.timer = (action) => metricsHelper.wrapTimer(eventBus, DB_TIME, { store: 'client-feature-toggle-read-model', action, }); } async getAll() { const stopTimer = this.timer(`getAll`); const selectColumns = [ 'features.name as name', 'features.description as description', 'features.type as type', 'features.project as project', 'features.stale as stale', 'features.impression_data as impression_data', 'fe.variants as variants', 'fe.enabled as enabled', 'fe.environment as environment', 'fs.id as strategy_id', 'fs.strategy_name as strategy_name', 'fs.disabled as strategy_disabled', 'fs.parameters as parameters', 'fs.constraints as constraints', 'fs.sort_order as sort_order', 'fs.variants as strategy_variants', 'segments.id as segment_id', 'segments.constraints as segment_constraints', 'df.parent as parent', 'df.variants as parent_variants', 'df.enabled as parent_enabled', ]; let query = this.db('features') .modify(FeatureToggleStore.filterByArchived, false) .leftJoin(this.db('feature_environments') .select('feature_name', 'enabled', 'environment', 'variants') .as('fe'), 'fe.feature_name', 'features.name') .leftJoin('feature_strategies as fs', function () { this.on('fs.feature_name', '=', 'features.name').andOn('fs.environment', '=', 'fe.environment'); }) .leftJoin('feature_strategy_segment as fss', `fss.feature_strategy_id`, `fs.id`) .leftJoin('segments', `segments.id`, `fss.segment_id`) .leftJoin('dependent_features as df', 'df.child', 'features.name') .where('fe.enabled', true); query = query.select(selectColumns); const rows = await query; stopTimer(); const data = this.getAggregatedData(rows); return data; } getAggregatedData(rows) { const featureTogglesByEnv = {}; rows.forEach((row) => { const environment = row.environment; const featureName = row.name; if (!featureTogglesByEnv[environment]) { featureTogglesByEnv[environment] = {}; } if (!featureTogglesByEnv[environment][featureName]) { featureTogglesByEnv[environment][featureName] = { name: featureName, strategies: [], variants: row.variants || [], impressionData: row.impression_data, enabled: !!row.enabled, description: row.description, project: row.project, stale: row.stale, type: row.type, }; } const feature = featureTogglesByEnv[environment][featureName]; if (row.parent) { feature.dependencies = feature.dependencies || []; feature.dependencies.push({ feature: row.parent, enabled: row.parent_enabled, ...(row.parent_enabled ? { variants: row.parent_variants } : {}), }); } if (this.isUnseenStrategyRow(feature, row) && !row.strategy_disabled) { feature.strategies = feature.strategies || []; feature.strategies.push(this.rowToStrategy(row)); } if (row.segment_id) { this.addSegmentIdsToStrategy(feature, row); } }); Object.values(featureTogglesByEnv).forEach((envFeatures) => { Object.values(envFeatures).forEach((feature) => { if (feature.strategies) { feature.strategies = feature.strategies .sort((a, b) => { return (a.sortOrder || 0) - (b.sortOrder || 0); }) .map(({ id, sortOrder, ...strategy }) => strategy); } }); }); return featureTogglesByEnv; } addSegmentIdsToStrategy(feature, row) { const strategy = feature.strategies?.find((s) => s?.id === row.strategy_id); if (!strategy) { return; } if (!strategy.segments) { strategy.segments = []; } strategy.segments.push(row.segment_id); } rowToStrategy(row) { const strategy = { id: row.strategy_id, name: row.strategy_name, title: row.strategy_title, constraints: row.constraints || [], parameters: mapValues(row.parameters || {}, ensureStringValue), sortOrder: row.sort_order, }; strategy.variants = row.strategy_variants || []; return strategy; } isUnseenStrategyRow(feature, row) { return (row.strategy_id && !feature.strategies?.find((s) => s?.id === row.strategy_id)); } } //# sourceMappingURL=client-feature-toggle-read-model.js.map