Use strict type checking

This commit is contained in:
Hornwitser committed 2023-08-12 02:31:17 +02:00
1 parent 2ca8e69025
commit a66e930997
36 files changed
+714 -676

No files matched your search

+1
View File
@@ -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"
}
}
+12 -13
View File
@@ -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<typeof PlayerStats.jsonSchema> = {}) {
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<typeof PlayerStats.jsonSchema>) {
return new this(json);
}
toJSON() {
let json = {};
let json: Static<typeof PlayerStats.jsonSchema> = {};
if (this.joinCount) {
json["join_count"] = this.joinCount;
}
+10 -9
View File
@@ -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;
+4 -9
View File
@@ -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;
+73 -72
View File
@@ -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<string, unknown>;
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<string, unknown> = {};
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`);
+3 -3
View File
@@ -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<typeof ModInfo.jsonSchema>;
{
// 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) {
+11 -10
View File
@@ -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 });
}
}
}
-29
View File
@@ -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;
}
+38 -38
View File
@@ -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,
+5 -4
View File
@@ -323,7 +323,7 @@ export class ReadyData {
});
static fromJSON(json: Static<typeof this.jsonSchema>) {
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;
}
+23 -23
View File
@@ -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<string>,
+143 -143
View File
@@ -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<string, string>,
@@ -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,
+60 -60
View File
@@ -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,
+78 -76
View File
@@ -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<unknown>(PlayerStats.jsonSchema)),
playerStats: Type.Optional(PlayerStats.jsonSchema),
instanceStats: Type.Optional(
Type.Array(
Type.Tuple([Type.Integer(), Type.Unsafe<unknown>(PlayerStats.jsonSchema)]),
Type.Tuple([Type.Integer(), PlayerStats.jsonSchema]),
)
),
});
static fromJSON(json: Static<typeof this.jsonSchema>) {
let playerStats: PlayerStats;
let playerStats: PlayerStats | undefined;
if (json.playerStats) {
playerStats = PlayerStats.fromJSON(json.playerStats);
}
let instanceStats: Map<number, PlayerStats>;
let instanceStats: Map<number, PlayerStats> | 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,
+4 -4
View File
@@ -54,7 +54,7 @@ export async function loadJsonAsMap(filePath: string): Promise<Map<string, unkno
return new Map(Object.entries(parsed));
} catch (err) {
} catch (err: any) {
if (err.code === "ENOENT") {
// File does not exist, return empty map
return new Map();
@@ -115,7 +115,7 @@ export async function loadJsonArrayAsMap(filePath: string): Promise<Map<unknown,
}
return map;
} catch (err) {
} catch (err: any) {
if (err.code === "ENOENT") {
// File does not exist, return empty map
return new Map();
@@ -247,7 +247,7 @@ export class ItemDatabase {
checkCount(count);
if (this._items.has(name)) {
count += this._items.get(name);
count += this._items.get(name)!;
}
this._items.set(name, count);
@@ -269,7 +269,7 @@ export class ItemDatabase {
count = -count;
if (this._items.has(name)) {
count += this._items.get(name);
count += this._items.get(name)!;
}
this._items.set(name, count);
+8 -8
View File
@@ -7,7 +7,7 @@
* Thrown by commands when they fail
*/
export class CommandError extends Error {
code: "CommandError";
code = "CommandError";
}
/**
@@ -45,10 +45,10 @@ export class PermissionError extends RequestError {
* Signal for messages that fail validation
*/
export class InvalidMessage extends Error {
code: "InvalidMessage";
code = "InvalidMessage";
constructor(
message: string,
public errors: object = null,
public errors?: object | null,
) {
super(message);
}
@@ -58,35 +58,35 @@ export class InvalidMessage extends Error {
* Thrown from requests when the session it was sent on was lost
*/
export class SessionLost extends Error {
code: "SessionLost";
code = "SessionLost";
}
/**
* Thrown when WebSocket authentication failed
*/
export class AuthenticationFailed extends Error {
code: "AuthenticationFailed";
code = "AuthenticationFailed";
}
/**
* Errror class for known errors occuring during startup
*/
export class StartupError extends Error {
code: "StartupError";
code = "StartupError";
}
/**
* Errors outside of our control
*/
export class EnvironmentError extends Error {
code: "EnvironmentError";
code = "EnvironmentError";
}
/**
* Errors caused by plugins
*/
export class PluginError extends Error {
code: "PluginError";
code = "PluginError";
constructor(
public pluginName: string,
public original: Error
+2 -2
View File
@@ -363,7 +363,7 @@ export function readMapExchangeString(exchangeString: string) {
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 map exchange string: zlib inflate failed");
}
@@ -380,7 +380,7 @@ export function readMapExchangeString(exchangeString: string) {
map_settings: readMapSettings(state),
checksum: readUInt32(state),
};
} catch (err) {
} catch (err: any) {
if (err.code === "ERR_OUT_OF_RANGE") {
throw new Error("Malformed map exchange string: reached end before finishing parsing");
}
+2 -2
View File
@@ -46,7 +46,7 @@ export async function directorySize(directory: string) {
let dirEntries: fs.Dirent[];
try {
dirEntries = await fs.readdir(directory, { withFileTypes: true });
} catch (err) {
} catch (err: any) {
if (err.code === "ENOENT") {
return 0;
}
@@ -92,7 +92,7 @@ export async function findUnusedName(directory: string, name: string, extension
return `${name}${extension}`;
}
let match = /^(.*?)(-(\d+))?$/.exec(name);
let match = /^(.*?)(-(\d+))?$/.exec(name)!;
if (!match[2]) {
name = `${match[1]}-2`;
} else {
+6 -6
View File
@@ -37,7 +37,7 @@ export async function wait(duration: number) {
* @param {*=} timeoutResult - Value to return if the operation timed out.
*/
export async function timeout<T>(promise: Promise<T>, time: number, timeoutResult: T) {
let timer: ReturnType<typeof setTimeout>;
let timer: NodeJS.Timer | undefined;
try {
return await Promise.race([
promise,
@@ -157,10 +157,10 @@ function parseSearchTerm(
input: string,
attributes: Record<string, string>,
issues: Array<string>
): [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);
+2
View File
@@ -0,0 +1,2 @@
import ws = require("ws");
export = ws;
+3
View File
@@ -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");
+41 -37
View File
@@ -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<Req, Res>(
request: Request<Req, Res>,
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<T>(event: Event<T>, 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;
}
+98 -61
View File
@@ -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<Req, Res> {
constructor: Partial<JSONDeserialisable<Request<Req, Res>>> & {
new (...args: any): Request<Req, Res>,
name: string,
type: "request";
src: AddressType | readonly AddressType[];
dst: AddressType | readonly AddressType[];
permission?: null | string | ((user: User, message: MessageRequest) => void);
plugin?: string;
Response?: JSONDeserialisable<Res>,
}
}
export type RequestClass<Req, Res> = Request<Req, Res>["constructor"];
export interface Event<T> {
constructor: Partial<JSONDeserialisable<Event<T>>> & {
new (...args: any): Event<T>,
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<T> = Event<T>["constructor"];
interface RequestEntry {
Request: typeof libData.Request;
Request: RequestClass<unknown, unknown>;
name: string,
allowedSrcTypes: Set<number>;
allowedDstTypes: Set<number>;
requestFromJSON: (json: any) => libData.Request;
requestFromJSON: (json: any) => Request<unknown, unknown>;
Response?: any;
responseFromJSON: (json: any) => any;
}
@@ -32,14 +61,18 @@ interface ForwardedRequest {
}
interface EventEntry {
Event: typeof libData.Event;
Event: EventClass<unknown>;
name: string,
allowedSrcTypes: Set<number>;
allowedDstTypes: Set<number>;
eventFromJSON: (json: any) => libData.Event;
eventFromJSON: (json: any) => Event<unknown>;
}
type RequestHandler<Req, Res> = (request: Request<Req, Res>, src: libData.Address, dst: libData.Address) => any;
type EventHandler<T> = (event: Event<T>, 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<unknown, unknown>,
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<unknown>;
send(requestOrEvent: libData.Event): void;
send(requestOrEvent: libData.Request | libData.Event): Promise<unknown> | void {
return this.sendTo(this.connector.dst, requestOrEvent);
send<Req, Res = void>(requestOrEvent: Request<Req, Res>): Promise<Res>;
send<T>(requestOrEvent: Event<T>): void;
send(requestOrEvent: Request<unknown, unknown> | Event<unknown>): Promise<unknown> | 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<unknown>;
sendTo(destination: libData.AddressShorthand, requestOrEvent: libData.Event): void;
sendTo<Req, Res = void>(destination: libData.AddressShorthand, requestOrEvent: Request<Req, Res>): Promise<Res>;
sendTo<T>(destination: libData.AddressShorthand, requestOrEvent: Event<T>): void;
sendTo(
destination: libData.AddressShorthand,
requestOrEvent: libData.Request | libData.Event,
requestOrEvent: Request<unknown, unknown> | Event<unknown>,
): Promise<unknown> | 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<unknown, unknown>, dst);
}
if ((requestOrEvent.constructor as any).type === "event") {
return this.sendEvent(requestOrEvent, dst);
if (requestOrEvent.constructor.type === "event") {
return this.sendEvent(requestOrEvent as Event<unknown>, 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<Req, Res>(request: Request<Req, Res>, dst: libData.Address) {
let entry = Link._requestsByClass.get(request.constructor as RequestClass<unknown, unknown>);
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<T>(event: Event<T>, dst: libData.Address) {
let entry = Link._eventsByClass.get(event.constructor as EventClass<unknown>);
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<Req, Res>(Class: RequestClass<Req, Res>, handler: RequestHandler<Req, Res>): void;
handle<T>(Class: EventClass<T>, handler: EventHandler<T>): void;
handle(
Class: typeof libData.Request | typeof libData.Event,
handler: RequestHandler | EventHandler,
Class: RequestClass<unknown, unknown> | EventClass<unknown>,
handler: RequestHandler<unknown, unknown> | EventHandler<unknown>,
) {
if (Class.type === "request") {
this.handleRequest(Class, handler);
this.handleRequest(Class, handler as RequestHandler<unknown, unknown>);
} else if (Class.type === "event") {
this.handleEvent(Class, handler);
this.handleEvent(Class, handler as EventHandler<unknown>);
} 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<Req, Res>(Request: RequestClass<Req, Res>, handler: RequestHandler<Req, Res>) {
let entry = Link._requestsByClass.get(Request as RequestClass<unknown, unknown>);
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<Req, Res>(Request: RequestClass<Req, Res>, handler: RequestHandler<Req, Res>) {
let entry = Link._requestsByClass.get(Request as RequestClass<unknown, unknown>);
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<T>(Event: EventClass<T>, handler: EventHandler<T>) {
let entry = Link._eventsByClass.get(Event as EventClass<unknown>);
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<T>(Event: EventClass<T>, handler: EventHandler<T>) {
let entry = Link._eventsByClass.get(Event as EventClass<unknown>);
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<Req, Res>(Class: RequestClass<Req, Res>): void;
static register<T>(Class: EventClass<T>): void;
static register(Class: RequestClass<unknown, unknown> | EventClass<unknown>) {
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<Req, Res>(Request: RequestClass<Req, Res>, name: string): (json: any) => Request<Req, Res> {
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<T>(Response: JSONDeserialisable<T>, 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<string, RequestEntry>();
static _requestsByClass = new Map<typeof libData.Request, RequestEntry>();
static _requestsByClass = new Map<RequestClass<unknown, unknown>, RequestEntry>();
static registerRequest(Request: typeof libData.Request) {
static registerRequest(Request: RequestClass<unknown, unknown>) {
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<T>(Event: EventClass<T>, 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<string, EventEntry>();
static _eventsByClass = new Map<typeof libData.Event, EventEntry>();
static _eventsByClass = new Map<EventClass<unknown>, EventEntry>();
static registerEvent(Event: typeof libData.Event) {
static registerEvent<T>(Event: EventClass<T>) {
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<unknown>,
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<unknown>, 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<unknown, unknown>);
}
export function registerPluginMessages(pluginInfos: PluginInfo[]) {
+2 -1
View File
@@ -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<unknown, unknown> | EventClass<unknown>)[] = [
core.PingRequest,
controller.ControllerConfigGetRequest,
+1 -1
View File
@@ -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;
}
+14 -9
View File
@@ -256,7 +256,12 @@ export class LogIndex {
serialize() {
let serialized = {
version: logIndexVersion,
files: {},
files: {} as Record<string, {
levels: string[],
controller: boolean,
hostIds: number[],
instanceIds: number[],
}>,
};
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;
}
}
+4 -4
View File
@@ -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<string, BasePlugin>, 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<string, BasePlugin>, 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}`);
}
}
+1 -1
View File
@@ -30,7 +30,7 @@ export async function loadPluginInfos(pluginList: Map<string, string>) {
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);
}
+37 -34
View File
@@ -307,11 +307,11 @@ function removeMatchingLabels(mapping: Map<string, unknown>, labels: Record<stri
* @extends Collector
*/
export class LabeledCollector<Child> extends Collector {
callback: (collector: LabeledCollector<Child>) => void | Promise<void>;
callback: ((collector: any) => (void | Promise<void>)) | undefined;
metric: Metric;
private _children: Map<string, Child>;
private _childClass: { new(collector: LabeledCollector<Child>, key: string): Child };
private _childClass: { new(collector: any, key: string): Child };
/**
* Create optionally labeled collector
@@ -343,9 +343,9 @@ export class LabeledCollector<Child> extends Collector {
labels?: string[],
_reservedLabels?: string[],
register?: boolean,
callback?: (collector: LabeledCollector<Child>) => void | Promise<void>,
callback?: (collector: any) => (void | Promise<void>),
},
childClass: { new(collector: LabeledCollector<Child>, 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<Child extends { get(): number }> extends LabeledColl
labels?: string[],
_reservedLabels?: string[],
register?: boolean,
callback?: (collector: ValueCollector<Child>) => void | Promise<void>,
callback?: (collector: any) => (void | Promise<void>),
},
childClass: { new(collector: ValueCollector<Child>, key: string): Child }
) {
@@ -507,12 +507,13 @@ export class ValueCollector<Child extends { get(): number }> 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<string, string>) {
@@ -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<CounterChild> {
options: {
labels?: string[],
register?: boolean,
callback?: (collector: Counter) => void | Promise<void>,
callback?: (collector: Collector) => (void | Promise<void>),
} = {},
) {
super("counter", name, help, options, CounterChild);
@@ -686,7 +687,7 @@ export class Counter extends ValueCollector<CounterChild> {
* @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<GaugeChild> {
options: {
labels?: string[],
register?: boolean,
callback?: (collector: Gauge) => void | Promise<void>,
callback?: (collector: Gauge) => (void | Promise<void>),
} = {},
) {
super("gauge", name, help, options, GaugeChild);
@@ -882,7 +883,7 @@ export class Gauge extends ValueCollector<GaugeChild> {
* @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<GaugeChild> {
* @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<GaugeChild> {
* @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<GaugeChild> {
* 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<GaugeChild> {
* 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<SummaryChild> {
options: {
labels?: string[],
register?: boolean,
callback?: (collector: Summary) => void | Promise<void>,
callback?: (collector: Summary) => (void | Promise<void>),
} = {},
) {
super("summary", name, help, options, SummaryChild);
@@ -1111,7 +1112,7 @@ export class Summary extends LabeledCollector<SummaryChild> {
* @type {number}
*/
get sum() {
return this._defaultChild.sum;
return this._defaultChild!.sum;
}
/**
@@ -1121,7 +1122,7 @@ export class Summary extends LabeledCollector<SummaryChild> {
* @type {number}
*/
get count() {
return this._defaultChild.count;
return this._defaultChild!.count;
}
/**
@@ -1131,7 +1132,7 @@ export class Summary extends LabeledCollector<SummaryChild> {
* @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<SummaryChild> {
* 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<string, string>) {
@@ -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<HistogramChild> {
buckets?: number[],
labels?: string[],
register?: boolean,
callback?: (collector: Histogram) => void | Promise<void>,
callback?: (collector: Histogram) => (void | Promise<void>),
} = {},
) {
// These defaults are taken from the Python Prometheus client
@@ -1411,7 +1413,7 @@ export class Histogram extends LabeledCollector<HistogramChild> {
* 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<HistogramChild> {
* 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<HistogramChild> {
* 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<HistogramChild> {
* 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<HistogramChild> {
* 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<HistogramChild> {
}
this._sumValues.delete(key);
this._countValues.delete(key);
return key;
}
removeAll(labels: Record<string, string>) {
+1 -1
View File
@@ -17,7 +17,7 @@ const ajv = new Ajv({
* @returns Validator for the schema.
*/
export function compile<T>(schema: JSONSchemaType<T>) {
if (typeof global !== "object" || !global.lazySchemaCompilation) {
if (typeof global !== "object" || !(global as any).lazySchemaCompilation) {
return ajv.compile<T>(schema);
}
+3 -3
View File
@@ -49,7 +49,7 @@ export async function handlePluginCommand(
pluginList: Map<string, string>,
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()) {
+8 -2
View File
@@ -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;
}
+3 -3
View File
@@ -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");
}
+1 -1
View File
@@ -7,7 +7,7 @@
"rootDir": ".",
"outDir": "dist",
"composite": false,
"strict": false,
"strict": true,
"alwaysStrict": true,
"allowJs": true,
"checkJs": false,
-2
View File
@@ -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));
}
+12 -5
View File
@@ -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",
)
),
]);
});