mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
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:
1 parent
477b600b1b
commit
50f12c719b
26 files changed
+104
-102
No files matched your search
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
],
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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: {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,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.",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -13,7 +13,7 @@ InstanceConfigGroup.define({
|
||||
});
|
||||
InstanceConfigGroup.finalize();
|
||||
|
||||
module.exports = {
|
||||
module.exports.default = {
|
||||
name: "statistics_exporter",
|
||||
title: "Statistics Exporter",
|
||||
description:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user