@confkit/azure
Version:
[](https://www.npmjs.com/package/@confkit/azure) [](https://github.com/alexdotpink/confkit/blob/main/LICENSE) 
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { DefaultAzureCredential, type TokenCredential } from '@azure/identity';\nimport { SecretClient } from '@azure/keyvault-secrets';\n\nexport type AzureSecretsOptions = {\n /** e.g. https://my-vault.vault.azure.net */\n vaultUrl: string;\n credential?: TokenCredential;\n /** Filter secret names by prefix */\n namePrefix?: string;\n /** Map secret name to config key */\n mapNameToKey?: (name: string) => string;\n ttlMs?: number;\n jitter?: number;\n background?: boolean;\n onRotate?: (key: string, value: string, meta: { version?: string }) => void;\n /** Max concurrent getSecret calls */\n maxConcurrency?: number;\n};\n\ntype Source = () => Promise<Record<string, string>> | Record<string, string>;\n\nfunction defaultKeyFromName(name: string) {\n return name.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase();\n}\n\nexport function azureKeyVaultSource(opts: AzureSecretsOptions): Source {\n const cred = opts.credential ?? new DefaultAzureCredential();\n const client = new SecretClient(opts.vaultUrl, cred);\n const mapNameToKey = opts.mapNameToKey ?? defaultKeyFromName;\n let cache: { value: Record<string, string>; expires: number; versions: Record<string, string | undefined> } | undefined;\n let timer: NodeJS.Timeout | undefined;\n\n async function fetchNow() {\n const values: Record<string, string> = {};\n const versions: Record<string, string | undefined> = {};\n const names: string[] = [];\n for await (const prop of client.listPropertiesOfSecrets().byPage({ maxPageSize: 100 })) {\n for (const p of prop) {\n const name = p.name;\n if (opts.namePrefix && !name.startsWith(opts.namePrefix)) continue;\n names.push(name);\n }\n }\n const maxConc = Math.max(1, Math.min(opts.maxConcurrency ?? 8, 24));\n let i = 0;\n await Promise.all(\n Array.from({ length: maxConc }).map(async () => {\n while (i < names.length) {\n const idx = i++;\n const name = names[idx];\n const key = mapNameToKey(name);\n try {\n const s = await client.getSecret(name);\n const val = s.value ?? '';\n values[key] = val;\n versions[key] = s.properties.version;\n } catch {\n // ignore\n }\n }\n })\n );\n return { values, versions };\n }\n\n async function refresh() {\n const ttl = opts.ttlMs ?? 5 * 60 * 1000;\n const jitter = opts.jitter ?? 0.1;\n const now = Date.now();\n const { values: nextValues, versions: nextVersions } = await fetchNow();\n if (cache) {\n const keys = new Set([...Object.keys(cache.value), ...Object.keys(nextValues)]);\n for (const k of keys) {\n const prevV = cache.value[k];\n const curV = nextValues[k];\n const prevVer = cache.versions[k];\n const curVer = nextVersions[k];\n if ((prevV !== curV || prevVer !== curVer) && curV !== undefined && opts.onRotate) {\n opts.onRotate(k, curV, { version: curVer });\n }\n }\n }\n const expires = now + Math.floor(ttl * (1 - jitter + Math.random() * jitter * 2));\n cache = { value: nextValues, expires, versions: nextVersions };\n }\n\n function schedule() {\n if (!opts.background) return;\n const now = Date.now();\n const ms = cache ? Math.max(0, cache.expires - now) : (opts.ttlMs ?? 5 * 60 * 1000);\n if (timer) clearTimeout(timer);\n timer = setTimeout(async () => { try { await refresh(); } finally { schedule(); } }, ms);\n }\n\n return async () => {\n const now = Date.now();\n if (!cache || now >= cache.expires) {\n await refresh();\n schedule();\n }\n return cache!.value;\n };\n}\n\nexport default azureKeyVaultSource;\n\n"],"mappings":"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","names":[]}