From a49f45127cb280b9cf297dc976dfb1bc0a8503e9 Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Sat, 25 Nov 2023 23:01:49 +0700 Subject: [PATCH] chore(packages): add more docs and improve types --- packages/api/src/classes/Client.ts | 57 ++++++++++++++++--- packages/api/src/classes/ClientGateway.ts | 34 +++++++++++ .../constants/HumanizedDisconnectReason.ts | 3 + packages/shared/src/schemas/Packet.ts | 28 +-------- packages/shared/src/utils/string.ts | 5 ++ 5 files changed, 91 insertions(+), 36 deletions(-) diff --git a/packages/api/src/classes/Client.ts b/packages/api/src/classes/Client.ts index 725a811..e7e925a 100755 --- a/packages/api/src/classes/Client.ts +++ b/packages/api/src/classes/Client.ts @@ -19,14 +19,27 @@ export default class Client { }) } + /** + * Connects to the WebSocket API + * @returns A promise that resolves when the client is ready + */ connect() { return this.gateway.connect() } + /** + * Checks whether the client is ready + * @returns Whether the client is ready + */ isReady(): this is ReadiedClient { return this.ready } + /** + * Requests the API to parse the given text + * @param text The text to parse + * @returns An object containing the ID of the request and the labels + */ async parseText(text: string) { this.#throwIfNotReady() @@ -42,11 +55,11 @@ export default class Client { type CorrectPacket = Packet - const promise = new Promise((rs, rj) => { + const promise = new Promise((rs, rj) => { const parsedTextListener = (packet: CorrectPacket) => { if (packet.d.id !== currentId) return this.gateway.off('parsedText', parsedTextListener) - rs(packet) + rs(packet.d) } const parseTextFailedListener = ( @@ -54,7 +67,7 @@ export default class Client { ) => { if (packet.d.id !== currentId) return this.gateway.off('parseTextFailed', parseTextFailedListener) - rj(packet) + rj() } this.gateway.on('parsedText', parsedTextListener) @@ -64,6 +77,11 @@ export default class Client { return await promise } + /** + * Requests the API to parse the given image and return the text + * @param url The URL of the image + * @returns An object containing the ID of the request and the parsed text + */ async parseImage(url: string) { this.#throwIfNotReady() @@ -79,11 +97,11 @@ export default class Client { type CorrectPacket = Packet - const promise = new Promise((rs, rj) => { + const promise = new Promise((rs, rj) => { const parsedImageListener = (packet: CorrectPacket) => { if (packet.d.id !== currentId) return this.gateway.off('parsedImage', parsedImageListener) - rs(packet) + rs(packet.d) } const parseImageFailedListener = ( @@ -91,7 +109,7 @@ export default class Client { ) => { if (packet.d.id !== currentId) return this.gateway.off('parseImageFailed', parseImageFailedListener) - rj(packet) + rj() } this.gateway.on('parsedImage', parsedImageListener) @@ -101,25 +119,46 @@ export default class Client { return await promise } + /** + * Adds an event listener + * @param name The event name to listen for + * @param handler The event handler + * @returns The event handler function + */ on( name: TOpName, - handler: ClientGatewayEventHandlers[typeof name] + handler: ClientGatewayEventHandlers[TOpName] ) { this.gateway.on(name, handler) + return handler } + /** + * Removes an event listener + * @param name The event name to remove a listener from + * @param handler The event handler to remove + * @returns The removed event handler function + */ off( name: TOpName, - handler: ClientGatewayEventHandlers[typeof name] + handler: ClientGatewayEventHandlers[TOpName] ) { this.gateway.off(name, handler) + return handler } + /** + * Adds an event listener that will only be called once + * @param name The event name to listen for + * @param handler The event handler + * @returns The event handler function + */ once( name: TOpName, - handler: ClientGatewayEventHandlers[typeof name] + handler: ClientGatewayEventHandlers[TOpName] ) { this.gateway.once(name, handler) + return handler } #throwIfNotReady() { diff --git a/packages/api/src/classes/ClientGateway.ts b/packages/api/src/classes/ClientGateway.ts index eb119b4..ef4b2da 100755 --- a/packages/api/src/classes/ClientGateway.ts +++ b/packages/api/src/classes/ClientGateway.ts @@ -30,6 +30,10 @@ export default class ClientGateway { this.url = options.url } + /** + * Connects to the WebSocket API + * @returns A promise that resolves when the client is ready + */ connect() { return new Promise((rs, rj) => { try { @@ -53,6 +57,12 @@ export default class ClientGateway { }) } + /** + * Adds an event listener + * @param name The event name to listen for + * @param handler The event handler + * @returns The event handler function + */ on( name: TOpName, handler: ClientGatewayEventHandlers[typeof name] @@ -60,6 +70,12 @@ export default class ClientGateway { this.#emitter.on(name, handler) } + /** + * Removes an event listener + * @param name The event name to remove a listener from + * @param handler The event handler to remove + * @returns The removed event handler function + */ off( name: TOpName, handler: ClientGatewayEventHandlers[typeof name] @@ -67,6 +83,12 @@ export default class ClientGateway { this.#emitter.off(name, handler) } + /** + * Adds an event listener that will only be called once + * @param name The event name to listen for + * @param handler The event handler + * @returns The event handler function + */ once( name: TOpName, handler: ClientGatewayEventHandlers[typeof name] @@ -74,6 +96,11 @@ export default class ClientGateway { this.#emitter.once(name, handler) } + /** + * Sends a packet to the server + * @param packet The packet to send + * @returns A promise that resolves when the packet has been sent + */ send(packet: Packet) { this.#throwIfDisconnected( 'Cannot send a packet when already disconnected from the server' @@ -86,6 +113,9 @@ export default class ClientGateway { ) } + /** + * Disconnects from the WebSocket API + */ disconnect() { this.#throwIfDisconnected( 'Cannot disconnect when already disconnected from the server' @@ -94,6 +124,10 @@ export default class ClientGateway { this.#handleDisconnect(DisconnectReason.Generic) } + /** + * Checks whether the client is ready + * @returns Whether the client is ready + */ isReady(): this is ReadiedClientGateway { return this.ready } diff --git a/packages/shared/src/constants/HumanizedDisconnectReason.ts b/packages/shared/src/constants/HumanizedDisconnectReason.ts index d9b4022..fa88738 100755 --- a/packages/shared/src/constants/HumanizedDisconnectReason.ts +++ b/packages/shared/src/constants/HumanizedDisconnectReason.ts @@ -1,5 +1,8 @@ import DisconnectReason from './DisconnectReason.js' +/** + * Humanized disconnect reasons for logs + */ const HumanizedDisconnectReason = { [DisconnectReason.InvalidPacket]: 'has sent invalid packet', [DisconnectReason.Generic]: 'has been disconnected for unknown reasons', diff --git a/packages/shared/src/schemas/Packet.ts b/packages/shared/src/schemas/Packet.ts index 07267a3..34148fa 100755 --- a/packages/shared/src/schemas/Packet.ts +++ b/packages/shared/src/schemas/Packet.ts @@ -44,33 +44,6 @@ export const PacketSchema = special(input => { return false }, 'Invalid packet data') -// merge([ -// object({ -// op: nativeEnum(Operation, 'Not a valid operation number'), -// }), -// object({ -// d: special(input => { -// if ( -// typeof input === 'object' && -// input && -// 'op' in input && -// typeof input.op === 'number' && -// input.op in Operation && -// 'd' in input && -// typeof input.d === 'object' -// ) { -// try { -// PacketDataSchemas[input.op as Operation].parse(input) -// return true -// } catch { -// return false -// } -// } -// return false -// }, 'Invalid packet data'), -// }), -// ]) - /** * Schema to validate packet data for each possible operations */ @@ -118,6 +91,7 @@ export const PacketDataSchemas = { }), } as const satisfies Record< Operation, + // eslint-disable-next-line @typescript-eslint/no-explicit-any ObjectSchema | AnySchema | NullSchema > diff --git a/packages/shared/src/utils/string.ts b/packages/shared/src/utils/string.ts index 589bfa5..c9d44fe 100755 --- a/packages/shared/src/utils/string.ts +++ b/packages/shared/src/utils/string.ts @@ -1,3 +1,8 @@ +/** + * Uncapitalizes the first letter of a string + * @param str The string to uncapitalize + * @returns The uncapitalized string + */ export function uncapitalize(str: T): Uncapitalize { return (str.charAt(0).toLowerCase() + str.slice(1)) as Uncapitalize }