feature flags

This commit is contained in:
2026-01-06 12:40:58 +01:00
parent 6aad7897db
commit c55ef731a1
11 changed files with 517 additions and 30 deletions

View File

@@ -1,5 +1,7 @@
import { Injectable } from '@nestjs/common';
import { readFile } from 'node:fs/promises';
import { loadFeatureConfig } from '../../config/feature-loader';
import { FlattenedFeatures } from '../../config/feature-types';
export type OperationalMode = 'normal' | 'maintenance' | 'test';
export type FeatureState = 'enabled' | 'disabled' | 'coming_soon' | 'hidden';
@@ -72,24 +74,18 @@ export class PolicyService {
};
}
const anyEnvConfigured =
Boolean(process.env.GRIDPILOT_OPERATIONAL_MODE) ||
Boolean(process.env.GRIDPILOT_FEATURES_JSON) ||
Boolean(process.env.GRIDPILOT_MAINTENANCE_ALLOW_VIEW) ||
Boolean(process.env.GRIDPILOT_MAINTENANCE_ALLOW_MUTATE);
const raw: RawPolicySnapshot = {};
// Load from TypeScript config file
const configResult = await loadFeatureConfig();
const raw: RawPolicySnapshot = {
capabilities: convertFlattenedToCapabilities(configResult.features),
};
// Include other env vars if set
const operationalMode = process.env.GRIDPILOT_OPERATIONAL_MODE;
if (operationalMode) {
raw.operationalMode = operationalMode;
}
const capabilities = parseFeaturesJson(process.env.GRIDPILOT_FEATURES_JSON);
if (capabilities) {
raw.capabilities = capabilities;
}
const maintenanceAllowView = parseCsvList(process.env.GRIDPILOT_MAINTENANCE_ALLOW_VIEW);
const maintenanceAllowMutate = parseCsvList(process.env.GRIDPILOT_MAINTENANCE_ALLOW_MUTATE);
@@ -102,7 +98,7 @@ export class PolicyService {
return {
raw,
loadedFrom: anyEnvConfigured ? 'env' : 'defaults',
loadedFrom: configResult.loadedFrom === 'config-file' ? 'file' : 'defaults',
};
}
}
@@ -191,16 +187,6 @@ function parseFeatureState(value: unknown): FeatureState | null {
}
}
function parseFeaturesJson(raw: string | undefined): unknown {
if (!raw) {
return undefined;
}
try {
return JSON.parse(raw) as unknown;
} catch {
return undefined;
}
}
function parseCsvList(raw: string | undefined): readonly string[] | undefined {
if (!raw) {
@@ -226,4 +212,11 @@ function normalizeStringArray(value: unknown): readonly string[] {
.filter(Boolean);
return normalized;
}
// NEW: Helper function to convert flattened features to capabilities
function convertFlattenedToCapabilities(
flattened: FlattenedFeatures
): Record<string, FeatureState> {
return flattened as Record<string, FeatureState>;
}