From a66e9309978f62f822455bd304bcfd61daa82b1c Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sat, 12 Aug 2023 02:11:15 +0200 Subject: [PATCH] Use strict type checking --- packages/lib/package.json | 1 + packages/lib/src/PlayerStats.ts | 25 +- packages/lib/src/RateLimiter.ts | 19 +- packages/lib/src/command.ts | 13 +- packages/lib/src/config/classes.ts | 145 +++++----- packages/lib/src/data/ModInfo.ts | 6 +- packages/lib/src/data/ModPack.ts | 21 +- packages/lib/src/data/index.ts | 29 -- packages/lib/src/data/messages_controller.ts | 76 ++--- packages/lib/src/data/messages_core.ts | 9 +- packages/lib/src/data/messages_host.ts | 46 +-- packages/lib/src/data/messages_instance.ts | 286 +++++++++---------- packages/lib/src/data/messages_mod.ts | 120 ++++---- packages/lib/src/data/messages_user.ts | 154 +++++----- packages/lib/src/database.ts | 8 +- packages/lib/src/errors.ts | 16 +- packages/lib/src/factorio/exchange_string.ts | 4 +- packages/lib/src/file_ops.ts | 4 +- packages/lib/src/helpers.ts | 12 +- packages/lib/src/link/WebSocket.d.ts | 2 + packages/lib/src/link/WebSocket.js | 3 + packages/lib/src/link/connectors.ts | 78 ++--- packages/lib/src/link/link.ts | 159 +++++++---- packages/lib/src/link/messages.ts | 3 +- packages/lib/src/logging.ts | 2 +- packages/lib/src/logging_utils.ts | 23 +- packages/lib/src/plugin.ts | 8 +- packages/lib/src/plugin_loader.ts | 2 +- packages/lib/src/prometheus.ts | 71 ++--- packages/lib/src/schema.ts | 2 +- packages/lib/src/shared_commands.ts | 6 +- packages/lib/src/users.ts | 10 +- packages/lib/src/zip_ops.ts | 6 +- packages/lib/tsconfig.json | 2 +- plugins/research_sync/controller.js | 2 - test/lib/link/link.js | 17 +- 36 files changed, 714 insertions(+), 676 deletions(-) create mode 100644 packages/lib/src/link/WebSocket.d.ts create mode 100644 packages/lib/src/link/WebSocket.js diff --git a/packages/lib/package.json b/packages/lib/package.json index 93696564..7a56055a 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -38,6 +38,7 @@ "@types/fs-extra": "^11.0.1", "@types/node": "^20.4.5", "@types/triple-beam": "^1.3.2", + "@types/ws": "^8.5.5", "typescript": "^5.1.6" } } diff --git a/packages/lib/src/PlayerStats.ts b/packages/lib/src/PlayerStats.ts index ed1bb244..f3f96691 100644 --- a/packages/lib/src/PlayerStats.ts +++ b/packages/lib/src/PlayerStats.ts @@ -1,3 +1,5 @@ +import { Type, Static } from "@sinclair/typebox"; + /** * Stastics collected about a player. */ @@ -27,18 +29,15 @@ export default class PlayerStats { */ lastLeaveReason?: string; - static jsonSchema = { - type: "object", - properties: { - "join_count": { type: "integer" }, - "online_time_ms": { type: "number" }, - "last_join_at": { type: "number" }, - "last_leave_at": { type: "number" }, - "last_leave_reason": { type: "string" }, - }, - }; + static jsonSchema = Type.Object({ + "join_count": Type.Optional(Type.Integer()), + "online_time_ms": Type.Optional(Type.Number()), + "last_join_at": Type.Optional(Type.Number()), + "last_leave_at": Type.Optional(Type.Number()), + "last_leave_reason": Type.Optional(Type.String()), + }); - constructor(json = {}) { + constructor(json: Static = {}) { if (json["join_count"]) { this.joinCount = json["join_count"]; } @@ -54,12 +53,12 @@ export default class PlayerStats { } } - static fromJSON(json: any) { + static fromJSON(json: Static) { return new this(json); } toJSON() { - let json = {}; + let json: Static = {}; if (this.joinCount) { json["join_count"] = this.joinCount; } diff --git a/packages/lib/src/RateLimiter.ts b/packages/lib/src/RateLimiter.ts index c7362881..24390c6b 100644 --- a/packages/lib/src/RateLimiter.ts +++ b/packages/lib/src/RateLimiter.ts @@ -27,11 +27,10 @@ export default class RateLimiter { /** * Callback invoked at most `maxRate` per second on activation. */ - action: Function | null; + action?: Function; private _lastRun = 0; - private _runTimeout = null; - private lastProgressBroadcast = Date.now(); + private _runTimeout?: NodeJS.Timeout; /** * Construct RateLimiter helper @@ -46,7 +45,7 @@ export default class RateLimiter { */ constructor(options: { maxRate?: number, action?: Function } = {}) { this.maxRate = options.maxRate || 1; - this.action = options.action || null; + this.action = options.action || undefined; } /** @@ -62,11 +61,13 @@ export default class RateLimiter { activate() { let now = Date.now(); if (now < this._lastRun + 1000 / this.maxRate) { - if (!this._runTimeout && this.action !== null) { + if (!this._runTimeout && this.action) { this._runTimeout = setTimeout(() => { - this._runTimeout = null; + this._runTimeout = undefined; this._lastRun = Date.now(); - this.action(); + if (this.action) { + this.action(); + } }, this._lastRun + 1000 / this.maxRate - now); } return false; @@ -75,11 +76,11 @@ export default class RateLimiter { // We may end up activating before the timeout does. if (this._runTimeout) { clearTimeout(this._runTimeout); - this._runTimeout = null; + this._runTimeout = undefined; } this._lastRun = now; - if (this.action !== null) { + if (this.action) { this.action(); } return true; diff --git a/packages/lib/src/command.ts b/packages/lib/src/command.ts index 1577b486..d2173ed0 100644 --- a/packages/lib/src/command.ts +++ b/packages/lib/src/command.ts @@ -157,12 +157,11 @@ export class CommandTree { * @returns host ID. */ export async function resolveHost(client: Link, hostName: string) { - let hostId: number; + let hostId: number | undefined; if (/^-?\d+$/.test(hostName)) { hostId = parseInt(hostName, 10); } else { let hosts = await client.sendTo("controller", new libData.HostListRequest()); - // @ts-ignore: TODO Remove when lib/data is migrated to ts for (let host of hosts) { if (host.name === hostName) { hostId = host.id; @@ -189,12 +188,11 @@ export async function resolveHost(client: Link, hostName: string) { * @returns instance ID. */ export async function resolveInstance(client: Link, instanceName: string) { - let instanceId: number; + let instanceId: number | undefined; if (/^-?\d+$/.test(instanceName)) { instanceId = parseInt(instanceName, 10); } else { let instances = await client.sendTo("controller", new libData.InstanceDetailsListRequest()); - // @ts-ignore: TODO Remove when lib/data is migrated to ts for (let instance of instances) { if (instance.name === instanceName) { instanceId = instance.id; @@ -222,12 +220,11 @@ export async function resolveInstance(client: Link, instanceName: string) { * @returns mod pack ID. */ export async function resolveModPack(client: Link, modPackName: string) { - let modPackId: number; + let modPackId: number | undefined; if (/^-?\d+/.test(modPackName)) { modPackId = parseInt(modPackName, 10); } else { let modPacks = await client.sendTo("controller", new libData.ModPackListRequest()); - // @ts-ignore: TODO Remove when lib/data is migrated to ts for (let modPack of modPacks) { if (modPack.name === modPackName) { modPackId = modPack.id; @@ -256,10 +253,9 @@ export async function resolveModPack(client: Link, modPackName: string) { export async function retrieveRole(client: Link, roleName: string) { let roles = await client.sendTo("controller", new libData.RoleListRequest()); - let resolvedRole: libData.RawRole; + let resolvedRole: libData.RawRole | undefined; if (/^-?\d+$/.test(roleName)) { let roleId = parseInt(roleName, 10); - // @ts-ignore: TODO Remove when lib/data is migrated to ts for (let role of roles) { if (role.id === roleId) { resolvedRole = role; @@ -268,7 +264,6 @@ export async function retrieveRole(client: Link, roleName: string) { } } else { - // @ts-ignore: TODO Remove when lib/data is migrated to ts for (let role of roles) { if (role.name === roleName) { resolvedRole = role; diff --git a/packages/lib/src/config/classes.ts b/packages/lib/src/config/classes.ts index a05bff29..b1e956d1 100644 --- a/packages/lib/src/config/classes.ts +++ b/packages/lib/src/config/classes.ts @@ -521,7 +521,7 @@ export class ConfigGroup { } else if (def.type === "object") { try { value = JSON.parse(value); - } catch (err) { + } catch (err: any) { throw new InvalidValue(`Error parsing value for ${name}: ${err.message}`); } } @@ -567,7 +567,7 @@ export class ConfigGroup { throw new InvalidValue(`Cannot set property on non-object field '${name}'`); } - let prev = this._fields.get(name) as object; + let prev = this._fields.get(name) as Record; let updated = {...prev || {}}; if (value !== undefined) { @@ -648,9 +648,9 @@ export class ConfigGroup { * @returns JSON serializable representation of the group. */ serialize(location: ConfigLocation = this.config.location) { - let fields = {}; + let fields: Record = {}; for (let [name, value] of this._fields) { - let def = (this.constructor as typeof ConfigGroup)._definitions.get(name); + let def = (this.constructor as typeof ConfigGroup)._definitions.get(name)!; if (!this._checkAccess(def, location, false)) { continue; } @@ -753,76 +753,77 @@ export class ConfigGroup { }); // Validate properties - let validTypes = ["boolean", "string", "number", "object"]; - // eslint-disable-next-line complexity - Object.keys(item).forEach(key => { - let value = item[key]; - let valueType = basicType(value); - switch (key) { - case "type": - if (!validTypes.includes(value)) { - throw new Error(`${value} is not a valid type`); - } - break; + { + const { + type, access, enum: enum_, name, title, description, restartRequired, + restartRequiredProps, optional, initial_value, ...rest + } = item; - case "access": - if (valueType !== "array") { - throw new Error("access must be an array"); - } - break; - - case "enum": - if (valueType !== "array") { - throw new Error("enum must be an array"); - } - break; - - case "name": - if (valueType !== "string") { - throw new Error("name must be a string"); - } - break; - - case "title": - if (valueType !== "string") { - throw new Error("title must be a string"); - } - break; - - case "description": - if (valueType !== "string") { - throw new Error("description must be a string"); - } - break; - - case "restartRequired": - if (valueType !== "boolean") { - throw new Error("restartRequired must be a boolean"); - } - break; - - case "restartRequiredProps": - if (valueType !== "array") { - throw new Error("restartRequiredProps must be a array"); - } - break; - - case "optional": - if (valueType !== "boolean") { - throw new Error("optional must be a boolean"); - } - break; - - case "initial_value": - if (valueType !== item.type && valueType !== "function") { - throw new Error("initial_value must match the type or be a function"); - } - break; - - default: - throw new Error(`Unknown property ${key}`); + let validTypes = ["boolean", "string", "number", "object"]; + if (type !== undefined) { + if (!validTypes.includes(type)) { + throw new Error(`${type} is not a valid type`); + } } - }); + + if (access !== undefined) { + if (basicType(access) !== "array") { + throw new Error("access must be an array"); + } + } + + if (enum_ !== undefined) { + if (basicType(enum_) !== "array") { + throw new Error("enum must be an array"); + } + } + + if (name !== undefined) { + if (typeof name !== "string") { + throw new Error("name must be a string"); + } + } + + if (title !== undefined) { + if (typeof title !== "string") { + throw new Error("title must be a string"); + } + } + + if (description !== undefined) { + if (typeof description !== "string") { + throw new Error("description must be a string"); + } + } + + if (restartRequired !== undefined) { + if (typeof restartRequired !== "boolean") { + throw new Error("restartRequired must be a boolean"); + } + } + + if (restartRequiredProps !== undefined) { + if (basicType(restartRequiredProps) !== "array") { + throw new Error("restartRequiredProps must be a array"); + } + } + + if (optional !== undefined) { + if (typeof optional !== "boolean") { + throw new Error("optional must be a boolean"); + } + } + + if (initial_value !== undefined) { + if (basicType(initial_value) !== item.type && basicType(initial_value) !== "function") { + throw new Error("initial_value must match the type or be a function"); + } + } + + for (let key of Object.keys(rest)) { + throw new Error(`Unknown property ${key}`); + } + } if (this._definitions.has(item.name)) { throw new Error(`Config field ${item.name} has already been defined`); diff --git a/packages/lib/src/data/ModInfo.ts b/packages/lib/src/data/ModInfo.ts index ce9e46b4..f642a9f7 100644 --- a/packages/lib/src/data/ModInfo.ts +++ b/packages/lib/src/data/ModInfo.ts @@ -101,7 +101,7 @@ export default class ModInfo { /** * SHA1 hash of this mod */ - sha1: string; + sha1?: string; /** * True if this mod has been deleted @@ -174,13 +174,13 @@ export default class ModInfo { return json; } - static async fromModFile(modPath) { + static async fromModFile(modPath: string) { let modInfo: Static; { // XXX: JSZip needs the whole archive loaded in memory to work. // This is clearly untenable and will be replaced later. let zip = await JSZip.loadAsync(await fs.readFile(modPath)); - let root = zip.folder(findRoot(zip)); + let root = zip.folder(findRoot(zip))!; let infoFile = root.file("info.json"); if (!infoFile) { diff --git a/packages/lib/src/data/ModPack.ts b/packages/lib/src/data/ModPack.ts index 47dfce83..b3194ec4 100644 --- a/packages/lib/src/data/ModPack.ts +++ b/packages/lib/src/data/ModPack.ts @@ -57,7 +57,7 @@ export default class ModPack { /** * Id of this mod pack */ - id: number; + id?: number; /** * Name of this mod pack. @@ -197,7 +197,7 @@ export default class ModPack { try { // eslint-disable-next-line node/no-sync buf = zlib.inflateSync(buf); - } catch (err) { + } catch (err: any) { if (err.code.startsWith("Z_")) { throw new Error("Malformed mod pack string: zlib inflate failed"); } @@ -206,7 +206,7 @@ export default class ModPack { let json: unknown; try { json = JSON.parse(buf.toString()); - } catch (err) { + } catch (err: any) { throw new Error(`Malformed mod pack string: ${err.message}`); } @@ -246,7 +246,7 @@ export default class ModPack { buf, ]); } - function immutableStringBytes(str: string) { + function immutableStringBytes(str?: string) { if (str === undefined) { return uint8Byte(1); // empty } @@ -265,7 +265,7 @@ export default class ModPack { Buffer.alloc(1), // reserved byte ]); } - function propertyTreeListBytes(entries: [string, PropertyType][]) { + function propertyTreeListBytes(entries: [string | undefined, PropertyType][]) { const sizeBytes = uint32Bytes(entries.length); const itemBytes = entries.flatMap(([key, item]) => [ immutableStringBytes(key), @@ -295,7 +295,7 @@ export default class ModPack { } else if (element instanceof Array) { type = 4; dataBytes = propertyTreeListBytes(element.map(item => [undefined, item])); - } else if (typeof element === "object") { + } else if (typeof element === "object" && element !== null) { type = 5; dataBytes = propertyTreeListBytes(Object.entries(element)); } else { @@ -332,19 +332,20 @@ export default class ModPack { ; for (let prototype of prototypes) { - if (!["startup", "runtime-global", "runtime-per-user"].includes(prototype.setting_type)) { - logger.warn(`Ignoring ${prototype.name} with unknown setting_type ${prototype.setting_type}`); + const settingType = prototype.setting_type as keyof typeof this.settings; + if (!["startup", "runtime-global", "runtime-per-user"].includes(settingType)) { + logger.warn(`Ignoring ${prototype.name} with unknown setting_type ${settingType}`); continue; } if (prototype.default_value === undefined) { logger.warn(`Ignoring ${prototype.name} with missing default_value`); continue; } - if (this.settings[prototype.setting_type].get(prototype.name)) { + if (this.settings[settingType].get(prototype.name)) { continue; } - this.settings[prototype.setting_type].set(prototype.name, { value: prototype.default_value }); + this.settings[settingType].set(prototype.name, { value: prototype.default_value }); } } } diff --git a/packages/lib/src/data/index.ts b/packages/lib/src/data/index.ts index 7f5e2349..46c1ed2a 100644 --- a/packages/lib/src/data/index.ts +++ b/packages/lib/src/data/index.ts @@ -14,32 +14,3 @@ export * from "./messages_instance"; export * from "./messages_mod"; export * from "./messages_user"; export * from "./version"; - -// TODO: Remove/migrate after lib/data is migrated to ts -import type { User } from "../users"; -export interface Serialisable { - jsonSchema: object, - fromJSON(json: any): object, -} -import { AddressType } from "./messages_core"; - -export class Request { - static type: "request"; - static src: AddressType | AddressType[]; - static dst: AddressType | AddressType[]; - static permission: null | "string" | ((user: User, message: Request) => void); - static plugin?: string; - static jsonSchema?: object; - static fromJSON?: (json: any) => Request; - static Response?: Serialisable; -} - -export class Event { - static type: "event"; - static src: AddressType | AddressType[]; - static dst: AddressType | AddressType[]; - static permission: null | "string" | ((user: User, message: Event) => void); - static plugin?: string; - static jsonSchema?: object; - static fromJSON?: (json: any) => Event; -} diff --git a/packages/lib/src/data/messages_controller.ts b/packages/lib/src/data/messages_controller.ts index 3ee14f7e..ba885145 100644 --- a/packages/lib/src/data/messages_controller.ts +++ b/packages/lib/src/data/messages_controller.ts @@ -19,19 +19,19 @@ export class RawConfig { export class ControllerConfigGetRequest { declare ["constructor"]: typeof ControllerConfigGetRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.controller.get_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.controller.get_config" as const; static Response = RawConfig; } export class ControllerConfigSetFieldRequest { declare ["constructor"]: typeof ControllerConfigSetFieldRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.controller.update_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.controller.update_config" as const; constructor( public field: string, @@ -50,10 +50,10 @@ export class ControllerConfigSetFieldRequest { export class ControllerConfigSetPropRequest { declare ["constructor"]: typeof ControllerConfigSetPropRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.controller.update_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.controller.update_config" as const; constructor( public field: string, @@ -74,10 +74,10 @@ export class ControllerConfigSetPropRequest { export class HostGenerateTokenRequest { declare ["constructor"]: typeof HostGenerateTokenRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.host.generate_token"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.host.generate_token" as const; constructor( public hostId?: number, @@ -96,10 +96,10 @@ export class HostGenerateTokenRequest { export class HostConfigCreateRequest { declare ["constructor"]: typeof HostConfigCreateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.host.create_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.host.create_config" as const; constructor( public id: number | undefined, @@ -122,10 +122,10 @@ export class HostConfigCreateRequest { export class LogSetSubscriptionsRequest { declare ["constructor"]: typeof LogSetSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.log.follow"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.log.follow" as const; constructor( public all?: boolean, @@ -150,10 +150,10 @@ export class LogSetSubscriptionsRequest { export class LogQueryRequest { declare ["constructor"]: typeof LogQueryRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.log.query"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.log.query" as const; constructor( public all: boolean, @@ -197,9 +197,9 @@ export class LogQueryRequest { export class LogMessageEvent { declare ["constructor"]: typeof LogMessageEvent; - static type = "event"; - static src = ["host", "controller"]; - static dst = ["controller", "control"]; + static type = "event" as const; + static src = ["host", "controller"] as const; + static dst = ["controller", "control"] as const; constructor( public info: object, @@ -219,17 +219,17 @@ export class LogMessageEvent { export class DebugDumpWsRequest { declare ["constructor"]: typeof DebugDumpWsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.debug.dump_ws"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.debug.dump_ws" as const; } export class DebugWsMessageEvent { declare ["constructor"]: typeof DebugWsMessageEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public direction: string, diff --git a/packages/lib/src/data/messages_core.ts b/packages/lib/src/data/messages_core.ts index 5f6b8ac4..207fc01a 100644 --- a/packages/lib/src/data/messages_core.ts +++ b/packages/lib/src/data/messages_core.ts @@ -323,7 +323,7 @@ export class ReadyData { }); static fromJSON(json: Static) { - let account: AccountDetails; + let account: AccountDetails | undefined; if (json.account) { account = AccountDetails.fromJSON(json.account); } return new this( Address.fromJSON(json.src), @@ -622,8 +622,9 @@ Message.jsonSchema = Type.Union([ ]); export class PingRequest { - static type = "request"; - static src = ["controller", "host", "control"]; - static dst = ["controller", "host", "control"]; + declare ["constructor"]: typeof PingRequest; + static type = "request" as const; + static src = ["controller", "host", "control"] as const; + static dst = ["controller", "host", "control"] as const; static permission = null; } diff --git a/packages/lib/src/data/messages_host.ts b/packages/lib/src/data/messages_host.ts index bbde6a6a..c271a3b9 100644 --- a/packages/lib/src/data/messages_host.ts +++ b/packages/lib/src/data/messages_host.ts @@ -28,19 +28,19 @@ export class HostDetails { export class HostListRequest { declare ["constructor"]: typeof HostListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.host.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.host.list" as const; static Response = jsonArray(HostDetails); } export class HostSetSubscriptionsRequest { declare ["constructor"]: typeof HostSetSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.host.subscribe"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.host.subscribe" as const; constructor( public all: boolean, @@ -60,9 +60,9 @@ export class HostSetSubscriptionsRequest { export class HostUpdateEvent { declare ["constructor"]: typeof HostUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public update: HostDetails, @@ -79,9 +79,9 @@ export class HostUpdateEvent { export class HostMetricsRequest { declare ["constructor"]: typeof HostMetricsRequest; - static type = "request"; - static src = "controller"; - static dst = "host"; + static type = "request" as const; + static src = "controller" as const; + static dst = "host" as const; static Response = class Response { // TODO: Use JSON class pattern in Prometheus constructor( public results: object[], @@ -99,9 +99,9 @@ export class HostMetricsRequest { export class ControllerConnectionEvent { declare ["constructor"]: typeof ControllerConnectionEvent; - static type = "event"; - static src = "host"; - static dst = "instance"; + static type = "event" as const; + static src = "host" as const; + static dst = "instance" as const; constructor( public event: string, @@ -118,16 +118,16 @@ export class ControllerConnectionEvent { export class PrepareControllerDisconnectRequest { declare ["constructor"]: typeof PrepareControllerDisconnectRequest; - static type = "request"; - static src = "host"; - static dst = "instance"; + static type = "request" as const; + static src = "host" as const; + static dst = "instance" as const; } export class SyncUserListsEvent { declare ["constructor"]: typeof SyncUserListsEvent; - static type = "event"; - static src = "controller"; - static dst = "host"; + static type = "event" as const; + static src = "controller" as const; + static dst = "host" as const; constructor( public adminlist: Set, diff --git a/packages/lib/src/data/messages_instance.ts b/packages/lib/src/data/messages_instance.ts index 214a665a..9fc2741a 100644 --- a/packages/lib/src/data/messages_instance.ts +++ b/packages/lib/src/data/messages_instance.ts @@ -35,10 +35,10 @@ export class InstanceDetails { export class InstanceDetailsGetRequest { declare ["constructor"]: typeof InstanceDetailsGetRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.get"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.get" as const; constructor( public instanceId: number, @@ -57,19 +57,19 @@ export class InstanceDetailsGetRequest { export class InstanceDetailsListRequest { declare ["constructor"]: typeof InstanceDetailsListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.list" as const; static Response = jsonArray(InstanceDetails); }; export class InstanceDetailsSetSubscriptionsRequest { declare ["constructor"]: typeof InstanceDetailsSetSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.subscribe"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.subscribe" as const; constructor( public all: boolean = false, @@ -88,9 +88,9 @@ export class InstanceDetailsSetSubscriptionsRequest { export class InstanceDetailsUpdateEvent { declare ["constructor"]: typeof InstanceDetailsUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public details: InstanceDetails, @@ -109,10 +109,10 @@ export class InstanceDetailsUpdateEvent { export class InstanceCreateRequest { declare ["constructor"]: typeof InstanceCreateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.create"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.create" as const; constructor( public config: object, @@ -130,10 +130,10 @@ export class InstanceCreateRequest { export class InstanceConfigGetRequest { declare ["constructor"]: typeof InstanceConfigGetRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.get_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.get_config" as const; constructor( public instanceId: number, @@ -165,10 +165,10 @@ export class InstanceConfigGetRequest { export class InstanceConfigSetFieldRequest { declare ["constructor"]: typeof InstanceConfigSetFieldRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.update_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.update_config" as const; constructor( public instanceId: number, @@ -189,10 +189,10 @@ export class InstanceConfigSetFieldRequest { export class InstanceConfigSetPropRequest { declare ["constructor"]: typeof InstanceConfigSetPropRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.update_config"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.update_config" as const; constructor( public instanceId: number, @@ -215,10 +215,10 @@ export class InstanceConfigSetPropRequest { export class InstanceAssignRequest { declare ["constructor"]: typeof InstanceAssignRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.assign"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.assign" as const; constructor( public instanceId: number, @@ -237,9 +237,9 @@ export class InstanceAssignRequest { export class InstanceMetricsRequest { declare ["constructor"]: typeof InstanceMetricsRequest; - static type = "request"; - static src = "host"; - static dst = "instance"; + static type = "request" as const; + static src = "host" as const; + static dst = "instance" as const; static Response = class Response { // TODO: Use JSON class pattern in Prometheus constructor( @@ -258,10 +258,10 @@ export class InstanceMetricsRequest { export class InstanceStartRequest { declare ["constructor"]: typeof InstanceStartRequest; - static type = "request"; - static src = ["control", "controller"]; - static dst = "instance"; - static permission = "core.instance.start"; + static type = "request" as const; + static src = ["control", "controller"] as const; + static dst = "instance" as const; + static permission = "core.instance.start" as const; constructor( public save?: string, @@ -302,19 +302,19 @@ export class SaveDetails { export class InstanceListSavesRequest { declare ["constructor"]: typeof InstanceListSavesRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.save.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.save.list" as const; static Response = jsonArray(SaveDetails); } export class InstanceSetSaveListSubscriptionsRequest { declare ["constructor"]: typeof InstanceSetSaveListSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.save.list_subscribe"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.save.list_subscribe" as const; constructor( public all: boolean = false, @@ -333,9 +333,9 @@ export class InstanceSetSaveListSubscriptionsRequest { export class InstanceSaveListUpdateEvent { declare ["constructor"]: typeof InstanceSaveListUpdateEvent; - static type = "event"; - static src = ["instance", "host", "controller"]; - static dst = ["controller", "control"]; + static type = "event" as const; + static src = ["instance", "host", "controller"] as const; + static dst = ["controller", "control"] as const; constructor( public instanceId: number, @@ -354,10 +354,10 @@ export class InstanceSaveListUpdateEvent { export class InstanceCreateSaveRequest { declare ["constructor"]: typeof InstanceCreateSaveRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.save.create"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.save.create" as const; constructor( public name: string, @@ -380,10 +380,10 @@ export class InstanceCreateSaveRequest { export class InstanceRenameSaveRequest { declare ["constructor"]: typeof InstanceRenameSaveRequest; - static type = "request"; - static src = ["control", "controller"]; - static dst = ["controller", "host"]; - static permission = "core.instance.save.rename"; + static type = "request" as const; + static src = ["control", "controller"] as const; + static dst = ["controller", "host"] as const; + static permission = "core.instance.save.rename" as const; constructor( public instanceId: number, @@ -404,10 +404,10 @@ export class InstanceRenameSaveRequest { export class InstanceCopySaveRequest { declare ["constructor"]: typeof InstanceCopySaveRequest; - static type = "request"; - static src = ["control", "controller"]; - static dst = ["controller", "host"]; - static permission = "core.instance.save.copy"; + static type = "request" as const; + static src = ["control", "controller"] as const; + static dst = ["controller", "host"] as const; + static permission = "core.instance.save.copy" as const; constructor( public instanceId: number, @@ -428,10 +428,10 @@ export class InstanceCopySaveRequest { export class InstanceDeleteSaveRequest { declare ["constructor"]: typeof InstanceDeleteSaveRequest; - static type = "request"; - static src = ["control", "controller"]; - static dst = ["controller", "host"]; - static permission = "core.instance.save.delete"; + static type = "request" as const; + static src = ["control", "controller"] as const; + static dst = ["controller", "host"] as const; + static permission = "core.instance.save.delete" as const; constructor( public instanceId: number, @@ -450,10 +450,10 @@ export class InstanceDeleteSaveRequest { export class InstanceDownloadSaveRequest { declare ["constructor"]: typeof InstanceDownloadSaveRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.save.download"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.save.download" as const; constructor( public instanceId: number, @@ -474,9 +474,9 @@ export class InstanceDownloadSaveRequest { export class InstanceTransferSaveRequest { declare ["constructor"]: typeof InstanceTransferSaveRequest; - static type = "request"; - static src = ["control", "controller"]; - static dst = ["controller", "host"]; + static type = "request" as const; + static src = ["control", "controller"] as const; + static dst = ["controller", "host"] as const; static permission(user: User, message: MessageRequest) { user.checkPermission("core.instance.save.transfer"); if (typeof message.data === "object" && message.data !== null) { @@ -517,9 +517,9 @@ export class InstanceTransferSaveRequest { export class InstancePullSaveRequest { declare ["constructor"]: typeof InstancePullSaveRequest; - static type = "request"; - static src = "controller"; - static dst = "host"; + static type = "request" as const; + static src = "controller" as const; + static dst = "host" as const; constructor( public instanceId: number, @@ -542,9 +542,9 @@ export class InstancePullSaveRequest { export class InstancePushSaveRequest { declare ["constructor"]: typeof InstancePushSaveRequest; - static type = "request"; - static src = "controller"; - static dst = "host"; + static type = "request" as const; + static src = "controller" as const; + static dst = "host" as const; constructor( public instanceId: number, @@ -565,10 +565,10 @@ export class InstancePushSaveRequest { export class InstanceLoadScenarioRequest { declare ["constructor"]: typeof InstanceLoadScenarioRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.load_scenario"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.load_scenario" as const; constructor( public scenario: string, @@ -591,42 +591,42 @@ export class InstanceLoadScenarioRequest { export class InstanceExportDataRequest { declare ["constructor"]: typeof InstanceExportDataRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.export_data"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.export_data" as const; } export class InstanceExtractPlayersRequest { declare ["constructor"]: typeof InstanceExtractPlayersRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.extract_players"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.extract_players" as const; } export class InstanceStopRequest { declare ["constructor"]: typeof InstanceStopRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.stop"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.stop" as const; } export class InstanceKillRequest { declare ["constructor"]: typeof InstanceKillRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.kill"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.kill" as const; } export class InstanceDeleteRequest { declare ["constructor"]: typeof InstanceDeleteRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.instance.delete"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.instance.delete" as const; constructor( public instanceId: number, @@ -643,9 +643,9 @@ export class InstanceDeleteRequest { export class InstanceDeleteInternalRequest { declare ["constructor"]: typeof InstanceDeleteInternalRequest; - static type = "request"; - static src = "controller"; - static dst = "host"; + static type = "request" as const; + static src = "controller" as const; + static dst = "host" as const; constructor( public instanceId: number, @@ -662,10 +662,10 @@ export class InstanceDeleteInternalRequest { export class InstanceSendRconRequest { declare ["constructor"]: typeof InstanceSendRconRequest; - static type = "request"; - static src = "control"; - static dst = "instance"; - static permission = "core.instance.send_rcon"; + static type = "request" as const; + static src = "control" as const; + static dst = "instance" as const; + static permission = "core.instance.send_rcon" as const; constructor( public command: string, @@ -704,9 +704,9 @@ export class RawInstanceInfo { export class InstancesUpdateRequest { declare ["constructor"]: typeof InstancesUpdateRequest; - static type = "request"; - static src = "host"; - static dst = "controller"; + static type = "request" as const; + static src = "host" as const; + static dst = "controller" as const; constructor( public instances: RawInstanceInfo[], @@ -725,9 +725,9 @@ export class InstancesUpdateRequest { export class InstanceAssignInternalRequest { declare ["constructor"]: typeof InstanceAssignInternalRequest; - static type = "request"; - static src = "controller"; - static dst = "host"; + static type = "request" as const; + static src = "controller" as const; + static dst = "host" as const; constructor( public instanceId: number, @@ -747,9 +747,9 @@ export class InstanceAssignInternalRequest { export class InstanceUnassignInternalRequest { declare ["constructor"]: typeof InstanceUnassignInternalRequest; - static type = "request"; - static src = "controller"; - static dst = "host"; + static type = "request" as const; + static src = "controller" as const; + static dst = "host" as const; constructor( public instanceId: number, @@ -766,9 +766,9 @@ export class InstanceUnassignInternalRequest { export class InstanceInitialisedEvent { declare ["constructor"]: typeof InstanceInitialisedEvent; - static type = "event"; - static src = "instance"; - static dst = "host"; + static type = "event" as const; + static src = "instance" as const; + static dst = "host" as const; constructor( public plugins: Record, @@ -785,9 +785,9 @@ export class InstanceInitialisedEvent { export class InstanceStatusChangedEvent { declare ["constructor"]: typeof InstanceStatusChangedEvent; - static type = "event"; - static src = ["instance", "host"]; - static dst = "controller"; + static type = "event" as const; + static src = ["instance", "host"] as const; + static dst = "controller" as const; constructor( public instanceId: number, @@ -810,9 +810,9 @@ export class InstanceStatusChangedEvent { export class InstanceDetailsChangedEvent { declare ["constructor"]: typeof InstanceDetailsChangedEvent; - static type = "event"; - static src = "instance"; - static dst = "controller"; + static type = "event" as const; + static src = "instance" as const; + static dst = "controller" as const; constructor( public details: InstanceDetails, @@ -827,9 +827,9 @@ export class InstanceDetailsChangedEvent { export class InstanceBanlistUpdateEvent { declare ["constructor"]: typeof InstanceBanlistUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "instance"; + static type = "event" as const; + static src = "controller" as const; + static dst = "instance" as const; constructor( public name: string, @@ -850,9 +850,9 @@ export class InstanceBanlistUpdateEvent { export class InstanceAdminlistUpdateEvent { declare ["constructor"]: typeof InstanceAdminlistUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "instance"; + static type = "event" as const; + static src = "controller" as const; + static dst = "instance" as const; constructor( public name: string, @@ -871,9 +871,9 @@ export class InstanceAdminlistUpdateEvent { export class InstanceWhitelistUpdateEvent { declare ["constructor"]: typeof InstanceWhitelistUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "instance"; + static type = "event" as const; + static src = "controller" as const; + static dst = "instance" as const; constructor( public name: string, @@ -892,9 +892,9 @@ export class InstanceWhitelistUpdateEvent { export class InstancePlayerUpdateEvent { declare ["constructor"]: typeof InstancePlayerUpdateEvent; - static type = "event"; - static src = "instance"; - static dst = "controller"; + static type = "event" as const; + static src = "instance" as const; + static dst = "controller" as const; constructor( public type: string, diff --git a/packages/lib/src/data/messages_mod.ts b/packages/lib/src/data/messages_mod.ts index a7c8c72c..0fadcfda 100644 --- a/packages/lib/src/data/messages_mod.ts +++ b/packages/lib/src/data/messages_mod.ts @@ -6,10 +6,10 @@ import { JsonString, jsonArray } from "./composites"; export class ModPackGetRequest { declare ["constructor"]: typeof ModPackGetRequest; - static type = "request"; - static src = ["instance", "control"]; - static dst = "controller"; - static permission = "core.mod_pack.get"; + static type = "request" as const; + static src = ["instance", "control"] as const; + static dst = "controller" as const; + static permission = "core.mod_pack.get" as const; constructor( public id: number, @@ -28,28 +28,28 @@ export class ModPackGetRequest { export class ModPackGetDefaultRequest { declare ["constructor"]: typeof ModPackGetDefaultRequest; - static type = "request"; - static src = ["instance", "control"]; - static dst = "controller"; - static permission = "core.mod_pack.get"; + static type = "request" as const; + static src = ["instance", "control"] as const; + static dst = "controller" as const; + static permission = "core.mod_pack.get" as const; static Response = ModPack; } export class ModPackListRequest { declare ["constructor"]: typeof ModPackListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod_pack.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod_pack.list" as const; static Response = jsonArray(ModPack); } export class ModPackCreateRequest { declare ["constructor"]: typeof ModPackCreateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod_pack.create"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod_pack.create" as const; constructor( public modPack: ModPack, @@ -66,10 +66,10 @@ export class ModPackCreateRequest { export class ModPackUpdateRequest { declare ["constructor"]: typeof ModPackUpdateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod_pack.update"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod_pack.update" as const; constructor( public modPack: ModPack, @@ -86,10 +86,10 @@ export class ModPackUpdateRequest { export class ModPackDeleteRequest { declare ["constructor"]: typeof ModPackDeleteRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod_pack.delete"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod_pack.delete" as const; constructor( public id: number, @@ -106,10 +106,10 @@ export class ModPackDeleteRequest { export class ModPackSetSubscriptionsRequest { declare ["constructor"]: typeof ModPackSetSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod_pack.subscribe"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod_pack.subscribe" as const; constructor( public all: boolean, @@ -128,10 +128,10 @@ export class ModPackSetSubscriptionsRequest { export class ModGetRequest { declare ["constructor"]: typeof ModGetRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod.get"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod.get" as const; constructor( public name: string, @@ -152,19 +152,19 @@ export class ModGetRequest { export class ModListRequest { declare ["constructor"]: typeof ModListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod.list" as const; static Response = jsonArray(ModInfo); } export class ModSearchRequest { declare ["constructor"]: typeof ModSearchRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod.search"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod.search" as const; constructor( public query: string, @@ -178,8 +178,8 @@ export class ModSearchRequest { static jsonSchema = Type.Object({ "query": Type.String(), "factorioVersion": Type.String(), - "pageSize": Type.Integer(), - "page": Type.Optional(Type.Integer()), + "page": Type.Integer(), + "pageSize": Type.Optional(Type.Integer()), "sort": Type.Optional(Type.String()), "sortOrder": Type.Optional(Type.String()), }); @@ -219,10 +219,10 @@ export class ModSearchRequest { export class ModSetSubscriptionsRequest { declare ["constructor"]: typeof ModSetSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod.subscribe"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod.subscribe" as const; constructor( public all: boolean, @@ -241,10 +241,10 @@ export class ModSetSubscriptionsRequest { export class ModDownloadRequest { declare ["constructor"]: typeof ModDownloadRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod.download"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod.download" as const; constructor( public name: string, @@ -265,10 +265,10 @@ export class ModDownloadRequest { export class ModDeleteRequest { declare ["constructor"]: typeof ModDeleteRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.mod.delete"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.mod.delete" as const; constructor( public name: string, @@ -287,9 +287,9 @@ export class ModDeleteRequest { export class ModPackUpdateEvent { declare ["constructor"]: typeof ModPackUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public modPack: ModPack, @@ -306,9 +306,9 @@ export class ModPackUpdateEvent { export class ModUpdateEvent { declare ["constructor"]: typeof ModUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public mod: ModInfo, diff --git a/packages/lib/src/data/messages_user.ts b/packages/lib/src/data/messages_user.ts index a9b72769..a975476b 100644 --- a/packages/lib/src/data/messages_user.ts +++ b/packages/lib/src/data/messages_user.ts @@ -22,10 +22,10 @@ export class RawPermission { // TODO refactor into lib/user.Permission export class PermissionListRequest { declare ["constructor"]: typeof PermissionListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.permission.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.permission.list" as const; static Response = jsonArray(RawPermission); } @@ -51,19 +51,19 @@ export class RawRole { // TODO refactor into lib/user.Role export class RoleListRequest { declare ["constructor"]: typeof RoleListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.role.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.role.list" as const; static Response = jsonArray(RawRole); } export class RoleCreateRequest { declare ["constructor"]: typeof RoleCreateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.role.create"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.role.create" as const; constructor( public name: string, @@ -86,10 +86,10 @@ export class RoleCreateRequest { export class RoleUpdateRequest { declare ["constructor"]: typeof RoleUpdateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.role.update"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.role.update" as const; constructor( public id: number, @@ -112,10 +112,10 @@ export class RoleUpdateRequest { export class RoleGrantDefaultPermissionsRequest { declare ["constructor"]: typeof RoleGrantDefaultPermissionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.role.update"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.role.update" as const; constructor( public id: number, @@ -132,10 +132,10 @@ export class RoleGrantDefaultPermissionsRequest { export class RoleDeleteRequest { declare ["constructor"]: typeof RoleDeleteRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.role.delete"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.role.delete" as const; constructor( public id: number, @@ -173,20 +173,20 @@ export class RawUser { // TODO refactor into lib/user.User isWhitelisted: Type.Optional(Type.Boolean()), banReason: Type.Optional(Type.String()), isDeleted: Type.Optional(Type.Boolean()), - playerStats: Type.Optional(Type.Unsafe(PlayerStats.jsonSchema)), + playerStats: Type.Optional(PlayerStats.jsonSchema), instanceStats: Type.Optional( Type.Array( - Type.Tuple([Type.Integer(), Type.Unsafe(PlayerStats.jsonSchema)]), + Type.Tuple([Type.Integer(), PlayerStats.jsonSchema]), ) ), }); static fromJSON(json: Static) { - let playerStats: PlayerStats; + let playerStats: PlayerStats | undefined; if (json.playerStats) { playerStats = PlayerStats.fromJSON(json.playerStats); } - let instanceStats: Map; + let instanceStats: Map | undefined; if (json.instanceStats) { instanceStats = new Map( json.instanceStats.map(([id, stats]) => [id, PlayerStats.fromJSON(stats)]) @@ -208,10 +208,12 @@ export class RawUser { // TODO refactor into lib/user.User isWhitelisted: this.isWhitelisted, banReason: this.banReason, isDeleted: this.isDeleted, - playerStats: this.playerStats, }; + if (this.playerStats) { + json.playerStats = this.playerStats.toJSON() + } if (this.instanceStats) { - json.instanceStats = [...this.instanceStats]; + json.instanceStats = [...this.instanceStats].map(([k, v]) => [k, v.toJSON()]); } return json; } @@ -219,10 +221,10 @@ export class RawUser { // TODO refactor into lib/user.User export class UserGetRequest { declare ["constructor"]: typeof UserGetRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.get"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.get" as const; constructor( public name: string, @@ -241,19 +243,19 @@ export class UserGetRequest { export class UserListRequest { declare ["constructor"]: typeof UserListRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.list"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.list" as const; static Response = jsonArray(RawUser); } export class UserSetSubscriptionsRequest { declare ["constructor"]: typeof UserSetSubscriptionsRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.subscribe"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.subscribe" as const; constructor( public all: boolean, @@ -272,10 +274,10 @@ export class UserSetSubscriptionsRequest { export class UserCreateRequest { declare ["constructor"]: typeof UserCreateRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.create"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.create" as const; constructor( public name: string, @@ -292,10 +294,10 @@ export class UserCreateRequest { export class UserRevokeTokenRequest { declare ["constructor"]: typeof UserRevokeTokenRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.revoke_token"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.revoke_token" as const; constructor( public name: string, @@ -312,10 +314,10 @@ export class UserRevokeTokenRequest { export class UserUpdateRolesRequest { declare ["constructor"]: typeof UserUpdateRolesRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.update_roles"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.update_roles" as const; constructor( public name: string, @@ -334,10 +336,10 @@ export class UserUpdateRolesRequest { export class UserSetAdminRequest { declare ["constructor"]: typeof UserSetAdminRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.set_admin"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.set_admin" as const; constructor( public name: string, @@ -358,10 +360,10 @@ export class UserSetAdminRequest { export class UserSetWhitelistedRequest { declare ["constructor"]: typeof UserSetWhitelistedRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.set_whitelisted"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.set_whitelisted" as const; constructor( public name: string, @@ -382,10 +384,10 @@ export class UserSetWhitelistedRequest { export class UserSetBannedRequest { declare ["constructor"]: typeof UserSetBannedRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.set_banned"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.set_banned" as const; constructor( public name: string, @@ -408,10 +410,10 @@ export class UserSetBannedRequest { export class UserDeleteRequest { declare ["constructor"]: typeof UserDeleteRequest; - static type = "request"; - static src = "control"; - static dst = "controller"; - static permission = "core.user.delete"; + static type = "request" as const; + static src = "control" as const; + static dst = "controller" as const; + static permission = "core.user.delete" as const; constructor( public name: string, @@ -429,9 +431,9 @@ export class UserDeleteRequest { export class AccountUpdateEvent { declare ["constructor"]: typeof AccountUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public roles?: { name: string, id: number, permissions: string[] }[], @@ -454,9 +456,9 @@ export class AccountUpdateEvent { export class UserUpdateEvent { declare ["constructor"]: typeof UserUpdateEvent; - static type = "event"; - static src = "controller"; - static dst = "control"; + static type = "event" as const; + static src = "controller" as const; + static dst = "control" as const; constructor( public user: RawUser, diff --git a/packages/lib/src/database.ts b/packages/lib/src/database.ts index 3bc65235..3b388ecf 100644 --- a/packages/lib/src/database.ts +++ b/packages/lib/src/database.ts @@ -54,7 +54,7 @@ export async function loadJsonAsMap(filePath: string): Promise(promise: Promise, time: number, timeoutResult: T) { - let timer: ReturnType; + let timer: NodeJS.Timer | undefined; try { return await Promise.race([ promise, @@ -157,10 +157,10 @@ function parseSearchTerm( input: string, attributes: Record, issues: Array -): [number, ParsedTerm] { +): [number, ParsedTerm | undefined] { // attribute = identifier, ':', word // term = word | attribute - let term: ParsedTerm; + let term: ParsedTerm | undefined; if (["-", '"'].includes(input.charAt(pos))) { ([pos, term] = parseSearchWord(pos, input)); } else { @@ -274,12 +274,12 @@ export function parseSearchString( // search = [ term, *( [ whitespace ], term ) ] input = input.trim(); let parsed = { - terms: [], - issues: [], + terms: [] as ParsedTerm[], + issues: [] as string[], }; let pos = 0; while (pos < input.length) { - let term: ParsedTerm; + let term: ParsedTerm | undefined; ([pos, term] = parseSearchTerm(pos, input, attributes, parsed.issues)); if (term) { parsed.terms.push(term); diff --git a/packages/lib/src/link/WebSocket.d.ts b/packages/lib/src/link/WebSocket.d.ts new file mode 100644 index 00000000..c44f2672 --- /dev/null +++ b/packages/lib/src/link/WebSocket.d.ts @@ -0,0 +1,2 @@ +import ws = require("ws"); +export = ws; diff --git a/packages/lib/src/link/WebSocket.js b/packages/lib/src/link/WebSocket.js new file mode 100644 index 00000000..b85227a1 --- /dev/null +++ b/packages/lib/src/link/WebSocket.js @@ -0,0 +1,3 @@ +"use strict"; +// eslint-disable-next-line node/no-process-env +module.exports = process.env.APP_ENV === "browser" ? window.WebSocket : require("ws"); diff --git a/packages/lib/src/link/connectors.ts b/packages/lib/src/link/connectors.ts index 86ec3980..b52d2103 100644 --- a/packages/lib/src/link/connectors.ts +++ b/packages/lib/src/link/connectors.ts @@ -2,14 +2,13 @@ "use strict"; import { strict as assert } from "assert"; import events from "events"; -// eslint-disable-next-line node/no-process-env -// @ts-ignore -const WebSocket = process.env.APP_ENV === "browser" ? window.WebSocket : require("ws"); +import WebSocket from "./WebSocket"; import * as libData from "../data"; import * as libErrors from "../errors"; import { logger } from "../logging"; import ExponentialBackoff from "../ExponentialBackoff"; +import type { Request, Event } from "./link"; /** @@ -37,15 +36,15 @@ export abstract class BaseConnector extends events.EventEmitter { abstract send(message: libData.Message): void; - sendRequest( - request: libData.Request, + sendRequest( + request: Request, requestId: number, dst: libData.Address ) { let seq = this._seq; this._seq += 1; let src = new libData.Address(this.src.type, this.src.id, requestId); - let Request = request.constructor as typeof libData.Request; + let Request = request.constructor; let name = Request.plugin ? `${Request.plugin}:${Request.name}` : Request.name; let hasData = Boolean(Request.jsonSchema); const message = new libData.MessageRequest(seq, src, dst, name, hasData ? request : undefined); @@ -69,10 +68,10 @@ export abstract class BaseConnector extends events.EventEmitter { return seq; } - sendEvent(event: libData.Event, dst: libData.Address) { + sendEvent(event: Event, dst: libData.Address) { let seq = this._seq; this._seq += 1; - let Event = event.constructor as typeof libData.Event; + let Event = event.constructor; let name = Event.plugin ? `${Event.plugin}:${Event.name}` : Event.name; let hasData = Boolean(Event.jsonSchema); const message = new libData.MessageEvent(seq, this.src, dst, name, hasData ? event : undefined); @@ -82,6 +81,12 @@ export abstract class BaseConnector extends events.EventEmitter { } type ConnectorState = "closed" | "connecting" | "connected" | "resuming"; +type ReliableMessages = + | libData.MessageRequest + | libData.MessageResponse + | libData.MessageResponseError + | libData.MessageEvent +; /** * Base connector for links @@ -92,12 +97,12 @@ export abstract class WebSocketBaseConnector extends BaseConnector { // One of closed, connecting (client only), connected and resuming. _state: ConnectorState = "closed"; _closing = false; - _socket = null; - _lastHeartbeat = null; - _heartbeatId: NodeJS.Timer = null; + _socket: WebSocket | null = null; + _lastHeartbeat: number | null = null; + _heartbeatId: NodeJS.Timer | null = null; _heartbeatInterval: number | null = null; _lastReceivedSeq = undefined; - _sendBuffer = []; + _sendBuffer: (ReliableMessages)[] = []; constructor(src: libData.Address, dst: libData.Address) { super(src, dst); @@ -194,13 +199,13 @@ export abstract class WebSocketBaseConnector extends BaseConnector { _doHeartbeat() { this._check("connected"); - if (Date.now() - this._lastHeartbeat > 2000 * this._heartbeatInterval) { + if (Date.now() - this._lastHeartbeat! > 2000 * this._heartbeatInterval!) { logger.verbose("Connector | closing after heartbeat timed out"); // eslint-disable-next-line node/no-process-env if (process.env.APP_ENV === "browser") { - this._socket.close(4008, "Heartbeat timeout"); + this._socket!.close(4008, "Heartbeat timeout"); } else { - this._socket.terminate(); + this._socket!.terminate(); } } else { @@ -223,7 +228,7 @@ export abstract class WebSocketBaseConnector extends BaseConnector { this._lastHeartbeat = Date.now(); this._heartbeatId = setInterval(() => { this._doHeartbeat(); - }, this._heartbeatInterval * 1000); + }, this._heartbeatInterval! * 1000); } /** @@ -244,7 +249,7 @@ export abstract class WebSocketBaseConnector extends BaseConnector { * * @param message - Message to send. */ - send(message: libData.Message) { + send(message: ReliableMessages) { if (!["connected", "resuming"].includes(this._state)) { throw new libErrors.SessionLost("No session"); } @@ -256,7 +261,7 @@ export abstract class WebSocketBaseConnector extends BaseConnector { } _sendInternal(message: libData.Message) { - this._socket.send(JSON.stringify(message)); + this._socket!.send(JSON.stringify(message)); } /** @@ -280,9 +285,9 @@ export abstract class WebSocketBaseConnector extends BaseConnector { } this.setClosing(); - this.send(new libData.MessageDisconnect("prepare")); + this._sendInternal(new libData.MessageDisconnect("prepare")); - let timeout: NodeJS.Timeout; + let timeout: NodeJS.Timeout | undefined; let waitTimeout = new Promise(resolve => { timeout = setTimeout(resolve, 10000); }); // Make Configurable? try { await Promise.race([ @@ -326,7 +331,7 @@ export abstract class WebSocketBaseConnector extends BaseConnector { * @extends module:lib.WebSocketBaseConnector */ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { - _reconnectId: NodeJS.Timeout | null = null; + _reconnectId?: NodeJS.Timeout; _sessionToken: string | null = null; _sessionTimeout: number | null = null; _startedResuming: number | null = null; @@ -337,7 +342,7 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { maxReconnectDelay: number, protected _tlsCa = null ) { - super(undefined, new libData.Address(libData.Address.controller, 0)); + super(undefined as any, new libData.Address(libData.Address.controller, 0)); this._backoff = new ExponentialBackoff({ max: maxReconnectDelay }); // The following states are used in the client connector @@ -349,21 +354,21 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { _reset() { clearTimeout(this._reconnectId); - this._reconnectId = null; + this._reconnectId = undefined; this._sessionToken = null; this._sessionTimeout = null; this._startedResuming = null; super._reset(); - this.src = undefined; + this.src = undefined as any; } _invalidate() { - assert(this._reconnectId === null); + assert(this._reconnectId === undefined); this._sessionToken = null; this._sessionTimeout = null; this._startedResuming = null; super._invalidate(); - this.src = undefined; + this.src = undefined as any; } /** @@ -394,7 +399,7 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { this._closing = true; if (this._state === "connected" || this._socket) { - this._socket.close(code, reason); + this._socket!.close(code, reason); await events.once(this, "close"); } else { @@ -421,7 +426,7 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { } if (this._socket) { - this._socket.close(1000, "Connector closing"); + this._socket!.close(1000, "Connector closing"); } else { this._reset(); @@ -471,14 +476,14 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { throw new Error("Cannot reconnect while socket is open"); } - if (this._reconnectId !== null) { + if (this._reconnectId !== undefined) { logger.error("Unexpected double call to reconnect"); } let delay = this._backoff.delay(); if ( this._state === "resuming" - && this._startedResuming + this._sessionTimeout * 1000 < Date.now() + delay + && this._startedResuming! + this._sessionTimeout! * 1000 < Date.now() + delay ) { logger.error("Connector | Session timed out trying to resume"); this._reset(); @@ -494,14 +499,13 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { `Connector | waiting ${(Math.round(delay / 10) / 100)} seconds for reconnect` ); this._reconnectId = setTimeout(() => { - this._reconnectId = null; + this._reconnectId = undefined; this._doConnect(); }, delay); } _attachSocketHandlers() { - // TODO type event - this._socket.onclose = (event: any) => { + this._socket!.onclose = (event) => { const previousState = this._state; // Authentication failed @@ -544,7 +548,7 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { } }; - this._socket.onerror = (event: any) => { + this._socket!.onerror = (event) => { // It's assumed that close is always called by ws let code = !event.error ? "" : `, code: ${event.error.code}`; let message = `Connector | Socket error: ${event.message || "unknown error"}${code}`; @@ -568,13 +572,13 @@ export abstract class WebSocketClientConnector extends WebSocketBaseConnector { } }; - this._socket.onopen = () => { + this._socket!.onopen = () => { logger.verbose("Connector | Open"); }; // Handle messages - this._socket.onmessage = (event: any) => { - let message = this._parseMessage(event.data); + this._socket!.onmessage = (event) => { + let message = this._parseMessage(event.data as string); if (!message) { return; } diff --git a/packages/lib/src/link/link.ts b/packages/lib/src/link/link.ts index 20d50713..e4352b3a 100644 --- a/packages/lib/src/link/link.ts +++ b/packages/lib/src/link/link.ts @@ -7,13 +7,42 @@ import { dataClasses } from "./messages"; import { BaseConnector, WebSocketBaseConnector } from "./connectors"; import { strict as assert } from "assert"; import type { PluginInfo } from "../plugin"; +import type { User } from "../users"; +import type { AddressType, JSONDeserialisable, Message, MessageRequest, MessageEvent } from "../data"; + +export interface Request { + constructor: Partial>> & { + new (...args: any): Request, + name: string, + type: "request"; + src: AddressType | readonly AddressType[]; + dst: AddressType | readonly AddressType[]; + permission?: null | string | ((user: User, message: MessageRequest) => void); + plugin?: string; + Response?: JSONDeserialisable, + } +} +export type RequestClass = Request["constructor"]; + +export interface Event { + constructor: Partial>> & { + new (...args: any): Event, + name: string, + type: "event"; + src: AddressType | readonly AddressType[]; + dst: AddressType | readonly AddressType[]; + permission?: null | string | ((user: User, message: MessageEvent) => void); + plugin?: string; + } +} +export type EventClass = Event["constructor"]; interface RequestEntry { - Request: typeof libData.Request; + Request: RequestClass; name: string, allowedSrcTypes: Set; allowedDstTypes: Set; - requestFromJSON: (json: any) => libData.Request; + requestFromJSON: (json: any) => Request; Response?: any; responseFromJSON: (json: any) => any; } @@ -32,14 +61,18 @@ interface ForwardedRequest { } interface EventEntry { - Event: typeof libData.Event; + Event: EventClass; name: string, allowedSrcTypes: Set; allowedDstTypes: Set; - eventFromJSON: (json: any) => libData.Event; + eventFromJSON: (json: any) => Event; +} +type RequestHandler = (request: Request, src: libData.Address, dst: libData.Address) => any; +type EventHandler = (event: Event, src: libData.Address, dst: libData.Address) => any; + +interface Router { + forwardMessage(origin: Link, message: Message, fallback: boolean): boolean, } -type RequestHandler = (request: libData.Request, src: libData.Address, dst: libData.Address) => any; -type EventHandler = (request: libData.Event, src: libData.Address, dst: libData.Address) => any; // Some definitions for the terminology used here: // link: Either side of a controller - client connection @@ -52,7 +85,7 @@ type EventHandler = (request: libData.Event, src: libData.Address, dst: libData. * Common interface for server and client connections */ export class Link { - router = undefined; + router?: Router = undefined; validateSent = true; _requestHandlers = new Map(); @@ -66,7 +99,6 @@ export class Link { constructor( public connector: BaseConnector ) { - // @ts-ignore: TODO Remove when lib/data is migrated to ts this.handle(libData.PingRequest, () => {}); // Process messages received by the connector @@ -207,7 +239,7 @@ export class Link { throw new libErrors.InvalidMessage("Message src may not be broadcast"); } this.validateIngress(message); - } catch (err) { + } catch (err: any) { if (message.type === "request") { this.connector.sendResponseError(new libData.ResponseError(err.message, err.code), message.src); } @@ -314,7 +346,7 @@ export class Link { _processRequest( message: libData.MessageRequest, entry: RequestEntry, - handler: RequestHandler, + handler: RequestHandler, spoofedSrc?: libData.Address ) { if (!handler) { @@ -327,7 +359,7 @@ export class Link { let response: any; try { response = handler(entry.requestFromJSON(message.data), message.src, message.dst); - } catch (err) { + } catch (err: any) { if (err.errors) { logger.error(JSON.stringify(err.errors, null, 4)); } @@ -366,7 +398,7 @@ export class Link { this.connector.sendResponseError( new libData.ResponseError(err.message, err.code, err.stack), message.src, spoofedSrc ); - } catch (err) { + } catch (err: any) { logger.error(`Unexpected error sending error response for ${message.name}:\n${err.stack}`); } } @@ -374,7 +406,7 @@ export class Link { } _processResponse(message: libData.MessageResponse) { - let pending = this._pendingRequests.get(message.dst.requestId); + let pending = this._pendingRequests.get(message.dst.requestId!); if (!pending) { throw new libErrors.InvalidMessage( `Received response ${message.dst.requestId} without a pending request` @@ -387,14 +419,14 @@ export class Link { try { pending.resolve(pending.request.responseFromJSON(message.data)); - } catch (err) { + } catch (err: any) { // An invalid response object was likely received pending.reject(err); } } _processResponseError(message: libData.MessageResponseError) { - let pending = this._pendingRequests.get(message.dst.requestId); + let pending = this._pendingRequests.get(message.dst.requestId!); if (!pending) { throw new libErrors.InvalidMessage( `Received error response ${message.dst.requestId} without a pending request` @@ -441,10 +473,10 @@ export class Link { * Promise that resolves to the response if a request was sent or * undefined if it was an event. */ - send(requestOrEvent: libData.Request): Promise; - send(requestOrEvent: libData.Event): void; - send(requestOrEvent: libData.Request | libData.Event): Promise | void { - return this.sendTo(this.connector.dst, requestOrEvent); + send(requestOrEvent: Request): Promise; + send(requestOrEvent: Event): void; + send(requestOrEvent: Request | Event): Promise | void { + return this.sendTo(this.connector.dst, requestOrEvent as any); } /** @@ -456,26 +488,26 @@ export class Link { * Promise that resolves to the response if a request was sent or * undefined if it was an event. */ - sendTo(destination: libData.AddressShorthand, requestOrEvent: libData.Request): Promise; - sendTo(destination: libData.AddressShorthand, requestOrEvent: libData.Event): void; + sendTo(destination: libData.AddressShorthand, requestOrEvent: Request): Promise; + sendTo(destination: libData.AddressShorthand, requestOrEvent: Event): void; sendTo( destination: libData.AddressShorthand, - requestOrEvent: libData.Request | libData.Event, + requestOrEvent: Request | Event, ): Promise | void { let dst = libData.Address.fromShorthand(destination); // TODO investigate if these types can be inferred - if ((requestOrEvent.constructor as any).type === "request") { - return this.sendRequest(requestOrEvent, dst); + if (requestOrEvent.constructor.type === "request") { + return this.sendRequest(requestOrEvent as Request, dst); } - if ((requestOrEvent.constructor as any).type === "event") { - return this.sendEvent(requestOrEvent, dst); + if (requestOrEvent.constructor.type === "event") { + return this.sendEvent(requestOrEvent as Event, dst); } throw Error(`Expected request or event but got type ${(requestOrEvent.constructor as any).type}`); } - sendRequest(request: libData.Request, dst: libData.Address) { - let entry = Link._requestsByClass.get(request.constructor as typeof libData.Request); + sendRequest(request: Request, dst: libData.Address) { + let entry = Link._requestsByClass.get(request.constructor as RequestClass); if (!entry) { throw new Error(`Attempt to send unregistered Request ${request.constructor.name}`); } @@ -492,7 +524,7 @@ export class Link { let requestId = this._nextRequestId; this._nextRequestId += 1; this._pendingRequests.set( - requestId, { request: entry, promise, resolve, reject, dst, } + requestId, { request: entry, promise, resolve: resolve!, reject: reject!, dst, } ); this.connector.sendRequest(request, requestId, dst); return promise; @@ -508,8 +540,8 @@ export class Link { this.connector.send(message); } - sendEvent(event: libData.Event, dst: libData.Address) { - let entry = Link._eventsByClass.get(event.constructor as typeof libData.Event); + sendEvent(event: Event, dst: libData.Address) { + let entry = Link._eventsByClass.get(event.constructor as EventClass); if (!entry) { throw new Error(`Attempt to send unregistered Event ${event.constructor.name}`); } @@ -520,23 +552,23 @@ export class Link { this.connector.sendEvent(event, dst); } - handle(Class: typeof libData.Request, handler: RequestHandler): void; - handle(Class: typeof libData.Event, handler: EventHandler): void; + handle(Class: RequestClass, handler: RequestHandler): void; + handle(Class: EventClass, handler: EventHandler): void; handle( - Class: typeof libData.Request | typeof libData.Event, - handler: RequestHandler | EventHandler, + Class: RequestClass | EventClass, + handler: RequestHandler | EventHandler, ) { if (Class.type === "request") { - this.handleRequest(Class, handler); + this.handleRequest(Class, handler as RequestHandler); } else if (Class.type === "event") { - this.handleEvent(Class, handler); + this.handleEvent(Class, handler as EventHandler); } else { throw new Error(`Class ${(Class as any).name} has unrecognized type ${(Class as any).type}`); } } - handleRequest(Request: typeof libData.Request, handler: RequestHandler) { - let entry = Link._requestsByClass.get(Request); + handleRequest(Request: RequestClass, handler: RequestHandler) { + let entry = Link._requestsByClass.get(Request as RequestClass); if (!entry) { throw new Error(`Unregistered Request class ${Request.name}`); } @@ -546,8 +578,8 @@ export class Link { this._requestHandlers.set(Request, handler); } - fallbackRequest(Request: typeof libData.Request, handler: RequestHandler) { - let entry = Link._requestsByClass.get(Request); + fallbackRequest(Request: RequestClass, handler: RequestHandler) { + let entry = Link._requestsByClass.get(Request as RequestClass); if (!entry) { throw new Error(`Unregistered Request class ${Request.name}`); } @@ -557,8 +589,8 @@ export class Link { this._requestFallbacks.set(Request, handler); } - handleEvent(Event: typeof libData.Event, handler: EventHandler) { - let entry = Link._eventsByClass.get(Event); + handleEvent(Event: EventClass, handler: EventHandler) { + let entry = Link._eventsByClass.get(Event as EventClass); if (!entry) { throw new Error(`Unregistered Event class ${Event.name}`); } @@ -568,8 +600,8 @@ export class Link { this._eventHandlers.set(Event, handler); } - snoopEvent(Event: typeof libData.Event, handler: EventHandler) { - let entry = Link._eventsByClass.get(Event); + snoopEvent(Event: EventClass, handler: EventHandler) { + let entry = Link._eventsByClass.get(Event as EventClass); if (!entry) { throw new Error(`Unregistered Event class ${Event.name}`); } @@ -579,7 +611,9 @@ export class Link { this._eventSnoopers.set(Event, handler); } - static register(Class: typeof libData.Request | typeof libData.Event) { + static register(Class: RequestClass): void; + static register(Class: EventClass): void; + static register(Class: RequestClass | EventClass) { if (Class.type === "request") { this.registerRequest(Class); } else if (Class.type === "event") { @@ -589,7 +623,7 @@ export class Link { } } - static requestFromJSON(Request: typeof libData.Request, name: string) { + static requestFromJSON(Request: RequestClass, name: string): (json: any) => Request { if (Request.fromJSON) { if (!Request.jsonSchema) { throw new Error(`Request ${name} has static fromJSON but is missing static jsonSchema`); @@ -599,7 +633,7 @@ export class Link { if (!validate(json)) { throw new libErrors.InvalidMessage(`Request ${name} failed validation`, validate.errors); } - return Request.fromJSON(json); + return Request.fromJSON!(json); }; } if (Request.jsonSchema) { @@ -608,7 +642,7 @@ export class Link { return () => new Request(); } - static responseFromJSON(Response: libData.Serialisable, name: string) { + static responseFromJSON(Response: JSONDeserialisable, name: string) { if (!Response.jsonSchema) { throw new Error(`Response for Request ${name} is missing static jsonSchema`); } @@ -627,7 +661,11 @@ export class Link { }; } - static allowedTypes(types: libData.AddressType | libData.AddressType[], name: string, side: "src" | "dst") { + static allowedTypes( + types: libData.AddressType | readonly libData.AddressType[], + name: string, + side: "src" | "dst" + ) { if (types === undefined) { throw new Error(`Missing ${side} specification in ${name}`); } @@ -651,9 +689,9 @@ export class Link { } static _requestsByName = new Map(); - static _requestsByClass = new Map(); + static _requestsByClass = new Map, RequestEntry>(); - static registerRequest(Request: typeof libData.Request) { + static registerRequest(Request: RequestClass) { const name = Request.plugin ? `${Request.plugin}:${Request.name}` : Request.name; if (this._requestsByName.has(name)) { throw new Error(`Request ${name} is already registered`); @@ -685,7 +723,7 @@ export class Link { this._requestsByClass.set(Request, entry); } - static eventFromJSON(Event: typeof libData.Event, name: string) { + static eventFromJSON(Event: EventClass, name: string) { if (Event.fromJSON) { if (!Event.jsonSchema) { throw new Error(`Event ${name} has static fromJSON but is missing static jsonSchema`); @@ -695,7 +733,7 @@ export class Link { if (!validate(json)) { throw new libErrors.InvalidMessage(`Event ${name} failed validation`, validate.errors); } - return Event.fromJSON(json); + return Event.fromJSON!(json); }; } if (Event.jsonSchema) { @@ -705,16 +743,16 @@ export class Link { } static _eventsByName = new Map(); - static _eventsByClass = new Map(); + static _eventsByClass = new Map, EventEntry>(); - static registerEvent(Event: typeof libData.Event) { + static registerEvent(Event: EventClass) { const name = Event.plugin ? `${Event.plugin}:${Event.name}` : Event.name; if (this._eventsByName.has(name)) { throw new Error(`Event ${name} is already registered`); } - let entry = { - Event, + let entry: EventEntry = { + Event: Event as EventClass, name, eventFromJSON: this.eventFromJSON(Event, name), allowedSrcTypes: this.allowedTypes(Event.src, name, "src"), @@ -729,13 +767,12 @@ export class Link { } this._eventsByName.set(name, entry); - this._eventsByClass.set(Event, entry); + this._eventsByClass.set(Event as EventClass, entry); } } for (let Class of dataClasses) { - // @ts-ignore: TODO Remove when lib/data is migrated to ts - Link.register(Class); + Link.register(Class as RequestClass); } export function registerPluginMessages(pluginInfos: PluginInfo[]) { diff --git a/packages/lib/src/link/messages.ts b/packages/lib/src/link/messages.ts index 1566c1de..b6161e10 100644 --- a/packages/lib/src/link/messages.ts +++ b/packages/lib/src/link/messages.ts @@ -5,6 +5,7 @@ import * as host from "../data/messages_host"; import * as instance from "../data/messages_instance"; import * as mod from "../data/messages_mod"; import * as user from "../data/messages_user"; +import type { RequestClass, EventClass } from "./link"; /** * Event and Request payloads registered with the Link class. Used to decode @@ -12,7 +13,7 @@ import * as user from "../data/messages_user"; * their proper classes. * @internal */ -export const dataClasses = [ +export const dataClasses: (RequestClass | EventClass)[] = [ core.PingRequest, controller.ControllerConfigGetRequest, diff --git a/packages/lib/src/logging.ts b/packages/lib/src/logging.ts index 0a24cfb7..8eac6098 100644 --- a/packages/lib/src/logging.ts +++ b/packages/lib/src/logging.ts @@ -130,7 +130,7 @@ export interface LogFilter { export function logFilter({ all, controller, hostIds, instanceIds, maxLevel }: LogFilter) { return (info: any) => { // Note: reversed to filter out undefined levels - if (maxLevel && !(levels[info.level] <= levels[maxLevel])) { + if (maxLevel && !((levels as any)[info.level] <= levels[maxLevel])) { return false; } diff --git a/packages/lib/src/logging_utils.ts b/packages/lib/src/logging_utils.ts index 0d075e5c..f55b0ddd 100644 --- a/packages/lib/src/logging_utils.ts +++ b/packages/lib/src/logging_utils.ts @@ -256,7 +256,12 @@ export class LogIndex { serialize() { let serialized = { version: logIndexVersion, - files: {}, + files: {} as Record, }; for (let [file, entry] of this.index) { @@ -285,7 +290,7 @@ export class LogIndex { try { let content = await fs.readFile(path.join(logDirectory, "index.json")); return new LogIndex(logDirectory, JSON.parse(content.toString())); - } catch (err) { + } catch (err: any) { if (err.code !== "ENOENT") { logger.warn(`Failed to load ${path.join(logDirectory, "index.json")}: ${err}`); } @@ -369,7 +374,7 @@ export class LogIndex { * true if the file may contain entries included by the filter. */ filterIncludesFile(file: string, { maxLevel, all, controller, instanceIds, hostIds }: LogFilter) { - let entry = this.index.get(file); + const entry = this.index.get(file); if (!entry) { return true; } @@ -412,7 +417,7 @@ export interface QueryLogFilter { * Return entries in ascending ("asc") date order or desceding ("desc") * date order. Defaults to "asc". */ - order: "asc" | "desc"; + order?: "asc" | "desc"; /** * Maximum log level to include. Higher levels are more verbose. */ @@ -461,7 +466,7 @@ export async function queryLog(logDirectory: string, filter: QueryLogFilter, ind } const includeEntry = logFilter(filter); - let log = []; + let log: object[] = []; for (let file of files) { if (index && !index.filterIncludesFile(file, filter)) { continue; @@ -485,7 +490,7 @@ export async function queryLog(logDirectory: string, filter: QueryLogFilter, ind } if (includeEntry(info)) { log.push(info); - if (log.length >= filter.limit) { + if (log.length >= Number(filter.limit)) { lineStream.destroy(); fileStream.destroy(); } @@ -494,13 +499,13 @@ export async function queryLog(logDirectory: string, filter: QueryLogFilter, ind fileStream.pipe(lineStream); try { await finished(lineStream); - } catch (err) { - if (log.length < filter.limit || err.code !== "ERR_STREAM_PREMATURE_CLOSE") { + } catch (err: any) { + if (log.length < Number(filter.limit) || err.code !== "ERR_STREAM_PREMATURE_CLOSE") { throw err; } } - if (log.length >= filter.limit) { + if (log.length >= Number(filter.limit)) { break; } } diff --git a/packages/lib/src/plugin.ts b/packages/lib/src/plugin.ts index 7ccf4b20..de231701 100644 --- a/packages/lib/src/plugin.ts +++ b/packages/lib/src/plugin.ts @@ -297,11 +297,11 @@ export class BaseInstancePlugin { async _sendPendingRconMessages() { this._sendingRconMessages = true; while (this._pendingRconMessages.length) { - let task = this._pendingRconMessages.shift(); + let task = this._pendingRconMessages.shift()!; try { let result = await this.sendRcon(task.message, task.expectEmpty); task.resolve(result); - } catch (err) { + } catch (err: any) { task.reject(err); } } @@ -820,7 +820,7 @@ export async function invokeHook(plugins: Map, hook: string, // Use an object to detect if the hook failed on timeout or tried to return a value looking like an error const timeout = {}; let result = await libHelpers.timeout( - plugin[hook](...args), + (plugin as any)[hook](...args), 15000, timeout ); @@ -829,7 +829,7 @@ export async function invokeHook(plugins: Map, hook: string, } else if (result !== undefined) { results.push(result); } - } catch (err) { + } catch (err: any) { plugin.logger.error(`Ignoring error from plugin ${name} in ${hook}:\n${err.stack}`); } } diff --git a/packages/lib/src/plugin_loader.ts b/packages/lib/src/plugin_loader.ts index 6771dd7b..e557bea9 100644 --- a/packages/lib/src/plugin_loader.ts +++ b/packages/lib/src/plugin_loader.ts @@ -30,7 +30,7 @@ export async function loadPluginInfos(pluginList: Map) { pluginInfo = require(path.posix.join(pluginPath, "info")); pluginPackage = require(path.posix.join(pluginPath, "package.json")); - } catch (err) { + } catch (err: any) { throw new libErrors.PluginError(pluginName, err); } diff --git a/packages/lib/src/prometheus.ts b/packages/lib/src/prometheus.ts index 93540e8c..5ce2d685 100644 --- a/packages/lib/src/prometheus.ts +++ b/packages/lib/src/prometheus.ts @@ -307,11 +307,11 @@ function removeMatchingLabels(mapping: Map, labels: Record extends Collector { - callback: (collector: LabeledCollector) => void | Promise; + callback: ((collector: any) => (void | Promise)) | undefined; metric: Metric; private _children: Map; - private _childClass: { new(collector: LabeledCollector, key: string): Child }; + private _childClass: { new(collector: any, key: string): Child }; /** * Create optionally labeled collector @@ -343,9 +343,9 @@ export class LabeledCollector extends Collector { labels?: string[], _reservedLabels?: string[], register?: boolean, - callback?: (collector: LabeledCollector) => void | Promise, + callback?: (collector: any) => (void | Promise), }, - childClass: { new(collector: LabeledCollector, key: string): Child } + childClass: { new(collector: any, key: string): Child } ) { const { labels = [], _reservedLabels = [], register = true, callback, ...rest } = options; @@ -485,7 +485,7 @@ export class ValueCollector extends LabeledColl labels?: string[], _reservedLabels?: string[], register?: boolean, - callback?: (collector: ValueCollector) => void | Promise, + callback?: (collector: any) => (void | Promise), }, childClass: { new(collector: ValueCollector, key: string): Child } ) { @@ -507,12 +507,13 @@ export class ValueCollector extends LabeledColl * @returns value stored. */ get() { - return this._defaultChild.get(); + return this._defaultChild!.get(); } remove(...labels: LabelValues) { let key = super.remove(...labels); this._values.delete(key); + return key; } removeAll(labels: Record) { @@ -546,7 +547,7 @@ class ValueCollectorChild { * @returns value stored. */ get() { - return this._values.get(this._key); + return this._values.get(this._key)!; } } @@ -565,7 +566,7 @@ class CounterChild extends ValueCollectorChild { throw new Error("Expected value to be a positive number"); } - this._values.set(this._key, this._values.get(this._key) + value); + this._values.set(this._key, this._values.get(this._key)! + value); } } @@ -673,7 +674,7 @@ export class Counter extends ValueCollector { options: { labels?: string[], register?: boolean, - callback?: (collector: Counter) => void | Promise, + callback?: (collector: Collector) => (void | Promise), } = {}, ) { super("counter", name, help, options, CounterChild); @@ -686,7 +687,7 @@ export class Counter extends ValueCollector { * @param value - Positive number to increment by. */ inc(value = 1) { - this._defaultChild.inc(value); + this._defaultChild!.inc(value); } } @@ -701,7 +702,7 @@ class GaugeChild extends ValueCollectorChild { * @param value - number to increment by. */ inc(value = 1) { - this._values.set(this._key, this._values.get(this._key) + value); + this._values.set(this._key, this._values.get(this._key)! + value); } /** @@ -710,7 +711,7 @@ class GaugeChild extends ValueCollectorChild { * @param value - number to decrease by. */ dec(value = 1) { - this._values.set(this._key, this._values.get(this._key) - value); + this._values.set(this._key, this._values.get(this._key)! - value); } /** @@ -869,7 +870,7 @@ export class Gauge extends ValueCollector { options: { labels?: string[], register?: boolean, - callback?: (collector: Gauge) => void | Promise, + callback?: (collector: Gauge) => (void | Promise), } = {}, ) { super("gauge", name, help, options, GaugeChild); @@ -882,7 +883,7 @@ export class Gauge extends ValueCollector { * @param value - number to increment by. */ inc(value = 1) { - this._defaultChild.inc(value); + this._defaultChild!.inc(value); } /** @@ -892,7 +893,7 @@ export class Gauge extends ValueCollector { * @param value - number to decrease by. */ dec(value = 1) { - this._defaultChild.dec(value); + this._defaultChild!.dec(value); } /** @@ -902,7 +903,7 @@ export class Gauge extends ValueCollector { * @param value - number to set gauge to. */ set(value: number) { - this._defaultChild.set(value); + this._defaultChild!.set(value); } /** @@ -911,7 +912,7 @@ export class Gauge extends ValueCollector { * Note: Only works if this is an unlabeled collector. */ setToCurrentTime() { - this._defaultChild.setToCurrentTime(); + this._defaultChild!.setToCurrentTime(); } /** @@ -923,7 +924,7 @@ export class Gauge extends ValueCollector { * seconds from when the timer was started */ startTimer() { - return this._defaultChild.startTimer(); + return this._defaultChild!.startTimer(); } } @@ -964,8 +965,8 @@ class SummaryChild { * @param value - number to count into summary. */ observe(value: number) { - this._sumValues.set(this._key, this._sumValues.get(this._key) + value); - this._countValues.set(this._key, this._countValues.get(this._key) + 1); + this._sumValues.set(this._key, this._sumValues.get(this._key)! + value); + this._countValues.set(this._key, this._countValues.get(this._key)! + 1); } /** @@ -1083,7 +1084,7 @@ export class Summary extends LabeledCollector { options: { labels?: string[], register?: boolean, - callback?: (collector: Summary) => void | Promise, + callback?: (collector: Summary) => (void | Promise), } = {}, ) { super("summary", name, help, options, SummaryChild); @@ -1111,7 +1112,7 @@ export class Summary extends LabeledCollector { * @type {number} */ get sum() { - return this._defaultChild.sum; + return this._defaultChild!.sum; } /** @@ -1121,7 +1122,7 @@ export class Summary extends LabeledCollector { * @type {number} */ get count() { - return this._defaultChild.count; + return this._defaultChild!.count; } /** @@ -1131,7 +1132,7 @@ export class Summary extends LabeledCollector { * @param value - number to count into histogram buckets. */ observe(value: number) { - this._defaultChild.observe(value); + this._defaultChild!.observe(value); } /** @@ -1143,13 +1144,14 @@ export class Summary extends LabeledCollector { * when the timer was started into the metric. */ startTimer() { - return this._defaultChild.startTimer(); + return this._defaultChild!.startTimer(); } remove(...labels: LabelValues) { let key = super.remove(...labels); this._sumValues.delete(key); this._countValues.delete(key); + return key; } removeAll(labels: Record) { @@ -1240,12 +1242,12 @@ class HistogramChild { observe(value: number) { for (let [bound, key] of this._bucketKeys) { if (value <= bound) { - this._bucketValues.set(key, this._bucketValues.get(key) + 1); + this._bucketValues.set(key, this._bucketValues.get(key)! + 1); } } - this._sumValues.set(this._key, this._sumValues.get(this._key) + value); - this._countValues.set(this._key, this._countValues.get(this._key) + 1); + this._sumValues.set(this._key, this._sumValues.get(this._key)! + value); + this._countValues.set(this._key, this._countValues.get(this._key)! + 1); } /** @@ -1371,7 +1373,7 @@ export class Histogram extends LabeledCollector { buckets?: number[], labels?: string[], register?: boolean, - callback?: (collector: Histogram) => void | Promise, + callback?: (collector: Histogram) => (void | Promise), } = {}, ) { // These defaults are taken from the Python Prometheus client @@ -1411,7 +1413,7 @@ export class Histogram extends LabeledCollector { * Note: Only available if this is an unlabeled collector. */ get buckets() { - return this._defaultChild.buckets; + return this._defaultChild!.buckets; } /** @@ -1420,7 +1422,7 @@ export class Histogram extends LabeledCollector { * Note: Only available if this is an unlabeled collector. */ get sum() { - return this._defaultChild.sum; + return this._defaultChild!.sum; } /** @@ -1429,7 +1431,7 @@ export class Histogram extends LabeledCollector { * Note: Only available if this is an unlabeled collector. */ get count() { - return this._defaultChild.count; + return this._defaultChild!.count; } /** @@ -1438,7 +1440,7 @@ export class Histogram extends LabeledCollector { * Note: Only works if this is an unlabeled collector. */ observe(value: number) { - this._defaultChild.observe(value); + this._defaultChild!.observe(value); } /** @@ -1450,7 +1452,7 @@ export class Histogram extends LabeledCollector { * when the timer was started into the metric. */ startTimer() { - return this._defaultChild.startTimer(); + return this._defaultChild!.startTimer(); } remove(...labels: LabelValues) { @@ -1461,6 +1463,7 @@ export class Histogram extends LabeledCollector { } this._sumValues.delete(key); this._countValues.delete(key); + return key; } removeAll(labels: Record) { diff --git a/packages/lib/src/schema.ts b/packages/lib/src/schema.ts index d06fdfc2..d39416e9 100644 --- a/packages/lib/src/schema.ts +++ b/packages/lib/src/schema.ts @@ -17,7 +17,7 @@ const ajv = new Ajv({ * @returns Validator for the schema. */ export function compile(schema: JSONSchemaType) { - if (typeof global !== "object" || !global.lazySchemaCompilation) { + if (typeof global !== "object" || !(global as any).lazySchemaCompilation) { return ajv.compile(schema); } diff --git a/packages/lib/src/shared_commands.ts b/packages/lib/src/shared_commands.ts index 5635f1ad..06fc5f1c 100644 --- a/packages/lib/src/shared_commands.ts +++ b/packages/lib/src/shared_commands.ts @@ -49,7 +49,7 @@ export async function handlePluginCommand( pluginList: Map, pluginListPath: string ) { - let command = args._[1]; + let command = (args._ as string[])[1]; if (command === "add") { let pluginPath = args.path as string; @@ -61,7 +61,7 @@ export async function handlePluginCommand( try { // eslint-disable-next-line node/global-require pluginInfo = require(path.posix.join(pluginPath, "info")); - } catch (err) { + } catch (err: any) { logger.error(`Unable to import plugin info from ${args.path}:\n${err.stack}`); process.exitCode = 1; return; @@ -132,7 +132,7 @@ export async function handleConfigCommand( instance: libConfig.Config, configPath: string ) { - let command = args._[1]; + let command = (args._ as string[])[1]; if (command === "list") { for (let GroupClass of (instance.constructor as typeof libConfig.Config).groups.values()) { diff --git a/packages/lib/src/users.ts b/packages/lib/src/users.ts index 40d93b10..fd2469fc 100644 --- a/packages/lib/src/users.ts +++ b/packages/lib/src/users.ts @@ -310,10 +310,16 @@ export class User { _calculatePlayerStats() { let playerStats = new PlayerStats(); for (let instanceStats of this.instanceStats.values()) { - if (!playerStats.lastJoinAt || instanceStats.lastJoinAt > playerStats.lastJoinAt) { + if ( + instanceStats.lastJoinAt + && (!playerStats.lastJoinAt || instanceStats.lastJoinAt > playerStats.lastJoinAt) + ) { playerStats.lastJoinAt = instanceStats.lastJoinAt; } - if (!playerStats.lastLeaveAt || instanceStats.lastLeaveAt > playerStats.lastLeaveAt) { + if ( + instanceStats.lastLeaveAt + && (!playerStats.lastLeaveAt || instanceStats.lastLeaveAt > playerStats.lastLeaveAt) + ) { playerStats.lastLeaveAt = instanceStats.lastLeaveAt; playerStats.lastLeaveReason = instanceStats.lastLeaveReason; } diff --git a/packages/lib/src/zip_ops.ts b/packages/lib/src/zip_ops.ts index f69f63e8..492d2072 100644 --- a/packages/lib/src/zip_ops.ts +++ b/packages/lib/src/zip_ops.ts @@ -10,7 +10,7 @@ import type JSZip from "jszip"; * @returns name of the root folder. */ export function findRoot(zip: JSZip) { - let root = null; + let root: undefined | string; zip.forEach((relativePath, file) => { let index = relativePath.indexOf("/"); if (index === -1) { @@ -18,14 +18,14 @@ export function findRoot(zip: JSZip) { } let pathRoot = relativePath.slice(0, index); - if (root === null) { + if (root === undefined) { root = pathRoot; } else if (root !== pathRoot) { throw new Error("Zip contains multiple root folders"); } }); - if (root === null) { + if (root === undefined) { throw new Error("Empty zip file"); } diff --git a/packages/lib/tsconfig.json b/packages/lib/tsconfig.json index 0f0b112f..da4d5a41 100644 --- a/packages/lib/tsconfig.json +++ b/packages/lib/tsconfig.json @@ -7,7 +7,7 @@ "rootDir": ".", "outDir": "dist", "composite": false, - "strict": false, + "strict": true, "alwaysStrict": true, "allowJs": true, "checkJs": false, diff --git a/plugins/research_sync/controller.js b/plugins/research_sync/controller.js index dc82ead3..20503480 100644 --- a/plugins/research_sync/controller.js +++ b/plugins/research_sync/controller.js @@ -44,7 +44,6 @@ class ControllerPlugin extends lib.BaseControllerPlugin { action: () => this.broadcastProgress(), }); - this.lastProgressBroadcast = Date.now(); this.progressBroadcastId = null; this.progressToBroadcast = new Set(); @@ -68,7 +67,6 @@ class ControllerPlugin extends lib.BaseControllerPlugin { } this.progressToBroadcast.clear(); - this.lastProgressBroadcast = Date.now(); if (techs.length) { this.controller.sendTo("allInstances", new ProgressEvent(techs)); } diff --git a/test/lib/link/link.js b/test/lib/link/link.js index 169c8c72..0c991031 100644 --- a/test/lib/link/link.js +++ b/test/lib/link/link.js @@ -80,7 +80,7 @@ describe("lib/link/link", function() { testConnector._seq - 1, src, dst, - new lib.ResponseError("Unrecognized request UnhandledRequest") + new lib.ResponseError("Unrecognized request UnhandledRequest", "InvalidMessage") ), ]); }); @@ -114,7 +114,10 @@ describe("lib/link/link", function() { testConnector._seq - 1, src, dst, - new lib.ResponseError("Source [Address controller:0] is not allowed for InvalidSrcRequest") + new lib.ResponseError( + "Source [Address controller:0] is not allowed for InvalidSrcRequest", + "InvalidMessage" + ) ), ]); }); @@ -132,7 +135,8 @@ describe("lib/link/link", function() { src, dst, new lib.ResponseError( - "Destination [Address control:1] is not allowed for InvalidDstRequest" + "Destination [Address control:1] is not allowed for InvalidDstRequest", + "InvalidMessage", ) ), ]); @@ -144,7 +148,7 @@ describe("lib/link/link", function() { testConnector._seq - 1, src, addr("allControls"), - new lib.ResponseError("Message src may not be broadcast") + new lib.ResponseError("Message src may not be broadcast", "InvalidMessage") ), ]); }); @@ -155,7 +159,10 @@ describe("lib/link/link", function() { testConnector._seq - 1, src, dst, - new lib.ResponseError("Destination [Address 4:control] is not allowed for SimpleRequest") + new lib.ResponseError( + "Destination [Address 4:control] is not allowed for SimpleRequest", + "InvalidMessage", + ) ), ]); });