refactor web socket layer

This commit is contained in:
seavor 2026-04-14 14:39:46 -05:00
parent 19f5eefdd2
commit 141f0e59f5
124 changed files with 927 additions and 853 deletions

View file

@ -3,9 +3,6 @@ vi.mock('websocket', () => ({
connect: vi.fn(), connect: vi.fn(),
disconnect: vi.fn(), disconnect: vi.fn(),
}, },
webClient: {
connectionAttemptMade: false,
},
})); }));
vi.mock('generated/proto/serverinfo_user_pb', () => ({ vi.mock('generated/proto/serverinfo_user_pb', () => ({
@ -15,7 +12,7 @@ vi.mock('generated/proto/serverinfo_user_pb', () => ({
})); }));
import { AuthenticationService } from './AuthenticationService'; import { AuthenticationService } from './AuthenticationService';
import { SessionCommands, webClient } from 'websocket'; import { SessionCommands } from 'websocket';
import { StatusEnum, WebSocketConnectOptions, WebSocketConnectReason } from 'types'; import { StatusEnum, WebSocketConnectOptions, WebSocketConnectReason } from 'types';
const testOptions: WebSocketConnectOptions = { host: 'localhost', port: '4748', userName: 'user', password: 'pw' }; const testOptions: WebSocketConnectOptions = { host: 'localhost', port: '4748', userName: 'user', password: 'pw' };
@ -124,16 +121,4 @@ describe('AuthenticationService', () => {
expect(AuthenticationService.isAdmin()).toBeUndefined(); expect(AuthenticationService.isAdmin()).toBeUndefined();
}); });
}); });
describe('connectionAttemptMade', () => {
it('returns webClient.connectionAttemptMade when false', () => {
(webClient as any).connectionAttemptMade = false;
expect(AuthenticationService.connectionAttemptMade()).toBe(false);
});
it('returns webClient.connectionAttemptMade when true', () => {
(webClient as any).connectionAttemptMade = true;
expect(AuthenticationService.connectionAttemptMade()).toBe(true);
});
});
}); });

View file

@ -1,5 +1,5 @@
import { StatusEnum, User, WebSocketConnectReason, WebSocketConnectOptions } from 'types'; import { StatusEnum, User, WebSocketConnectReason, WebSocketConnectOptions } from 'types';
import { SessionCommands, webClient } from 'websocket'; import { SessionCommands } from 'websocket';
import { ServerInfo_User_UserLevelFlag } from 'generated/proto/serverinfo_user_pb'; import { ServerInfo_User_UserLevelFlag } from 'generated/proto/serverinfo_user_pb';
export class AuthenticationService { export class AuthenticationService {
@ -48,8 +48,4 @@ export class AuthenticationService {
static isAdmin() { static isAdmin() {
} }
static connectionAttemptMade() {
return webClient.connectionAttemptMade;
}
} }

View file

@ -5,11 +5,12 @@ import { useTranslation } from 'react-i18next';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { AuthenticationService } from 'api';
import { CheckboxField, InputField, KnownHosts } from 'components'; import { CheckboxField, InputField, KnownHosts } from 'components';
import { useAutoConnect } from 'hooks'; import { useAutoConnect } from 'hooks';
import { HostDTO, SettingDTO } from 'services'; import { HostDTO, SettingDTO } from 'services';
import { APP_USER } from 'types'; import { APP_USER } from 'types';
import { useAppSelector } from 'store';
import { Selectors as ServerSelectors } from 'store/server';
import './LoginForm.css'; import './LoginForm.css';
@ -21,6 +22,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
const [host, setHost] = useState(null); const [host, setHost] = useState(null);
const [useStoredPasswordLabel, setUseStoredPasswordLabel] = useState(false); const [useStoredPasswordLabel, setUseStoredPasswordLabel] = useState(false);
const [autoConnect, setAutoConnect] = useAutoConnect(); const [autoConnect, setAutoConnect] = useAutoConnect();
const connectionAttemptMade = useAppSelector(ServerSelectors.getConnectionAttemptMade);
const validate = values => { const validate = values => {
const errors: any = {}; const errors: any = {};
@ -54,7 +56,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
useEffect(() => { useEffect(() => {
SettingDTO.get(APP_USER).then((userSetting: SettingDTO) => { SettingDTO.get(APP_USER).then((userSetting: SettingDTO) => {
if (userSetting?.autoConnect && !AuthenticationService.connectionAttemptMade()) { if (userSetting?.autoConnect && !connectionAttemptMade) {
HostDTO.getAll().then(hosts => { HostDTO.getAll().then(hosts => {
let lastSelectedHost = hosts.find(({ lastSelected }) => lastSelected); let lastSelectedHost = hosts.find(({ lastSelected }) => lastSelected);

View file

@ -1,4 +1,4 @@
export { store } from './store'; export { store, useAppSelector, useAppDispatch } from './store';
// Common // Common
export { SortUtil } from './common'; export { SortUtil } from './common';

View file

@ -130,6 +130,7 @@ export function makeServerState(overrides: Partial<ServerState> = {}): ServerSta
buddyList: [], buddyList: [],
ignoreList: [], ignoreList: [],
status: { status: {
connectionAttemptMade: false,
state: StatusEnum.DISCONNECTED, state: StatusEnum.DISCONNECTED,
description: null, description: null,
}, },

View file

@ -25,6 +25,10 @@ describe('Actions', () => {
expect(Actions.clearStore()).toEqual({ type: Types.CLEAR_STORE }); expect(Actions.clearStore()).toEqual({ type: Types.CLEAR_STORE });
}); });
it('connectionAttempted', () => {
expect(Actions.connectionAttempted()).toEqual({ type: Types.CONNECTION_ATTEMPTED });
});
it('loginSuccessful', () => { it('loginSuccessful', () => {
const options = makeConnectOptions(); const options = makeConnectOptions();
expect(Actions.loginSuccessful(options)).toEqual({ type: Types.LOGIN_SUCCESSFUL, options }); expect(Actions.loginSuccessful(options)).toEqual({ type: Types.LOGIN_SUCCESSFUL, options });
@ -360,4 +364,8 @@ describe('Actions', () => {
const gametypeMap = { 1: 'Standard' }; const gametypeMap = { 1: 'Standard' };
expect(Actions.gamesOfUser('alice', games, gametypeMap)).toEqual({ type: Types.GAMES_OF_USER, userName: 'alice', games, gametypeMap }); expect(Actions.gamesOfUser('alice', games, gametypeMap)).toEqual({ type: Types.GAMES_OF_USER, userName: 'alice', games, gametypeMap });
}); });
it('clearRegistrationErrors', () => {
expect(Actions.clearRegistrationErrors()).toEqual({ type: Types.CLEAR_REGISTRATION_ERRORS });
});
}); });

View file

@ -14,6 +14,9 @@ export const Actions = {
clearStore: () => ({ clearStore: () => ({
type: Types.CLEAR_STORE type: Types.CLEAR_STORE
}), }),
connectionAttempted: () => ({
type: Types.CONNECTION_ATTEMPTED
}),
loginSuccessful: (options: WebSocketConnectOptions) => ({ loginSuccessful: (options: WebSocketConnectOptions) => ({
type: Types.LOGIN_SUCCESSFUL, type: Types.LOGIN_SUCCESSFUL,
options options

View file

@ -32,6 +32,11 @@ describe('Dispatch', () => {
expect(store.dispatch).toHaveBeenCalledWith(Actions.clearStore()); expect(store.dispatch).toHaveBeenCalledWith(Actions.clearStore());
}); });
it('connectionAttempted dispatches Actions.connectionAttempted()', () => {
Dispatch.connectionAttempted();
expect(store.dispatch).toHaveBeenCalledWith(Actions.connectionAttempted());
});
it('loginSuccessful dispatches Actions.loginSuccessful()', () => { it('loginSuccessful dispatches Actions.loginSuccessful()', () => {
const options = makeConnectOptions(); const options = makeConnectOptions();
Dispatch.loginSuccessful(options); Dispatch.loginSuccessful(options);
@ -391,4 +396,9 @@ describe('Dispatch', () => {
Dispatch.gamesOfUser('alice', games, gametypeMap); Dispatch.gamesOfUser('alice', games, gametypeMap);
expect(store.dispatch).toHaveBeenCalledWith(Actions.gamesOfUser('alice', games, gametypeMap)); expect(store.dispatch).toHaveBeenCalledWith(Actions.gamesOfUser('alice', games, gametypeMap));
}); });
it('clearRegistrationErrors dispatches correctly', () => {
Dispatch.clearRegistrationErrors();
expect(store.dispatch).toHaveBeenCalledWith(Actions.clearRegistrationErrors());
});
}); });

View file

@ -14,6 +14,9 @@ export const Dispatch = {
clearStore: () => { clearStore: () => {
store.dispatch(Actions.clearStore()); store.dispatch(Actions.clearStore());
}, },
connectionAttempted: () => {
store.dispatch(Actions.connectionAttempted());
},
loginSuccessful: (options: WebSocketConnectOptions) => { loginSuccessful: (options: WebSocketConnectOptions) => {
store.dispatch(Actions.loginSuccessful(options)); store.dispatch(Actions.loginSuccessful(options));
}, },

View file

@ -76,6 +76,7 @@ export interface ServerState {
} }
export interface ServerStateStatus { export interface ServerStateStatus {
connectionAttemptMade: boolean;
description: string; description: string;
state: number; state: number;
} }

View file

@ -55,6 +55,12 @@ describe('Initialisation', () => {
// ── Account & Connection ───────────────────────────────────────────────────── // ── Account & Connection ─────────────────────────────────────────────────────
describe('Account & Connection', () => { describe('Account & Connection', () => {
it('CONNECTION_ATTEMPTED → sets connectionAttemptMade to true', () => {
const state = makeServerState({ status: { connectionAttemptMade: false, state: StatusEnum.DISCONNECTED, description: null } });
const result = serverReducer(state, { type: Types.CONNECTION_ATTEMPTED });
expect(result.status.connectionAttemptMade).toBe(true);
});
it('ACCOUNT_AWAITING_ACTIVATION → returns state unchanged', () => { it('ACCOUNT_AWAITING_ACTIVATION → returns state unchanged', () => {
const options = makeConnectOptions(); const options = makeConnectOptions();
const state = makeServerState(); const state = makeServerState();

View file

@ -69,6 +69,7 @@ const initialState: ServerState = {
ignoreList: [], ignoreList: [],
status: { status: {
connectionAttemptMade: false,
state: StatusEnum.DISCONNECTED, state: StatusEnum.DISCONNECTED,
description: null description: null
}, },
@ -112,6 +113,12 @@ export const serverReducer = (state = initialState, action: ServerAction) => {
initialized: true initialized: true
} }
} }
case Types.CONNECTION_ATTEMPTED: {
return {
...state,
status: { ...state.status, connectionAttemptMade: true }
};
}
case Types.ACCOUNT_AWAITING_ACTIVATION: { case Types.ACCOUNT_AWAITING_ACTIVATION: {
return state; return state;
} }

View file

@ -34,15 +34,20 @@ describe('Selectors', () => {
}); });
it('getDescription → returns status.description', () => { it('getDescription → returns status.description', () => {
const state = makeServerState({ status: { state: StatusEnum.CONNECTED, description: 'ok' } }); const state = makeServerState({ status: { connectionAttemptMade: false, state: StatusEnum.CONNECTED, description: 'ok' } });
expect(Selectors.getDescription(rootState(state))).toBe('ok'); expect(Selectors.getDescription(rootState(state))).toBe('ok');
}); });
it('getState → returns status.state', () => { it('getState → returns status.state', () => {
const state = makeServerState({ status: { state: StatusEnum.LOGGED_IN, description: null } }); const state = makeServerState({ status: { connectionAttemptMade: false, state: StatusEnum.LOGGED_IN, description: null } });
expect(Selectors.getState(rootState(state))).toBe(StatusEnum.LOGGED_IN); expect(Selectors.getState(rootState(state))).toBe(StatusEnum.LOGGED_IN);
}); });
it('getConnectionAttemptMade → returns status.connectionAttemptMade', () => {
const state = makeServerState({ status: { connectionAttemptMade: true, state: StatusEnum.DISCONNECTED, description: null } });
expect(Selectors.getConnectionAttemptMade(rootState(state))).toBe(true);
});
it('getUser → returns user', () => { it('getUser → returns user', () => {
const user = makeUser({ name: 'Alice' }); const user = makeUser({ name: 'Alice' });
const state = makeServerState({ user }); const state = makeServerState({ user });
@ -89,4 +94,9 @@ describe('Selectors', () => {
const state = makeServerState({ backendDecks: null }); const state = makeServerState({ backendDecks: null });
expect(Selectors.getBackendDecks(rootState(state))).toBeNull(); expect(Selectors.getBackendDecks(rootState(state))).toBeNull();
}); });
it('getRegistrationError → returns registrationError', () => {
const state = makeServerState({ registrationError: 'bad input' });
expect(Selectors.getRegistrationError(rootState(state))).toBe('bad input');
});
}); });

View file

@ -11,6 +11,7 @@ export const Selectors = {
getVersion: ({ server }: State) => server.info.version, getVersion: ({ server }: State) => server.info.version,
getDescription: ({ server }: State) => server.status.description, getDescription: ({ server }: State) => server.status.description,
getState: ({ server }: State) => server.status.state, getState: ({ server }: State) => server.status.state,
getConnectionAttemptMade: ({ server }: State) => server.status.connectionAttemptMade,
getUser: ({ server }: State) => server.user, getUser: ({ server }: State) => server.user,
getUsers: ({ server }: State) => server.users, getUsers: ({ server }: State) => server.users,
getLogs: ({ server }: State) => server.logs, getLogs: ({ server }: State) => server.logs,

View file

@ -1,6 +1,7 @@
export const Types = { export const Types = {
INITIALIZED: '[Server] Initialized', INITIALIZED: '[Server] Initialized',
CLEAR_STORE: '[Server] Clear Store', CLEAR_STORE: '[Server] Clear Store',
CONNECTION_ATTEMPTED: '[Server] Connection Attempted',
LOGIN_SUCCESSFUL: '[Server] Login Successful', LOGIN_SUCCESSFUL: '[Server] Login Successful',
LOGIN_FAILED: '[Server] Login Failed', LOGIN_FAILED: '[Server] Login Failed',
CONNECTION_CLOSED: '[Server] Connection Closed', CONNECTION_CLOSED: '[Server] Connection Closed',

View file

@ -1,19 +1,27 @@
const captured = vi.hoisted(() => ({
wsOptions: null as any,
pbOptions: null as any,
}));
vi.mock('./services/WebSocketService', () => ({ vi.mock('./services/WebSocketService', () => ({
WebSocketService: vi.fn().mockImplementation(function WebSocketServiceImpl() { WebSocketService: vi.fn().mockImplementation(function WebSocketServiceImpl(options: any) {
captured.wsOptions = options;
return { return {
message$: { subscribe: vi.fn() }, message$: { subscribe: vi.fn() },
connect: vi.fn(), connect: vi.fn(),
testConnect: vi.fn(), testConnect: vi.fn(),
disconnect: vi.fn(), disconnect: vi.fn(),
send: vi.fn(),
checkReadyState: vi.fn().mockReturnValue(true),
}; };
}), }),
})); }));
vi.mock('./services/ProtobufService', () => ({ vi.mock('./services/ProtobufService', () => ({
ProtobufService: vi.fn().mockImplementation(function ProtobufServiceImpl() { ProtobufService: vi.fn().mockImplementation(function ProtobufServiceImpl(options: any) {
captured.pbOptions = options;
return { return {
handleMessageEvent: vi.fn(), handleMessageEvent: vi.fn(),
sendKeepAliveCommand: vi.fn(),
resetCommands: vi.fn(), resetCommands: vi.fn(),
}; };
}), }),
@ -21,17 +29,22 @@ vi.mock('./services/ProtobufService', () => ({
vi.mock('./persistence', () => ({ vi.mock('./persistence', () => ({
RoomPersistence: { clearStore: vi.fn() }, RoomPersistence: { clearStore: vi.fn() },
SessionPersistence: { clearStore: vi.fn(), initialized: vi.fn() }, SessionPersistence: { clearStore: vi.fn(), initialized: vi.fn(), connectionAttempted: vi.fn() },
})); }));
vi.mock('store', () => ({ vi.mock('store', () => ({
GameDispatch: { clearStore: vi.fn() }, GameDispatch: { clearStore: vi.fn() },
})); }));
vi.mock('./commands/session', () => ({
ping: vi.fn(),
}));
import { WebClient } from './WebClient'; import { WebClient } from './WebClient';
import { WebSocketService } from './services/WebSocketService'; import { WebSocketService } from './services/WebSocketService';
import { ProtobufService } from './services/ProtobufService'; import { ProtobufService } from './services/ProtobufService';
import { RoomPersistence, SessionPersistence } from './persistence'; import { RoomPersistence, SessionPersistence } from './persistence';
import { ping } from './commands/session';
import { StatusEnum } from 'types'; import { StatusEnum } from 'types';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { Mock } from 'vitest'; import { Mock } from 'vitest';
@ -42,20 +55,23 @@ describe('WebClient', () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
(ProtobufService as Mock).mockImplementation(function ProtobufServiceImpl() { (ProtobufService as Mock).mockImplementation(function ProtobufServiceImpl(options: any) {
captured.pbOptions = options;
return { return {
handleMessageEvent: vi.fn(), handleMessageEvent: vi.fn(),
sendKeepAliveCommand: vi.fn(),
resetCommands: vi.fn(), resetCommands: vi.fn(),
}; };
}); });
messageSubject = new Subject<MessageEvent>(); messageSubject = new Subject<MessageEvent>();
(WebSocketService as Mock).mockImplementation(function WebSocketServiceImpl() { (WebSocketService as Mock).mockImplementation(function WebSocketServiceImpl(options: any) {
captured.wsOptions = options;
return { return {
message$: messageSubject, message$: messageSubject,
connect: vi.fn(), connect: vi.fn(),
testConnect: vi.fn(), testConnect: vi.fn(),
disconnect: vi.fn(), disconnect: vi.fn(),
send: vi.fn(),
checkReadyState: vi.fn().mockReturnValue(true),
}; };
}); });
// suppress console.log from constructor in non-test-env check // suppress console.log from constructor in non-test-env check
@ -80,10 +96,10 @@ describe('WebClient', () => {
}); });
describe('connect', () => { describe('connect', () => {
it('sets connectionAttemptMade to true', () => { it('calls SessionPersistence.connectionAttempted', () => {
const opts: any = { host: 'h', port: 1 }; const opts: any = { host: 'h', port: 1 };
client.connect(opts); client.connect(opts);
expect(client.connectionAttemptMade).toBe(true); expect(SessionPersistence.connectionAttempted).toHaveBeenCalled();
}); });
it('stores options and calls socket.connect', () => { it('stores options and calls socket.connect', () => {
@ -109,14 +125,6 @@ describe('WebClient', () => {
}); });
}); });
describe('keepAlive', () => {
it('delegates to protobuf.sendKeepAliveCommand', () => {
const pingCb = vi.fn();
client.keepAlive(pingCb);
expect(client.protobuf.sendKeepAliveCommand).toHaveBeenCalledWith(pingCb);
});
});
describe('updateStatus', () => { describe('updateStatus', () => {
it('sets the status', () => { it('sets the status', () => {
client.updateStatus(StatusEnum.CONNECTED); client.updateStatus(StatusEnum.CONNECTED);
@ -136,4 +144,24 @@ describe('WebClient', () => {
expect(RoomPersistence.clearStore).not.toHaveBeenCalled(); expect(RoomPersistence.clearStore).not.toHaveBeenCalled();
}); });
}); });
describe('constructor closures', () => {
it('keepAliveFn calls ping with the callback', () => {
const cb = vi.fn();
captured.wsOptions.keepAliveFn(cb);
expect(ping).toHaveBeenCalledWith(cb);
});
it('send closure delegates to socket.send', () => {
const data = new Uint8Array([1, 2, 3]);
captured.pbOptions.send(data);
expect(client.socket.send).toHaveBeenCalledWith(data);
});
it('isOpen closure delegates to socket.checkReadyState', () => {
const result = captured.pbOptions.isOpen();
expect(client.socket.checkReadyState).toHaveBeenCalledWith(WebSocket.OPEN);
expect(result).toBe(true);
});
});
}); });

View file

@ -2,47 +2,28 @@ import { StatusEnum, WebSocketConnectOptions } from 'types';
import { ProtobufService } from './services/ProtobufService'; import { ProtobufService } from './services/ProtobufService';
import { WebSocketService } from './services/WebSocketService'; import { WebSocketService } from './services/WebSocketService';
import { ping } from './commands/session';
import { GameDispatch } from 'store'; import { GameDispatch } from 'store';
import { RoomPersistence, SessionPersistence } from './persistence'; import { RoomPersistence, SessionPersistence } from './persistence';
export class WebClient { export class WebClient {
public socket = new WebSocketService(this); public socket: WebSocketService;
public protobuf = new ProtobufService(this); public protobuf: ProtobufService;
public protocolVersion = 14;
public clientConfig = {
clientid: 'webatrice',
clientver: 'webclient-1.0 (2019-10-31)',
clientfeatures: [
'client_id',
'client_ver',
'feature_set',
'room_chat_history',
'client_warnings',
/* unimplemented features */
'forgot_password',
'idle_client',
'mod_log_lookup',
'user_ban_history',
// satisfy server reqs for POC
'websocket',
'2.7.0_min_version',
'2.8.0_min_version'
]
};
public clientOptions = {
autojoinrooms: true,
keepalive: 5000
};
public options: WebSocketConnectOptions; public options: WebSocketConnectOptions;
public status: StatusEnum; public status: StatusEnum;
public connectionAttemptMade = false;
constructor() { constructor() {
this.socket = new WebSocketService({
keepAliveFn: (cb) => ping(cb),
});
this.protobuf = new ProtobufService({
send: (data) => this.socket.send(data),
isOpen: () => this.socket.checkReadyState(WebSocket.OPEN),
});
this.socket.message$.subscribe((message: MessageEvent) => { this.socket.message$.subscribe((message: MessageEvent) => {
this.protobuf.handleMessageEvent(message); this.protobuf.handleMessageEvent(message);
}); });
@ -55,7 +36,7 @@ export class WebClient {
} }
public connect(options: WebSocketConnectOptions) { public connect(options: WebSocketConnectOptions) {
this.connectionAttemptMade = true; SessionPersistence.connectionAttempted();
this.options = options; this.options = options;
this.socket.connect(options); this.socket.connect(options);
} }
@ -77,10 +58,6 @@ export class WebClient {
} }
} }
public keepAlive(pingReceived: () => void) {
this.protobuf.sendKeepAliveCommand(pingReceived);
}
private clearStores() { private clearStores() {
GameDispatch.clearStore(); GameDispatch.clearStore();
RoomPersistence.clearStore(); RoomPersistence.clearStore();

View file

@ -17,11 +17,11 @@ export function makeWebClientMock() {
testConnect: vi.fn(), testConnect: vi.fn(),
disconnect: vi.fn(), disconnect: vi.fn(),
updateStatus: vi.fn(), updateStatus: vi.fn(),
clientConfig: { clientid: 'webatrice', clientver: '1.0', clientfeatures: [] },
options: {}, options: {},
protocolVersion: 14,
status: 0, status: 0,
connectionAttemptMade: false, protobuf: {
sendSessionCommand: vi.fn(),
},
}; };
} }

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_AdjustMod_ext, Command_AdjustModSchema } from 'generated/proto/admin_commands_pb'; import { Command_AdjustMod_ext, Command_AdjustModSchema } from 'generated/proto/admin_commands_pb';
import { AdminPersistence } from '../../persistence'; import { AdminPersistence } from '../../persistence';
export function adjustMod(userName: string, shouldBeMod?: boolean, shouldBeJudge?: boolean): void { export function adjustMod(userName: string, shouldBeMod?: boolean, shouldBeJudge?: boolean): void {
BackendService.sendAdminCommand(Command_AdjustMod_ext, create(Command_AdjustModSchema, { userName, shouldBeMod, shouldBeJudge }), { webClient.protobuf.sendAdminCommand(Command_AdjustMod_ext, create(Command_AdjustModSchema, { userName, shouldBeMod, shouldBeJudge }), {
onSuccess: () => { onSuccess: () => {
AdminPersistence.adjustMod(userName, shouldBeMod, shouldBeJudge); AdminPersistence.adjustMod(userName, shouldBeMod, shouldBeJudge);
}, },

View file

@ -1,7 +1,6 @@
vi.mock('../../services/BackendService', () => ({ vi.mock('../../WebClient', () => ({
BackendService: { __esModule: true,
sendAdminCommand: vi.fn(), default: { protobuf: { sendAdminCommand: vi.fn() } },
},
})); }));
vi.mock('../../persistence', () => ({ vi.mock('../../persistence', () => ({
@ -14,7 +13,7 @@ vi.mock('../../persistence', () => ({
})); }));
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers'; import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { AdminPersistence } from '../../persistence'; import { AdminPersistence } from '../../persistence';
import { adjustMod } from './adjustMod'; import { adjustMod } from './adjustMod';
import { reloadConfig } from './reloadConfig'; import { reloadConfig } from './reloadConfig';
@ -24,7 +23,7 @@ import { updateServerMessage } from './updateServerMessage';
import { Mock } from 'vitest'; import { Mock } from 'vitest';
const { invokeOnSuccess } = makeCallbackHelpers( const { invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendAdminCommand as Mock, webClient.protobuf.sendAdminCommand as Mock,
2 2
); );
@ -37,7 +36,7 @@ describe('adjustMod', () => {
it('calls sendAdminCommand with Command_AdjustMod', () => { it('calls sendAdminCommand with Command_AdjustMod', () => {
adjustMod('alice', true, false); adjustMod('alice', true, false);
expect(BackendService.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object));
}); });
it('onSuccess calls AdminPersistence.adjustMod', () => { it('onSuccess calls AdminPersistence.adjustMod', () => {
@ -54,7 +53,7 @@ describe('reloadConfig', () => {
it('calls sendAdminCommand with Command_ReloadConfig', () => { it('calls sendAdminCommand with Command_ReloadConfig', () => {
reloadConfig(); reloadConfig();
expect(BackendService.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object));
}); });
it('onSuccess calls AdminPersistence.reloadConfig', () => { it('onSuccess calls AdminPersistence.reloadConfig', () => {
@ -71,7 +70,7 @@ describe('shutdownServer', () => {
it('calls sendAdminCommand with Command_ShutdownServer', () => { it('calls sendAdminCommand with Command_ShutdownServer', () => {
shutdownServer('maintenance', 10); shutdownServer('maintenance', 10);
expect(BackendService.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object));
}); });
it('onSuccess calls AdminPersistence.shutdownServer', () => { it('onSuccess calls AdminPersistence.shutdownServer', () => {
@ -88,7 +87,7 @@ describe('updateServerMessage', () => {
it('calls sendAdminCommand with Command_UpdateServerMessage', () => { it('calls sendAdminCommand with Command_UpdateServerMessage', () => {
updateServerMessage(); updateServerMessage();
expect(BackendService.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendAdminCommand).toHaveBeenCalledWith(expect.any(Object), expect.any(Object), expect.any(Object));
}); });
it('onSuccess calls AdminPersistence.updateServerMessage', () => { it('onSuccess calls AdminPersistence.updateServerMessage', () => {

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReloadConfig_ext, Command_ReloadConfigSchema } from 'generated/proto/admin_commands_pb'; import { Command_ReloadConfig_ext, Command_ReloadConfigSchema } from 'generated/proto/admin_commands_pb';
import { AdminPersistence } from '../../persistence'; import { AdminPersistence } from '../../persistence';
export function reloadConfig(): void { export function reloadConfig(): void {
BackendService.sendAdminCommand(Command_ReloadConfig_ext, create(Command_ReloadConfigSchema), { webClient.protobuf.sendAdminCommand(Command_ReloadConfig_ext, create(Command_ReloadConfigSchema), {
onSuccess: () => { onSuccess: () => {
AdminPersistence.reloadConfig(); AdminPersistence.reloadConfig();
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ShutdownServer_ext, Command_ShutdownServerSchema } from 'generated/proto/admin_commands_pb'; import { Command_ShutdownServer_ext, Command_ShutdownServerSchema } from 'generated/proto/admin_commands_pb';
import { AdminPersistence } from '../../persistence'; import { AdminPersistence } from '../../persistence';
export function shutdownServer(reason: string, minutes: number): void { export function shutdownServer(reason: string, minutes: number): void {
BackendService.sendAdminCommand(Command_ShutdownServer_ext, create(Command_ShutdownServerSchema, { reason, minutes }), { webClient.protobuf.sendAdminCommand(Command_ShutdownServer_ext, create(Command_ShutdownServerSchema, { reason, minutes }), {
onSuccess: () => { onSuccess: () => {
AdminPersistence.shutdownServer(); AdminPersistence.shutdownServer();
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_UpdateServerMessage_ext, Command_UpdateServerMessageSchema } from 'generated/proto/admin_commands_pb'; import { Command_UpdateServerMessage_ext, Command_UpdateServerMessageSchema } from 'generated/proto/admin_commands_pb';
import { AdminPersistence } from '../../persistence'; import { AdminPersistence } from '../../persistence';
export function updateServerMessage(): void { export function updateServerMessage(): void {
BackendService.sendAdminCommand(Command_UpdateServerMessage_ext, create(Command_UpdateServerMessageSchema), { webClient.protobuf.sendAdminCommand(Command_UpdateServerMessage_ext, create(Command_UpdateServerMessageSchema), {
onSuccess: () => { onSuccess: () => {
AdminPersistence.updateServerMessage(); AdminPersistence.updateServerMessage();
}, },

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_AttachCardSchema, Command_AttachCard_ext } from 'generated/proto/command_attach_card_pb'; import { Command_AttachCardSchema, Command_AttachCard_ext } from 'generated/proto/command_attach_card_pb';
import { AttachCardParams } from 'types'; import { AttachCardParams } from 'types';
export function attachCard(gameId: number, params: AttachCardParams): void { export function attachCard(gameId: number, params: AttachCardParams): void {
BackendService.sendGameCommand(gameId, Command_AttachCard_ext, create(Command_AttachCardSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_AttachCard_ext, create(Command_AttachCardSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ChangeZonePropertiesSchema, Command_ChangeZoneProperties_ext } from 'generated/proto/command_change_zone_properties_pb'; import { Command_ChangeZonePropertiesSchema, Command_ChangeZoneProperties_ext } from 'generated/proto/command_change_zone_properties_pb';
import { ChangeZonePropertiesParams } from 'types'; import { ChangeZonePropertiesParams } from 'types';
export function changeZoneProperties(gameId: number, params: ChangeZonePropertiesParams): void { export function changeZoneProperties(gameId: number, params: ChangeZonePropertiesParams): void {
BackendService.sendGameCommand(gameId, Command_ChangeZoneProperties_ext, create(Command_ChangeZonePropertiesSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_ChangeZoneProperties_ext, create(Command_ChangeZonePropertiesSchema, params));
} }

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ConcedeSchema, Command_Concede_ext } from 'generated/proto/command_concede_pb'; import { Command_ConcedeSchema, Command_Concede_ext } from 'generated/proto/command_concede_pb';
export function concede(gameId: number): void { export function concede(gameId: number): void {
BackendService.sendGameCommand(gameId, Command_Concede_ext, create(Command_ConcedeSchema)); webClient.protobuf.sendGameCommand(gameId, Command_Concede_ext, create(Command_ConcedeSchema));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_CreateArrowSchema, Command_CreateArrow_ext } from 'generated/proto/command_create_arrow_pb'; import { Command_CreateArrowSchema, Command_CreateArrow_ext } from 'generated/proto/command_create_arrow_pb';
import { CreateArrowParams } from 'types'; import { CreateArrowParams } from 'types';
export function createArrow(gameId: number, params: CreateArrowParams): void { export function createArrow(gameId: number, params: CreateArrowParams): void {
BackendService.sendGameCommand(gameId, Command_CreateArrow_ext, create(Command_CreateArrowSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_CreateArrow_ext, create(Command_CreateArrowSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_CreateCounterSchema, Command_CreateCounter_ext } from 'generated/proto/command_create_counter_pb'; import { Command_CreateCounterSchema, Command_CreateCounter_ext } from 'generated/proto/command_create_counter_pb';
import { CreateCounterParams } from 'types'; import { CreateCounterParams } from 'types';
export function createCounter(gameId: number, params: CreateCounterParams): void { export function createCounter(gameId: number, params: CreateCounterParams): void {
BackendService.sendGameCommand(gameId, Command_CreateCounter_ext, create(Command_CreateCounterSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_CreateCounter_ext, create(Command_CreateCounterSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_CreateTokenSchema, Command_CreateToken_ext } from 'generated/proto/command_create_token_pb'; import { Command_CreateTokenSchema, Command_CreateToken_ext } from 'generated/proto/command_create_token_pb';
import { CreateTokenParams } from 'types'; import { CreateTokenParams } from 'types';
export function createToken(gameId: number, params: CreateTokenParams): void { export function createToken(gameId: number, params: CreateTokenParams): void {
BackendService.sendGameCommand(gameId, Command_CreateToken_ext, create(Command_CreateTokenSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_CreateToken_ext, create(Command_CreateTokenSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeckSelectSchema, Command_DeckSelect_ext } from 'generated/proto/command_deck_select_pb'; import { Command_DeckSelectSchema, Command_DeckSelect_ext } from 'generated/proto/command_deck_select_pb';
import { DeckSelectParams } from 'types'; import { DeckSelectParams } from 'types';
export function deckSelect(gameId: number, params: DeckSelectParams): void { export function deckSelect(gameId: number, params: DeckSelectParams): void {
BackendService.sendGameCommand(gameId, Command_DeckSelect_ext, create(Command_DeckSelectSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_DeckSelect_ext, create(Command_DeckSelectSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DelCounterSchema, Command_DelCounter_ext } from 'generated/proto/command_del_counter_pb'; import { Command_DelCounterSchema, Command_DelCounter_ext } from 'generated/proto/command_del_counter_pb';
import { DelCounterParams } from 'types'; import { DelCounterParams } from 'types';
export function delCounter(gameId: number, params: DelCounterParams): void { export function delCounter(gameId: number, params: DelCounterParams): void {
BackendService.sendGameCommand(gameId, Command_DelCounter_ext, create(Command_DelCounterSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_DelCounter_ext, create(Command_DelCounterSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeleteArrowSchema, Command_DeleteArrow_ext } from 'generated/proto/command_delete_arrow_pb'; import { Command_DeleteArrowSchema, Command_DeleteArrow_ext } from 'generated/proto/command_delete_arrow_pb';
import { DeleteArrowParams } from 'types'; import { DeleteArrowParams } from 'types';
export function deleteArrow(gameId: number, params: DeleteArrowParams): void { export function deleteArrow(gameId: number, params: DeleteArrowParams): void {
BackendService.sendGameCommand(gameId, Command_DeleteArrow_ext, create(Command_DeleteArrowSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_DeleteArrow_ext, create(Command_DeleteArrowSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DrawCardsSchema, Command_DrawCards_ext } from 'generated/proto/command_draw_cards_pb'; import { Command_DrawCardsSchema, Command_DrawCards_ext } from 'generated/proto/command_draw_cards_pb';
import { DrawCardsParams } from 'types'; import { DrawCardsParams } from 'types';
export function drawCards(gameId: number, params: DrawCardsParams): void { export function drawCards(gameId: number, params: DrawCardsParams): void {
BackendService.sendGameCommand(gameId, Command_DrawCards_ext, create(Command_DrawCardsSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_DrawCards_ext, create(Command_DrawCardsSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DumpZoneSchema, Command_DumpZone_ext } from 'generated/proto/command_dump_zone_pb'; import { Command_DumpZoneSchema, Command_DumpZone_ext } from 'generated/proto/command_dump_zone_pb';
import { DumpZoneParams } from 'types'; import { DumpZoneParams } from 'types';
export function dumpZone(gameId: number, params: DumpZoneParams): void { export function dumpZone(gameId: number, params: DumpZoneParams): void {
BackendService.sendGameCommand(gameId, Command_DumpZone_ext, create(Command_DumpZoneSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_DumpZone_ext, create(Command_DumpZoneSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_FlipCardSchema, Command_FlipCard_ext } from 'generated/proto/command_flip_card_pb'; import { Command_FlipCardSchema, Command_FlipCard_ext } from 'generated/proto/command_flip_card_pb';
import { FlipCardParams } from 'types'; import { FlipCardParams } from 'types';
export function flipCard(gameId: number, params: FlipCardParams): void { export function flipCard(gameId: number, params: FlipCardParams): void {
BackendService.sendGameCommand(gameId, Command_FlipCard_ext, create(Command_FlipCardSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_FlipCard_ext, create(Command_FlipCardSchema, params));
} }

View file

@ -1,4 +1,4 @@
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { create, setExtension } from '@bufbuild/protobuf'; import { create, setExtension } from '@bufbuild/protobuf';
import { GameCommandSchema, Command_Judge_ext } from 'generated/proto/game_commands_pb'; import { GameCommandSchema, Command_Judge_ext } from 'generated/proto/game_commands_pb';
import { Command_DrawCardsSchema, Command_DrawCards_ext } from 'generated/proto/command_draw_cards_pb'; import { Command_DrawCardsSchema, Command_DrawCards_ext } from 'generated/proto/command_draw_cards_pb';
@ -66,8 +66,9 @@ import { undoDraw } from './undoDraw';
import { unconcede } from './unconcede'; import { unconcede } from './unconcede';
import { judge } from './judge'; import { judge } from './judge';
vi.mock('../../services/BackendService', () => ({ vi.mock('../../WebClient', () => ({
BackendService: { sendGameCommand: vi.fn() }, __esModule: true,
default: { protobuf: { sendGameCommand: vi.fn() } },
})); }));
const gameId = 1; const gameId = 1;
@ -75,116 +76,124 @@ const gameId = 1;
import { Mock } from 'vitest'; import { Mock } from 'vitest';
beforeEach(() => { beforeEach(() => {
(BackendService.sendGameCommand as Mock).mockClear(); (webClient.protobuf.sendGameCommand as Mock).mockClear();
}); });
describe('Game commands — delegate to BackendService.sendGameCommand', () => { describe('Game commands — delegate to webClient.protobuf.sendGameCommand', () => {
it('attachCard sends Command_AttachCard', () => { it('attachCard sends Command_AttachCard', () => {
attachCard(gameId, { cardId: 10, startZone: 'hand' }); attachCard(gameId, { cardId: 10, startZone: 'hand' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_AttachCard_ext, expect.objectContaining({ cardId: 10, startZone: 'hand' }) gameId, Command_AttachCard_ext, expect.objectContaining({ cardId: 10, startZone: 'hand' })
); );
}); });
it('changeZoneProperties sends Command_ChangeZoneProperties', () => { it('changeZoneProperties sends Command_ChangeZoneProperties', () => {
changeZoneProperties(gameId, { zoneName: 'side' }); changeZoneProperties(gameId, { zoneName: 'side' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_ChangeZoneProperties_ext, expect.objectContaining({ zoneName: 'side' }) gameId, Command_ChangeZoneProperties_ext, expect.objectContaining({ zoneName: 'side' })
); );
}); });
it('concede sends Command_Concede with empty object', () => { it('concede sends Command_Concede with empty object', () => {
concede(gameId); concede(gameId);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Concede_ext, expect.any(Object)); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Concede_ext, expect.any(Object));
}); });
it('createArrow sends Command_CreateArrow', () => { it('createArrow sends Command_CreateArrow', () => {
createArrow(gameId, { startPlayerId: 1, startZone: 'hand' }); createArrow(gameId, { startPlayerId: 1, startZone: 'hand' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_CreateArrow_ext, expect.objectContaining({ startPlayerId: 1, startZone: 'hand' }) gameId, Command_CreateArrow_ext, expect.objectContaining({ startPlayerId: 1, startZone: 'hand' })
); );
}); });
it('createCounter sends Command_CreateCounter', () => { it('createCounter sends Command_CreateCounter', () => {
createCounter(gameId, { counterName: 'life' }); createCounter(gameId, { counterName: 'life' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_CreateCounter_ext, expect.objectContaining({ counterName: 'life' }) gameId, Command_CreateCounter_ext, expect.objectContaining({ counterName: 'life' })
); );
}); });
it('createToken sends Command_CreateToken', () => { it('createToken sends Command_CreateToken', () => {
createToken(gameId, { cardName: 'Goblin', zone: 'play' }); createToken(gameId, { cardName: 'Goblin', zone: 'play' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_CreateToken_ext, expect.objectContaining({ cardName: 'Goblin', zone: 'play' }) gameId, Command_CreateToken_ext, expect.objectContaining({ cardName: 'Goblin', zone: 'play' })
); );
}); });
it('deckSelect sends Command_DeckSelect', () => { it('deckSelect sends Command_DeckSelect', () => {
deckSelect(gameId, { deckId: 5 }); deckSelect(gameId, { deckId: 5 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_DeckSelect_ext, expect.objectContaining({ deckId: 5 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_DeckSelect_ext, expect.objectContaining({ deckId: 5 }));
}); });
it('delCounter sends Command_DelCounter', () => { it('delCounter sends Command_DelCounter', () => {
delCounter(gameId, { counterId: 3 }); delCounter(gameId, { counterId: 3 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_DelCounter_ext, expect.objectContaining({ counterId: 3 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_DelCounter_ext, expect.objectContaining({ counterId: 3 })
);
}); });
it('deleteArrow sends Command_DeleteArrow', () => { it('deleteArrow sends Command_DeleteArrow', () => {
deleteArrow(gameId, { arrowId: 2 }); deleteArrow(gameId, { arrowId: 2 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_DeleteArrow_ext, expect.objectContaining({ arrowId: 2 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_DeleteArrow_ext, expect.objectContaining({ arrowId: 2 })
);
}); });
it('drawCards sends Command_DrawCards', () => { it('drawCards sends Command_DrawCards', () => {
drawCards(gameId, { number: 3 }); drawCards(gameId, { number: 3 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_DrawCards_ext, expect.objectContaining({ number: 3 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_DrawCards_ext, expect.objectContaining({ number: 3 }));
}); });
it('dumpZone sends Command_DumpZone', () => { it('dumpZone sends Command_DumpZone', () => {
dumpZone(gameId, { playerId: 2, zoneName: 'library' }); dumpZone(gameId, { playerId: 2, zoneName: 'library' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_DumpZone_ext, expect.objectContaining({ playerId: 2, zoneName: 'library' }) gameId, Command_DumpZone_ext, expect.objectContaining({ playerId: 2, zoneName: 'library' })
); );
}); });
it('flipCard sends Command_FlipCard', () => { it('flipCard sends Command_FlipCard', () => {
flipCard(gameId, { cardId: 7, faceDown: false }); flipCard(gameId, { cardId: 7, faceDown: false });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_FlipCard_ext, expect.objectContaining({ cardId: 7, faceDown: false }) gameId, Command_FlipCard_ext, expect.objectContaining({ cardId: 7, faceDown: false })
); );
}); });
it('gameSay sends Command_GameSay', () => { it('gameSay sends Command_GameSay', () => {
gameSay(gameId, { message: 'hello' }); gameSay(gameId, { message: 'hello' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_GameSay_ext, expect.objectContaining({ message: 'hello' })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_GameSay_ext, expect.objectContaining({ message: 'hello' })
);
}); });
it('incCardCounter sends Command_IncCardCounter', () => { it('incCardCounter sends Command_IncCardCounter', () => {
incCardCounter(gameId, { cardId: 5, counterId: 1 }); incCardCounter(gameId, { cardId: 5, counterId: 1 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_IncCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 }) gameId, Command_IncCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 })
); );
}); });
it('incCounter sends Command_IncCounter', () => { it('incCounter sends Command_IncCounter', () => {
incCounter(gameId, { counterId: 1, delta: 5 }); incCounter(gameId, { counterId: 1, delta: 5 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_IncCounter_ext, expect.objectContaining({ counterId: 1, delta: 5 }) gameId, Command_IncCounter_ext, expect.objectContaining({ counterId: 1, delta: 5 })
); );
}); });
it('kickFromGame sends Command_KickFromGame', () => { it('kickFromGame sends Command_KickFromGame', () => {
kickFromGame(gameId, { playerId: 2 }); kickFromGame(gameId, { playerId: 2 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_KickFromGame_ext, expect.objectContaining({ playerId: 2 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_KickFromGame_ext, expect.objectContaining({ playerId: 2 })
);
}); });
it('leaveGame sends Command_LeaveGame with empty object', () => { it('leaveGame sends Command_LeaveGame with empty object', () => {
leaveGame(gameId); leaveGame(gameId);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_LeaveGame_ext, expect.any(Object)); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_LeaveGame_ext, expect.any(Object));
}); });
it('moveCard sends Command_MoveCard', () => { it('moveCard sends Command_MoveCard', () => {
moveCard(gameId, { startZone: 'hand', targetZone: 'graveyard' }); moveCard(gameId, { startZone: 'hand', targetZone: 'graveyard' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_MoveCard_ext, gameId, Command_MoveCard_ext,
expect.objectContaining({ startZone: 'hand', targetZone: 'graveyard' }) expect.objectContaining({ startZone: 'hand', targetZone: 'graveyard' })
); );
@ -192,39 +201,45 @@ describe('Game commands — delegate to BackendService.sendGameCommand', () => {
it('mulligan sends Command_Mulligan', () => { it('mulligan sends Command_Mulligan', () => {
mulligan(gameId, { number: 7 }); mulligan(gameId, { number: 7 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Mulligan_ext, expect.objectContaining({ number: 7 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_Mulligan_ext, expect.objectContaining({ number: 7 })
);
}); });
it('nextTurn sends Command_NextTurn with empty object', () => { it('nextTurn sends Command_NextTurn with empty object', () => {
nextTurn(gameId); nextTurn(gameId);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_NextTurn_ext, expect.any(Object)); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_NextTurn_ext, expect.any(Object));
}); });
it('readyStart sends Command_ReadyStart', () => { it('readyStart sends Command_ReadyStart', () => {
readyStart(gameId, { ready: true }); readyStart(gameId, { ready: true });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_ReadyStart_ext, expect.objectContaining({ ready: true })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_ReadyStart_ext, expect.objectContaining({ ready: true })
);
}); });
it('revealCards sends Command_RevealCards', () => { it('revealCards sends Command_RevealCards', () => {
revealCards(gameId, { zoneName: 'hand', cardId: [1, 2] }); revealCards(gameId, { zoneName: 'hand', cardId: [1, 2] });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_RevealCards_ext, expect.objectContaining({ zoneName: 'hand', cardId: [1, 2] }) gameId, Command_RevealCards_ext, expect.objectContaining({ zoneName: 'hand', cardId: [1, 2] })
); );
}); });
it('reverseTurn sends Command_ReverseTurn with empty object', () => { it('reverseTurn sends Command_ReverseTurn with empty object', () => {
reverseTurn(gameId); reverseTurn(gameId);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_ReverseTurn_ext, expect.any(Object)); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_ReverseTurn_ext, expect.any(Object));
}); });
it('setActivePhase sends Command_SetActivePhase', () => { it('setActivePhase sends Command_SetActivePhase', () => {
setActivePhase(gameId, { phase: 2 }); setActivePhase(gameId, { phase: 2 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_SetActivePhase_ext, expect.objectContaining({ phase: 2 })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_SetActivePhase_ext, expect.objectContaining({ phase: 2 })
);
}); });
it('setCardAttr sends Command_SetCardAttr', () => { it('setCardAttr sends Command_SetCardAttr', () => {
setCardAttr(gameId, { zone: 'play', cardId: 5, attrValue: '2' }); setCardAttr(gameId, { zone: 'play', cardId: 5, attrValue: '2' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_SetCardAttr_ext, gameId, Command_SetCardAttr_ext,
expect.objectContaining({ zone: 'play', cardId: 5, attrValue: '2' }) expect.objectContaining({ zone: 'play', cardId: 5, attrValue: '2' })
); );
@ -232,45 +247,47 @@ describe('Game commands — delegate to BackendService.sendGameCommand', () => {
it('setCardCounter sends Command_SetCardCounter', () => { it('setCardCounter sends Command_SetCardCounter', () => {
setCardCounter(gameId, { cardId: 5, counterId: 1 }); setCardCounter(gameId, { cardId: 5, counterId: 1 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_SetCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 }) gameId, Command_SetCardCounter_ext, expect.objectContaining({ cardId: 5, counterId: 1 })
); );
}); });
it('setCounter sends Command_SetCounter', () => { it('setCounter sends Command_SetCounter', () => {
setCounter(gameId, { counterId: 1, value: 10 }); setCounter(gameId, { counterId: 1, value: 10 });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_SetCounter_ext, expect.objectContaining({ counterId: 1, value: 10 }) gameId, Command_SetCounter_ext, expect.objectContaining({ counterId: 1, value: 10 })
); );
}); });
it('setSideboardLock sends Command_SetSideboardLock', () => { it('setSideboardLock sends Command_SetSideboardLock', () => {
setSideboardLock(gameId, { locked: true }); setSideboardLock(gameId, { locked: true });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_SetSideboardLock_ext, expect.objectContaining({ locked: true }) gameId, Command_SetSideboardLock_ext, expect.objectContaining({ locked: true })
); );
}); });
it('setSideboardPlan sends Command_SetSideboardPlan', () => { it('setSideboardPlan sends Command_SetSideboardPlan', () => {
setSideboardPlan(gameId, { moveList: [] }); setSideboardPlan(gameId, { moveList: [] });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_SetSideboardPlan_ext, expect.objectContaining({ moveList: expect.any(Array) }) gameId, Command_SetSideboardPlan_ext, expect.objectContaining({ moveList: expect.any(Array) })
); );
}); });
it('shuffle sends Command_Shuffle', () => { it('shuffle sends Command_Shuffle', () => {
shuffle(gameId, { zoneName: 'hand' }); shuffle(gameId, { zoneName: 'hand' });
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Shuffle_ext, expect.objectContaining({ zoneName: 'hand' })); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, Command_Shuffle_ext, expect.objectContaining({ zoneName: 'hand' })
);
}); });
it('undoDraw sends Command_UndoDraw with empty object', () => { it('undoDraw sends Command_UndoDraw with empty object', () => {
undoDraw(gameId); undoDraw(gameId);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_UndoDraw_ext, expect.any(Object)); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_UndoDraw_ext, expect.any(Object));
}); });
it('unconcede sends Command_Unconcede with empty object', () => { it('unconcede sends Command_Unconcede with empty object', () => {
unconcede(gameId); unconcede(gameId);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Unconcede_ext, expect.any(Object)); expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(gameId, Command_Unconcede_ext, expect.any(Object));
}); });
it('judge sends Command_Judge with targetId and wrapped gameCommand array', () => { it('judge sends Command_Judge with targetId and wrapped gameCommand array', () => {
@ -278,7 +295,7 @@ describe('Game commands — delegate to BackendService.sendGameCommand', () => {
const innerCmd = create(GameCommandSchema); const innerCmd = create(GameCommandSchema);
setExtension(innerCmd, Command_DrawCards_ext, create(Command_DrawCardsSchema, { number: 2 })); setExtension(innerCmd, Command_DrawCards_ext, create(Command_DrawCardsSchema, { number: 2 }));
judge(gameId, targetId, innerCmd); judge(gameId, targetId, innerCmd);
expect(BackendService.sendGameCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendGameCommand).toHaveBeenCalledWith(
gameId, gameId,
Command_Judge_ext, Command_Judge_ext,
expect.objectContaining({ targetId: 3, gameCommand: expect.any(Array) }) expect.objectContaining({ targetId: 3, gameCommand: expect.any(Array) })

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GameSaySchema, Command_GameSay_ext } from 'generated/proto/command_game_say_pb'; import { Command_GameSaySchema, Command_GameSay_ext } from 'generated/proto/command_game_say_pb';
import { GameSayParams } from 'types'; import { GameSayParams } from 'types';
export function gameSay(gameId: number, params: GameSayParams): void { export function gameSay(gameId: number, params: GameSayParams): void {
BackendService.sendGameCommand(gameId, Command_GameSay_ext, create(Command_GameSaySchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_GameSay_ext, create(Command_GameSaySchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_IncCardCounterSchema, Command_IncCardCounter_ext } from 'generated/proto/command_inc_card_counter_pb'; import { Command_IncCardCounterSchema, Command_IncCardCounter_ext } from 'generated/proto/command_inc_card_counter_pb';
import { IncCardCounterParams } from 'types'; import { IncCardCounterParams } from 'types';
export function incCardCounter(gameId: number, params: IncCardCounterParams): void { export function incCardCounter(gameId: number, params: IncCardCounterParams): void {
BackendService.sendGameCommand(gameId, Command_IncCardCounter_ext, create(Command_IncCardCounterSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_IncCardCounter_ext, create(Command_IncCardCounterSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_IncCounterSchema, Command_IncCounter_ext } from 'generated/proto/command_inc_counter_pb'; import { Command_IncCounterSchema, Command_IncCounter_ext } from 'generated/proto/command_inc_counter_pb';
import { IncCounterParams } from 'types'; import { IncCounterParams } from 'types';
export function incCounter(gameId: number, params: IncCounterParams): void { export function incCounter(gameId: number, params: IncCounterParams): void {
BackendService.sendGameCommand(gameId, Command_IncCounter_ext, create(Command_IncCounterSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_IncCounter_ext, create(Command_IncCounterSchema, params));
} }

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_JudgeSchema, Command_Judge_ext } from 'generated/proto/game_commands_pb'; import { Command_JudgeSchema, Command_Judge_ext } from 'generated/proto/game_commands_pb';
import type { GameCommand } from 'generated/proto/game_commands_pb'; import type { GameCommand } from 'generated/proto/game_commands_pb';
export function judge(gameId: number, targetId: number, innerGameCommand: GameCommand): void { export function judge(gameId: number, targetId: number, innerGameCommand: GameCommand): void {
BackendService.sendGameCommand(gameId, Command_Judge_ext, create(Command_JudgeSchema, { webClient.protobuf.sendGameCommand(gameId, Command_Judge_ext, create(Command_JudgeSchema, {
targetId, targetId,
gameCommand: [innerGameCommand], gameCommand: [innerGameCommand],
})); }));

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_KickFromGameSchema, Command_KickFromGame_ext } from 'generated/proto/command_kick_from_game_pb'; import { Command_KickFromGameSchema, Command_KickFromGame_ext } from 'generated/proto/command_kick_from_game_pb';
import { KickFromGameParams } from 'types'; import { KickFromGameParams } from 'types';
export function kickFromGame(gameId: number, params: KickFromGameParams): void { export function kickFromGame(gameId: number, params: KickFromGameParams): void {
BackendService.sendGameCommand(gameId, Command_KickFromGame_ext, create(Command_KickFromGameSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_KickFromGame_ext, create(Command_KickFromGameSchema, params));
} }

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_LeaveGameSchema, Command_LeaveGame_ext } from 'generated/proto/command_leave_game_pb'; import { Command_LeaveGameSchema, Command_LeaveGame_ext } from 'generated/proto/command_leave_game_pb';
export function leaveGame(gameId: number): void { export function leaveGame(gameId: number): void {
BackendService.sendGameCommand(gameId, Command_LeaveGame_ext, create(Command_LeaveGameSchema)); webClient.protobuf.sendGameCommand(gameId, Command_LeaveGame_ext, create(Command_LeaveGameSchema));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_MoveCardSchema, Command_MoveCard_ext } from 'generated/proto/command_move_card_pb'; import { Command_MoveCardSchema, Command_MoveCard_ext } from 'generated/proto/command_move_card_pb';
import { MoveCardParams } from 'types'; import { MoveCardParams } from 'types';
export function moveCard(gameId: number, params: MoveCardParams): void { export function moveCard(gameId: number, params: MoveCardParams): void {
BackendService.sendGameCommand(gameId, Command_MoveCard_ext, create(Command_MoveCardSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_MoveCard_ext, create(Command_MoveCardSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_MulliganSchema, Command_Mulligan_ext } from 'generated/proto/command_mulligan_pb'; import { Command_MulliganSchema, Command_Mulligan_ext } from 'generated/proto/command_mulligan_pb';
import { MulliganParams } from 'types'; import { MulliganParams } from 'types';
export function mulligan(gameId: number, params: MulliganParams): void { export function mulligan(gameId: number, params: MulliganParams): void {
BackendService.sendGameCommand(gameId, Command_Mulligan_ext, create(Command_MulliganSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_Mulligan_ext, create(Command_MulliganSchema, params));
} }

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_NextTurnSchema, Command_NextTurn_ext } from 'generated/proto/command_next_turn_pb'; import { Command_NextTurnSchema, Command_NextTurn_ext } from 'generated/proto/command_next_turn_pb';
export function nextTurn(gameId: number): void { export function nextTurn(gameId: number): void {
BackendService.sendGameCommand(gameId, Command_NextTurn_ext, create(Command_NextTurnSchema)); webClient.protobuf.sendGameCommand(gameId, Command_NextTurn_ext, create(Command_NextTurnSchema));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReadyStartSchema, Command_ReadyStart_ext } from 'generated/proto/command_ready_start_pb'; import { Command_ReadyStartSchema, Command_ReadyStart_ext } from 'generated/proto/command_ready_start_pb';
import { ReadyStartParams } from 'types'; import { ReadyStartParams } from 'types';
export function readyStart(gameId: number, params: ReadyStartParams): void { export function readyStart(gameId: number, params: ReadyStartParams): void {
BackendService.sendGameCommand(gameId, Command_ReadyStart_ext, create(Command_ReadyStartSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_ReadyStart_ext, create(Command_ReadyStartSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_RevealCardsSchema, Command_RevealCards_ext } from 'generated/proto/command_reveal_cards_pb'; import { Command_RevealCardsSchema, Command_RevealCards_ext } from 'generated/proto/command_reveal_cards_pb';
import { RevealCardsParams } from 'types'; import { RevealCardsParams } from 'types';
export function revealCards(gameId: number, params: RevealCardsParams): void { export function revealCards(gameId: number, params: RevealCardsParams): void {
BackendService.sendGameCommand(gameId, Command_RevealCards_ext, create(Command_RevealCardsSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_RevealCards_ext, create(Command_RevealCardsSchema, params));
} }

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReverseTurnSchema, Command_ReverseTurn_ext } from 'generated/proto/command_reverse_turn_pb'; import { Command_ReverseTurnSchema, Command_ReverseTurn_ext } from 'generated/proto/command_reverse_turn_pb';
export function reverseTurn(gameId: number): void { export function reverseTurn(gameId: number): void {
BackendService.sendGameCommand(gameId, Command_ReverseTurn_ext, create(Command_ReverseTurnSchema)); webClient.protobuf.sendGameCommand(gameId, Command_ReverseTurn_ext, create(Command_ReverseTurnSchema));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_SetActivePhaseSchema, Command_SetActivePhase_ext } from 'generated/proto/command_set_active_phase_pb'; import { Command_SetActivePhaseSchema, Command_SetActivePhase_ext } from 'generated/proto/command_set_active_phase_pb';
import { SetActivePhaseParams } from 'types'; import { SetActivePhaseParams } from 'types';
export function setActivePhase(gameId: number, params: SetActivePhaseParams): void { export function setActivePhase(gameId: number, params: SetActivePhaseParams): void {
BackendService.sendGameCommand(gameId, Command_SetActivePhase_ext, create(Command_SetActivePhaseSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_SetActivePhase_ext, create(Command_SetActivePhaseSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_SetCardAttrSchema, Command_SetCardAttr_ext } from 'generated/proto/command_set_card_attr_pb'; import { Command_SetCardAttrSchema, Command_SetCardAttr_ext } from 'generated/proto/command_set_card_attr_pb';
import { SetCardAttrParams } from 'types'; import { SetCardAttrParams } from 'types';
export function setCardAttr(gameId: number, params: SetCardAttrParams): void { export function setCardAttr(gameId: number, params: SetCardAttrParams): void {
BackendService.sendGameCommand(gameId, Command_SetCardAttr_ext, create(Command_SetCardAttrSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_SetCardAttr_ext, create(Command_SetCardAttrSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_SetCardCounterSchema, Command_SetCardCounter_ext } from 'generated/proto/command_set_card_counter_pb'; import { Command_SetCardCounterSchema, Command_SetCardCounter_ext } from 'generated/proto/command_set_card_counter_pb';
import { SetCardCounterParams } from 'types'; import { SetCardCounterParams } from 'types';
export function setCardCounter(gameId: number, params: SetCardCounterParams): void { export function setCardCounter(gameId: number, params: SetCardCounterParams): void {
BackendService.sendGameCommand(gameId, Command_SetCardCounter_ext, create(Command_SetCardCounterSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_SetCardCounter_ext, create(Command_SetCardCounterSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_SetCounterSchema, Command_SetCounter_ext } from 'generated/proto/command_set_counter_pb'; import { Command_SetCounterSchema, Command_SetCounter_ext } from 'generated/proto/command_set_counter_pb';
import { SetCounterParams } from 'types'; import { SetCounterParams } from 'types';
export function setCounter(gameId: number, params: SetCounterParams): void { export function setCounter(gameId: number, params: SetCounterParams): void {
BackendService.sendGameCommand(gameId, Command_SetCounter_ext, create(Command_SetCounterSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_SetCounter_ext, create(Command_SetCounterSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_SetSideboardLockSchema, Command_SetSideboardLock_ext } from 'generated/proto/command_set_sideboard_lock_pb'; import { Command_SetSideboardLockSchema, Command_SetSideboardLock_ext } from 'generated/proto/command_set_sideboard_lock_pb';
import { SetSideboardLockParams } from 'types'; import { SetSideboardLockParams } from 'types';
export function setSideboardLock(gameId: number, params: SetSideboardLockParams): void { export function setSideboardLock(gameId: number, params: SetSideboardLockParams): void {
BackendService.sendGameCommand(gameId, Command_SetSideboardLock_ext, create(Command_SetSideboardLockSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_SetSideboardLock_ext, create(Command_SetSideboardLockSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_SetSideboardPlanSchema, Command_SetSideboardPlan_ext } from 'generated/proto/command_set_sideboard_plan_pb'; import { Command_SetSideboardPlanSchema, Command_SetSideboardPlan_ext } from 'generated/proto/command_set_sideboard_plan_pb';
import { SetSideboardPlanParams } from 'types'; import { SetSideboardPlanParams } from 'types';
export function setSideboardPlan(gameId: number, params: SetSideboardPlanParams): void { export function setSideboardPlan(gameId: number, params: SetSideboardPlanParams): void {
BackendService.sendGameCommand(gameId, Command_SetSideboardPlan_ext, create(Command_SetSideboardPlanSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_SetSideboardPlan_ext, create(Command_SetSideboardPlanSchema, params));
} }

View file

@ -1,8 +1,8 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ShuffleSchema, Command_Shuffle_ext } from 'generated/proto/command_shuffle_pb'; import { Command_ShuffleSchema, Command_Shuffle_ext } from 'generated/proto/command_shuffle_pb';
import { ShuffleParams } from 'types'; import { ShuffleParams } from 'types';
export function shuffle(gameId: number, params: ShuffleParams): void { export function shuffle(gameId: number, params: ShuffleParams): void {
BackendService.sendGameCommand(gameId, Command_Shuffle_ext, create(Command_ShuffleSchema, params)); webClient.protobuf.sendGameCommand(gameId, Command_Shuffle_ext, create(Command_ShuffleSchema, params));
} }

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_UnconcedeSchema, Command_Unconcede_ext } from 'generated/proto/command_concede_pb'; import { Command_UnconcedeSchema, Command_Unconcede_ext } from 'generated/proto/command_concede_pb';
export function unconcede(gameId: number): void { export function unconcede(gameId: number): void {
BackendService.sendGameCommand(gameId, Command_Unconcede_ext, create(Command_UnconcedeSchema)); webClient.protobuf.sendGameCommand(gameId, Command_Unconcede_ext, create(Command_UnconcedeSchema));
} }

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_UndoDrawSchema, Command_UndoDraw_ext } from 'generated/proto/command_undo_draw_pb'; import { Command_UndoDrawSchema, Command_UndoDraw_ext } from 'generated/proto/command_undo_draw_pb';
export function undoDraw(gameId: number): void { export function undoDraw(gameId: number): void {
BackendService.sendGameCommand(gameId, Command_UndoDraw_ext, create(Command_UndoDrawSchema)); webClient.protobuf.sendGameCommand(gameId, Command_UndoDraw_ext, create(Command_UndoDrawSchema));
} }

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_BanFromServer_ext, Command_BanFromServerSchema } from 'generated/proto/moderator_commands_pb'; import { Command_BanFromServer_ext, Command_BanFromServerSchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
export function banFromServer(minutes: number, userName?: string, address?: string, reason?: string, export function banFromServer(minutes: number, userName?: string, address?: string, reason?: string,
visibleReason?: string, clientid?: string, removeMessages?: number): void { visibleReason?: string, clientid?: string, removeMessages?: number): void {
BackendService.sendModeratorCommand(Command_BanFromServer_ext, create(Command_BanFromServerSchema, { webClient.protobuf.sendModeratorCommand(Command_BanFromServer_ext, create(Command_BanFromServerSchema, {
minutes, userName, address, reason, visibleReason, clientid, removeMessages minutes, userName, address, reason, visibleReason, clientid, removeMessages
}), { }), {
onSuccess: () => { onSuccess: () => {

View file

@ -1,5 +1,5 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { import {
Command_ForceActivateUser_ext, Command_ForceActivateUserSchema, Command_ForceActivateUser_ext, Command_ForceActivateUserSchema,
} from 'generated/proto/moderator_commands_pb'; } from 'generated/proto/moderator_commands_pb';
@ -7,7 +7,7 @@ import { ModeratorPersistence } from '../../persistence';
export function forceActivateUser(usernameToActivate: string, moderatorName: string): void { export function forceActivateUser(usernameToActivate: string, moderatorName: string): void {
const cmd = create(Command_ForceActivateUserSchema, { usernameToActivate, moderatorName }); const cmd = create(Command_ForceActivateUserSchema, { usernameToActivate, moderatorName });
BackendService.sendModeratorCommand(Command_ForceActivateUser_ext, cmd, { webClient.protobuf.sendModeratorCommand(Command_ForceActivateUser_ext, cmd, {
onSuccess: () => { onSuccess: () => {
ModeratorPersistence.forceActivateUser(usernameToActivate, moderatorName); ModeratorPersistence.forceActivateUser(usernameToActivate, moderatorName);
}, },

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GetAdminNotes_ext, Command_GetAdminNotesSchema } from 'generated/proto/moderator_commands_pb'; import { Command_GetAdminNotes_ext, Command_GetAdminNotesSchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
import { Response_GetAdminNotes_ext } from 'generated/proto/response_get_admin_notes_pb'; import { Response_GetAdminNotes_ext } from 'generated/proto/response_get_admin_notes_pb';
export function getAdminNotes(userName: string): void { export function getAdminNotes(userName: string): void {
BackendService.sendModeratorCommand(Command_GetAdminNotes_ext, create(Command_GetAdminNotesSchema, { userName }), { webClient.protobuf.sendModeratorCommand(Command_GetAdminNotes_ext, create(Command_GetAdminNotesSchema, { userName }), {
responseExt: Response_GetAdminNotes_ext, responseExt: Response_GetAdminNotes_ext,
onSuccess: (response) => { onSuccess: (response) => {
ModeratorPersistence.getAdminNotes(userName, response.notes); ModeratorPersistence.getAdminNotes(userName, response.notes);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GetBanHistory_ext, Command_GetBanHistorySchema } from 'generated/proto/moderator_commands_pb'; import { Command_GetBanHistory_ext, Command_GetBanHistorySchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
import { Response_BanHistory_ext } from 'generated/proto/response_ban_history_pb'; import { Response_BanHistory_ext } from 'generated/proto/response_ban_history_pb';
export function getBanHistory(userName: string): void { export function getBanHistory(userName: string): void {
BackendService.sendModeratorCommand(Command_GetBanHistory_ext, create(Command_GetBanHistorySchema, { userName }), { webClient.protobuf.sendModeratorCommand(Command_GetBanHistory_ext, create(Command_GetBanHistorySchema, { userName }), {
responseExt: Response_BanHistory_ext, responseExt: Response_BanHistory_ext,
onSuccess: (response) => { onSuccess: (response) => {
ModeratorPersistence.banHistory(userName, response.banList); ModeratorPersistence.banHistory(userName, response.banList);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GetWarnHistory_ext, Command_GetWarnHistorySchema } from 'generated/proto/moderator_commands_pb'; import { Command_GetWarnHistory_ext, Command_GetWarnHistorySchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
import { Response_WarnHistory_ext } from 'generated/proto/response_warn_history_pb'; import { Response_WarnHistory_ext } from 'generated/proto/response_warn_history_pb';
export function getWarnHistory(userName: string): void { export function getWarnHistory(userName: string): void {
BackendService.sendModeratorCommand(Command_GetWarnHistory_ext, create(Command_GetWarnHistorySchema, { userName }), { webClient.protobuf.sendModeratorCommand(Command_GetWarnHistory_ext, create(Command_GetWarnHistorySchema, { userName }), {
responseExt: Response_WarnHistory_ext, responseExt: Response_WarnHistory_ext,
onSuccess: (response) => { onSuccess: (response) => {
ModeratorPersistence.warnHistory(userName, response.warnList); ModeratorPersistence.warnHistory(userName, response.warnList);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GetWarnList_ext, Command_GetWarnListSchema } from 'generated/proto/moderator_commands_pb'; import { Command_GetWarnList_ext, Command_GetWarnListSchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
import { Response_WarnList_ext } from 'generated/proto/response_warn_list_pb'; import { Response_WarnList_ext } from 'generated/proto/response_warn_list_pb';
export function getWarnList(modName: string, userName: string, userClientid: string): void { export function getWarnList(modName: string, userName: string, userClientid: string): void {
BackendService.sendModeratorCommand(Command_GetWarnList_ext, create(Command_GetWarnListSchema, { modName, userName, userClientid }), { webClient.protobuf.sendModeratorCommand(Command_GetWarnList_ext, create(Command_GetWarnListSchema, { modName, userName, userClientid }), {
responseExt: Response_WarnList_ext, responseExt: Response_WarnList_ext,
onSuccess: (response) => { onSuccess: (response) => {
ModeratorPersistence.warnListOptions([response]); ModeratorPersistence.warnListOptions([response]);

View file

@ -1,14 +1,18 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { import {
Command_GrantReplayAccess_ext, Command_GrantReplayAccessSchema, Command_GrantReplayAccess_ext, Command_GrantReplayAccessSchema,
} from 'generated/proto/moderator_commands_pb'; } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
export function grantReplayAccess(replayId: number, moderatorName: string): void { export function grantReplayAccess(replayId: number, moderatorName: string): void {
BackendService.sendModeratorCommand(Command_GrantReplayAccess_ext, create(Command_GrantReplayAccessSchema, { replayId, moderatorName }), { webClient.protobuf.sendModeratorCommand(
onSuccess: () => { Command_GrantReplayAccess_ext,
ModeratorPersistence.grantReplayAccess(replayId, moderatorName); create(Command_GrantReplayAccessSchema, { replayId, moderatorName }),
{
onSuccess: () => {
ModeratorPersistence.grantReplayAccess(replayId, moderatorName);
},
}, },
}); );
} }

View file

@ -1,7 +1,6 @@
vi.mock('../../services/BackendService', () => ({ vi.mock('../../WebClient', () => ({
BackendService: { __esModule: true,
sendModeratorCommand: vi.fn(), default: { protobuf: { sendModeratorCommand: vi.fn() } },
},
})); }));
vi.mock('../../persistence', () => ({ vi.mock('../../persistence', () => ({
@ -20,7 +19,7 @@ vi.mock('../../persistence', () => ({
})); }));
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers'; import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
import { import {
Command_BanFromServer_ext, Command_BanFromServer_ext,
@ -53,7 +52,7 @@ import { warnUser } from './warnUser';
import { Mock } from 'vitest'; import { Mock } from 'vitest';
const { invokeOnSuccess } = makeCallbackHelpers( const { invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendModeratorCommand as Mock, webClient.protobuf.sendModeratorCommand as Mock,
2 2
); );
@ -66,7 +65,7 @@ describe('banFromServer', () => {
it('calls sendModeratorCommand with Command_BanFromServer', () => { it('calls sendModeratorCommand with Command_BanFromServer', () => {
banFromServer(30, 'alice', '1.2.3.4', 'reason', 'visible', 'cid', 1); banFromServer(30, 'alice', '1.2.3.4', 'reason', 'visible', 'cid', 1);
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_BanFromServer_ext, Command_BanFromServer_ext,
expect.objectContaining({ minutes: 30, userName: 'alice' }), expect.objectContaining({ minutes: 30, userName: 'alice' }),
expect.any(Object) expect.any(Object)
@ -87,7 +86,9 @@ describe('forceActivateUser', () => {
it('calls sendModeratorCommand with Command_ForceActivateUser', () => { it('calls sendModeratorCommand with Command_ForceActivateUser', () => {
forceActivateUser('alice', 'mod1'); forceActivateUser('alice', 'mod1');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith(Command_ForceActivateUser_ext, expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_ForceActivateUser_ext, expect.any(Object), expect.any(Object)
);
}); });
it('onSuccess calls ModeratorPersistence.forceActivateUser', () => { it('onSuccess calls ModeratorPersistence.forceActivateUser', () => {
@ -104,7 +105,7 @@ describe('getAdminNotes', () => {
it('calls sendModeratorCommand with Command_GetAdminNotes', () => { it('calls sendModeratorCommand with Command_GetAdminNotes', () => {
getAdminNotes('alice'); getAdminNotes('alice');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_GetAdminNotes_ext, Command_GetAdminNotes_ext,
expect.any(Object), expect.any(Object),
expect.objectContaining({ responseExt: Response_GetAdminNotes_ext }) expect.objectContaining({ responseExt: Response_GetAdminNotes_ext })
@ -126,7 +127,7 @@ describe('getBanHistory', () => {
it('calls sendModeratorCommand with Command_GetBanHistory', () => { it('calls sendModeratorCommand with Command_GetBanHistory', () => {
getBanHistory('alice'); getBanHistory('alice');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_GetBanHistory_ext, Command_GetBanHistory_ext,
expect.any(Object), expect.any(Object),
expect.objectContaining({ responseExt: Response_BanHistory_ext }) expect.objectContaining({ responseExt: Response_BanHistory_ext })
@ -148,7 +149,7 @@ describe('getWarnHistory', () => {
it('calls sendModeratorCommand with Command_GetWarnHistory', () => { it('calls sendModeratorCommand with Command_GetWarnHistory', () => {
getWarnHistory('alice'); getWarnHistory('alice');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_GetWarnHistory_ext, Command_GetWarnHistory_ext,
expect.any(Object), expect.any(Object),
expect.objectContaining({ responseExt: Response_WarnHistory_ext }) expect.objectContaining({ responseExt: Response_WarnHistory_ext })
@ -170,7 +171,7 @@ describe('getWarnList', () => {
it('calls sendModeratorCommand with Command_GetWarnList', () => { it('calls sendModeratorCommand with Command_GetWarnList', () => {
getWarnList('mod1', 'alice', 'US'); getWarnList('mod1', 'alice', 'US');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_GetWarnList_ext, Command_GetWarnList_ext,
expect.any(Object), expect.any(Object),
expect.objectContaining({ responseExt: Response_WarnList_ext }) expect.objectContaining({ responseExt: Response_WarnList_ext })
@ -192,7 +193,9 @@ describe('grantReplayAccess', () => {
it('calls sendModeratorCommand with Command_GrantReplayAccess', () => { it('calls sendModeratorCommand with Command_GrantReplayAccess', () => {
grantReplayAccess(10, 'mod1'); grantReplayAccess(10, 'mod1');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith(Command_GrantReplayAccess_ext, expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_GrantReplayAccess_ext, expect.any(Object), expect.any(Object)
);
}); });
it('onSuccess calls ModeratorPersistence.grantReplayAccess', () => { it('onSuccess calls ModeratorPersistence.grantReplayAccess', () => {
@ -209,7 +212,9 @@ describe('updateAdminNotes', () => {
it('calls sendModeratorCommand with Command_UpdateAdminNotes', () => { it('calls sendModeratorCommand with Command_UpdateAdminNotes', () => {
updateAdminNotes('alice', 'new notes'); updateAdminNotes('alice', 'new notes');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith(Command_UpdateAdminNotes_ext, expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_UpdateAdminNotes_ext, expect.any(Object), expect.any(Object)
);
}); });
it('onSuccess calls ModeratorPersistence.updateAdminNotes', () => { it('onSuccess calls ModeratorPersistence.updateAdminNotes', () => {
@ -226,7 +231,7 @@ describe('viewLogHistory', () => {
it('calls sendModeratorCommand with Command_ViewLogHistory', () => { it('calls sendModeratorCommand with Command_ViewLogHistory', () => {
viewLogHistory({ dateRange: 7 } as any); viewLogHistory({ dateRange: 7 } as any);
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(
Command_ViewLogHistory_ext, Command_ViewLogHistory_ext,
expect.any(Object), expect.any(Object),
expect.objectContaining({ responseExt: Response_ViewLogHistory_ext }) expect.objectContaining({ responseExt: Response_ViewLogHistory_ext })
@ -248,7 +253,7 @@ describe('warnUser', () => {
it('calls sendModeratorCommand with Command_WarnUser', () => { it('calls sendModeratorCommand with Command_WarnUser', () => {
warnUser('alice', 'bad behavior', 'cid'); warnUser('alice', 'bad behavior', 'cid');
expect(BackendService.sendModeratorCommand).toHaveBeenCalledWith(Command_WarnUser_ext, expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendModeratorCommand).toHaveBeenCalledWith(Command_WarnUser_ext, expect.any(Object), expect.any(Object));
}); });
it('onSuccess calls ModeratorPersistence.warnUser', () => { it('onSuccess calls ModeratorPersistence.warnUser', () => {

View file

@ -1,12 +1,12 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { import {
Command_UpdateAdminNotes_ext, Command_UpdateAdminNotesSchema, Command_UpdateAdminNotes_ext, Command_UpdateAdminNotesSchema,
} from 'generated/proto/moderator_commands_pb'; } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
export function updateAdminNotes(userName: string, notes: string): void { export function updateAdminNotes(userName: string, notes: string): void {
BackendService.sendModeratorCommand(Command_UpdateAdminNotes_ext, create(Command_UpdateAdminNotesSchema, { userName, notes }), { webClient.protobuf.sendModeratorCommand(Command_UpdateAdminNotes_ext, create(Command_UpdateAdminNotesSchema, { userName, notes }), {
onSuccess: () => { onSuccess: () => {
ModeratorPersistence.updateAdminNotes(userName, notes); ModeratorPersistence.updateAdminNotes(userName, notes);
}, },

View file

@ -1,12 +1,12 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ViewLogHistory_ext, Command_ViewLogHistorySchema } from 'generated/proto/moderator_commands_pb'; import { Command_ViewLogHistory_ext, Command_ViewLogHistorySchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
import { Response_ViewLogHistory_ext } from 'generated/proto/response_viewlog_history_pb'; import { Response_ViewLogHistory_ext } from 'generated/proto/response_viewlog_history_pb';
import { LogFilters } from 'types'; import { LogFilters } from 'types';
export function viewLogHistory(filters: LogFilters): void { export function viewLogHistory(filters: LogFilters): void {
BackendService.sendModeratorCommand(Command_ViewLogHistory_ext, create(Command_ViewLogHistorySchema, filters), { webClient.protobuf.sendModeratorCommand(Command_ViewLogHistory_ext, create(Command_ViewLogHistorySchema, filters), {
responseExt: Response_ViewLogHistory_ext, responseExt: Response_ViewLogHistory_ext,
onSuccess: (response) => { onSuccess: (response) => {
ModeratorPersistence.viewLogs(response.logMessage); ModeratorPersistence.viewLogs(response.logMessage);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_WarnUser_ext, Command_WarnUserSchema } from 'generated/proto/moderator_commands_pb'; import { Command_WarnUser_ext, Command_WarnUserSchema } from 'generated/proto/moderator_commands_pb';
import { ModeratorPersistence } from '../../persistence'; import { ModeratorPersistence } from '../../persistence';
export function warnUser(userName: string, reason: string, clientid?: string, removeMessages?: number): void { export function warnUser(userName: string, reason: string, clientid?: string, removeMessages?: number): void {
const cmd = create(Command_WarnUserSchema, { userName, reason, clientid, removeMessages }); const cmd = create(Command_WarnUserSchema, { userName, reason, clientid, removeMessages });
BackendService.sendModeratorCommand(Command_WarnUser_ext, cmd, { webClient.protobuf.sendModeratorCommand(Command_WarnUser_ext, cmd, {
onSuccess: () => { onSuccess: () => {
ModeratorPersistence.warnUser(userName); ModeratorPersistence.warnUser(userName);
}, },

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_CreateGame_ext, Command_CreateGameSchema } from 'generated/proto/room_commands_pb'; import { Command_CreateGame_ext, Command_CreateGameSchema } from 'generated/proto/room_commands_pb';
import { RoomPersistence } from '../../persistence'; import { RoomPersistence } from '../../persistence';
import { GameConfig } from 'types'; import { GameConfig } from 'types';
export function createGame(roomId: number, gameConfig: GameConfig): void { export function createGame(roomId: number, gameConfig: GameConfig): void {
BackendService.sendRoomCommand(roomId, Command_CreateGame_ext, create(Command_CreateGameSchema, gameConfig), { webClient.protobuf.sendRoomCommand(roomId, Command_CreateGame_ext, create(Command_CreateGameSchema, gameConfig), {
onSuccess: () => { onSuccess: () => {
RoomPersistence.gameCreated(roomId); RoomPersistence.gameCreated(roomId);
}, },

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_JoinGame_ext, Command_JoinGameSchema } from 'generated/proto/room_commands_pb'; import { Command_JoinGame_ext, Command_JoinGameSchema } from 'generated/proto/room_commands_pb';
import { RoomPersistence } from '../../persistence'; import { RoomPersistence } from '../../persistence';
import { JoinGameParams } from 'types'; import { JoinGameParams } from 'types';
export function joinGame(roomId: number, joinGameParams: JoinGameParams): void { export function joinGame(roomId: number, joinGameParams: JoinGameParams): void {
BackendService.sendRoomCommand(roomId, Command_JoinGame_ext, create(Command_JoinGameSchema, joinGameParams), { webClient.protobuf.sendRoomCommand(roomId, Command_JoinGame_ext, create(Command_JoinGameSchema, joinGameParams), {
onSuccess: () => { onSuccess: () => {
RoomPersistence.joinedGame(roomId, joinGameParams.gameId); RoomPersistence.joinedGame(roomId, joinGameParams.gameId);
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_LeaveRoom_ext, Command_LeaveRoomSchema } from 'generated/proto/room_commands_pb'; import { Command_LeaveRoom_ext, Command_LeaveRoomSchema } from 'generated/proto/room_commands_pb';
import { RoomPersistence } from '../../persistence'; import { RoomPersistence } from '../../persistence';
export function leaveRoom(roomId: number): void { export function leaveRoom(roomId: number): void {
BackendService.sendRoomCommand(roomId, Command_LeaveRoom_ext, create(Command_LeaveRoomSchema), { webClient.protobuf.sendRoomCommand(roomId, Command_LeaveRoom_ext, create(Command_LeaveRoomSchema), {
onSuccess: () => { onSuccess: () => {
RoomPersistence.leaveRoom(roomId); RoomPersistence.leaveRoom(roomId);
}, },

View file

@ -1,7 +1,6 @@
vi.mock('../../services/BackendService', () => ({ vi.mock('../../WebClient', () => ({
BackendService: { __esModule: true,
sendRoomCommand: vi.fn(), default: { protobuf: { sendRoomCommand: vi.fn() } },
},
})); }));
vi.mock('../../persistence', () => ({ vi.mock('../../persistence', () => ({
@ -13,7 +12,7 @@ vi.mock('../../persistence', () => ({
})); }));
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers'; import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { RoomPersistence } from '../../persistence'; import { RoomPersistence } from '../../persistence';
import { Command_CreateGame_ext, Command_JoinGame_ext, Command_LeaveRoom_ext, Command_RoomSay_ext } from 'generated/proto/room_commands_pb'; import { Command_CreateGame_ext, Command_JoinGame_ext, Command_LeaveRoom_ext, Command_RoomSay_ext } from 'generated/proto/room_commands_pb';
import { createGame } from './createGame'; import { createGame } from './createGame';
@ -24,7 +23,7 @@ import { roomSay } from './roomSay';
import { Mock } from 'vitest'; import { Mock } from 'vitest';
const { invokeOnSuccess } = makeCallbackHelpers( const { invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendRoomCommand as Mock, webClient.protobuf.sendRoomCommand as Mock,
// sendRoomCommand(roomId, ext, value, options) — options at index 3 // sendRoomCommand(roomId, ext, value, options) — options at index 3
3 3
); );
@ -38,7 +37,7 @@ describe('createGame', () => {
it('calls sendRoomCommand with Command_CreateGame', () => { it('calls sendRoomCommand with Command_CreateGame', () => {
createGame(5, { maxPlayers: 4 } as any); createGame(5, { maxPlayers: 4 } as any);
expect(BackendService.sendRoomCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalledWith(
5, Command_CreateGame_ext, expect.objectContaining({ maxPlayers: 4 }), expect.any(Object) 5, Command_CreateGame_ext, expect.objectContaining({ maxPlayers: 4 }), expect.any(Object)
); );
}); });
@ -57,7 +56,7 @@ describe('joinGame', () => {
it('calls sendRoomCommand with Command_JoinGame', () => { it('calls sendRoomCommand with Command_JoinGame', () => {
joinGame(7, { gameId: 42, password: '' } as any); joinGame(7, { gameId: 42, password: '' } as any);
expect(BackendService.sendRoomCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalledWith(
7, Command_JoinGame_ext, expect.objectContaining({ gameId: 42, password: '' }), expect.any(Object) 7, Command_JoinGame_ext, expect.objectContaining({ gameId: 42, password: '' }), expect.any(Object)
); );
}); });
@ -76,7 +75,7 @@ describe('leaveRoom', () => {
it('calls sendRoomCommand with Command_LeaveRoom', () => { it('calls sendRoomCommand with Command_LeaveRoom', () => {
leaveRoom(3); leaveRoom(3);
expect(BackendService.sendRoomCommand).toHaveBeenCalledWith(3, Command_LeaveRoom_ext, expect.any(Object), expect.any(Object)); expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalledWith(3, Command_LeaveRoom_ext, expect.any(Object), expect.any(Object));
}); });
it('onSuccess calls RoomPersistence.leaveRoom with roomId', () => { it('onSuccess calls RoomPersistence.leaveRoom with roomId', () => {
@ -93,7 +92,7 @@ describe('roomSay', () => {
it('calls sendRoomCommand with trimmed message', () => { it('calls sendRoomCommand with trimmed message', () => {
roomSay(2, ' hello '); roomSay(2, ' hello ');
expect(BackendService.sendRoomCommand).toHaveBeenCalledWith( expect(webClient.protobuf.sendRoomCommand).toHaveBeenCalledWith(
2, 2,
Command_RoomSay_ext, Command_RoomSay_ext,
expect.objectContaining({ message: 'hello' }) expect.objectContaining({ message: 'hello' })
@ -102,11 +101,11 @@ describe('roomSay', () => {
it('does not call sendRoomCommand when message is blank', () => { it('does not call sendRoomCommand when message is blank', () => {
roomSay(2, ' '); roomSay(2, ' ');
expect(BackendService.sendRoomCommand).not.toHaveBeenCalled(); expect(webClient.protobuf.sendRoomCommand).not.toHaveBeenCalled();
}); });
it('does not call sendRoomCommand when message is empty string', () => { it('does not call sendRoomCommand when message is empty string', () => {
roomSay(2, ''); roomSay(2, '');
expect(BackendService.sendRoomCommand).not.toHaveBeenCalled(); expect(webClient.protobuf.sendRoomCommand).not.toHaveBeenCalled();
}); });
}); });

View file

@ -1,5 +1,5 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_RoomSay_ext, Command_RoomSaySchema } from 'generated/proto/room_commands_pb'; import { Command_RoomSay_ext, Command_RoomSaySchema } from 'generated/proto/room_commands_pb';
export function roomSay(roomId: number, message: string): void { export function roomSay(roomId: number, message: string): void {
@ -9,5 +9,5 @@ export function roomSay(roomId: number, message: string): void {
return; return;
} }
BackendService.sendRoomCommand(roomId, Command_RoomSay_ext, create(Command_RoomSaySchema, { message: trimmed })); webClient.protobuf.sendRoomCommand(roomId, Command_RoomSay_ext, create(Command_RoomSaySchema, { message: trimmed }));
} }

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_AccountEdit_ext, Command_AccountEditSchema } from 'generated/proto/session_commands_pb'; import { Command_AccountEdit_ext, Command_AccountEditSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function accountEdit(passwordCheck: string, realName?: string, email?: string, country?: string): void { export function accountEdit(passwordCheck: string, realName?: string, email?: string, country?: string): void {
const cmd = create(Command_AccountEditSchema, { passwordCheck, realName, email, country }); const cmd = create(Command_AccountEditSchema, { passwordCheck, realName, email, country });
BackendService.sendSessionCommand(Command_AccountEdit_ext, cmd, { webClient.protobuf.sendSessionCommand(Command_AccountEdit_ext, cmd, {
onSuccess: () => { onSuccess: () => {
SessionPersistence.accountEditChanged(realName, email, country); SessionPersistence.accountEditChanged(realName, email, country);
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_AccountImage_ext, Command_AccountImageSchema } from 'generated/proto/session_commands_pb'; import { Command_AccountImage_ext, Command_AccountImageSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function accountImage(image: Uint8Array): void { export function accountImage(image: Uint8Array): void {
BackendService.sendSessionCommand(Command_AccountImage_ext, create(Command_AccountImageSchema, { image }), { webClient.protobuf.sendSessionCommand(Command_AccountImage_ext, create(Command_AccountImageSchema, { image }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.accountImageChanged(image); SessionPersistence.accountImageChanged(image);
}, },

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_AccountPassword_ext, Command_AccountPasswordSchema } from 'generated/proto/session_commands_pb'; import { Command_AccountPassword_ext, Command_AccountPasswordSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function accountPassword(oldPassword: string, newPassword: string, hashedNewPassword: string): void { export function accountPassword(oldPassword: string, newPassword: string, hashedNewPassword: string): void {
const cmd = create(Command_AccountPasswordSchema, { oldPassword, newPassword, hashedNewPassword }); const cmd = create(Command_AccountPasswordSchema, { oldPassword, newPassword, hashedNewPassword });
BackendService.sendSessionCommand(Command_AccountPassword_ext, cmd, { webClient.protobuf.sendSessionCommand(Command_AccountPassword_ext, cmd, {
onSuccess: () => { onSuccess: () => {
SessionPersistence.accountPasswordChange(); SessionPersistence.accountPasswordChange();
}, },

View file

@ -2,8 +2,8 @@ import { AccountActivationParams } from 'store';
import { StatusEnum, WebSocketConnectOptions } from 'types'; import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { CLIENT_CONFIG } from '../../config';
import webClient from '../../WebClient'; import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
import { Command_Activate_ext, Command_ActivateSchema } from 'generated/proto/session_commands_pb'; import { Command_Activate_ext, Command_ActivateSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_ResponseCode } from 'generated/proto/response_pb'; import { Response_ResponseCode } from 'generated/proto/response_pb';
@ -13,8 +13,8 @@ import { disconnect, login, updateStatus } from './';
export function activate(options: WebSocketConnectOptions, password?: string, passwordSalt?: string): void { export function activate(options: WebSocketConnectOptions, password?: string, passwordSalt?: string): void {
const { userName, token } = options as unknown as AccountActivationParams; const { userName, token } = options as unknown as AccountActivationParams;
BackendService.sendSessionCommand(Command_Activate_ext, create(Command_ActivateSchema, { webClient.protobuf.sendSessionCommand(Command_Activate_ext, create(Command_ActivateSchema, {
...webClient.clientConfig, ...CLIENT_CONFIG,
userName, userName,
token, token,
}), { }), {

View file

@ -1,5 +1,5 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_AddToList_ext, Command_AddToListSchema } from 'generated/proto/session_commands_pb'; import { Command_AddToList_ext, Command_AddToListSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
@ -12,7 +12,7 @@ export function addToIgnoreList(userName: string): void {
} }
export function addToList(list: string, userName: string): void { export function addToList(list: string, userName: string): void {
BackendService.sendSessionCommand(Command_AddToList_ext, create(Command_AddToListSchema, { list, userName }), { webClient.protobuf.sendSessionCommand(Command_AddToList_ext, create(Command_AddToListSchema, { list, userName }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.addToList(list, userName); SessionPersistence.addToList(list, userName);
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeckDelSchema, Command_DeckDel_ext } from 'generated/proto/command_deck_del_pb'; import { Command_DeckDelSchema, Command_DeckDel_ext } from 'generated/proto/command_deck_del_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function deckDel(deckId: number): void { export function deckDel(deckId: number): void {
BackendService.sendSessionCommand(Command_DeckDel_ext, create(Command_DeckDelSchema, { deckId }), { webClient.protobuf.sendSessionCommand(Command_DeckDel_ext, create(Command_DeckDelSchema, { deckId }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.deleteServerDeck(deckId); SessionPersistence.deleteServerDeck(deckId);
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeckDelDirSchema, Command_DeckDelDir_ext } from 'generated/proto/command_deck_del_dir_pb'; import { Command_DeckDelDirSchema, Command_DeckDelDir_ext } from 'generated/proto/command_deck_del_dir_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function deckDelDir(path: string): void { export function deckDelDir(path: string): void {
BackendService.sendSessionCommand(Command_DeckDelDir_ext, create(Command_DeckDelDirSchema, { path }), { webClient.protobuf.sendSessionCommand(Command_DeckDelDir_ext, create(Command_DeckDelDirSchema, { path }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.deleteServerDeckDir(path); SessionPersistence.deleteServerDeckDir(path);
}, },

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeckListSchema, Command_DeckList_ext } from 'generated/proto/command_deck_list_pb'; import { Command_DeckListSchema, Command_DeckList_ext } from 'generated/proto/command_deck_list_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_DeckList_ext } from 'generated/proto/response_deck_list_pb'; import { Response_DeckList_ext } from 'generated/proto/response_deck_list_pb';
export function deckList(): void { export function deckList(): void {
BackendService.sendSessionCommand(Command_DeckList_ext, create(Command_DeckListSchema), { webClient.protobuf.sendSessionCommand(Command_DeckList_ext, create(Command_DeckListSchema), {
responseExt: Response_DeckList_ext, responseExt: Response_DeckList_ext,
onSuccess: (response) => { onSuccess: (response) => {
if (response.root) { if (response.root) {

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeckNewDirSchema, Command_DeckNewDir_ext } from 'generated/proto/command_deck_new_dir_pb'; import { Command_DeckNewDirSchema, Command_DeckNewDir_ext } from 'generated/proto/command_deck_new_dir_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function deckNewDir(path: string, dirName: string): void { export function deckNewDir(path: string, dirName: string): void {
BackendService.sendSessionCommand(Command_DeckNewDir_ext, create(Command_DeckNewDirSchema, { path, dirName }), { webClient.protobuf.sendSessionCommand(Command_DeckNewDir_ext, create(Command_DeckNewDirSchema, { path, dirName }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.createServerDeckDir(path, dirName); SessionPersistence.createServerDeckDir(path, dirName);
}, },

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_DeckUploadSchema, Command_DeckUpload_ext } from 'generated/proto/command_deck_upload_pb'; import { Command_DeckUploadSchema, Command_DeckUpload_ext } from 'generated/proto/command_deck_upload_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_DeckUpload_ext } from 'generated/proto/response_deck_upload_pb'; import { Response_DeckUpload_ext } from 'generated/proto/response_deck_upload_pb';
export function deckUpload(path: string, deckId: number, deckList: string): void { export function deckUpload(path: string, deckId: number, deckList: string): void {
BackendService.sendSessionCommand(Command_DeckUpload_ext, create(Command_DeckUploadSchema, { path, deckId, deckList }), { webClient.protobuf.sendSessionCommand(Command_DeckUpload_ext, create(Command_DeckUploadSchema, { path, deckId, deckList }), {
responseExt: Response_DeckUpload_ext, responseExt: Response_DeckUpload_ext,
onSuccess: (response) => { onSuccess: (response) => {
if (response.newFile) { if (response.newFile) {

View file

@ -2,8 +2,8 @@ import { ForgotPasswordChallengeParams } from 'store';
import { StatusEnum, WebSocketConnectOptions } from 'types'; import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { CLIENT_CONFIG } from '../../config';
import webClient from '../../WebClient'; import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
import { import {
Command_ForgotPasswordChallenge_ext, Command_ForgotPasswordChallengeSchema, Command_ForgotPasswordChallenge_ext, Command_ForgotPasswordChallengeSchema,
} from 'generated/proto/session_commands_pb'; } from 'generated/proto/session_commands_pb';
@ -13,8 +13,8 @@ import { disconnect, updateStatus } from './';
export function forgotPasswordChallenge(options: WebSocketConnectOptions): void { export function forgotPasswordChallenge(options: WebSocketConnectOptions): void {
const { userName, email } = options as unknown as ForgotPasswordChallengeParams; const { userName, email } = options as unknown as ForgotPasswordChallengeParams;
BackendService.sendSessionCommand(Command_ForgotPasswordChallenge_ext, create(Command_ForgotPasswordChallengeSchema, { webClient.protobuf.sendSessionCommand(Command_ForgotPasswordChallenge_ext, create(Command_ForgotPasswordChallengeSchema, {
...webClient.clientConfig, ...CLIENT_CONFIG,
userName, userName,
email, email,
}), { }), {

View file

@ -2,8 +2,8 @@ import { ForgotPasswordParams } from 'store';
import { StatusEnum, WebSocketConnectOptions } from 'types'; import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { CLIENT_CONFIG } from '../../config';
import webClient from '../../WebClient'; import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
import { import {
Command_ForgotPasswordRequest_ext, Command_ForgotPasswordRequestSchema, Command_ForgotPasswordRequest_ext, Command_ForgotPasswordRequestSchema,
} from 'generated/proto/session_commands_pb'; } from 'generated/proto/session_commands_pb';
@ -15,8 +15,8 @@ import { disconnect, updateStatus } from './';
export function forgotPasswordRequest(options: WebSocketConnectOptions): void { export function forgotPasswordRequest(options: WebSocketConnectOptions): void {
const { userName } = options as unknown as ForgotPasswordParams; const { userName } = options as unknown as ForgotPasswordParams;
BackendService.sendSessionCommand(Command_ForgotPasswordRequest_ext, create(Command_ForgotPasswordRequestSchema, { webClient.protobuf.sendSessionCommand(Command_ForgotPasswordRequest_ext, create(Command_ForgotPasswordRequestSchema, {
...webClient.clientConfig, ...CLIENT_CONFIG,
userName, userName,
}), { }), {
responseExt: Response_ForgotPasswordRequest_ext, responseExt: Response_ForgotPasswordRequest_ext,

View file

@ -3,8 +3,8 @@ import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import type { MessageInitShape } from '@bufbuild/protobuf'; import type { MessageInitShape } from '@bufbuild/protobuf';
import { CLIENT_CONFIG } from '../../config';
import webClient from '../../WebClient'; import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
import { import {
Command_ForgotPasswordReset_ext, Command_ForgotPasswordResetSchema, Command_ForgotPasswordReset_ext, Command_ForgotPasswordResetSchema,
} from 'generated/proto/session_commands_pb'; } from 'generated/proto/session_commands_pb';
@ -17,7 +17,7 @@ export function forgotPasswordReset(options: WebSocketConnectOptions, newPasswor
const { userName, token } = options as unknown as ForgotPasswordResetParams; const { userName, token } = options as unknown as ForgotPasswordResetParams;
const params: MessageInitShape<typeof Command_ForgotPasswordResetSchema> = { const params: MessageInitShape<typeof Command_ForgotPasswordResetSchema> = {
...webClient.clientConfig, ...CLIENT_CONFIG,
userName, userName,
token, token,
...(passwordSalt ...(passwordSalt
@ -25,7 +25,7 @@ export function forgotPasswordReset(options: WebSocketConnectOptions, newPasswor
: { newPassword }), : { newPassword }),
}; };
BackendService.sendSessionCommand(Command_ForgotPasswordReset_ext, create(Command_ForgotPasswordResetSchema, params), { webClient.protobuf.sendSessionCommand(Command_ForgotPasswordReset_ext, create(Command_ForgotPasswordResetSchema, params), {
onSuccess: () => { onSuccess: () => {
updateStatus(StatusEnum.DISCONNECTED, null); updateStatus(StatusEnum.DISCONNECTED, null);
SessionPersistence.resetPasswordSuccess(); SessionPersistence.resetPasswordSuccess();

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GetGamesOfUser_ext, Command_GetGamesOfUserSchema } from 'generated/proto/session_commands_pb'; import { Command_GetGamesOfUser_ext, Command_GetGamesOfUserSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_GetGamesOfUser_ext } from 'generated/proto/response_get_games_of_user_pb'; import { Response_GetGamesOfUser_ext } from 'generated/proto/response_get_games_of_user_pb';
export function getGamesOfUser(userName: string): void { export function getGamesOfUser(userName: string): void {
BackendService.sendSessionCommand(Command_GetGamesOfUser_ext, create(Command_GetGamesOfUserSchema, { userName }), { webClient.protobuf.sendSessionCommand(Command_GetGamesOfUser_ext, create(Command_GetGamesOfUserSchema, { userName }), {
responseExt: Response_GetGamesOfUser_ext, responseExt: Response_GetGamesOfUser_ext,
onSuccess: (response) => { onSuccess: (response) => {
SessionPersistence.getGamesOfUser(userName, response); SessionPersistence.getGamesOfUser(userName, response);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_GetUserInfo_ext, Command_GetUserInfoSchema } from 'generated/proto/session_commands_pb'; import { Command_GetUserInfo_ext, Command_GetUserInfoSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_GetUserInfo_ext } from 'generated/proto/response_get_user_info_pb'; import { Response_GetUserInfo_ext } from 'generated/proto/response_get_user_info_pb';
export function getUserInfo(userName: string): void { export function getUserInfo(userName: string): void {
BackendService.sendSessionCommand(Command_GetUserInfo_ext, create(Command_GetUserInfoSchema, { userName }), { webClient.protobuf.sendSessionCommand(Command_GetUserInfo_ext, create(Command_GetUserInfoSchema, { userName }), {
responseExt: Response_GetUserInfo_ext, responseExt: Response_GetUserInfo_ext,
onSuccess: (response) => { onSuccess: (response) => {
SessionPersistence.getUserInfo(response.userInfo); SessionPersistence.getUserInfo(response.userInfo);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_JoinRoom_ext, Command_JoinRoomSchema } from 'generated/proto/session_commands_pb'; import { Command_JoinRoom_ext, Command_JoinRoomSchema } from 'generated/proto/session_commands_pb';
import { RoomPersistence } from '../../persistence'; import { RoomPersistence } from '../../persistence';
import { Response_JoinRoom_ext } from 'generated/proto/response_join_room_pb'; import { Response_JoinRoom_ext } from 'generated/proto/response_join_room_pb';
export function joinRoom(roomId: number): void { export function joinRoom(roomId: number): void {
BackendService.sendSessionCommand(Command_JoinRoom_ext, create(Command_JoinRoomSchema, { roomId }), { webClient.protobuf.sendSessionCommand(Command_JoinRoom_ext, create(Command_JoinRoomSchema, { roomId }), {
responseExt: Response_JoinRoom_ext, responseExt: Response_JoinRoom_ext,
onSuccess: (response) => { onSuccess: (response) => {
if (response.roomInfo) { if (response.roomInfo) {

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ListRooms_ext, Command_ListRoomsSchema } from 'generated/proto/session_commands_pb'; import { Command_ListRooms_ext, Command_ListRoomsSchema } from 'generated/proto/session_commands_pb';
export function listRooms(): void { export function listRooms(): void {
BackendService.sendSessionCommand(Command_ListRooms_ext, create(Command_ListRoomsSchema)); webClient.protobuf.sendSessionCommand(Command_ListRooms_ext, create(Command_ListRoomsSchema));
} }

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ListUsers_ext, Command_ListUsersSchema } from 'generated/proto/session_commands_pb'; import { Command_ListUsers_ext, Command_ListUsersSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_ListUsers_ext } from 'generated/proto/response_list_users_pb'; import { Response_ListUsers_ext } from 'generated/proto/response_list_users_pb';
export function listUsers(): void { export function listUsers(): void {
BackendService.sendSessionCommand(Command_ListUsers_ext, create(Command_ListUsersSchema), { webClient.protobuf.sendSessionCommand(Command_ListUsers_ext, create(Command_ListUsersSchema), {
responseExt: Response_ListUsers_ext, responseExt: Response_ListUsers_ext,
onSuccess: (response) => { onSuccess: (response) => {
SessionPersistence.updateUsers(response.userList); SessionPersistence.updateUsers(response.userList);

View file

@ -1,8 +1,8 @@
import { StatusEnum, WebSocketConnectOptions } from 'types'; import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import type { MessageInitShape } from '@bufbuild/protobuf'; import type { MessageInitShape } from '@bufbuild/protobuf';
import { CLIENT_CONFIG } from '../../config';
import webClient from '../../WebClient'; import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
import { Command_Login_ext, Command_LoginSchema } from 'generated/proto/session_commands_pb'; import { Command_Login_ext, Command_LoginSchema } from 'generated/proto/session_commands_pb';
import { hashPassword } from '../../utils'; import { hashPassword } from '../../utils';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
@ -20,7 +20,7 @@ export function login(options: WebSocketConnectOptions, password?: string, passw
const { userName, hashedPassword } = options; const { userName, hashedPassword } = options;
const loginConfig: MessageInitShape<typeof Command_LoginSchema> = { const loginConfig: MessageInitShape<typeof Command_LoginSchema> = {
...webClient.clientConfig, ...CLIENT_CONFIG,
clientid: 'webatrice', clientid: 'webatrice',
userName, userName,
...(passwordSalt ...(passwordSalt
@ -35,7 +35,7 @@ export function login(options: WebSocketConnectOptions, password?: string, passw
disconnect(); disconnect();
}; };
BackendService.sendSessionCommand(Command_Login_ext, create(Command_LoginSchema, loginConfig), { webClient.protobuf.sendSessionCommand(Command_Login_ext, create(Command_LoginSchema, loginConfig), {
responseExt: Response_Login_ext, responseExt: Response_Login_ext,
onSuccess: (resp) => { onSuccess: (resp) => {
const { buddyList, ignoreList, userInfo } = resp; const { buddyList, ignoreList, userInfo } = resp;

View file

@ -1,7 +1,7 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_Message_ext, Command_MessageSchema } from 'generated/proto/session_commands_pb'; import { Command_Message_ext, Command_MessageSchema } from 'generated/proto/session_commands_pb';
export function message(userName: string, message: string): void { export function message(userName: string, message: string): void {
BackendService.sendSessionCommand(Command_Message_ext, create(Command_MessageSchema, { userName, message })); webClient.protobuf.sendSessionCommand(Command_Message_ext, create(Command_MessageSchema, { userName, message }));
} }

View file

@ -1,9 +1,9 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_Ping_ext, Command_PingSchema } from 'generated/proto/session_commands_pb'; import { Command_Ping_ext, Command_PingSchema } from 'generated/proto/session_commands_pb';
export function ping(pingReceived: () => void): void { export function ping(pingReceived: () => void): void {
BackendService.sendSessionCommand(Command_Ping_ext, create(Command_PingSchema), { webClient.protobuf.sendSessionCommand(Command_Ping_ext, create(Command_PingSchema), {
onResponse: () => pingReceived(), onResponse: () => pingReceived(),
}); });
} }

View file

@ -3,8 +3,8 @@ import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create, getExtension } from '@bufbuild/protobuf'; import { create, getExtension } from '@bufbuild/protobuf';
import type { MessageInitShape } from '@bufbuild/protobuf'; import type { MessageInitShape } from '@bufbuild/protobuf';
import { CLIENT_CONFIG } from '../../config';
import webClient from '../../WebClient'; import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
import { Command_Register_ext, Command_RegisterSchema } from 'generated/proto/session_commands_pb'; import { Command_Register_ext, Command_RegisterSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { hashPassword } from '../../utils'; import { hashPassword } from '../../utils';
@ -17,7 +17,7 @@ export function register(options: WebSocketConnectOptions, password?: string, pa
const { userName, email, country, realName } = options as ServerRegisterParams; const { userName, email, country, realName } = options as ServerRegisterParams;
const params: MessageInitShape<typeof Command_RegisterSchema> = { const params: MessageInitShape<typeof Command_RegisterSchema> = {
...webClient.clientConfig, ...CLIENT_CONFIG,
userName, userName,
email, email,
country, country,
@ -33,7 +33,7 @@ export function register(options: WebSocketConnectOptions, password?: string, pa
disconnect(); disconnect();
}; };
BackendService.sendSessionCommand(Command_Register_ext, create(Command_RegisterSchema, params), { webClient.protobuf.sendSessionCommand(Command_Register_ext, create(Command_RegisterSchema, params), {
onResponseCode: { onResponseCode: {
[Response_ResponseCode.RespRegistrationAccepted]: () => { [Response_ResponseCode.RespRegistrationAccepted]: () => {
login(options, password, passwordSalt); login(options, password, passwordSalt);

View file

@ -1,5 +1,5 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_RemoveFromList_ext, Command_RemoveFromListSchema } from 'generated/proto/session_commands_pb'; import { Command_RemoveFromList_ext, Command_RemoveFromListSchema } from 'generated/proto/session_commands_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
@ -12,7 +12,7 @@ export function removeFromIgnoreList(userName: string): void {
} }
export function removeFromList(list: string, userName: string): void { export function removeFromList(list: string, userName: string): void {
BackendService.sendSessionCommand(Command_RemoveFromList_ext, create(Command_RemoveFromListSchema, { list, userName }), { webClient.protobuf.sendSessionCommand(Command_RemoveFromList_ext, create(Command_RemoveFromListSchema, { list, userName }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.removeFromList(list, userName); SessionPersistence.removeFromList(list, userName);
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReplayDeleteMatchSchema, Command_ReplayDeleteMatch_ext } from 'generated/proto/command_replay_delete_match_pb'; import { Command_ReplayDeleteMatchSchema, Command_ReplayDeleteMatch_ext } from 'generated/proto/command_replay_delete_match_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function replayDeleteMatch(gameId: number): void { export function replayDeleteMatch(gameId: number): void {
BackendService.sendSessionCommand(Command_ReplayDeleteMatch_ext, create(Command_ReplayDeleteMatchSchema, { gameId }), { webClient.protobuf.sendSessionCommand(Command_ReplayDeleteMatch_ext, create(Command_ReplayDeleteMatchSchema, { gameId }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.replayDeleteMatch(gameId); SessionPersistence.replayDeleteMatch(gameId);
}, },

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReplayGetCodeSchema, Command_ReplayGetCode_ext } from 'generated/proto/command_replay_get_code_pb'; import { Command_ReplayGetCodeSchema, Command_ReplayGetCode_ext } from 'generated/proto/command_replay_get_code_pb';
import { Response_ReplayGetCode_ext } from 'generated/proto/response_replay_get_code_pb'; import { Response_ReplayGetCode_ext } from 'generated/proto/response_replay_get_code_pb';
export function replayGetCode(gameId: number, onCodeReceived: (code: string) => void): void { export function replayGetCode(gameId: number, onCodeReceived: (code: string) => void): void {
BackendService.sendSessionCommand(Command_ReplayGetCode_ext, create(Command_ReplayGetCodeSchema, { gameId }), { webClient.protobuf.sendSessionCommand(Command_ReplayGetCode_ext, create(Command_ReplayGetCodeSchema, { gameId }), {
responseExt: Response_ReplayGetCode_ext, responseExt: Response_ReplayGetCode_ext,
onSuccess: (response) => { onSuccess: (response) => {
onCodeReceived(response.replayCode); onCodeReceived(response.replayCode);

View file

@ -1,11 +1,11 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReplayListSchema, Command_ReplayList_ext } from 'generated/proto/command_replay_list_pb'; import { Command_ReplayListSchema, Command_ReplayList_ext } from 'generated/proto/command_replay_list_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
import { Response_ReplayList_ext } from 'generated/proto/response_replay_list_pb'; import { Response_ReplayList_ext } from 'generated/proto/response_replay_list_pb';
export function replayList(): void { export function replayList(): void {
BackendService.sendSessionCommand(Command_ReplayList_ext, create(Command_ReplayListSchema), { webClient.protobuf.sendSessionCommand(Command_ReplayList_ext, create(Command_ReplayListSchema), {
responseExt: Response_ReplayList_ext, responseExt: Response_ReplayList_ext,
onSuccess: (response) => { onSuccess: (response) => {
SessionPersistence.replayList(response.matchList); SessionPersistence.replayList(response.matchList);

View file

@ -1,10 +1,10 @@
import { create } from '@bufbuild/protobuf'; import { create } from '@bufbuild/protobuf';
import { BackendService } from '../../services/BackendService'; import webClient from '../../WebClient';
import { Command_ReplayModifyMatchSchema, Command_ReplayModifyMatch_ext } from 'generated/proto/command_replay_modify_match_pb'; import { Command_ReplayModifyMatchSchema, Command_ReplayModifyMatch_ext } from 'generated/proto/command_replay_modify_match_pb';
import { SessionPersistence } from '../../persistence'; import { SessionPersistence } from '../../persistence';
export function replayModifyMatch(gameId: number, doNotHide: boolean): void { export function replayModifyMatch(gameId: number, doNotHide: boolean): void {
BackendService.sendSessionCommand(Command_ReplayModifyMatch_ext, create(Command_ReplayModifyMatchSchema, { gameId, doNotHide }), { webClient.protobuf.sendSessionCommand(Command_ReplayModifyMatch_ext, create(Command_ReplayModifyMatchSchema, { gameId, doNotHide }), {
onSuccess: () => { onSuccess: () => {
SessionPersistence.replayModifyMatch(gameId, doNotHide); SessionPersistence.replayModifyMatch(gameId, doNotHide);
}, },

Some files were not shown because too many files have changed in this diff Show more