Fix bad typings left over from the migration

This commit is contained in:
Hornwitser committed 2023-11-19 04:50:07 +01:00
1 parent 7314dc99c8
commit 80e1904175
22 files changed
+93 -117

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@ const { ConsoleTransport, levels, logger } = lib;
import Controller from "./src/Controller";
import UserManager from "./src/UserManager";
const version = require("./package.json").version;
import { version } from "./package.json";
// globals
let controller: Controller;
+4 -8
View File
@@ -29,17 +29,13 @@ export default class ControlConnection extends BaseConnection {
private _agent: string;
private _version: string;
logTransport: lib.LinkTransport | null = null;
logSubscriptions: {
all: boolean,
controller: boolean,
hostIds: number[],
instanceIds: number[],
} = {
logSubscriptions = {
all: false,
controller: false,
hostIds: [],
instanceIds: [],
hostIds: [] as number[],
instanceIds: [] as number[],
};
ws_dumper: ((...args: any[]) => void) | null = null;
declare connector: WsServerConnector;
+9 -13
View File
@@ -1,13 +1,10 @@
import type winston from "winston";
import type { AddressInfo } from "net";
import type { ControllerArgs } from "../controller";
import type { HostInfo } from "./HostConnection";
import type { Request, Response, Application } from "express";
import express, { type Request, type Response, type NextFunction, type Application } from "express";
import compression from "compression";
import events, { EventEmitter } from "events";
import express from "express";
import fs from "fs-extra";
import http from "http";
import https from "https";
@@ -20,12 +17,11 @@ const { logger, Summary, Gauge } = lib;
import HttpCloser from "./HttpCloser";
import InstanceInfo, { InstanceStatus } from "./InstanceInfo";
import metrics from "./metrics";
import * as metrics from "./metrics";
import * as routes from "./routes";
import UserManager from "./UserManager";
import WsServer from "./WsServer";
import yargs from "yargs";
import HostConnection from "./HostConnection";
import HostConnection, { type HostInfo } from "./HostConnection";
const endpointDurationSummary = new Summary(
"clusterio_controller_http_endpoint_duration_seconds",
@@ -176,7 +172,8 @@ export default class Controller {
const webpackConfigs = [];
if (args.dev) {
webpackConfigs.push(require("../../../webpack.config")({}));
// eslint-disable-next-line node/no-missing-require
webpackConfigs.push(require("../../../webpack.config")({})); // Path outside of build
}
if (args.devPlugin) {
let devPlugins = new Map();
@@ -882,8 +879,7 @@ export default class Controller {
ControllerPluginClass = await lib.loadControllerPluginClass(pluginInfo);
}
//@ts-ignore //TODO::: metrics is lib.Counter but ControllerPluginClass expect any[], can't figure out how the metrics is used.
let controllerPlugin = new ControllerPluginClass(pluginInfo, this, metrics, logger);
let controllerPlugin = new ControllerPluginClass(pluginInfo, this, metrics as any, logger);
await controllerPlugin.init();
this.plugins.set(pluginInfo.name, controllerPlugin);
@@ -950,8 +946,8 @@ export default class Controller {
/**
* Servers the web interface with the root path set apropriately
*
* @param {string} route - route the interface is served under.
* @returns {function} Experess.js route handler.
* @param route - route the interface is served under.
* @returns Experess.js route handler.
*/
static serveWeb(route: string) {
// The depth is is the number of slashes in the route minus one, but due
@@ -959,7 +955,7 @@ export default class Controller {
// compensate if the request path contains a slash but not the route,
// and vice versa.
let routeDepth = (route.match(/\//g) || []).length - 1 - Number(route.slice(-1) === "/");
return function(req: Request, res: Response, next: Function) {
return function(req: Request, res: Response, next: NextFunction) {
let depth = routeDepth + Number(req.path.slice(-1) === "/");
let webRoot = "../".repeat(depth) || "./";
let staticRoot = webRoot;
+3 -3
View File
@@ -13,7 +13,7 @@ export interface HostInfo {
id: number;
name: string;
version: string;
plugins: [number, any][];
plugins: Record<string, string>;
public_address: string | undefined;
token_valid_after?: number;
}
@@ -30,10 +30,10 @@ export default class HostConnection extends BaseConnection {
private _id: any;
private _name: any;
private _version: any;
plugins: Map<string, Object>;
plugins: Map<string, string>;
constructor(
registerData: any,
registerData: lib.RegisterHostData,
connector: WsServerConnector,
controller: Controller,
) {
+1 -1
View File
@@ -36,7 +36,7 @@ export default class InstanceInfo {
this.status = status;
}
toJSON(): Object {
toJSON() {
return {
config: this.config.serialize(),
status: this.status,
+2 -3
View File
@@ -12,7 +12,7 @@ import ControlConnection from "./ControlConnection";
import HostConnection, { HostInfo } from "./HostConnection";
import WsServerConnector from "./WsServerConnector";
const packageVersion = require("../package.json").version;
import { version as packageVersion } from "../package.json";
const wsMessageCounter = new lib.Counter(
"clusterio_controller_websocket_message_total",
@@ -111,12 +111,11 @@ export default class WsServer {
}
});
let originalSend = socket.send;
socket.send = (...args: any[]) => {
socket.send = (...args: [string, any]) => {
wsMessageCounter.labels("out").inc();
if (typeof args[0] === "string" && !socket.clusterio_ignore_dump) {
this.controller.debugEvents.emit("message", { direction: "out", content: args[0] });
}
// @ts-ignore TODO::: Issue with originalSend having multiple signatures ?
return originalSend.call(socket, ...args);
};
+1 -3
View File
@@ -1,7 +1,7 @@
import * as lib from "@clusterio/lib";
import util from "util";
const endpointHitCounter = new lib.Counter(
export const endpointHitCounter = new lib.Counter(
"clusterio_controller_http_endpoint_hits_total",
"How many requests a particular HTTP endpoint has gotten",
{ labels: ["route"], register: false }
@@ -11,5 +11,3 @@ endpointHitCounter.labels = util.deprecate(
endpointHitCounter.labels,
"incrementing endpointHitCounter is no longer needed and has no effect"
);
export default endpointHitCounter;
+1 -1
View File
@@ -61,7 +61,7 @@ async function getMetrics(req: Request, res: Response, next: any) {
));
}
for await (let result of await lib.defaultRegistry.collect()) {
for await (let result of lib.defaultRegistry.collect()) {
results.push(result);
}
+16 -16
View File
@@ -89,7 +89,7 @@ const controllerConfigCommands = new lib.CommandTree({
controllerConfigCommands.add(new lib.Command({
definition: ["list", "List controller configuration"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let response = await control.send(new lib.ControllerConfigGetRequest());
for (let group of (response.serializedConfig as any).groups) {
@@ -212,13 +212,13 @@ const controllerPluginCommands = new lib.CommandTree({
});
controllerPluginCommands.add(new lib.Command({
definition: ["list", "List plugins on controller"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let url = new URL(control.config.get("control.controller_url") as string);
url.pathname += "api/plugins";
let response = await phin<[]>({
url,
parse: "json",
core: { ca: control.tlsCa } as {},
core: { ca: control.tlsCa } as object,
});
print(asTable(response.body));
},
@@ -229,7 +229,7 @@ controllerCommands.add(controllerPluginCommands);
const hostCommands = new lib.CommandTree({ name: "host", description: "Host management" });
hostCommands.add(new lib.Command({
definition: [["list", "l"], "List hosts connected to the controller"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let hosts = await control.send(new lib.HostListRequest());
print(asTable(hosts));
},
@@ -288,7 +288,7 @@ const instanceCommands = new lib.CommandTree({
});
instanceCommands.add(new lib.Command({
definition: [["list", "l"], "List instances known to the controller"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let list = await control.send(new lib.InstanceDetailsListRequest());
print(asTable(list));
},
@@ -612,7 +612,7 @@ instanceSaveCommands.add(new lib.Command({
"X-Access-Token": control.config.get("control.controller_token"),
"Content-Type": "application/zip",
},
core: { ca: control.tlsCa } as {},
core: { ca: control.tlsCa } as object,
data: content,
parse: "json",
});
@@ -687,7 +687,7 @@ instanceSaveCommands.add(new lib.Command({
url.pathname += `api/stream/${streamId}`;
let response = await phin({
url, method: "GET",
core: { ca: control.tlsCa } as {},
core: { ca: control.tlsCa } as object,
stream: true,
});
@@ -898,13 +898,13 @@ modPackCommands.add(new lib.Command({
modPackCommands.add(new lib.Command({
definition: [["list", "l"], "List mod packs in the cluster"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let modPacks = await control.send(new lib.ModPackListRequest());
let fields = ["id", "name", "factorioVersion"];
for (let entry of modPacks) {
for (let field of Object.keys(entry)) {
if (!fields.includes(field)) {
// @ts-ignore
// @ts-expect-error terrible hack
delete entry[field];
}
}
@@ -1176,7 +1176,7 @@ modCommands.add(new lib.Command({
for (let entry of mods) {
for (let field of Object.keys(entry)) {
if (!args.fields.includes(field)) {
// @ts-ignore
// @ts-expect-error terrible hack
delete entry[field];
}
}
@@ -1243,7 +1243,7 @@ modCommands.add(new lib.Command({
for (let entry of results) {
for (let field of Object.keys(entry)) {
if (!args.fields.includes(field)) {
// @ts-ignore
// @ts-expect-error terrible hack
delete entry[field];
}
}
@@ -1281,7 +1281,7 @@ modCommands.add(new lib.Command({
"X-Access-Token": control.config.get("control.controller_token"),
"Content-Type": "application/zip",
},
core: { ca: control.tlsCa } as {},
core: { ca: control.tlsCa } as object,
data: content,
parse: "json",
});
@@ -1317,7 +1317,7 @@ modCommands.add(new lib.Command({
url.pathname += `api/stream/${streamId}`;
let response = await phin({
url, method: "GET",
core: { ca: control.tlsCa } as {},
core: { ca: control.tlsCa } as object,
stream: true,
});
@@ -1358,7 +1358,7 @@ modCommands.add(new lib.Command({
const permissionCommands = new lib.CommandTree({ name: "permission", description: "Permission inspection" });
permissionCommands.add(new lib.Command({
definition: [["list", "l"], "List permissions in the cluster"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let permissions = await control.send(new lib.PermissionListRequest());
print(asTable(permissions));
},
@@ -1368,7 +1368,7 @@ permissionCommands.add(new lib.Command({
const roleCommands = new lib.CommandTree({ name: "role", description: "Role management" });
roleCommands.add(new lib.Command({
definition: [["list", "l"], "List roles in the cluster"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
let roles = await control.send(new lib.RoleListRequest());
print(asTable(roles));
},
@@ -1716,7 +1716,7 @@ logCommands.add(new lib.Command({
const debugCommands = new lib.CommandTree({ name: "debug", description: "Debugging utilities" });
debugCommands.add(new lib.Command({
definition: ["dump-ws", "Dump WebSocket messages sent and received by controller"],
handler: async function(args: {}, control: Control) {
handler: async function(args: object, control: Control) {
await control.send(new lib.DebugDumpWsRequest());
control.keepOpen = true;
},
+2 -2
View File
@@ -688,7 +688,7 @@ export default class Host extends lib.Link {
url.pathname += `api/stream/${streamId}`;
let response = await phin({
url, method: "GET",
core: { ca: this.tlsCa } as {},
core: { ca: this.tlsCa } as object,
stream: true,
});
@@ -743,7 +743,7 @@ export default class Host extends lib.Link {
url.pathname += `api/stream/${streamId}`;
phin({
url, method: "PUT",
core: { ca: this.tlsCa } as {},
core: { ca: this.tlsCa } as object,
data: content,
}).catch(err => {
logger.error(`Error pushing save to controller:\n${err.stack}`, this.instanceLogMeta(instanceId));
+1 -1
View File
@@ -1067,7 +1067,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " ");
let response = await phin({
url, method: "PUT",
data: content,
core: { ca: this._host.tlsCa } as {},
core: { ca: this._host.tlsCa } as object,
headers: {
"Content-Type": "application/zip",
"x-access-token": this._host.config.get("host.controller_token"),
+2 -2
View File
@@ -692,9 +692,9 @@ export class FactorioServer extends events.EventEmitter {
this._maxConcurrentCommands = value;
this.setMaxListeners(value + 5);
if (this._rconClient) {
// @ts-ignore
// @ts-expect-error sendQueue is private
if (this._rconClient.sendQueue) {
// @ts-ignore
// @ts-expect-error sendQueue is private
this._rconClient.sendQueue.maxConcurrent = value;
}
// XXX: Workaround to suppress bogus event listener warning
+2 -2
View File
@@ -27,7 +27,7 @@ export default class RateLimiter {
/**
* Callback invoked at most `maxRate` per second on activation.
*/
action?: Function;
action?: () => void;
private _lastRun = 0;
private _runTimeout?: ReturnType<typeof setTimeout>;
@@ -43,7 +43,7 @@ export default class RateLimiter {
* @param options.action -
* Callback invoked at maste `maxRate` per second on activation.
*/
constructor(options: { maxRate?: number, action?: Function } = {}) {
constructor(options: { maxRate?: number, action?: () => void } = {}) {
this.maxRate = options.maxRate || 1;
this.action = options.action || undefined;
}
+1 -1
View File
@@ -41,7 +41,7 @@ export async function timeout<T>(promise: Promise<T>, time: number, timeoutResul
try {
return await Promise.race([
promise,
new Promise(resolve => {
new Promise<T>(resolve => {
timer = setTimeout(() => resolve(timeoutResult), time);
}),
]);
-4
View File
@@ -101,10 +101,6 @@ export abstract class WebSocketBaseConnector extends BaseConnector {
_lastReceivedSeq = undefined;
_sendBuffer: (libData.MessageRoutable)[] = [];
constructor(src: libData.Address, dst: libData.Address) {
super(src, dst);
}
_reset() {
this._state = "closed";
this._closing = false;
+3 -3
View File
@@ -44,7 +44,7 @@ export class ConsoleTransport extends Transport {
this.filter = options.filter || (() => true);
}
log(info: any, callback: Function) {
log(info: any, callback: () => void) {
if (!this.filter(info)) {
return callback();
}
@@ -70,7 +70,7 @@ export class WebConsoleFormat {
public options = {}
) { }
transform(info: any, _options: {}) {
transform(info: any, _options: object) {
let src = " ";
if (info.host_id !== undefined) {
src += `s:${info.host_name} - `;
@@ -174,5 +174,5 @@ export type Logger = Omit<winston.Logger,
info: winston.LeveledLogMethod,
server: winston.LeveledLogMethod,
verbose: winston.LeveledLogMethod,
child(options: Object): Logger,
child(options: object): Logger,
};
+1 -1
View File
@@ -201,7 +201,7 @@ export class LinkTransport extends Transport {
this.filter = options.filter;
}
log(info: any, callback: Function) {
log(info: any, callback: () => void) {
if (this.filter && !this.filter(info)) {
return callback();
}
+2 -5
View File
@@ -4,15 +4,12 @@
*/
import * as libHelpers from "./helpers";
import type { Logger } from "./logging";
import type { ConfigGroup } from "./config";
import type { ConfigGroup, PluginConfigGroup } from "./config";
import type { CollectorResult } from "./prometheus";
import type { ParsedFactorioOutput } from "./logging_utils";
import type { ModPack, ModInfo } from "./data";
import type { Link } from "./link";
import type { CommandTree } from "./command";
import type { User } from "./users";
import type { MessageRequest, MessageEvent } from "./data";
import type { PluginConfigGroup } from "./config";
/**
* Conceptual base for controller and instance plugins.
@@ -365,7 +362,7 @@ export class BaseControllerPlugin {
constructor(
public info: PluginNodeEnvInfo,
public controller: Controller,
public metrics: any[],
public metrics: any,
logger: Logger
) {
this.logger = logger.child({ plugin: this.info.name }) as unknown as Logger;
+4 -7
View File
@@ -61,8 +61,7 @@ function GenerateHostTokenButton() {
}, [open]);
// Only install plugins that aren't filesystem paths. Npm modules have max 1 forward slash in their name.
//@ts-ignore TODO::: this doesn't filter anything, `x.split("/") <= 1` is always = true. repair or shouldn't filter ?
const pluginString = pluginList.map(p => `"${p.requirePath}"`).filter(x => x.split("/") <= 1).join(" ");
const pluginString = pluginList.map(p => `"${p.requirePath}"`).filter(x => x.split("/").length <= 1).join(" ");
return <>
<Button
onClick={() => { setOpen(true); }}
@@ -141,12 +140,11 @@ npm init "@clusterio" -- --controller-token ${token} --mode "host" --download-he
}
function CopyButton({ text, message }: { text:string, message:string }) {
let [clipboardPermision, setClipboardPermission] = useState("granted");
let [clipboardPermision, setClipboardPermission] = useState<PermissionState>("granted");
useEffect(() => {
(async () => {
//@ts-ignore https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write
// @ts-expect-error missing API https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write
let result = await navigator.permissions.query({ name: "clipboard-write" });
// result.state is "granted", "denied" or "prompt"
setClipboardPermission(result.state);
result.onchange = function () {
setClipboardPermission(result.state);
@@ -156,9 +154,8 @@ function CopyButton({ text, message }: { text:string, message:string }) {
async function checkClipboardPermission() {
try {
//@ts-ignore https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write
// @ts-expect-error missing API https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write
let result = await navigator.permissions.query({ name: "clipboard-write" });
// result.state is "granted", "denied" or "prompt"
setClipboardPermission(result.state);
result.onchange = function () {
setClipboardPermission(result.state);
+33 -34
View File
@@ -6,16 +6,19 @@ import * as lib from "@clusterio/lib";
const { useBreakpoint } = Grid;
type ModDetailsProps = {
mod: lib.ModInfo|lib.ModRecord;
actions: (mod: lib.ModInfo|lib.ModRecord) => React.JSX.Element;
type ModDetailsProps<T> = {
mod: T;
actions: (mod: T) => React.JSX.Element;
};
export default function ModDetails(props: ModDetailsProps) {
export default function ModDetails<T extends lib.ModInfo | lib.ModRecord>(props: ModDetailsProps<T>) {
let screens = useBreakpoint();
const mod = props.mod;
const mod: Partial<lib.ModInfo> & Partial<lib.ModRecord> = props.mod;
return <Descriptions className="borderless" bordered size="small" column={{ xs: 1, sm: 1, md: 1, lg: 2 }}>
{!(mod instanceof lib.ModInfo) && mod.error && <Descriptions.Item label={<><ExclamationCircleOutlined/> Error</>} span={2}>
{mod.error && <Descriptions.Item
label={<><ExclamationCircleOutlined/> Error</>}
span={2}
>
{mod.error === "missing" && "The given version of this mod is missing from the controller storage."}
{mod.error === "bad_checksum"
&& "Checksum of the mod in the controller storage does not match the checksum provided " +
@@ -23,15 +26,13 @@ export default function ModDetails(props: ModDetailsProps) {
}
</Descriptions.Item>}
{props.actions && !screens.lg
&& <Descriptions.Item label="Action">{props.actions(mod)}</Descriptions.Item>
&& <Descriptions.Item label="Action">{props.actions(props.mod)}</Descriptions.Item>
}
{ (mod instanceof lib.ModInfo) && <>
{mod.title && <Descriptions.Item label="Title">{mod.title}</Descriptions.Item>}
{mod.version && <Descriptions.Item label="Version" span={mod.title ? 1 : 2}>{mod.version}</Descriptions.Item>}
{mod.description && <Descriptions.Item label="Description" span={2}>{mod.description}</Descriptions.Item> }
{mod.author && <Descriptions.Item label="Author" span={2}>{mod.author}</Descriptions.Item>}
</>}
{mod.title && <Descriptions.Item label="Title">{mod.title}</Descriptions.Item>}
{mod.version && <Descriptions.Item label="Version" span={mod.title ? 1 : 2}>{mod.version}</Descriptions.Item>}
{mod.description && <Descriptions.Item label="Description" span={2}>{mod.description}</Descriptions.Item> }
{mod.author && <Descriptions.Item label="Author" span={2}>{mod.author}</Descriptions.Item>}
<Descriptions.Item label="Mod&nbsp;Portal" span={2}>
<Typography.Link href={`https://mods.factorio.com/mod/${mod.name}`}>
@@ -39,26 +40,24 @@ export default function ModDetails(props: ModDetailsProps) {
</Typography.Link>
</Descriptions.Item>
{ (mod instanceof lib.ModInfo) && <>
{mod.contact && <Descriptions.Item label="Contact" span={2}>{mod.contact}</Descriptions.Item>}
{mod.homepage && <Descriptions.Item label="Homepage" span={2}>{mod.homepage}</Descriptions.Item>}
<Descriptions.Item label="Internal&nbsp;Name" span={mod.factorioVersion ? 1 : 2}>{mod.name}</Descriptions.Item>
{mod.factorioVersion
&& <Descriptions.Item label="Factorio&nbsp;Version">{mod.factorioVersion}</Descriptions.Item>
}
{mod.filename && <Descriptions.Item label="Filename">{mod.filename}</Descriptions.Item>}
{mod.size !== undefined
&& <Descriptions.Item label="Size">{lib.formatBytes(mod.size)}</Descriptions.Item>
}
{mod.sha1 && <Descriptions.Item label="SHA1" span={2}>{mod.sha1}</Descriptions.Item>}
{mod.dependencies && mod.dependencies.length
&& <Descriptions.Item label="Dependencies" span={2}>
{mod.dependencies
.filter(e => !e.startsWith("(?)"))
.map((e, i) => <Fragment key={i}>{e}<br/></Fragment>)
}
</Descriptions.Item>
}
</>}
{mod.contact && <Descriptions.Item label="Contact" span={2}>{mod.contact}</Descriptions.Item>}
{mod.homepage && <Descriptions.Item label="Homepage" span={2}>{mod.homepage}</Descriptions.Item>}
<Descriptions.Item label="Internal&nbsp;Name" span={mod.factorioVersion ? 1 : 2}>{mod.name}</Descriptions.Item>
{mod.factorioVersion
&& <Descriptions.Item label="Factorio&nbsp;Version">{mod.factorioVersion}</Descriptions.Item>
}
{mod.filename && <Descriptions.Item label="Filename">{mod.filename}</Descriptions.Item>}
{mod.size !== undefined
&& <Descriptions.Item label="Size">{lib.formatBytes(mod.size)}</Descriptions.Item>
}
{mod.sha1 && <Descriptions.Item label="SHA1" span={2}>{mod.sha1}</Descriptions.Item>}
{mod.dependencies && mod.dependencies.length
&& <Descriptions.Item label="Dependencies" span={2}>
{mod.dependencies
.filter(e => !e.startsWith("(?)"))
.map((e, i) => <Fragment key={i}>{e}<br/></Fragment>)
}
</Descriptions.Item>
}
</Descriptions>;
}
+3 -3
View File
@@ -52,7 +52,7 @@ export class Control extends lib.Link {
accountRoles: lib.AccountRole[] | null = null;
/** Updates not handled by the subscription service */
accountUpdateHandlers: Function[] = [];
accountUpdateHandlers: accountHandler[] = [];
logHandlers: Map<lib.LogFilter, logHandler[]> = new Map();
/** Updates handled by the subscription service */
@@ -146,8 +146,8 @@ export class Control extends lib.Link {
emitAccountUpdate() {
for (let handler of this.accountUpdateHandlers) {
handler({
name: this.accountName,
roles: this.accountRoles,
name: this.accountName!,
roles: this.accountRoles!,
});
}
}
+1 -3
View File
@@ -1,7 +1,5 @@
import type { Request, Response } from "express";
import crypto from "crypto";
import express from "express";
import express, { type Request, type Response } from "express";
import util from "util";
import jwt from "jsonwebtoken";