import {BaseAction} from "./BaseAction"; import {SyncedState} from "../state/SyncedState"; import {AppAction} from "./AppAction"; import {SendableAction} from "./ClientAction"; export const SERVER_HELLO = "SERVER_HELLO" /** Sent in response to the client's ClientHelloAction when the client has been accepted. */ export interface ServerHelloCommand extends BaseAction { readonly type: typeof SERVER_HELLO /** The protocol version the server is running on. */ readonly version: number /** The current state of the server as of when the client connected. */ readonly state: SyncedState } export function isServerHelloCommand(action: AppAction): action is ServerHelloCommand { return action.type === SERVER_HELLO } export const SERVER_GOODBYE = "SERVER_GOODBYE" /** Synthesized out of the close message when the server closes the connection. */ export interface ServerGoodbyeAction extends BaseAction { readonly type: typeof SERVER_GOODBYE /** The exit code sent with the close message by the server. */ readonly code: number /** The text of the server's goodbye message. */ readonly reason: string /** The current time when this close message was received. */ readonly currentTime: Date } export function isServerGoodbyeAction(action: AppAction): action is ServerGoodbyeAction { return action.type === SERVER_GOODBYE } export const SERVER_REFRESH = "SERVER_REFRESH" /** Sent in response to the client's ClientRefreshCommand. */ export interface ServerRefreshCommand extends BaseAction { readonly type: typeof SERVER_REFRESH /** The current state of the server as of when the client's refresh request was processed. */ readonly state: SyncedState } export function isServerRefreshCommand(action: AppAction): action is ServerRefreshCommand { return action.type === SERVER_REFRESH } export const SERVER_OK = "SERVER_OK" /** Sent in response to the client's ClientActCommand, if it succeeds and is applied to the server map. */ export interface ServerOKCommand extends BaseAction { readonly type: typeof SERVER_OK /** * The IDs of the successful actions. * These will always be sent in sequential order - the order in which the server received and applied them. * This allows the client to apply that set of actions to its server-state copy and then refresh its local copy. */ readonly ids: readonly number[] } export function isServerOKCommand(action: AppAction): action is ServerOKCommand { return action.type === SERVER_OK } export const SERVER_FAILED = "SERVER_FAILED" /** Sent in response to the client's ClientActCommand, if it fails and has not been applied to the server map. */ export interface ServerFailedCommand extends BaseAction { readonly type: typeof SERVER_FAILED /** The IDs of the failed actions, all of which failed with the same error. */ readonly ids: readonly number[] /** The error the above actions failed with. */ readonly error: string } export function isServerFailedCommand(action: AppAction): action is ServerFailedCommand { return action.type === SERVER_FAILED } export enum SocketState { CONNECTING = "CONNECTING", OPEN = "OPEN", } export const SERVER_SOCKET_STARTUP = "SERVER_SOCKET_STARTUP" /** Synthesized when the ws begins connecting, i.e., enters the Connecting or Open states.. */ export interface ServerSocketStartupAction extends BaseAction { readonly type: typeof SERVER_SOCKET_STARTUP readonly state: SocketState } export function isServerSocketStartupAction(action: AppAction): action is ServerSocketStartupAction { return action.type === SERVER_SOCKET_STARTUP } export const SERVER_ACT = "SERVER_ACT" /** Sent by the server when another client has performed an action. Never sent for the client's own actions. */ export interface ServerActCommand extends BaseAction { readonly type: typeof SERVER_ACT readonly actions: readonly SyncableAction[] } export function isServerActCommand(action: AppAction): action is ServerActCommand { return action.type === SERVER_ACT } export const SERVER_MALFORMED = "SERVER_MALFORMED" /** Synthesized when the client can't understand a command the server sent, or when an error event appears on the ws. */ export interface ServerMalformedAction extends BaseAction { readonly type: typeof SERVER_MALFORMED, readonly error: Error | null, } export function isServerMalformedAction(action: AppAction): action is ServerMalformedAction { return action.type === SERVER_MALFORMED } export type SyncableAction = SendableAction export type ServerCommand = ServerHelloCommand | ServerRefreshCommand | ServerOKCommand | ServerFailedCommand | ServerActCommand export function isServerCommand(action: AppAction): action is ServerCommand { return isServerHelloCommand(action) || isServerRefreshCommand(action) || isServerOKCommand(action) || isServerFailedCommand(action) || isServerActCommand(action) } export type ServerAction = ServerCommand | ServerSocketStartupAction | ServerMalformedAction | ServerGoodbyeAction export function isServerAction(action: AppAction): action is ServerAction { return isServerCommand(action) || isServerSocketStartupAction(action) || isServerMalformedAction(action) || isServerGoodbyeAction(action) }