UNPKG

@sixbell-telco/sdk

Version:

A collection of reusable components designed for use in Sixbell Telco Angular projects

236 lines (170 loc) 5.08 kB
# Runtime Config Utility Shared runtime loader and update adapter used by Theme and Translation. It loads JSON at boot, checks updates, and stores last-known-good configs in IndexedDB (Dexie). This doc covers: - RuntimeConfigLoader flow - Cache and schema versioning - Update adapters (SSE/stream) - RuntimeHttpClient behavior - Examples for custom resources --- ## Core Concepts ### RuntimeConfigLoader Responsibilities: - Load a JSON config at boot (cache-first) - Store last-known-good in Dexie - Compare hash to detect updates - Refresh on demand ### RuntimeConfigStore Dexie-backed store that persists last-known-good config entries. ### RuntimeUpdateAdapter Optional SSE/Observable wiring that signals when updates are available. --- ## Basic Usage ```ts import { RuntimeConfigLoader, RuntimeConfigStore } from '@sixbell-telco/sdk/utils/runtime-config'; const store = new RuntimeConfigStore<MyConfig>('my-runtime-config', 'my-app'); const loader = new RuntimeConfigLoader<MyConfig>('/assets/config.json', { fallbackData: { enabled: true }, resource: 'theme', store, schemaVersion: '1', }); const result = await loader.loadLatest(); const check = await loader.checkForUpdates(result.hash); if (check.updated) { // show a "Refresh" CTA } const refreshed = await loader.refresh(); ``` --- ## Mermaid: Load Flow ```mermaid sequenceDiagram participant Loader participant Store as RuntimeConfigStore participant Net as Network Loader->>Store: get(cacheKey) alt cached & schema ok Store-->>Loader: cached Loader-->>Loader: return cached else cache miss / schema mismatch Loader->>Net: fetch(configPath) Net-->>Loader: JSON Loader->>Store: set(cacheKey) Loader-->>Loader: return network end ``` --- ## Schema Versioning If cached JSON is not compatible with the current code, set a schema version: ```ts const loader = new RuntimeConfigLoader<MyConfig>(path, { fallbackData, resource: 'theme', store, schemaVersion: '2', }); ``` Add the version in JSON: ```json { "meta": { "schemaVersion": "2" } } ``` If the schema version mismatches, cached entries are removed and a fresh network fetch occurs. Hash requirements: - `meta.hash` is mandatory and used for update detection. - If `meta.hash` is missing, the loader treats the config as invalid and falls back. Cache keys also include the schema version when provided, so new schema versions always create a fresh cache namespace. --- ## RuntimeUpdateAdapter (SSE/Stream) ### SSE ````ts import { RuntimeUpdateAdapter } from '@sixbell-telco/sdk/utils/runtime-config'; const adapter = new RuntimeUpdateAdapter(async (event) => { if (event.resource !== 'theme' && event.resource !== 'both') return; const check = await loader.checkForUpdates(currentHash); if (check.updated) { // show CTA } }); adapter.connectSse('/api/updates', { resource: 'both', eventType: 'message', }); ### Update payload requirements Translation updates must include `lang` so clients can refresh the affected locale only. ```json { "resource": "translation", "version": "translation-update", "hash": "translations-1700000000000", "url": "/api/runtime/translation/config", "lang": "es" } ```` ```json { "resource": "theme", "version": "theme-update", "hash": "theme-1700000000000", "url": "/api/runtime/theme/config", "theme": "sixbell_telco" } ``` If `lang` is missing, the update is rejected to avoid stale caches. For theme updates, `theme` is required so clients can refresh the affected theme only. ```` ### Observable ```ts adapter.connectStream(update$); ```` ### Observable from a polling endpoint ```ts import { from, timer } from 'rxjs'; import { switchMap } from 'rxjs/operators'; const update$ = timer(0, 8000).pipe( switchMap(() => from(fetch('http://localhost:4000/api/runtime/updates/poll'))), switchMap((response) => from(response.json())), ); adapter.connectStream(update$); ``` --- ## RuntimeHttpClient Built-in fetch with retries and timeouts: ```ts const client = new RuntimeHttpClient({ retries: 2, retryDelayMs: 400, timeoutMs: 8000, }); const response = await client.fetch('/assets/config.json', { cache: 'no-store' }); ``` --- ## Resource Loader Example (Custom Resource) ```ts type FeatureFlags = { meta?: { hash?: string; schemaVersion?: string }; flags: Record<string, boolean>; }; const store = new RuntimeConfigStore<FeatureFlags>('flags-runtime-config', 'host'); const loader = new RuntimeConfigLoader<FeatureFlags>('/assets/flags.json', { fallbackData: { flags: {} }, resource: 'both', store, schemaVersion: '1', }); const result = await loader.loadLatest(); const flags = result.data.flags; ``` --- ## Notes - Fetch uses `cache: 'no-store'` to avoid stale responses. - Dexie cache is last-known-good only, not an aggressive cache. - When meta.hash is missing, a stable hash is computed from JSON. ## Related Utilities - `@sixbell-telco/sdk/utils/theme` - Runtime theme system - `@sixbell-telco/sdk/utils/translation` - Runtime translation system