UNPKG

happypandax-client

Version:

A javascript client library for communicating with HappyPanda X servers

389 lines (388 loc) 12.1 kB
/// <reference types="node" /> import * as net from 'net'; import { CustomError } from 'ts-custom-error'; export declare const exception_codes: { AuthRequiredError: number; AuthWrongCredentialsError: number; AuthMissingCredentials: number; ServerError: number; AuthError: number; ClientError: number; ConnectionError: number; ServerDisconnectError: number; }; export interface CustomLogger { debug: (m: string) => void; info: (m: string) => void; warning: (m: string) => void; error: (m: string) => void; } /** * The logger * @group Logging */ export declare const log: { /** * Enable or disable logging */ enabled: boolean; /** * Can be set to a custom logger that will be used instead of console */ logger: CustomLogger; d: (msg: string) => void; i: (msg: string) => void; w: (msg: string) => void; e: (msg: string) => void; }; declare class EError extends CustomError { code: number; constructor(message: string); } /** * Base class for all server errors * @extends Error * @category Errors */ export declare class ServerError extends EError { constructor(message: string); } /** * Base class for all authentication errors * @extends ServerError * @category Errors */ export declare class AuthError extends ServerError { constructor(message: string); } /** * Wrong credentials error * @extends AuthError * @category Errors */ export declare class AuthWrongCredentialsError extends AuthError { constructor(message: string); } /** * Authentication required error * @extends AuthError * @category Errors */ export declare class AuthRequiredError extends AuthError { constructor(message: string); } /** * Missing credentials error * @extends AuthError * @category Errors */ export declare class AuthMissingCredentials extends AuthError { constructor(message: string); } /** * Base class for all client errors * @extends ServerError * @category Errors */ export declare class ClientError extends ServerError { constructor(message: string); } /** * Timeout error * @extends ClientError * @category Errors */ export declare class TimeoutError extends ClientError { constructor(message: string); } /** * Base class for all connection errors * @extends ClientError * @category Errors */ export declare class ConnectionError extends ClientError { constructor(message: string); } /** * Server disconnect error * @extends ConnectionError * @category Errors */ export declare class ServerDisconnectError extends ConnectionError { } export type AnyJson = boolean | number | string | null | JsonArray | JsonMap; export type JsonMap = { [key: string]: AnyJson; }; export interface JsonArray extends Array<AnyJson> { } export type Msg = JsonMap; export type JsonMapCompatible<TKeys extends string = string> = { [Key in TKeys]: AnyJson; }; export type ServerCommand = "handshake" | "call" | "requestauth" | "dropauth" | "serverquit" | "serverrestart" | 1 | 2 | 3 | 4 | 5 | 6; /** * A helper function that will wrap your message up like this: * ``` * msg = { * 'session': session_id, * 'name': name, * 'command': command, <--- your command is put here * 'data': data, # <--- your message is put here * } * ``` * @param {ServerCommand} command - message to wrap * @param {AnyJson} data - message to wrap * @param {string} session_id - optional, session id * @param {string} name - name of client * @param {AnyJson} msg_id - optional message id * @return {ServerMsg} */ export declare function finalize<C extends ServerCommand>(command: C, data: ClientMsg<C>["data"], session_id?: string | null, name?: string, msg_id?: ClientMsg<C>["__id__"]): ClientMsg<C>; type Version = { core: [number, number, number]; db: [number, number, number]; torrent: [number, number, number]; }; export type ServerErrorMsg = { code: number; msg: string; }; export interface ClientMsgBase<D = AnyJson> { __id__?: string | number; session: string; command: ServerCommand | AnyJson; name: string; data?: D; } export interface ClientMsg<C extends ServerCommand = "call"> extends ClientMsgBase { command: C; data: C extends "call" ? ClientFunctionMsg[] : C extends "handshake" ? { username: string; password: string; } | {} | undefined : AnyJson; } type ServerInfo = { version: Version; guest_allowed: boolean; }; export interface ServerMsgBase<D = AnyJson> { __id__?: string | number; session: string; name: string; data: D; error?: ServerErrorMsg; } export interface ServerMsg<C extends ServerCommand> extends ServerMsgBase { data: C extends "call" ? ServerFunctionMsg[] : C extends "handshake" ? "Authenticated" | null : C extends "requestauth" | "dropauth" ? ServerInfo | null : C extends "serverquit" | "serverrestart" ? "ok" | null : AnyJson; } export type ServerFunctionMsg = { fname: string; data: AnyJson; error?: ServerErrorMsg; }; export type ClientFunctionMsg = { fname: string; [arg: string]: AnyJson; }; /** * A class representing a HappyPanda X client */ export declare class Client { name: string; endpoint: [string, number]; /** * Whether to resolve localhost to IPv4 (default: true), see https://github.com/nodejs/node/issues/40702 */ resolve_IPV4_localhost: boolean; version: Version | null; guest_allowed: boolean; session: string; private _id_counter; private _alive; private _disconnected; private _ready; private _last_user; private _last_pass; private _stream; private _timeout; private _sock; private _encoder; private _decoder; private _connecting; private __data_promises_order; private __data_promises; /** * @param {Object} params - optional params * @param [params.name=js-client] {string} - name of client * @param [params.host] {string} - server host * @param [params.port] {integer} - server port * @param [params.user] {string} - username * @param [params.password] {string} - password * @param [params.session_id] {string} - a server session id * @param [params.timeout] {integer} - connection timeout */ constructor({ name, host, port, session_id, timeout, user, password, }: Partial<{ name: string; host: string; user: string | null; password: string | null; port: number; session_id: string; timeout: number; }>); private _create_socket; /** * Add a listener to the underlying socket * @param {string} event - event name * @param {Function} listener - listener function * @return {Client} */ on(event: 'connect' | 'close' | 'end' | 'error' | 'timeout', listener: (...args: any[]) => void): this; /** * Add a listener to the underlying socket * @param {string} event - event name * @param {Function} listener - listener function * @return {Client} */ once(...args: Parameters<net.Socket["once"]>): this; /** * Remove a listener from the underlying socket * @param {string} event - event name * @param {Function} listener - listener function * @return {Client} */ off(...args: Parameters<net.Socket["off"]>): this; /** * Check if server is still alive * @return {boolean} */ alive(): boolean; /** * Check if client is ready to exchange messages with server * @return {boolean} */ ready(): boolean; /** * Get the timeout value * @return {number} */ get timeout(): number; set timeout(t: number); private get _connect_msg_id(); private get _close_msg_id(); private _next_id; private _add_data_promise; private _get_data_promise; private _get_earliest_data_promise; private _server_info; /** * Set server address * @param {string} host - server host * @param {integer} port - server port */ set_endpoint(host: string, port: number): void; /** * Perfom a handshake with the HPX server * @category async * @param {object} params - optinal params * @param [params.user] {string} - username * @param [params.password] {integer} - password * @param [params.ignore_err] {boolean} - ignore error * @throws {AuthError} * @returns {Promise} */ handshake(params: Partial<{ user: string | null; password: string | null; ignore_err: boolean; }>): Promise<boolean>; /** * Forces client to request a new handshake, but doesn't invalidate previous session * @category async * @returns {Promise} */ request_auth(): Promise<void>; /** * Logout and invalidates the session * @category async * @returns {Promise} */ drop_auth(): Promise<void>; /** * Send the serverquit command * @category async * @returns {Promise} */ server_quit(): Promise<ServerMsg<"serverquit">>; /** * Send the serverrestart command * @category async * @returns {Promise} */ server_restart(): Promise<ServerMsg<"serverrestart">>; /** * Call a single function, this is even more of a shortcut than send * @category async * @param {ClientMsg<'call'>['data']} data - data * @returns {Promise} */ call(data: ClientMsg<'call'>['data']): Promise<ServerMsg<"call">>; /** * Call a single function, this is even more of a shortcut than send * @category async * @param {string} fname - function name * @param [args] {object} - function arguments * @returns {Promise} */ call_function(fname: string, args?: Record<string, AnyJson>): Promise<ServerMsg<"call">>; /** * Check if the client is still connected to the server * @return {boolean} */ is_connected(): boolean; /** * Connect to HPX server * @category async * @param {object} params - optional params * @param [params.host] {string} - server host * @param [params.port] {integer} - server port * @returns {Promise} */ connect(params?: { host?: string; port?: number; }): Promise<ServerMsgBase<ServerInfo> | undefined>; private _on_timeout; private _on_connect; private _on_error; private _on_disconnect; private _disconnect; /** * Like {@link send_raw}, but as a convenience, this method will wrap your message into the required message structure HPX expects and automatically sets the session and name * @category async * @param {JsonMap} data - the data part of the message * @param {ServerCommand} command - the command, defaults to 'call' * @returns {Promise} * @fullfil {Object} - message from server */ send<C extends ServerCommand>(command: C, data: ClientMsg<C>["data"]): Promise<ServerMsg<C>>; /** * Send json-compatible Object to server. Receive json-compatible Object from server. * * Note that this method will not modify your message and expects you to add the name and session yourself. See the {@link finalize} function. * @category async * @param {Object} msg - message to send to the server * @returns {Promise} * @fullfil {Object} - message from server */ send_raw<C extends ServerCommand>(msg: ClientMsg<C>): Promise<ServerMsg<C>>; private _send; private _recv; /** * Close the connection * @returns {Promise} */ close(): Promise<void>; } export default Client;