Port global_chat plugin to typescript (#497)

* .js to .ts

* translate

* update paths to dist/plugin

* add "tsc --build" to prepare

* use field main in package.json de find info

* tsc --build need to append before webpack

* update test and use for plugins package.main
This commit is contained in:
Luciole authored and GitHub committed 2023-08-18 00:06:49 +02:00
1 parent 477b600b1b
commit 50f12c719b
26 files changed
+104 -102

No files matched your search

+2 -3
View File
@@ -24,12 +24,11 @@ export async function loadPluginInfos(pluginList: Map<string, string>) {
let plugins: libPlugin.PluginInfo[] = [];
for (let [pluginName, pluginPath] of pluginList) {
let pluginInfo: libPlugin.PluginInfo;
let pluginPackage: { version: string };
let pluginPackage: { version: string, main?: string };
try {
pluginInfo = require(path.posix.join(pluginPath, "info"));
pluginInfo = require(pluginPath).default;
pluginPackage = require(path.posix.join(pluginPath, "package.json"));
} catch (err: any) {
throw new libErrors.PluginError(pluginName, err);
}
+1 -1
View File
@@ -60,7 +60,7 @@ export async function handlePluginCommand(
let pluginInfo: { name: string };
try {
// eslint-disable-next-line node/global-require
pluginInfo = require(path.posix.join(pluginPath, "info"));
pluginInfo = require(pluginPath).default;
} catch (err: any) {
logger.error(`Unable to import plugin info from ${args.path}:\n${err.stack}`);
process.exitCode = 1;
@@ -1,7 +1,5 @@
"use strict";
const { BaseControlPlugin, CommandTree, Command } = require("@clusterio/lib");
const { ChatEvent } = require("./messages");
import { BaseControlPlugin, CommandTree, Command } from "@clusterio/lib";
import { ChatEvent } from "./messages";
const globalChatCommands = new CommandTree({
name: "global-chat", description: "Global Chat plugin commands",
@@ -15,12 +13,8 @@ globalChatCommands.add(new Command({
},
}));
class ControlPlugin extends BaseControlPlugin {
async addCommands(rootCommand) {
export class ControlPlugin extends BaseControlPlugin {
async addCommands(rootCommand: CommandTree) {
rootCommand.add(globalChatCommands);
}
}
module.exports = {
ControlPlugin,
};
-14
View File
@@ -1,14 +0,0 @@
"use strict";
const messages = require("./messages");
module.exports = {
name: "global_chat",
title: "Global Chat",
description: "Forwards chat between instances.",
instanceEntrypoint: "instance",
controlEntrypoint: "control",
messages: [
messages.ChatEvent,
],
};
+17
View File
@@ -0,0 +1,17 @@
import type { PluginInfo } from "@clusterio/lib";
import { ChatEvent } from "./messages";
const info: PluginInfo = {
name: "global_chat",
title: "Global Chat",
description: "Forwards chat between instances.",
instanceEntrypoint: "dist/plugin/instance",
controlEntrypoint: "dist/plugin/control",
messages: [
ChatEvent,
],
}
export default info;
@@ -1,28 +1,24 @@
/**
* @module
*/
"use strict";
const lib = require("@clusterio/lib");
const { ChatEvent } = require("./messages");
import * as lib from "@clusterio/lib";
import { ChatEvent } from "./messages";
/**
* Removes gps and train tags from messags
*
* @param {string} content - string to strip tags from.
* @returns {string} stripped string.
* @param content - string to strip tags from.
* @returns stripped string.
*/
function removeTags(content) {
function removeTags(content: string): string {
return content.replace(/(\[gps=-?\d+,-?\d+\]|\[train=\d+\])/g, "");
}
class InstancePlugin extends lib.BaseInstancePlugin {
export class InstancePlugin extends lib.BaseInstancePlugin {
messageQueue: string[] = [];
async init() {
this.messageQueue = [];
this.instance.handle(ChatEvent, this.handleChatEvent.bind(this));
}
onControllerConnectionEvent(event) {
onControllerConnectionEvent(event: string) {
if (event === "connect") {
for (let message of this.messageQueue) {
this.sendChat(message);
@@ -31,17 +27,17 @@ class InstancePlugin extends lib.BaseInstancePlugin {
}
}
async handleChatEvent(event) {
async handleChatEvent(event: ChatEvent) {
// TODO check if cross server chat is enabled
let content = `[${event.instanceName}] ${removeTags(event.content)}`;
await this.sendRcon(`/sc game.print('${lib.escapeString(content)}')`, true);
}
sendChat(message) {
sendChat(message: string) {
this.instance.sendTo("allInstances", new ChatEvent(this.instance.name, message));
}
async onOutput(output) {
async onOutput(output: lib.ParsedFactorioOutput) {
if (output.type === "action" && output.action === "CHAT") {
if (this.host.connector.connected) {
this.sendChat(output.message);
@@ -54,9 +50,5 @@ class InstancePlugin extends lib.BaseInstancePlugin {
// TODO implement info command in lua?
}
module.exports = {
InstancePlugin,
// For testing only
_removeTags: removeTags,
};
// For testing only
export const _removeTags = removeTags;
-36
View File
@@ -1,36 +0,0 @@
"use strict";
class ChatEvent {
static type = "event";
static src = ["control", "instance"];
static dst = "instance";
static plugin = "global_chat";
static permission = null;
/** @type {string} */
instanceName;
/** @type {string} */
content;
constructor(instanceName, content) {
this.instanceName = instanceName;
this.content = content;
}
static jsonSchema = {
type: "object",
required: ["instanceName", "content"],
properties: {
instanceName: { type: "string" },
content: { type: "string" },
},
};
static fromJSON(json) {
return new this(json.instanceName, json.content);
}
}
module.exports = {
ChatEvent,
};
+23
View File
@@ -0,0 +1,23 @@
import { Type, Static } from "@sinclair/typebox";
export class ChatEvent {
static type = "event";
static src = ["control", "instance"];
static dst = "instance";
static plugin = "global_chat";
static permission = null;
constructor(
public instanceName: string,
public content: string,
) {
}
static jsonSchema = Type.Object({
"instanceName": Type.String(),
"content": Type.String(),
});
static fromJSON(json: Static<typeof ChatEvent.jsonSchema>) {
return new this(json.instanceName, json.content);
}
}
+7 -1
View File
@@ -6,8 +6,9 @@
"homepage": "https://github.com/clusterio/clusterio#readme",
"license": "MIT",
"repository": "clusterio/clusterio",
"main": "dist/plugin/info.js",
"scripts": {
"prepare": "webpack-cli --env production",
"prepare": "tsc --build && webpack-cli --env production",
"test": "echo \"Error: run tests from root\" && exit 1"
},
"bugs": {
@@ -22,11 +23,16 @@
"devDependencies": {
"@clusterio/lib": "^2.0.0-alpha.13",
"@clusterio/web_ui": "^2.0.0-alpha.13",
"@types/node": "^20.4.5",
"typescript": "^5.1.6",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-merge": "^5.9.0"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@sinclair/typebox": "^0.30.4"
}
}
+3 -3
View File
@@ -4,9 +4,9 @@ const lib = require("@clusterio/lib");
const mock = require("../../../test/mock");
const lines = require("../../../test/lib/factorio/lines");
const instance = require("../instance");
const info = require("../info");
const { ChatEvent } = require("../messages");
const instance = require("../dist/plugin/instance");
const info = require("../dist/plugin/info").default;
const { ChatEvent } = require("../dist/plugin/messages");
describe("global_chat plugin", function() {
+16
View File
@@ -0,0 +1,16 @@
{
"include": ["./**/*.ts"],
"exclude": ["test/*", "./dist/*"],
"compilerOptions": {
"lib": ["es2023"],
"module": "commonjs",
"target": "es2022",
"rootDir": ".",
"outDir": "dist/plugin",
"sourceMap": true,
"strict": true,
"alwaysStrict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
+1 -1
View File
@@ -16,7 +16,7 @@ module.exports = (env = {}) => merge(common(env), {
name: "global_chat",
library: { type: "var", name: "plugin_global_chat" },
exposes: {
"./info": "./info.js",
"./info": "./dist/plugin/info.js",
"./package.json": "./package.json",
},
shared: {
+1 -1
View File
@@ -41,7 +41,7 @@ lib.definePermission({
grantByDefault: true,
});
module.exports = {
module.exports.default = {
name: "inventory_sync",
title: "Inventory sync",
description: "Synchronizes players inventories between instances",
+1
View File
@@ -6,6 +6,7 @@
"homepage": "https://github.com/clusterio/factorioClusterio#readme",
"license": "MIT",
"repository": "clusterio/factorioClusterio",
"main": "./info.js",
"scripts": {
"prepare": "webpack-cli --env production",
"test": "echo \"Error: run tests from root\" && exit 1"
+1 -1
View File
@@ -22,7 +22,7 @@ ControllerConfigGroup.define({
});
ControllerConfigGroup.finalize();
module.exports = {
module.exports.default = {
name: "player_auth",
title: "Player Auth",
description: "Provides authentication to the cluster via logging into a Factorio server.",
+1
View File
@@ -6,6 +6,7 @@
"homepage": "https://github.com/clusterio/clusterio#readme",
"license": "MIT",
"repository": "clusterio/clusterio",
"main": "./info.js",
"scripts": {
"prepare": "webpack-cli --env production",
"test": "echo \"Error: run tests from root\" && exit 1"
+1 -1
View File
@@ -7,7 +7,7 @@ const mock = require("../../../test/mock");
const controller = require("../controller");
const instance = require("../instance");
const info = require("../info");
const info = require("../info").default;
const { FetchPlayerCodeRequest, SetVerifyCodeRequest } = require("../messages");
const lib = require("@clusterio/lib");
+1 -1
View File
@@ -1,7 +1,7 @@
"use strict";
const messages = require("./messages");
module.exports = {
module.exports.default = {
name: "research_sync",
title: "Research Sync",
description: "Synchronises technology research progress between instances.",
+1
View File
@@ -6,6 +6,7 @@
"homepage": "https://github.com/clusterio/clusterio#readme",
"license": "MIT",
"repository": "clusterio/clusterio",
"main": "./info.js",
"scripts": {
"prepare": "webpack-cli --env production",
"test": "echo \"Error: run tests from root\" && exit 1"
+1 -1
View File
@@ -13,7 +13,7 @@ InstanceConfigGroup.define({
});
InstanceConfigGroup.finalize();
module.exports = {
module.exports.default = {
name: "statistics_exporter",
title: "Statistics Exporter",
description:
+1
View File
@@ -6,6 +6,7 @@
"homepage": "https://github.com/clusterio/clusterio#readme",
"license": "MIT",
"repository": "clusterio/clusterio",
"main": "./info.js",
"scripts": {
"prepare": "webpack-cli --env production",
"test": "echo \"Error: run tests from root\" && exit 1"
+1 -1
View File
@@ -3,7 +3,7 @@ const assert = require("assert").strict;
const mock = require("../../../test/mock");
const instance = require("../instance");
const info = require("../info");
const info = require("../info").default;
describe("statistics_exporter plugin", function() {
+1 -1
View File
@@ -48,7 +48,7 @@ lib.definePermission({
grantByDefault: true,
});
module.exports = {
module.exports.default = {
name: "subspace_storage",
title: "Subspace Storage",
description: "Provides shared storage across instances for the Subspace Storage mod",
+1
View File
@@ -6,6 +6,7 @@
"homepage": "https://github.com/clusterio/clusterio#readme",
"license": "MIT",
"repository": "clusterio/clusterio",
"main": "./info.js",
"scripts": {
"prepare": "webpack-cli --env production",
"test": "echo \"Error: run tests from root\" && exit 1"
+1 -1
View File
@@ -12,7 +12,7 @@ const lib = require("@clusterio/lib");
const { LineSplitter, ConsoleTransport, logger } = lib;
// Make sure permissions from plugins are loaded
require("../../plugins/global_chat/info");
require("../../plugins/global_chat/dist/plugin/info");
require("../../plugins/player_auth/info");
require("../../plugins/research_sync/info");
require("../../plugins/statistics_exporter/info");
+3 -3
View File
@@ -18,11 +18,11 @@ describe("lib/plugin_loader", function() {
async function writePlugin(pluginPath, infoName) {
await fs.outputFile(
path.join(pluginPath, "info.js"),
`module.exports = { name: "${infoName}" };`
`module.exports.default = { name: "${infoName}" };`
);
await fs.outputFile(
path.join(pluginPath, "package.json"),
'{ "version": "0.0.1" }'
'{ "version": "0.0.1", "main":"info.js" }'
);
}
@@ -35,7 +35,7 @@ describe("lib/plugin_loader", function() {
it("should throw on missing plugin", async function() {
await assert.rejects(
lib.loadPluginInfos(new Map([["missing", missingPlugin]]), []),
new RegExp(`^Error: PluginError: Cannot find module '${escapeRegExp(missingPlugin)}/info'`)
new RegExp(`^Error: PluginError: Cannot find module '${escapeRegExp(missingPlugin)}'`)
);
});
it("should load test plugin", async function() {