Add js templates and config templates

This commit is contained in:
Cooldude2606 committed 2024-01-23 00:14:08 +00:00
1 parent de00a043c3
commit 9b0293501f
23 files changed
+543 -50

No files matched your search

+57 -40
View File
@@ -509,77 +509,89 @@ async function copyPluginTemplateFile(src, dst, props) {
}
const templateData = await fs.readFile(src, "utf8");
const outputData = templateData.replace(/\/\/ ([a-z_]*) \/\//g, (_, value) => {
if (!props.hasOwnProperty(value)) {
logger.warn(`Unknown property string (${value}) found in template file ${src}`);
return value;
}
const outputData = templateData
.replace(/\/\/ \[([a-z_]*)\] \/\/(.*?)\/\/ \[\] \/\//gs, (_, prop, content) => {
// Find and replace // [prop] //content// [] //
if (!props.hasOwnProperty(prop)) {
logger.warn(`Unknown property clause (${prop}) found in template file ${src}`);
return content;
}
return props[value];
});
return Boolean(props[prop]) ? content : "";
})
.replace(/\/\/ ([a-z_]*) \/\//g, (_, prop) => {
// Find and replace // prop //
if (!props.hasOwnProperty(prop)) {
logger.warn(`Unknown property string (${prop}) found in template file ${src}`);
return prop;
}
return props[prop];
});
await fs.outputFile(dst, outputData);
}
async function copyPluginTemplate(pluginName, templates) {
logger.info(`Please wait, coping templates for ${templates.join(", ")}`);
const noTypescript = templates.includes("js");
const devDependencies = new Map();
const dependencies = new Map();
const entryPoints = new Map();
const prepare = [];
const files = new Map();
const prepare = [];
let templatePath = "./templates/plugin-ts";
if (noTypescript) {
templatePath = "./templates/plugin-js";
logger.error("Javascript only templates are not currently supported");
return;
}
const javascriptOnly = templates.includes("js");
const webpack = templates.includes("controller") || templates.includes("web");
templatePath = path.resolve(__dirname, templatePath);
// Get the file extension and path to the templates
const ext = javascriptOnly ? "js" : "ts";
const templatePath = path.resolve(__dirname, javascriptOnly ? "./templates/plugin-js" : "./templates/plugin-ts");
// Files includes in all templates
// Files included in all templates
files.set(".gitignore", path.join(templatePath, ".gitignore"));
files.set(".npmignore", path.join(templatePath, ".npmignore"));
files.set("package.json", path.join(templatePath, "package.json"));
files.set("tsconfig.json", path.join(templatePath, "tsconfig.json"));
files.set("messages.ts", path.join(templatePath, "messages.ts"));
files.set("index.ts", path.join(templatePath, "index.ts"));
devDependencies.set("@types/node", "^20.4.5");
devDependencies.set("@types/node", "^20.4.5");
devDependencies.set("typescript", "^5.1.6");
dependencies.set("@sinclair/typebox", "^0.30.4");
prepare.push("tsc --build");
files.set(`messages.${ext}`, path.join(templatePath, `messages.${ext}`));
files.set(`index.${ext}`, path.join(templatePath, `index.${ext}`));
if (templates.includes("controller") || templates.includes("web")) {
devDependencies.set("@clusterio/web_ui", "^2.0.0-alpha.14");
devDependencies.set("@types/react", "^18.2.21");
// Files and dependencies to support typescript
if (!javascriptOnly) {
if (webpack) {
devDependencies.set("@types/react", "^18.2.21");
files.set("tsconfig.web.json", path.join(templatePath, "tsconfig.web.json"));
}
devDependencies.set("@types/node", "^20.4.5");
devDependencies.set("typescript", "^5.1.6");
files.set("tsconfig.json", path.join(templatePath, "tsconfig.json"));
prepare.push("tsc --build");
}
// Files and dependences to support webpack
if (webpack) {
devDependencies.set("webpack", "^5.88.2");
devDependencies.set("webpack-cli", "^5.1.4");
devDependencies.set("webpack-merge", "^5.9.0");
devDependencies.set("@clusterio/web_ui", "^2.0.0-alpha.14");
entryPoints.set("webEntrypoint", "./web");
prepare.push("webpack-cli --env production");
files.set("webpack.config.js", path.join(templatePath, "webpack.config.js"));
files.set("tsconfig.web.json", path.join(templatePath, "tsconfig.web.json"));
files.set("web/index.tsx", path.join(templatePath,
templates.includes("web") ? "web/plugin.tsx" : "web/no_plugin.tsx"
files.set(`web/index.${ext}x`, path.join(templatePath,
templates.includes("web") ? `web/plugin.${ext}x` : `web/no_plugin.${ext}x`
));
}
if (templates.includes("controller")) {
entryPoints.set("controllerEntrypoint", "dist/plugin/controller");
files.set("controller.ts", path.join(templatePath, "controller.ts"));
files.set(`controller.${ext}`, path.join(templatePath, `controller.${ext}`));
}
if (templates.includes("host")) {
entryPoints.set("hostEntrypoint", "dist/plugin/host");
files.set("host.ts", path.join(templatePath, "host.ts"));
files.set(`host.${ext}`, path.join(templatePath, `host.${ext}`));
}
if (templates.includes("instance")) {
entryPoints.set("instanceEntrypoint", "dist/plugin/instance");
files.set("instance.ts", path.join(templatePath, "instance.ts"));
files.set(`instance.${ext}`, path.join(templatePath, `instance.${ext}`));
}
if (templates.includes("module")) {
@@ -589,25 +601,30 @@ async function copyPluginTemplate(pluginName, templates) {
}
if (templates.includes("ctl")) {
files.set("ctl.ts", path.join(templatePath, "ctl.ts"));
entryPoints.set("ctlEntrypoint", "dist/plugin/ctl");
files.set(`ctl.${ext}`, path.join(templatePath, `ctl.${ext}`));
}
// Props that will be replaced in the template files, found with "// prop_name //"
// Properties that will control the replacements in the templates
const props = {
controller: templates.includes("controller"),
host: templates.includes("host"),
instance: templates.includes("instance"),
module: templates.includes("module"),
ctl: templates.includes("ctl"),
web: templates.includes("web"),
plugin_name: pluginName,
prepare: prepare
.join(" && "),
entry_points: [...entryPoints.entries()]
.map((entry) => `${entry[0]}: "${entry[1]}",`)
.join("\n\t"),
dependencies: [...dependencies.entries()]
.map((entry) => `"${entry[0]}": "${entry[1]}"`)
.join(",\n\t\t"),
dev_dependencies: [...devDependencies.entries()]
.map((entry) => `"${entry[0]}": "${entry[1]}",`)
.join("\n\t\t"),
};
// Write all the template files
const writes = [];
for (let [dst, src] of files) {
writes.push(copyPluginTemplateFile(src, dst, props));
@@ -0,0 +1,3 @@
dist/
node_modules/
package-lock.json
@@ -0,0 +1,2 @@
webpack.config.js
dist/web/build
@@ -0,0 +1,47 @@
"use strict";
const lib = require("@clusterio/lib");
const { BaseControllerPlugin } = require("@clusterio/controller");
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
class ControllerPlugin extends BaseControllerPlugin {
async init() {
this.controller.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
this.controller.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
}
async onControllerConfigFieldChanged(field, curr, prev) {
this.logger.info(`controller::onControllerConfigFieldChanged ${field}`);
}// [instance] //
async onInstanceConfigFieldChanged(instance, field, curr, prev) {
this.logger.info(`controller::onInstanceConfigFieldChanged ${instance.id} ${field}`);
}// [] //
async onSaveData() {
this.logger.info("controller::onSaveData");
}
async onShutdown() {
this.logger.info("controller::onShutdown");
}
async onPlayerEvent(instance, event) {
this.logger.info(`controller::onPlayerEvent ${instance.id} ${JSON.stringify(event)}`);
}
async handlePluginExampleEvent(event) {
this.logger.info(JSON.stringify(event));
}
async handlePluginExampleRequest(request) {
this.logger.info(JSON.stringify(request));
return {
myResponseString: request.myString,
myResponseNumbers: request.myNumberArray,
};
}
}
module.exports = {
ControllerPlugin,
};
@@ -0,0 +1,31 @@
"use strict";
const { BaseCtlPlugin } = require("@clusterio/ctl");
const { CommandTree, Command } = require("@clusterio/lib");
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
/* eslint-disable no-console */
const pluginCommands = new CommandTree({
name: "// plugin_name //", description: "The default description I forgot to change",
});
pluginCommands.add(new Command({
definition: ["my-command <foo>", "My command description that I really should change", (yargs) => {
yargs.positional("foo", { describe: "foo is foo!", type: "string" });
}],
handler: async function(args, control) {
const response = await control.sendTo("controller", new PluginExampleRequest(args.foo, [1, 2, 3]));
console.log(response);
console.log(args);
},
}));
/* eslint-enable no-console */
class CtlPlugin extends BaseCtlPlugin {
async addCommands(rootCommand) {
rootCommand.add(pluginCommands);
}
}
module.exports = {
CtlPlugin,
};
@@ -0,0 +1,35 @@
"use strict";
const lib = require("@clusterio/lib");
const { BaseHostPlugin } = require("@clusterio/host");
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
class HostPlugin extends BaseHostPlugin {
async init() {
this.host.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
this.host.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
}
async onHostConfigFieldChanged(field, curr, prev) {
this.logger.info(`host::onInstanceConfigFieldChanged ${field}`);
}
async onShutdown() {
this.logger.info("host::onShutdown");
}
async handlePluginExampleEvent(event) {
this.logger.info(JSON.stringify(event));
}
async handlePluginExampleRequest(request) {
this.logger.info(JSON.stringify(request));
return {
myResponseString: request.myString,
myResponseNumbers: request.myNumberArray,
};
}
}
module.exports = {
HostPlugin,
};
@@ -0,0 +1,65 @@
"use strict";
const lib = require("@clusterio/lib");
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
lib.definePermission({
name: "// plugin_name //.example.permission.event",
title: "Example permission event",
description: "My plugin's example permission that I forgot to remove",
});
lib.definePermission({
name: "// plugin_name //.example.permission.request",
title: "Example permission request",
description: "My plugin's example permission that I forgot to remove",
});// [web] //
lib.definePermission({
name: "// plugin_name //.page.view",
title: "Example page view permission",
description: "My plugin's example page permission that I forgot to remove",
});// [] //
const plugin = {
name: "// plugin_name //",
title: "// plugin_name //",
description: "I didn't update my description",
// entry_points //
// [controller] //
controlConfigFields: {
"// plugin_name //.myControllerField": {
title: "My Controller Field",
description: "This should be removed",
type: "string",
initialValue: "Remove Me",
},
},// [] //// [host] //
hostConfigFields: {
"// plugin_name //.myHostField": {
title: "My Host Field",
description: "This should be removed",
type: "string",
initialValue: "Remove Me",
},
},// [] //// [instance] //
instanceConfigFields: {
"// plugin_name //.myInstanceField": {
title: "My Instance Field",
description: "This should be removed",
type: "string",
initialValue: "Remove Me",
},
},// [] //
messages: [
PluginExampleEvent,
PluginExampleRequest,
],
};
module.exports = {
plugin,
PluginExampleEvent,
PluginExampleRequest,
};
@@ -0,0 +1,43 @@
"use strict";
const lib = require("@clusterio/lib");
const { BaseInstancePlugin } = require("@clusterio/host");
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
class InstancePlugin extends BaseInstancePlugin {
async init() {
this.instance.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
this.instance.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
}
async onInstanceConfigFieldChanged(field, curr, prev) {
this.logger.info(`instance::onInstanceConfigFieldChanged ${field}`);
}
async onStart() {
this.logger.info("instance::onStart");
}
async onStop() {
this.logger.info("instance::onStop");
}
async onPlayerEvent(event) {
this.logger.info(`onPlayerEvent::onPlayerEvent ${JSON.stringify(event)}`);
}
async handlePluginExampleEvent(event) {
this.logger.info(JSON.stringify(event));
}
async handlePluginExampleRequest(request) {
this.logger.info(JSON.stringify(request));
return {
myResponseString: request.myString,
myResponseNumbers: request.myNumberArray,
};
}
}
module.exports = {
InstancePlugin,
};
@@ -0,0 +1,57 @@
"use strict";
const { plainJson, jsonArray, JsonBoolean, JsonNumber, JsonString, StringEnum } = require("@clusterio/lib");
const { Type, Static } = require("@sinclair/typebox");
class PluginExampleEvent {
static type = "event";
static src = ["host", "control"];
static dst = ["controller", "host", "instance"];
static plugin = "// plugin_name //";
static permission = "// plugin_name //.example.permission.event";
constructor(myString, myNumberArray) {
this.myString = myString;
this.myNumberArray = myNumberArray;
}
static jsonSchema = Type.Object({
"myString": Type.String(),
"myNumberArray": Type.Array(Type.Number()),
});
static fromJson(json) {
return new PluginExampleEvent(json.myString, json.myNumberArray);
}
}
class PluginExampleRequest {
static type = "request";
static src = ["host", "control"];
static dst = ["controller", "host", "instance"];
static plugin = "// plugin_name //";
static permission = "// plugin_name //.example.permission.request";
constructor(myString, myNumberArray) {
this.myString = myString;
this.myNumberArray = myNumberArray;
}
static jsonSchema = Type.Object({
"myString": Type.String(),
"myNumberArray": Type.Array(Type.Number()),
});
static fromJson(json) {
return new PluginExampleEvent(json.myString, json.myNumberArray);
}
static Response = plainJson(Type.Object({
"myResponseString": Type.String(),
"myResponseNumbers": Type.Array(Type.Number()),
}));
}
module.exports = {
PluginExampleEvent,
PluginExampleRequest,
};
@@ -0,0 +1,24 @@
local clusterio_api = require("modules/clusterio/api")
local MyModule = {
events = {},
on_nth_tick = {},
}
function MyModule.foo()
game.print("foo")
end
MyModule.events[clusterio_api.events.on_server_startup] = function(event)
game.print(game.table_to_json(event))
end
MyModule.events[defines.events.on_player_crafted_item] = function(event)
game.print(game.table_to_json(event))
end
MyModule.on_nth_tick[300] = function()
game.print(game.tick)
end
return MyModule
@@ -0,0 +1,12 @@
{
"name": "// plugin_name //",
"load": [
"control.lua"
],
"require": [
],
"dependencies": [
]
}
@@ -0,0 +1,2 @@
return require("./control")
@@ -0,0 +1,29 @@
{
"name": "// plugin_name //",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"prepare": "// prepare //"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@clusterio/lib": "^2.0.0-alpha.14"
},
"devDependencies": {
// dev_dependencies //
"@clusterio/lib": "^2.0.0-alpha.14"
},
"dependencies": {
"@sinclair/typebox": "^0.30.4"
},
"publishConfig": {
"access": "public"
},
"keywords": [
"clusterio",
"factorio"
]
}
Whitespace-only changes.
@@ -0,0 +1,49 @@
const { useContext, useEffect, useState } = require("react");
// const { } = require("antd");
const {
BaseWebPlugin, PageLayout, Control, ControlContext, notifyErrorHandler,
} = require("@clusterio/web_ui");
const lib = require("@clusterio/lib");
const { PluginExampleEvent, PluginExampleRequest } = require("../messages");
function MyTemplatePage() {
let control = useContext(ControlContext);
return <PageLayout nav={[{ name: "// plugin_name //" }]}>
<h2>// plugin_name //</h2>
</PageLayout>;
}
class WebPlugin extends BaseWebPlugin {
async init() {
this.pages = [
{
path: "/// plugin_name //",
sidebarName: "// plugin_name //",
permission: "// plugin_name //.page.view",
content: <MyTemplatePage/>,
},
];
this.control.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
this.control.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
}
async handlePluginExampleEvent(event) {
this.logger.info(JSON.stringify(event));
}
async handlePluginExampleRequest(request) {
this.logger.info(JSON.stringify(request));
return {
myResponseString: request.myString,
myResponseNumbers: request.myNumberArray,
};
}
}
module.exports = {
WebPlugin,
}
@@ -0,0 +1,28 @@
"use strict";
const path = require("path");
const webpack = require("webpack");
const { merge } = require("webpack-merge");
const common = require("@clusterio/web_ui/webpack.common");
module.exports = (env = {}) => merge(common(env), {
context: __dirname,
entry: "./web/index.jsx",
output: {
path: path.resolve(__dirname, "dist", "web"),
},
plugins: [
new webpack.container.ModuleFederationPlugin({
name: "// plugin_name //",
library: { type: "var", name: "plugin_// plugin_name //" },
exposes: {
"./": "./info.js",
"./package.json": "./package.json",
},
shared: {
"@clusterio/lib": { import: false },
"@clusterio/web_ui": { import: false },
},
}),
],
});
@@ -1,2 +1,3 @@
dist/
node_modules/
package-lock.json
@@ -10,11 +10,11 @@ export class ControllerPlugin extends BaseControllerPlugin {
async onControllerConfigFieldChanged(field: string, curr: unknown, prev: unknown) {
this.logger.info(`controller::onControllerConfigFieldChanged ${field}`);
}
}// [instance] //
async onInstanceConfigFieldChanged(instance: InstanceInfo, field: string, curr: unknown, prev: unknown) {
this.logger.info(`controller::onInstanceConfigFieldChanged ${instance.id} ${field}`);
}
}// [] //
async onSaveData() {
this.logger.info("controller::onSaveData");
+2 -1
View File
@@ -13,7 +13,8 @@ pluginCommands.add(new Command({
yargs.positional("foo", { describe: "foo is foo!", type: "string" });
}],
handler: async function(args: { foo: string }, control: Control) {
await control.sendTo("controller", new PluginExampleEvent(args.foo, [1, 2, 3]));
const response = await control.sendTo("controller", new PluginExampleRequest(args.foo, [1, 2, 3]));
console.log(response);
console.log(args);
},
}));
+44 -1
View File
@@ -12,13 +12,56 @@ lib.definePermission({
name: "// plugin_name //.example.permission.request",
title: "Example permission request",
description: "My plugin's example permission that I forgot to remove",
});
});// [web] //
lib.definePermission({
name: "// plugin_name //.page.view",
title: "Example page view permission",
description: "My plugin's example page permission that I forgot to remove",
});// [] //
declare module "@clusterio/lib" {// [controller] //
export interface ControllerConfigFields {
"// plugin_name //.myControllerField": string;
}// [] //// [host] //
export interface HostConfigFields {
"// plugin_name //.myHostField": string;
}// [] //// [instance] //
export interface InstanceConfigFields {
"// plugin_name //.myInstanceField": string;
}// [] //
}
export const plugin: lib.PluginDeclaration = {
name: "// plugin_name //",
title: "// plugin_name //",
description: "I didn't update my description",
// entry_points //
// [controller] //
controlConfigFields: {
"// plugin_name //.myControllerField": {
title: "My Controller Field",
description: "This should be removed",
type: "string",
initialValue: "Remove Me",
},
},// [] //// [host] //
hostConfigFields: {
"// plugin_name //.myHostField": {
title: "My Host Field",
description: "This should be removed",
type: "string",
initialValue: "Remove Me",
},
},// [] //// [instance] //
instanceConfigFields: {
"// plugin_name //.myInstanceField": {
title: "My Instance Field",
description: "This should be removed",
type: "string",
initialValue: "Remove Me",
},
},// [] //
messages: [
PluginExampleEvent,
@@ -5,7 +5,7 @@ export class PluginExampleEvent {
declare ["constructor"]: typeof PluginExampleEvent;
static type = "event" as const;
static src = ["host", "control"] as const;
static dst = ["controller", "host"] as const;
static dst = ["controller", "host", "instance"] as const;
static plugin = "// plugin_name //" as const;
static permission = "// plugin_name //.example.permission.event";
@@ -29,7 +29,7 @@ export class PluginExampleRequest {
declare ["constructor"]: typeof PluginExampleRequest;
static type = "request" as const;
static src = ["host", "control"] as const;
static dst = ["controller", "host"] as const;
static dst = ["controller", "host", "instance"] as const;
static plugin = "// plugin_name //" as const;
static permission = "// plugin_name //.example.permission.request";
@@ -16,10 +16,14 @@
// dev_dependencies //
"@clusterio/lib": "^2.0.0-alpha.14"
},
"dependencies": {
"@sinclair/typebox": "^0.30.4"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
// dependencies //
}
"keywords": [
"clusterio",
"factorio"
]
}
@@ -14,7 +14,7 @@ module.exports = (env = {}) => merge(common(env), {
plugins: [
new webpack.container.ModuleFederationPlugin({
name: "// plugin_name //",
library: { type: "var", name: "plugin___plugin_name__" },
library: { type: "var", name: "plugin_// plugin_name //" },
exposes: {
"./": "./index.ts",
"./package.json": "./package.json",