@weaverslab/feature-flags
Version:
Feature flags for CodeWeavers
62 lines (49 loc) • 1.6 kB
text/typescript
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 }