106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
import fs from 'node:fs'
|
|
|
|
import { listAppConfigEntries, upsertAppConfigEntry } from '../../repositories/app-config-repo.js'
|
|
import { readJsonFile } from '../../utils/json-file-store.js'
|
|
|
|
type NormalizeJsonValue<T> = (value: unknown) => T
|
|
|
|
const configCache = new Map<string, unknown>()
|
|
let databaseCacheLoaded = false
|
|
|
|
export function hasAppConfigEntry(configKey: string, legacyFilePath = '') {
|
|
const key = normalizeConfigKey(configKey)
|
|
if (configCache.has(key)) {
|
|
return true
|
|
}
|
|
|
|
return Boolean(legacyFilePath) && fs.existsSync(legacyFilePath)
|
|
}
|
|
|
|
export function readAppConfigEntry<T>({
|
|
configKey,
|
|
legacyFilePath,
|
|
fallback,
|
|
normalize,
|
|
}: {
|
|
configKey: string
|
|
legacyFilePath?: string | undefined
|
|
fallback: T | (() => T)
|
|
normalize: NormalizeJsonValue<T>
|
|
}): T {
|
|
const key = normalizeConfigKey(configKey)
|
|
if (configCache.has(key)) {
|
|
return normalize(cloneJsonValue(configCache.get(key)))
|
|
}
|
|
|
|
if (!databaseCacheLoaded && legacyFilePath) {
|
|
return readJsonFile(legacyFilePath, fallback, normalize)
|
|
}
|
|
|
|
return normalize(resolveFallback(fallback))
|
|
}
|
|
|
|
export async function saveAppConfigEntry<T>({
|
|
configKey,
|
|
value,
|
|
legacyFilePath,
|
|
normalize,
|
|
}: {
|
|
configKey: string
|
|
value: unknown
|
|
legacyFilePath?: string | undefined
|
|
normalize: NormalizeJsonValue<T>
|
|
}): Promise<T> {
|
|
const key = normalizeConfigKey(configKey)
|
|
const normalized = normalize(value)
|
|
|
|
await upsertAppConfigEntry({
|
|
configKey: key,
|
|
configJson: normalized,
|
|
sourceFilePath: legacyFilePath,
|
|
migratedFromFile: false,
|
|
timestamp: new Date().toISOString(),
|
|
})
|
|
|
|
configCache.set(key, cloneJsonValue(normalized))
|
|
|
|
return normalized
|
|
}
|
|
|
|
export async function loadAppConfigCacheFromDatabase() {
|
|
const rows = await listAppConfigEntries()
|
|
configCache.clear()
|
|
|
|
for (const row of rows) {
|
|
const key = normalizeConfigKey(row.config_key)
|
|
if (!key) {
|
|
continue
|
|
}
|
|
|
|
configCache.set(key, cloneJsonValue(row.config_json))
|
|
}
|
|
|
|
databaseCacheLoaded = true
|
|
}
|
|
|
|
export function setAppConfigCacheEntry(configKey: string, value: unknown) {
|
|
const key = normalizeConfigKey(configKey)
|
|
if (!key) {
|
|
return
|
|
}
|
|
|
|
configCache.set(key, cloneJsonValue(value))
|
|
}
|
|
|
|
function normalizeConfigKey(value: unknown) {
|
|
return String(value || '').trim()
|
|
}
|
|
|
|
function resolveFallback<T>(fallback: T | (() => T)): T {
|
|
return typeof fallback === 'function' ? (fallback as () => T)() : fallback
|
|
}
|
|
|
|
function cloneJsonValue<T>(value: T): T {
|
|
return JSON.parse(JSON.stringify(value ?? null)) as T
|
|
}
|