// Generated, do not edit. sha256:eca3b25957829a0a34656d92265e558efc50996dc58250a690f2dba7d2ab107a import { AppError, errorPayload } from '../shared/app-error.js'; import { dataModules } from './registers.mjs'; import * as accountsMerge from './data/accounts-merge.js'; import * as accounts from './data/accounts.js'; import * as aiAudit from './data/ai-audit.js'; import * as aiProposals from './data/ai-proposals.js'; import * as apiMetrics from './data/api-metrics.js'; import * as assetNotes from './data/asset-notes.js'; import * as assets from './data/assets.js'; import * as bus from './data/bus.js'; import * as commands from './data/commands.js'; import * as connections from './data/connections.js'; import * as counts from './data/counts.js'; import * as dashboard from './data/dashboard.js'; import * as events from './data/events.js'; import * as hygiene from './data/hygiene.js'; import * as integrationLog from './data/integration-log.js'; import * as interestCredits from './data/interest-credits.js'; import * as interestSchedules from './data/interest-schedules.js'; import * as labels from './data/labels.js'; import * as licenseBuyer from './data/license-buyer.js'; import * as licenseInstall from './data/license-install.js'; import * as licenseStatus from './data/license-status.js'; import * as support from './data/support.js'; import * as market from './data/market.js'; import * as metals from './data/metals.js'; import * as notifications from './data/notifications.js'; import * as onboarding from './data/onboarding.js'; import * as positions from './data/positions.js'; import * as preferences from './data/preferences.js'; import * as priceHistory from './data/price-history.js'; import * as priceSource from './data/price-source.js'; import * as proposals from './data/proposals.js'; import * as providers from './data/providers.js'; import * as reservations from './data/reservations.js'; import * as scanLogs from './data/scan-logs.js'; import * as structure from './data/structure.js'; import * as tableViewer from './data/table-viewer.js'; import * as txLinks from './data/tx-links.js'; import * as valuations from './data/valuations.js'; import * as walletAddresses from './data/wallet-addresses.js'; import * as walletSources from './data/wallet-sources.js'; import * as walletTxs from './data/wallet-txs.js'; import { flushChanges } from './data/bus.js'; const MODULES = Object.freeze({ 'accounts': accounts, 'accounts-merge': accountsMerge, 'ai-audit': aiAudit, 'ai-proposals': aiProposals, 'api-metrics': apiMetrics, 'asset-notes': assetNotes, 'assets': assets, 'bus': bus, 'commands': commands, 'connections': connections, 'counts': counts, 'dashboard': dashboard, 'events': events, 'hygiene': hygiene, 'integration-log': integrationLog, 'interest-credits': interestCredits, 'interest-schedules': interestSchedules, 'labels': labels, 'license-buyer': licenseBuyer, 'license-install': licenseInstall, 'license-status': licenseStatus, 'market': market, 'metals': metals, 'notifications': notifications, 'onboarding': onboarding, 'positions': positions, 'preferences': preferences, 'price-history': priceHistory, 'price-source': priceSource, 'proposals': proposals, 'providers': providers, 'reservations': reservations, 'scan-logs': scanLogs, 'structure': structure, 'support': support, 'table-viewer': tableViewer, 'tx-links': txLinks, 'valuations': valuations, 'wallet-addresses': walletAddresses, 'wallet-sources': walletSources, 'wallet-txs': walletTxs, }); const INTERN = Object.freeze({ 'bus': ['flushChanges', 'pruneChanges'], 'integration-log': ['recordIntegrationCall', 'countServiceCall'], 'interest-schedules': ['realizedForSchedule'], 'preferences': ['forgetPrefRow', 'tableViewCfg'], 'providers': ['emitProvidersChanged'], 'tx-links': ['linkProposalTxSoft'], 'wallet-sources': ['purgeWalletSourceSecret', 'assertSourceMatchesAccount'], }); function modules() { const extra = dataModules.list(); const dubbel = extra.find(m => Object.hasOwn(MODULES, m.id)); if (dubbel) throw new Error(`data module '${dubbel.id}' is registered and also a core module`); return { all: { ...MODULES, ...Object.fromEntries(extra.map(m => [m.id, m.module])) }, intern: { ...INTERN, ...Object.fromEntries(extra.filter(m => m.intern).map(m => [m.id, m.intern])) }, }; } function oppervlakVan(module, internals = []) { const intern = new Set(internals); return Object.freeze(Object.entries(module) .filter(([naam, waarde]) => typeof waarde === 'function' && !intern.has(naam)) .map(([naam]) => naam) .sort()); } let cache = { count: -1, surface: null, all: null }; function current() { const count = dataModules.list().length; if (cache.count !== count) { const { all, intern } = modules(); const surface = Object.freeze(Object.fromEntries( Object.keys(all).sort().map(mod => [mod, oppervlakVan(all[mod], intern[mod])]))); cache = { count, surface, all }; } return cache; } export const surface = () => current().surface; export function isAllowed(mod, fn) { const s = surface(); return Object.hasOwn(s, mod) && s[mod].includes(fn); } export function codeer(waarde) { if (waarde instanceof Map) return { __t: 'Map', v: [...waarde].map(([k, v]) => [k, codeer(v)]) }; if (waarde instanceof Set) return { __t: 'Set', v: [...waarde].map(codeer) }; if (Array.isArray(waarde)) return waarde.map(codeer); if (waarde && typeof waarde === 'object' && Object.getPrototypeOf(waarde) === Object.prototype) { return Object.fromEntries(Object.entries(waarde).map(([k, v]) => [k, codeer(v)])); } return waarde; } function sendJson(res, status, obj) { res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'X-Content-Type-Options': 'nosniff' }); res.end(JSON.stringify(obj)); } const MAX_BODY = 5 * 1024 * 1024; function readJsonBody(req) { return new Promise((resolve, reject) => { let len = 0; const chunks = []; req.on('data', c => { len += c.length; if (len > MAX_BODY) { req.destroy(); reject(new AppError('common.requestTooLarge', null, 'Request too large.')); } else chunks.push(c); }); req.on('end', () => { const raw = Buffer.concat(chunks).toString('utf-8'); if (!raw) return resolve({}); try { resolve(JSON.parse(raw)); } catch { reject(new Error('Invalid JSON.')); } }); req.on('error', reject); }); } export async function handleDataApi(req, res, url) { const pad = url.split('?')[0]; if (!pad.startsWith('/api/data/')) return false; if (req.method !== 'POST') { sendJson(res, 405, { error: 'Alleen POST.' }); return true; } const delen = pad.slice('/api/data/'.length).split('/'); if (delen.length !== 2) { sendJson(res, 404, { error: 'Unknown endpoint.' }); return true; } const [mod, fn] = delen; if (!isAllowed(mod, fn)) { sendJson(res, 404, { error: `Unknown data-layer function '${mod}/${fn}'.` }); return true; } let args; try { const body = await readJsonBody(req); args = Array.isArray(body.args) ? body.args : []; } catch (e) { sendJson(res, 400, errorPayload(e)); return true; } try { flushChanges(); const result = await current().all[mod][fn](...args); sendJson(res, 200, { result: codeer(result === undefined ? null : result), changes: flushChanges() }); } catch (e) { sendJson(res, 400, errorPayload(e)); } return true; }