Versie 0.2.0

This commit is contained in:
Atreides Assets committed 2026-10-29 11:57:29 +01:00
commit e77d8fd373
495 files changed
+81026

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
// Generated, do not edit. sha256:e34176fb1b8095153c2f85bcad4807088cce9195b029b64bb8721d0f3610d90d
export const HISTORY_CAPABILITIES = Object.freeze(['daily_history', 'history_point']);
const has = (p, cap) => Array.isArray(p.endpoints) && p.endpoints.some(e => e.capability === cap);
const covers = (p, symbol) => Array.isArray(p.coverage) && p.coverage.includes(symbol);
const deliversHistory = p => HISTORY_CAPABILITIES.some(cap => has(p, cap));
export function diagnoseSources(asset, { providers = [], historyChain = [], usage = {}, serviceCovers = false } = {}) {
if (!asset) return [];
const byKey = new Map(providers.map(p => [p.key, p]));
const candidates = providers.filter(p => !p.isSystem && !p.fixedRate && covers(p, asset.symbol) && deliversHistory(p));
if (!candidates.length) return serviceCovers ? [] : [{ severity: 'problem', code: 'noCoverage' }];
const active = candidates.filter(p => p.isActive);
if (!active.length) return serviceCovers ? [] : [{ severity: 'problem', code: 'allInactive', names: candidates.map(p => p.name) }];
const chosen = [], unusable = [];
for (const key of historyChain) {
const p = byKey.get(key);
if (!p) continue;
const usable = p.isActive && deliversHistory(p) && covers(p, asset.symbol);
(usable ? chosen : unusable).push(p);
}
const unique = list => [...new Map(list.map(p => [p.id, p])).values()];
if (!chosen.length) {
if (serviceCovers) return [];
const proposal = proposalFrom(active);
return [{ severity: 'problem', code: unusable.length ? 'choiceUnusable' : 'noChoice',
names: unique(unusable).map(p => p.name), proposal }];
}
const out = [];
const atLimit = unique(chosen).filter(p => p.callsPerMonth && (usage[p.id] ?? 0) >= p.callsPerMonth);
if (atLimit.length) {
out.push({ severity: atLimit.length === unique(chosen).length && !serviceCovers ? 'problem' : 'attention',
code: 'limitReached', names: atLimit.map(p => p.name) });
}
const off = unique(unusable).filter(p => !p.isActive);
if (off.length) out.push({ severity: 'attention', code: 'choiceInactive', names: off.map(p => p.name) });
return out;
}
function proposalFrom(active) {
for (const cap of HISTORY_CAPABILITIES) {
const p = active.find(x => has(x, cap));
if (p) return { providerKey: p.key, providerId: p.id, providerName: p.name, capability: 'history' };
}
return null;
}