UNPKG

zephyr-agent

Version:
100 lines (99 loc) • 4.56 kB
import "node:module"; import { ze_api_gateway } from "zephyr-edge-contract"; import { isTokenStillValid } from "../auth/login.mjs"; import { ZeErrors, ZephyrError } from "../errors/index.mjs"; import { makeRequest } from "../http/http-request.mjs"; import { ze_log } from "../logging/index.mjs"; import { getAppConfig, getApplicationConfigStorageScope, saveAppConfig } from "../node-persist/application-configuration.mjs"; import { getToken } from "../node-persist/token.mjs"; const APPLICATION_CONFIG_TTL_MS = 60000; const inFlightByIdentity = new Map(); const cachedConfigByIdentity = new Map(); function getApplicationIdentity(scope, application_uid) { return JSON.stringify([ scope.apiEndpoint, scope.apiGatewayEndpoint, scope.environment, scope.preview, scope.principalFingerprint, application_uid ]); } function isIdentityForApplication(identity, application_uid) { try { const parsed = JSON.parse(identity); return Array.isArray(parsed) && parsed[parsed.length - 1] === application_uid; } catch { return false; } } function isValidConfig(config, application_uid) { return Boolean(config && config.application_uid === application_uid && isTokenStillValid(config.jwt) && config.fetched_at && Date.now() - config.fetched_at <= APPLICATION_CONFIG_TTL_MS); } async function loadApplicationConfiguration({ application_uid }, scope, token) { if (!application_uid) throw new ZephyrError(ZeErrors.ERR_MISSING_APPLICATION_UID); const application_config_url = new URL(`${ze_api_gateway.application_config}/${application_uid}`, scope.apiGatewayEndpoint); const [ok, cause, data] = await makeRequest(application_config_url, { headers: { Authorization: `Bearer ${token}` }, credentialToken: token }); if (!ok || !data?.value || data.value.application_uid !== application_uid) throw new ZephyrError(ZeErrors.ERR_LOAD_APP_CONFIG, { application_uid, operation: 'get-application-config', cause, data: { url: application_config_url.toString() } }); return { ...data.value, fetched_at: Date.now() }; } async function getApplicationConfiguration({ application_uid }) { try { if (!application_uid) throw new ZephyrError(ZeErrors.ERR_MISSING_APPLICATION_UID); const token = await getToken(); const scope = getApplicationConfigStorageScope(token); const identity = getApplicationIdentity(scope, application_uid); const cachedConfig = cachedConfigByIdentity.get(identity); if (isValidConfig(cachedConfig, application_uid)) { ze_log.app('Using cached application configuration'); return cachedConfig; } cachedConfigByIdentity.delete(identity); const existingRequest = inFlightByIdentity.get(identity); if (existingRequest) return existingRequest; ze_log.app('Getting application configuration from node-persist'); const request = (async ()=>{ const storedAppConfig = await getAppConfig(application_uid, scope); if (isValidConfig(storedAppConfig, application_uid)) return storedAppConfig; { ze_log.app('Loading Application Configuration from API...'); const loadedAppConfig = await loadApplicationConfiguration({ application_uid }, scope, token); ze_log.app('Saving Application Configuration to node-persist...'); await saveAppConfig(application_uid, loadedAppConfig, scope); return loadedAppConfig; } })().then((config)=>{ cachedConfigByIdentity.set(identity, config); return config; }).finally(()=>{ if (inFlightByIdentity.get(identity) === request) inFlightByIdentity.delete(identity); }); inFlightByIdentity.set(identity, request); return await request; } catch (error) { throw ZephyrError.withContext(error, 'get-application-config'); } } function invalidateApplicationConfigCache(application_uid) { if (!application_uid) return void cachedConfigByIdentity.clear(); for (const identity of cachedConfigByIdentity.keys())if (isIdentityForApplication(identity, application_uid)) cachedConfigByIdentity.delete(identity); } export { getApplicationConfiguration, invalidateApplicationConfigCache }; //# sourceMappingURL=get-application-configuration.mjs.map