services/FeatureFlagService.jsjavascript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FeatureFlagKey = void 0;
const winston_1 = __importDefault(require("../plugins/winston.js"));
const unleash_client_1 = require("unleash-client");
/**
 * Keys for available feature flags used by the application.
 */
var FeatureFlagKey;
(function (FeatureFlagKey) {
    FeatureFlagKey["MOBILE_EDITING"] = "mobile-editing";
    FeatureFlagKey["SOCIAL_LOGIN"] = "social-login";
    FeatureFlagKey["ACCESS_SHARING"] = "access-sharing";
})(FeatureFlagKey || (exports.FeatureFlagKey = FeatureFlagKey = {}));
/**
 * Service responsible for initializing and querying feature flags.
 *
 * This service initializes the client once and exposes helper
 * methods to validate configuration and to read feature flag values.
 */
class FeatureFlagService {
    initialization;
    unleash;
    _ready = false;
    /**
     * Create a new FeatureFlagService and start initialization.
     * The `initialization` promise resolves when the client emits
     * the `synchronized` event.
     */
    constructor() {
        this.unleash = {}; // only for type safety
        if (!process.env.UNLEASH_API_KEY) {
            this._ready = false;
            this.initialization = Promise.resolve();
            return;
        }
        this.initialization = new Promise((resolve) => {
            this.unleash = (0, unleash_client_1.initialize)({
                url: "https://features.choreo-planer.de/api",
                appName: "choreo-planer-server",
                customHeaders: {
                    Authorization: process.env.UNLEASH_API_KEY ?? "",
                },
            });
            this.unleash.on("synchronized", () => {
                this._ready = true;
                resolve();
            });
        });
    }
    isConfigured() {
        return !!process.env.UNLEASH_API_KEY;
    }
    isReady() {
        return this._ready;
    }
    /**
     * Check whether a feature flag is enabled.
     *
     * Waits for the client to finish initialization before querying.
     * Returns `false` when feature flags are not configured.
     *
     * @param {FeatureFlagKey} flagName - The feature flag key to check.
     * @returns {Promise<boolean>} True if the flag is enabled; otherwise false.
     */
    async isEnabled(flagName) {
        if (!this.isConfigured()) {
            winston_1.default.warn(`FeatureFlagService.isEnabled "${flagName}" — UNLEASH_API_KEY not set, returning false`);
            return false;
        }
        winston_1.default.debug(`FeatureFlagService.isEnabled "${flagName}"`);
        await this.initialization;
        const result = this.unleash.isEnabled(flagName);
        winston_1.default.debug(`Feature flag "${flagName}" is ${result ? "enabled" : "disabled"}`);
        return result;
    }
    /**
     * Retrieve all feature flag definitions.
     *
     * Filters out stale flags and returns an array of simplified flag states.
     * Returns an empty array when feature flags are not configured.
     *
     * @returns {Promise<Array<{name: string, enabled: boolean}>>}
     *          Array of feature flag states.
     */
    async getAll() {
        if (!this.isConfigured()) {
            winston_1.default.warn("FeatureFlagService.getAll — UNLEASH_API_KEY not set, returning empty array");
            return [];
        }
        winston_1.default.debug(`FeatureFlagService.getAll`);
        await this.initialization;
        const result = this.unleash.getFeatureToggleDefinitions();
        winston_1.default.debug(`Feature Flags: ${JSON.stringify(result)}`);
        return result.map(({ name, enabled, stale, description }) => ({
            name,
            enabled: enabled && !stale,
            description: description || name,
        }));
    }
}
exports.default = new FeatureFlagService();