UNPKG

@weaverslab/feature-flags

Version:

Feature flags for CodeWeavers

62 lines (49 loc) 1.6 kB
import dotenv from 'dotenv' import { sql } from 'drizzle-orm' import { drizzle } from 'drizzle-orm/postgres-js' import EventEmitter from 'events' import { LRUCache } from 'lru-cache' import { Pool } from 'pg' dotenv.config() interface FeatureFlag { name: string enabled: boolean } class FeatureFlagService { private db private cache private events constructor() { this.db = drizzle(new Pool({ connectionString: process.env.DATABASE_URL })) this.cache = new LRUCache<string, boolean>({ max: 100, ttl: 60000 }) this.events = new EventEmitter() this.initialize() } private async initialize() { await this.loadFeatureFlags() this.listenForChanges() } private async loadFeatureFlags() { const flags: FeatureFlag[] = await this.db.execute(sql`SELECT name, enabled FROM hub_feature_flag`) flags.forEach((flag) => this.cache.set(flag.name, flag.enabled)) } private async listenForChanges() { const client = new Pool({ connectionString: process.env.DATABASE_URL }) const pgClient = await client.connect() pgClient.query('LISTEN feature_flag_changes') pgClient.on('notification', async () => { await this.loadFeatureFlags() this.events.emit('update') }) } public isEnabled(flagName: string): boolean { return this.cache.get(flagName) ?? false } public onUpdate(callback: () => void) { this.events.on('update', callback) } static setDatabaseUrl(url: string) { process.env.DATABASE_URL = url } } export { FeatureFlagService }