// Transport shim used by S4, not a second product CLI. Input and proof never carry service tokens. import { randomBytes } from 'node:crypto'; import { spawnSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; import { readFileSync } from 'node:fs'; import { Client, NOT_SENT_EXIT } from './client.mjs'; import { readProcess } from './human.mjs'; const file = fileURLToPath(import.meta.url); if (!process.env.MOSAIC_BUS_CLI_NONCE) { const child = spawnSync(process.execPath, [file, ...process.argv.slice(2)], { stdio: 'inherit', env: { ...process.env, MOSAIC_BUS_CLI_NONCE: randomBytes(32).toString('hex') }, }); process.exit(child.status ?? 2); } try { const request = JSON.parse(readFileSync(0, 'utf8')); if ( !request || typeof request !== 'object' || Object.keys(request).some((k) => !['business', 'verb', 'args'].includes(k)) ) throw Error(); const me = readProcess(process.pid); const client = new Client({ path: process.argv[2], // Row 254: library.sync fetches for up to 100 s and the server holds its socket for 120 s, // so wait past that for the server's own answer. Row 236: the grants verbs call Gitea and get the // same wait. Every other verb keeps the 5 s default. timeout: request.verb === 'library.sync' || request.verb.startsWith('grants.') ? 130_000 : undefined, human: { business: request.business, pid: me.pid, startTime: me.startTime, nonce: process.env.MOSAIC_BUS_CLI_NONCE, }, }); const result = await client.call(request.verb, request.args ?? {}); process.stdout.write(JSON.stringify(result) + '\n'); } catch (e) { process.stderr.write((/^[a-z-]{1,64}$/.test(e.code ?? '') ? e.code : 'invalid-request') + '\n'); // E2E6 fix 6: a request that never left (no socket, or the connect refused) keeps its code and // exits NOT_SENT_EXIT, so `mosaic` can say the bus is not running. Every other failure exits 2. process.exitCode = e?.notSent === true ? NOT_SENT_EXIT : 2; }