Files
crates/api/src/rpc.ts
T
2022-09-11 21:16:33 +10:00

101 lines
2.8 KiB
TypeScript

import { EventEmitter } from 'node:events';
import { setTimeout } from 'timers/promises';
import assert from 'assert/strict';
import type Log from 'bunyan';
import type { Want, Offer, User } from '@prisma/client';
import { Pg } from './pg';
import { Status } from './offers';
function checkMsgType(msgType: RpcMessageType): msgType is RpcMessageType {
if (RpcMessageType[msgType]) {
return true;
}
return false;
}
// rpc is created per connection from the api
export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, offers) {
async function ping(): Promise<PongMessage> {
return [RpcMessageType.Pong, []];
}
async function offerStatusSet(params: OfferStatusSetParams): Promise<OffersMessage> {
log.info(params);
const { id, status } = params;
assert(id, 'no id supplied');
assert(Status[status], 'unknown status');
const offer = await offers.statusSet(user, id, status);
return [RpcMessageType.Offers, []]
}
async function receive(message: any): Promise<RpcMessage> {
const [msgType, params] = message;
if (msgType !== RpcMessageType.Ping) log.info({ msgType, params }, 'rpc message');
// // this sucks but can't figure out how to convince typescript to agree yet
if (checkMsgType(msgType)) {
switch (msgType) {
case RpcMessageType.Ping:
return ping();
case RpcMessageType.OfferStatusSet:
return offerStatusSet(params);
default:
throw new Error(`Message type ${msgType} is known but unhandled`);
}
} else {
throw new Error(`Unknown message type ${msgType}`);
}
throw new Error(`Invalid parameters for message type ${msgType}: ${JSON.stringify(message)}`);
}
function send(msg: RpcMessage) {
ws.send(JSON.stringify(msg, (key, value) =>
typeof value === 'bigint'
? value.toString()
: value // return everything else unchanged
))
}
return {
receive,
send,
}
}
export enum RpcMessageType {
Ping = 'Ping',
Pong = 'Pong',
Bundles = 'Bundles',
Offers = 'Offers',
List = 'List',
Error = 'Error',
OfferStatusSet = 'OfferStatusSet',
}
type ErrorMessage = [RpcMessageType.Error, string];
type PongMessage = [RpcMessageType.Pong, []];
type PingMessage = [RpcMessageType.Ping, []];
type OffersMessage = [RpcMessageType.Offers, Offer[]];
type OfferStatusSetMessage = [RpcMessageType.OfferStatusSet, Offer[]];
export type RpcMessage =
PingMessage |
PongMessage |
OffersMessage |
OfferStatusSetMessage |
ErrorMessage;
type OfferStatusSetParams = {
id: UUID,
status: Status,
};