// @flow import JsonRpcWs, { InvalidReply } from './jsonrpc-ws-ipc'; import { object, string, number, arrayOf } from 'validated/schema'; import { validate } from 'validated/object'; export type AccountData = {paid_until: string}; export type AccountNumber = string; export type Ip = string; export type Location = { latlong: Array, country: string, city: string, }; const LocationSchema = object({ latlong: arrayOf(number), country: string, city: string, }); export type BackendState = 'secured' | 'unsecured'; export interface IpcFacade { getAccountData(AccountNumber): Promise, setAccount(accountNumber: AccountNumber): Promise, setCountry(address: string): Promise, connect(): Promise, disconnect(): Promise, getIp(): Promise, getLocation(): Promise, getState(): Promise, registerStateListener((BackendState) => void): void, } export class RealIpc implements IpcFacade { _ipc: JsonRpcWs; constructor(connectionString: string) { this._ipc = new JsonRpcWs(connectionString); } getAccountData(accountNumber: AccountNumber): Promise { return this._ipc.send('get_account_data', accountNumber) .then(raw => { if (typeof raw === 'object' && raw && raw.paid_until) { return raw; } else { throw new InvalidReply(raw, 'Expected an object with paid_until'); } }); } setAccount(accountNumber: AccountNumber): Promise { return this._ipc.send('set_account', accountNumber) .then(this._ignoreResponse); } _ignoreResponse(_response: mixed): void { return; } setCountry(address: string): Promise { return this._ipc.send('set_country', address) .then(this._ignoreResponse); } connect(): Promise { return this._ipc.send('connect') .then(this._ignoreResponse); } disconnect(): Promise { return this._ipc.send('disconnect') .then(this._ignoreResponse); } getIp(): Promise { return this._ipc.send('get_ip') .then(raw => { if (typeof raw === 'string' && raw) { return raw; } else { throw new InvalidReply(raw, 'Expected a string'); } }); } getLocation(): Promise { return this._ipc.send('get_location') .then(raw => { try { return validate(LocationSchema, raw); } catch (e) { throw new InvalidReply(raw, e); } }); } getState(): Promise { return this._ipc.send('get_state') .then(raw => { return this._parseBackendState(raw); }); } _parseBackendState(raw: mixed): BackendState { if (raw === 'secured' || raw === 'unsecured') { return raw; } else { throw new InvalidReply(raw); } } registerStateListener(listener: (BackendState) => void) { this._ipc.on('new_state', (rawEvent) => { const parsedEvent : BackendState = this._parseBackendState(rawEvent); listener(parsedEvent); }); } }