upgrade packages + improve typing

This commit is contained in:
seavor 2026-04-14 11:34:29 -05:00
parent fd55f4fb7f
commit 19f5eefdd2
138 changed files with 4504 additions and 11015 deletions

View file

@ -21,8 +21,10 @@ import { reloadConfig } from './reloadConfig';
import { shutdownServer } from './shutdownServer';
import { updateServerMessage } from './updateServerMessage';
const { getLastSendOpts, invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendAdminCommand as vi.Mock,
import { Mock } from 'vitest';
const { invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendAdminCommand as Mock,
2
);

View file

@ -72,8 +72,10 @@ vi.mock('../../services/BackendService', () => ({
const gameId = 1;
import { Mock } from 'vitest';
beforeEach(() => {
(BackendService.sendGameCommand as vi.Mock).mockClear();
(BackendService.sendGameCommand as Mock).mockClear();
});
describe('Game commands — delegate to BackendService.sendGameCommand', () => {

View file

@ -8,7 +8,7 @@ export function getWarnList(modName: string, userName: string, userClientid: str
BackendService.sendModeratorCommand(Command_GetWarnList_ext, create(Command_GetWarnListSchema, { modName, userName, userClientid }), {
responseExt: Response_WarnList_ext,
onSuccess: (response) => {
ModeratorPersistence.warnListOptions(response.warning);
ModeratorPersistence.warnListOptions([response]);
},
});
}

View file

@ -50,8 +50,10 @@ import { updateAdminNotes } from './updateAdminNotes';
import { viewLogHistory } from './viewLogHistory';
import { warnUser } from './warnUser';
const { getLastSendOpts, invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendModeratorCommand as vi.Mock,
import { Mock } from 'vitest';
const { invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendModeratorCommand as Mock,
2
);
@ -175,11 +177,11 @@ describe('getWarnList', () => {
);
});
it('onSuccess calls ModeratorPersistence.warnListOptions with warning', () => {
it('onSuccess calls ModeratorPersistence.warnListOptions with the response', () => {
getWarnList('mod1', 'alice', 'US');
const resp = { warning: ['w1', 'w2'] };
const resp = { warning: ['w1', 'w2'], userName: 'alice', userClientid: 'US' };
invokeOnSuccess(resp, { responseCode: 0 });
expect(ModeratorPersistence.warnListOptions).toHaveBeenCalledWith(['w1', 'w2']);
expect(ModeratorPersistence.warnListOptions).toHaveBeenCalledWith([resp]);
});
});

View file

@ -21,8 +21,10 @@ import { joinGame } from './joinGame';
import { leaveRoom } from './leaveRoom';
import { roomSay } from './roomSay';
const { getLastSendOpts, invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendRoomCommand as vi.Mock,
import { Mock } from 'vitest';
const { invokeOnSuccess } = makeCallbackHelpers(
BackendService.sendRoomCommand as Mock,
// sendRoomCommand(roomId, ext, value, options) — options at index 3
3
);

View file

@ -8,7 +8,9 @@ export function deckList(): void {
BackendService.sendSessionCommand(Command_DeckList_ext, create(Command_DeckListSchema), {
responseExt: Response_DeckList_ext,
onSuccess: (response) => {
SessionPersistence.updateServerDecks(response);
if (response.root) {
SessionPersistence.updateServerDecks(response);
}
},
});
}

View file

@ -8,7 +8,9 @@ export function deckUpload(path: string, deckId: number, deckList: string): void
BackendService.sendSessionCommand(Command_DeckUpload_ext, create(Command_DeckUploadSchema, { path, deckId, deckList }), {
responseExt: Response_DeckUpload_ext,
onSuccess: (response) => {
SessionPersistence.uploadServerDeck(path, response.newFile);
if (response.newFile) {
SessionPersistence.uploadServerDeck(path, response.newFile);
}
},
});
}

View file

@ -8,7 +8,9 @@ export function joinRoom(roomId: number): void {
BackendService.sendSessionCommand(Command_JoinRoom_ext, create(Command_JoinRoomSchema, { roomId }), {
responseExt: Response_JoinRoom_ext,
onSuccess: (response) => {
RoomPersistence.joinRoom(response.roomInfo);
if (response.roomInfo) {
RoomPersistence.joinRoom(response.roomInfo);
}
},
});
}

View file

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

View file

@ -1,7 +1,7 @@
import { ServerRegisterParams } from 'store';
import { StatusEnum, WebSocketConnectOptions } from 'types';
import { create } from '@bufbuild/protobuf';
import { create, getExtension } from '@bufbuild/protobuf';
import type { MessageInitShape } from '@bufbuild/protobuf';
import webClient from '../../WebClient';
import { BackendService } from '../../services/BackendService';
@ -9,6 +9,7 @@ import { Command_Register_ext, Command_RegisterSchema } from 'generated/proto/se
import { SessionPersistence } from '../../persistence';
import { hashPassword } from '../../utils';
import { Response_ResponseCode } from 'generated/proto/response_pb';
import { Response_Register_ext } from 'generated/proto/response_register_pb';
import { login, disconnect, updateStatus } from './';
@ -65,9 +66,12 @@ export function register(options: WebSocketConnectOptions, password?: string, pa
[Response_ResponseCode.RespRegistrationDisabled]: () => onRegistrationError(
() => SessionPersistence.registrationFailed('Registration is currently disabled')
),
[Response_ResponseCode.RespUserIsBanned]: (raw) => onRegistrationError(
() => SessionPersistence.registrationFailed(raw.reasonStr, raw.endTime)
),
[Response_ResponseCode.RespUserIsBanned]: (raw) => {
const register = getExtension(raw, Response_Register_ext);
onRegistrationError(
() => SessionPersistence.registrationFailed(register.deniedReasonStr, Number(register.deniedEndTime))
);
},
},
onError: () => onRegistrationError(
() => SessionPersistence.registrationFailed('Registration failed due to a server issue')

View file

@ -31,6 +31,7 @@ vi.mock('./', async () => {
return makeSessionBarrelMock();
});
import { Mock } from 'vitest';
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
import { BackendService } from '../../services/BackendService';
import { SessionPersistence } from '../../persistence';
@ -51,6 +52,9 @@ import {
import { Response_ForgotPasswordRequest_ext } from 'generated/proto/response_forgotpasswordrequest_pb';
import { Response_Login_ext } from 'generated/proto/response_login_pb';
import { Response_PasswordSalt_ext } from 'generated/proto/response_password_salt_pb';
import { Response_Register_ext, Response_RegisterSchema } from 'generated/proto/response_register_pb';
import { create, setExtension } from '@bufbuild/protobuf';
import { ResponseSchema } from 'generated/proto/response_pb';
import { connect } from './connect';
import { updateStatus } from './updateStatus';
import { login } from './login';
@ -61,16 +65,16 @@ import { forgotPasswordRequest } from './forgotPasswordRequest';
import { forgotPasswordReset } from './forgotPasswordReset';
import { requestPasswordSalt } from './requestPasswordSalt';
const { getLastSendOpts, invokeOnSuccess, invokeResponseCode, invokeOnError } = makeCallbackHelpers(
BackendService.sendSessionCommand as vi.Mock,
const { invokeOnSuccess, invokeResponseCode, invokeOnError } = makeCallbackHelpers(
BackendService.sendSessionCommand as Mock,
2
);
beforeEach(() => {
vi.clearAllMocks();
(hashPassword as vi.Mock).mockReturnValue('hashed_pw');
(generateSalt as vi.Mock).mockReturnValue('randSalt');
(passwordSaltSupported as vi.Mock).mockReturnValue(0);
(hashPassword as Mock).mockReturnValue('hashed_pw');
(generateSalt as Mock).mockReturnValue('randSalt');
(passwordSaltSupported as Mock).mockReturnValue(0);
});
// ----------------------------------------------------------------
@ -182,7 +186,7 @@ describe('login', () => {
login({ userName: 'alice' } as any, 'secret');
const loginResp = { buddyList: [], ignoreList: [], userInfo: { name: 'alice' } };
invokeOnSuccess(loginResp, { responseCode: 0 });
const calledWith = (SessionPersistence.loginSuccessful as vi.Mock).mock.calls[0][0];
const calledWith = (SessionPersistence.loginSuccessful as Mock).mock.calls[0][0];
expect(calledWith).not.toHaveProperty('password');
});
@ -190,7 +194,7 @@ describe('login', () => {
login({ userName: 'alice' } as any, 'pw', 'salt');
const loginResp = { buddyList: [], ignoreList: [], userInfo: { name: 'alice' } };
invokeOnSuccess(loginResp, { responseCode: 0 });
const calledWith = (SessionPersistence.loginSuccessful as vi.Mock).mock.calls[0][0];
const calledWith = (SessionPersistence.loginSuccessful as Mock).mock.calls[0][0];
expect(calledWith).toHaveProperty('hashedPassword', 'hashed_pw');
});
@ -347,9 +351,11 @@ describe('register', () => {
expect(SessionPersistence.registrationFailed).toHaveBeenCalled();
});
it('RespUserIsBanned calls registrationFailed with raw.reasonStr and raw.endTime', () => {
it('RespUserIsBanned calls registrationFailed with deniedReasonStr and deniedEndTime', () => {
register({ userName: 'alice' } as any, 'pw');
invokeResponseCode(Response_ResponseCode.RespUserIsBanned, { reasonStr: 'bad user', endTime: 9999 });
const raw = create(ResponseSchema, { responseCode: Response_ResponseCode.RespUserIsBanned });
setExtension(raw, Response_Register_ext, create(Response_RegisterSchema, { deniedReasonStr: 'bad user', deniedEndTime: 9999n }));
invokeResponseCode(Response_ResponseCode.RespUserIsBanned, raw);
expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith('bad user', 9999);
});

View file

@ -31,12 +31,12 @@ vi.mock('./', async () => {
return { ...(actual as any), ...makeSessionBarrelMock() };
});
import { Mock } from 'vitest';
import { makeCallbackHelpers } from '../../__mocks__/callbackHelpers';
import { BackendService } from '../../services/BackendService';
import { SessionPersistence } from '../../persistence';
import { RoomPersistence } from '../../persistence';
import webClient from '../../WebClient';
import * as SessionCommands from './';
import { hashPassword, generateSalt, passwordSaltSupported } from '../../utils';
import {
Command_AccountEdit_ext,
@ -95,15 +95,15 @@ import { replayGetCode } from './replayGetCode';
import { replaySubmitCode } from './replaySubmitCode';
const { invokeOnSuccess, invokeCallback } = makeCallbackHelpers(
BackendService.sendSessionCommand as vi.Mock,
BackendService.sendSessionCommand as Mock,
2
);
beforeEach(() => {
vi.clearAllMocks();
(hashPassword as vi.Mock).mockReturnValue('hashed_pw');
(generateSalt as vi.Mock).mockReturnValue('randSalt');
(passwordSaltSupported as vi.Mock).mockReturnValue(0);
(hashPassword as Mock).mockReturnValue('hashed_pw');
(generateSalt as Mock).mockReturnValue('randSalt');
(passwordSaltSupported as Mock).mockReturnValue(0);
});
// ----------------------------------------------------------------
@ -215,9 +215,9 @@ describe('deckList', () => {
it('calls updateServerDecks on success', () => {
deckList();
const resp = { folders: [] };
invokeOnSuccess(resp, { responseCode: 0 });
expect(SessionPersistence.updateServerDecks).toHaveBeenCalledWith(resp);
const root = { items: [] };
invokeOnSuccess({ root }, { responseCode: 0 });
expect(SessionPersistence.updateServerDecks).toHaveBeenCalledWith({ root });
});
});
@ -380,9 +380,8 @@ describe('ping', () => {
it('calls pingReceived via onResponse', () => {
const pingReceived = vi.fn();
ping(pingReceived);
const raw = {};
invokeCallback('onResponse', raw);
expect(pingReceived).toHaveBeenCalledWith(raw);
invokeCallback('onResponse', {});
expect(pingReceived).toHaveBeenCalled();
});
});