import express from 'express'; import bodyParser from 'body-parser'; import { connectedInstances } from './connected-instances.js'; /** * REST request handler for Dispatcher Server. It handles 2 endpoints: * * - `POST /json-rpc`: for blocking call from Unified Client to Adapter * - `POST /auth-callback`: for auth callbacks from Adapter to Unified Client */ export const restHandler = express(); restHandler.use(bodyParser.json()); restHandler.post('/json-rpc', (req, res) => { redirectBlockingCallToAdapter(req.body).then((jsonRPCResponse) => { console.log('Blocking response resolved with: %s', JSON.stringify(jsonRPCResponse)); res.json(jsonRPCResponse); }); }); restHandler.post('/auth-callback', (req, res) => { redirectAuthCallbackToUnifiedClient(req.body).then((jsonRPCResponse) => { console.log('Auth callback resolved with: %s', JSON.stringify(jsonRPCResponse)); res.json(jsonRPCResponse); }); }); /** * Dictionary that is used by Dispatcher REST handler. JSON-RPC requests that comes from REST endpoints, * add JSON-RPC ID with the promise resolver that will be resolved once associated JSON-RPC response comes through WebSocket. */ const jsonRpcIdToResponseResolver: Record void> = {}; /** * @param jsonRpcId JSON-RPC id for the JSON-RPC response * * @return `true` if we have REST response resolver waiting for Response with `jsonRpcId` */ export const shouldBeIntercepted = (jsonRpcId: string) => { return Boolean(jsonRpcIdToResponseResolver[jsonRpcId]); }; /** * @param jsonRpcResponse JSON-RPC response * * resolve JSON-RPC Response using resolver from `jsonRpcIdToResponseResolver` */ export const intercept = (jsonRpcResponse: any) => { const resolver = jsonRpcIdToResponseResolver[jsonRpcResponse.id]; delete jsonRpcIdToResponseResolver[jsonRpcResponse.id]; resolver(jsonRpcResponse); }; /** * Redirects JSON-RPC request to the Adapter and waits for response * * @returns Promise that resolves when message from adapter comes back */ const redirectBlockingCallToAdapter = (jsonRpc: any) => { console.log('Received blocking request: %s', JSON.stringify(jsonRpc)); return new Promise((resolve) => { connectedInstances.adapter?.send(JSON.stringify(jsonRpc)); jsonRpcIdToResponseResolver[jsonRpc.id] = resolve; }); }; /** * Redirects JSON-RPC request to the Unified Client and waits for response * * @returns Promise that resolves when JSON-RPC response from the Adapter comes back */ const redirectAuthCallbackToUnifiedClient = (jsonRpc: any) => { console.log('Received blocking auth callback request: %s', JSON.stringify(jsonRpc)); return new Promise((resolve) => { connectedInstances.unifiedAblyClient?.send(JSON.stringify(jsonRpc)); jsonRpcIdToResponseResolver[jsonRpc.id] = resolve; }); };