Versie 0.2.0
This commit is contained in:
commit
e77d8fd373
495 files changed
+81026
No files matched your search
@@ -0,0 +1,200 @@
|
||||
// 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;
|
||||
}
|
||||
Reference in new issue
Block a user