@vigilbase/cli
Version:
Vigilbase CLI — security scanners, agent tools, and Vigilbase One from the terminal.
67 lines (66 loc) • 3.84 kB
JavaScript
import { z } from 'zod';
const record = z.record(z.string(), z.unknown());
const rows = z.array(record);
const object = (shape) => z.object(shape).passthrough();
const data = (schema) => object({ data: schema });
const responseSchemas = {
'customers list': data(rows), 'customers ls': data(rows),
'customers show': data(record), 'customers summary': data(record),
'customers services': data(rows), 'customers endpoints': data(rows),
'customers contacts': data(object({ contacts: rows })),
'customers organization': data(object({ hasOrganization: z.boolean() })),
'customers watchdog-targets': data(object({ targets: rows })),
'customers watchdog-scans': data(object({ scans: rows, total: z.number() })),
'customers reports': data(object({ reports: rows })), 'customers report': data(object({ report: record })),
'customers investigations': data(object({ investigations: rows, nextCursor: z.string().nullable() })),
'customers investigation': data(record), 'customers contracts': data(rows), 'customers billing': data(record),
'customers invoices': object({ invoices: rows }), 'customers subscriptions': object({ subscriptions: rows }),
'customers projects': data(object({ projects: rows })),
'orgs list': object({ organizations: rows }), 'orgs ls': object({ organizations: rows }),
'orgs show': data(record), 'orgs members': z.union([object({ members: rows }), data(rows)]),
'orgs roles': object({ roles: rows, permissionGroups: rows, permissionLabels: record }),
'monitoring health': data(object({ metrics_backend: record, alerting: record })),
'monitoring probes': data(object({ probes: rows })), 'monitoring probe-health': data(object({ probes: rows })),
'monitoring metrics': data(object({ metrics: rows })), 'monitoring targets': data(object({ targets: rows })),
'monitoring status': data(object({ aggregate: record, targets: rows })),
'monitoring history': data(object({ aggregatedUptime: rows, aggregatedLatency: rows })),
'support tickets': data(object({ issues: rows, total: z.number() })),
};
/** Only command-selected One paths reach the bearer-authenticated transport. */
export async function executeOneOperation(client, operation) {
const query = new URLSearchParams();
for (const [key, value] of Object.entries(operation.query ?? {})) {
if (value !== undefined)
query.set(key, String(value));
}
const suffix = query.size ? `?${query.toString()}` : '';
const payload = await client.requestJson(`${operation.path}${suffix}`);
const parsed = z.record(z.string(), z.unknown()).parse(payload);
if (parsed.success === false || parsed.ok === false) {
throw new Error('One API reported an unsuccessful operation.');
}
const schema = responseSchemas[operation.label];
if (!schema || !schema.safeParse(parsed).success) {
throw new Error(`Invalid One API response for ${operation.label}.`);
}
return parsed;
}
function safeText(value) {
return String(value).replace(/[\u0000-\u001f\u007f-\u009f]/g, ' ');
}
/** Render all fields, including pagination and degraded-health metadata. */
export function formatOnePayload(value, indent = '') {
if (value === null || typeof value !== 'object')
return [`${indent}${safeText(value)}`];
const entries = Array.isArray(value)
? value.map((item, index) => [String(index + 1), item])
: Object.entries(value);
if (entries.length === 0)
return [`${indent}${Array.isArray(value) ? '(none)' : '(empty)'}`];
return entries.flatMap(([key, item]) => {
if (item !== null && typeof item === 'object') {
return [`${indent}${safeText(key)}:`, ...formatOnePayload(item, `${indent} `)];
}
return [`${indent}${safeText(key)}: ${safeText(item)}`];
});
}