From 5908e9da15fded942f055473c6f21e82d0bf2aff Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 19 Jul 2025 15:21:57 +0000 Subject: [PATCH] api/env: add subscribe() for dynamic reloads --- api/src/config.js | 10 +++++++++- api/src/core/env.js | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/api/src/config.js b/api/src/config.js index 2d539c0d..c606b0ae 100644 --- a/api/src/config.js +++ b/api/src/config.js @@ -1,5 +1,5 @@ import { getVersion } from "@imput/version-info"; -import { loadEnvs, validateEnvs } from "./core/env.js"; +import { loadEnvs, validateEnvs, onEnvChanged } from "./core/env.js"; const version = await getVersion(); @@ -18,12 +18,20 @@ export const updateEnv = (newEnv) => { newEnv.tunnelPort = env.tunnelPort; for (const key in env) { + if (key === 'subscribe') { + continue; + } + if (String(env[key]) !== String(newEnv[key])) { changes.push(key); } env[key] = newEnv[key]; } + if (changes.length) { + onEnvChanged(changes); + } + return changes; } diff --git a/api/src/core/env.js b/api/src/core/env.js index f26b3986..2d2e7380 100644 --- a/api/src/core/env.js +++ b/api/src/core/env.js @@ -10,6 +10,30 @@ import { Green, Yellow } from "../misc/console-text.js"; const forceLocalProcessingOptions = ["never", "session", "always"]; const youtubeHlsOptions = ["never", "key", "always"]; +const changeCallbacks = {}; + +export const onEnvChanged = (changes) => { + for (const key of changes) { + if (changeCallbacks[key]) { + changeCallbacks[key].map(fn => { + try { fn() } catch {} + }); + } + } +} + +const subscribe = (keys, fn) => { + keys = [keys].flat(); + + for (const key of keys) { + if (key in currentEnv && key !== 'subscribe') { + changeCallbacks[key] ??= []; + changeCallbacks[key].push(fn); + fn(); + } else throw `invalid env key ${key}`; + } +} + export const loadEnvs = (env = process.env) => { const allServices = new Set(Object.keys(services)); const disabledServices = env.DISABLED_SERVICES?.split(',') || []; @@ -87,6 +111,8 @@ export const loadEnvs = (env = process.env) => { envFile: env.API_ENV_FILE, envRemoteReloadInterval: 300, + + subscribe, }; }