#!/usr/bin/env node /** * Build BridgeSwarm hrpc spec: writes spec/hyperschema/ and spec/hrpc/ * (schema + generated RPC index.js, messages.js, hrpc.json). * Run from repo root. Requires: hrpc, hyperschema (root devDependencies). */ const path = require('path'); const fs = require('fs'); const REPO_ROOT = path.join(__dirname, '..'); const SCHEMA_DIR = path.join(REPO_ROOT, 'spec', 'hyperschema'); const HRPC_DIR = path.join(REPO_ROOT, 'spec', 'hrpc'); // Ensure output dirs exist (Hyperschema.from works with existing or empty dir) fs.mkdirSync(SCHEMA_DIR, { recursive: true }); fs.mkdirSync(HRPC_DIR, { recursive: true }); const Hyperschema = require('hyperschema'); const HRPCBuilder = require('hrpc'); // --- Schema: bridgeswarm namespace --- const schema = Hyperschema.from(SCHEMA_DIR); const ns = schema.namespace('bridgeswarm'); // Unary: ping ns.register({ name: 'ping-request', fields: [{ name: 'value', type: 'string' }] }); ns.register({ name: 'ping-response', fields: [{ name: 'pong', type: 'string' }] }); // Request-stream -> single response (client streams, server replies once) ns.register({ name: 'stream-request-chunk', fields: [{ name: 'n', type: 'uint' }, { name: 'label', type: 'string' }] }); ns.register({ name: 'stream-sum-response', fields: [{ name: 'sum', type: 'uint' }, { name: 'count', type: 'uint' }] }); // Single request -> response-stream (client sends once, server streams back) ns.register({ name: 'fetch-request', fields: [{ name: 'count', type: 'uint' }] }); ns.register({ name: 'fetch-chunk', fields: [{ name: 'i', type: 'uint' }, { name: 'data', type: 'string' }] }); // Duplex (request-stream + response-stream) ns.register({ name: 'duplex-in', fields: [{ name: 'x', type: 'uint' }, { name: 'y', type: 'string' }] }); ns.register({ name: 'duplex-out', fields: [{ name: 'result', type: 'string' }, { name: 'n', type: 'uint' }] }); // Send-only (no response) ns.register({ name: 'notify-request', fields: [{ name: 'event', type: 'string' }, { name: 'payload', type: 'uint' }] }); Hyperschema.toDisk(schema); // --- HRPC: register commands --- const builder = HRPCBuilder.from(SCHEMA_DIR, HRPC_DIR); const rpcNs = builder.namespace('bridgeswarm'); rpcNs.register({ name: 'ping', request: { name: '@bridgeswarm/ping-request', stream: false }, response: { name: '@bridgeswarm/ping-response', stream: false } }); rpcNs.register({ name: 'streamSum', request: { name: '@bridgeswarm/stream-request-chunk', stream: true }, response: { name: '@bridgeswarm/stream-sum-response', stream: false } }); rpcNs.register({ name: 'fetchStream', request: { name: '@bridgeswarm/fetch-request', stream: false }, response: { name: '@bridgeswarm/fetch-chunk', stream: true } }); rpcNs.register({ name: 'duplex', request: { name: '@bridgeswarm/duplex-in', stream: true }, response: { name: '@bridgeswarm/duplex-out', stream: true } }); rpcNs.register({ name: 'notify', request: { name: '@bridgeswarm/notify-request', send: true } }); HRPCBuilder.toDisk(builder); // Mirror into native-host so bare-pack / distributable builds can require('./spec/hrpc') const HOST_SPEC = path.join(REPO_ROOT, 'native-host', 'spec'); function copyDir(src, dest) { fs.mkdirSync(dest, { recursive: true }); for (const name of fs.readdirSync(src)) { const from = path.join(src, name); const to = path.join(dest, name); if (fs.statSync(from).isDirectory()) copyDir(from, to); else fs.copyFileSync(from, to); } } copyDir(SCHEMA_DIR, path.join(HOST_SPEC, 'hyperschema')); copyDir(HRPC_DIR, path.join(HOST_SPEC, 'hrpc')); console.log('hrpc spec built: spec/hyperschema/, spec/hrpc/, native-host/spec/');