hivecast-sdk/scripts/doctor.mjs

120 lines
4.2 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
import { spawnSync } from 'node:child_process';
import { existsSync } from 'node:fs';
import { resolveNatsServer, readNatsServerVersion } from './lib/nats-server-tool.mjs';
const json = process.argv.includes('--json');
const mode = process.argv.includes('--standalone')
? 'standalone'
: process.argv.includes('--hivecast')
? 'hivecast'
: process.argv.includes('--all')
? 'all'
: 'base';
function check(name, ok, details = {}) {
return { name, ok, ...details };
}
function run(command, args) {
const result = spawnSync(command, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
if (result.error) return { ok: false, error: result.error.message };
if (result.status !== 0) return { ok: false, error: `${command} exited ${result.status}`, stderr: result.stderr.trim() };
return { ok: true, stdout: result.stdout.trim(), stderr: result.stderr.trim() };
}
function major(version) {
return Number(String(version).split('.')[0] ?? 0);
}
function findBrowser() {
if (process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE && existsSync(process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE)) {
return { path: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, source: 'PLAYWRIGHT_CHROMIUM_EXECUTABLE' };
}
for (const path of ['/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser']) {
if (existsSync(path)) return { path, source: 'system' };
}
return null;
}
const checks = [];
const nodeVersion = process.versions.node;
checks.push(check('node', major(nodeVersion) >= 22, {
version: nodeVersion,
required: '22+',
fix: 'Install Node.js 22 or newer.',
}));
const pnpm = run('pnpm', ['--version']);
checks.push(check('pnpm', pnpm.ok && major(pnpm.stdout) >= 10, {
version: pnpm.ok ? pnpm.stdout : null,
required: '10+',
fix: 'Install pnpm 10: corepack enable && corepack prepare pnpm@10.29.3 --activate',
error: pnpm.ok ? undefined : pnpm.error,
}));
let nats = null;
try {
nats = resolveNatsServer();
checks.push(check('nats-server', Boolean(nats), {
path: nats?.path ?? null,
source: nats?.source ?? null,
version: nats ? readNatsServerVersion(nats.path) : null,
requiredFor: 'pnpm demo:standalone',
fix: 'Run pnpm setup:nats, or install NATS Server and put nats-server on PATH.',
}));
} catch (error) {
checks.push(check('nats-server', false, {
error: error instanceof Error ? error.message : String(error),
requiredFor: 'pnpm demo:standalone',
fix: 'Run pnpm setup:nats, or set MATRIX_NATS_SERVER to the nats-server binary.',
}));
}
const browser = findBrowser();
checks.push(check('chromium', Boolean(browser), {
path: browser?.path ?? null,
source: browser?.source ?? null,
requiredFor: 'live browser proof in pnpm prove:fresh-samples',
fix: 'Run pnpm setup:browser, or set PLAYWRIGHT_CHROMIUM_EXECUTABLE to Chrome/Chromium.',
}));
const hivecastEnv = {
MATRIX_CLOUD: Boolean(process.env.MATRIX_CLOUD),
MATRIX_SPACE: Boolean(process.env.MATRIX_SPACE),
MATRIX_API_KEY: Boolean(process.env.MATRIX_API_KEY),
};
checks.push(check('hivecast-env', Object.values(hivecastEnv).every(Boolean), {
present: hivecastEnv,
requiredFor: 'live HiveCast server/browser samples in pnpm prove:fresh-samples',
fix: 'Create a HiveCast API key, then export MATRIX_CLOUD, MATRIX_SPACE, and MATRIX_API_KEY.',
}));
const requiredByMode = {
base: ['node', 'pnpm'],
standalone: ['node', 'pnpm', 'nats-server'],
hivecast: ['node', 'pnpm', 'chromium', 'hivecast-env'],
all: ['node', 'pnpm', 'nats-server', 'chromium', 'hivecast-env'],
};
const requiredFailures = checks.filter((item) => requiredByMode[mode].includes(item.name) && !item.ok);
const proof = {
ok: requiredFailures.length === 0,
mode,
checks,
};
if (json) {
console.log(JSON.stringify(proof, null, 2));
} else {
console.log(`Matrix SDK doctor mode: ${mode}`);
for (const item of checks) {
const required = requiredByMode[mode].includes(item.name);
const mark = item.ok ? 'ok' : required ? 'missing' : 'optional-missing';
console.log(`${mark} ${item.name}${item.version ? ` (${item.version})` : ''}${item.path ? ` at ${item.path}` : ''}`);
if (!item.ok) console.log(` fix: ${item.fix}`);
}
}
process.exit(proof.ok ? 0 : 1);