mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 23:14:53 +09:00
Add subscriptions and luacheck
This commit is contained in:
15 files changed
+3644
-39
No files matched your search
@@ -522,15 +522,18 @@ async function copyPluginTemplateFile(src, dst, props) {
|
||||
|
||||
const templateData = await fs.readFile(src, "utf8");
|
||||
const outputData = templateData
|
||||
.replace(/\/\/ \[([a-z_]*)\] \/\/(.*?)\/\/ \[\] \/\//gs, (_, prop, content) => {
|
||||
// matches: // [prop] // anything // [] // or /*/ [prop] /*/ anything /*/ [] /*/
|
||||
.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;
|
||||
}
|
||||
|
||||
// Would be nice to support + (and) | (or) for prop clauses
|
||||
return Boolean(props[prop]) ? content : "";
|
||||
})
|
||||
// matches: // prop //
|
||||
.replace(/\/\/ ([a-z_]*) \/\//g, (_, prop) => {
|
||||
// Find and replace // prop //
|
||||
if (!props.hasOwnProperty(prop)) {
|
||||
@@ -607,6 +610,7 @@ async function copyPluginTemplate(pluginName, templates) {
|
||||
}
|
||||
|
||||
if (templates.includes("module")) {
|
||||
files.set(".luacheckrc", path.join(templatePath, ".luacheckrc"));
|
||||
files.set("module/module.json", path.join(templatePath, "module/module.json"));
|
||||
files.set("module/control.lua", path.join(templatePath, "module/control.lua"));
|
||||
files.set("module/module_exports.lua", path.join(templatePath, "module/module_exports.lua"));
|
||||
@@ -620,6 +624,7 @@ async function copyPluginTemplate(pluginName, templates) {
|
||||
// Properties that will control the replacements in the templates
|
||||
const props = {
|
||||
controller: templates.includes("controller"),
|
||||
subscribable: templates.includes("controller") && templates.includes("web"),
|
||||
host: templates.includes("host"),
|
||||
instance: templates.includes("instance"),
|
||||
module: templates.includes("module"),
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,12 +1,17 @@
|
||||
"use strict";
|
||||
const lib = require("@clusterio/lib");
|
||||
const { BaseControllerPlugin } = require("@clusterio/controller");
|
||||
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
|
||||
const { PluginExampleEvent, PluginExampleRequest,/*/ [subscribable] /*/ ExampleSubscribableUpdate, ExampleSubscribableValue/*/ [] /*/ } = require("./messages");
|
||||
|
||||
class ControllerPlugin extends BaseControllerPlugin {
|
||||
class ControllerPlugin extends BaseControllerPlugin {// [subscribable] //
|
||||
exampleDatabase;
|
||||
storageDirty = false;
|
||||
// [] //
|
||||
async init() {
|
||||
this.controller.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
|
||||
this.controller.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
|
||||
this.controller.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));// [subscribable] //
|
||||
this.controller.subscriptions.handle(ExampleSubscribableUpdate, this.handleExampleSubscription.bind(this));
|
||||
this.exampleDatabase = new Map(); // If needed, replace with loading from database file // [] //
|
||||
}
|
||||
|
||||
async onControllerConfigFieldChanged(field, curr, prev) {
|
||||
@@ -39,7 +44,14 @@ class ControllerPlugin extends BaseControllerPlugin {
|
||||
myResponseString: request.myString,
|
||||
myResponseNumbers: request.myNumberArray,
|
||||
};
|
||||
}
|
||||
}// [subscribable] //
|
||||
|
||||
async handleExampleSubscription(request) {
|
||||
const values = [...this.exampleDatabase.values()].filter(
|
||||
value => value.updatedAtMs > request.lastRequestTimeMs,
|
||||
);
|
||||
return values.length ? new ExampleSubscribableUpdate(values) : null;
|
||||
}// [] //
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use strict";
|
||||
const lib = require("@clusterio/lib");
|
||||
|
||||
const { PluginExampleEvent, PluginExampleRequest } = require("./messages");
|
||||
const messages = require("./messages");
|
||||
|
||||
lib.definePermission({
|
||||
name: "// plugin_name //.example.permission.event",
|
||||
@@ -13,7 +12,13 @@ lib.definePermission({
|
||||
name: "// plugin_name //.example.permission.request",
|
||||
title: "Example permission request",
|
||||
description: "My plugin's example permission that I forgot to remove",
|
||||
});// [web] //
|
||||
});// [subscribable] //
|
||||
|
||||
lib.definePermission({
|
||||
name: "// plugin_name //.example.permission.subscribe",
|
||||
title: "Example permission subscribe",
|
||||
description: "My plugin's example permission that I forgot to remove",
|
||||
});// [] //// [web] //
|
||||
|
||||
lib.definePermission({
|
||||
name: "// plugin_name //.page.view",
|
||||
@@ -26,7 +31,7 @@ const plugin = {
|
||||
title: "// plugin_name //",
|
||||
description: "I didn't update my description",// [entry_points] //
|
||||
// entry_points //
|
||||
// [] //// [controller] //
|
||||
// [] //// [controller] //
|
||||
controllerConfigFields: {
|
||||
"// plugin_name //.myControllerField": {
|
||||
title: "My Controller Field",
|
||||
@@ -61,8 +66,9 @@ const plugin = {
|
||||
},// [] //
|
||||
|
||||
messages: [
|
||||
PluginExampleEvent,
|
||||
PluginExampleRequest,
|
||||
messages.PluginExampleEvent,
|
||||
messages.PluginExampleRequest,// [subscribable] //
|
||||
messages.ExampleSubscribableUpdate,// [] //
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const { plainJson, jsonArray, JsonBoolean, JsonNumber, JsonString, StringEnum } = require("@clusterio/lib");
|
||||
const { Type, Static } = require("@sinclair/typebox");
|
||||
const { Type } = require("@sinclair/typebox");
|
||||
|
||||
class PluginExampleEvent {
|
||||
static type = "event";
|
||||
@@ -49,9 +49,49 @@ class PluginExampleRequest {
|
||||
"myResponseString": Type.String(),
|
||||
"myResponseNumbers": Type.Array(Type.Number()),
|
||||
}));
|
||||
}// [subscribable] //
|
||||
|
||||
class ExampleSubscribableValue {
|
||||
constructor(id, updatedAtMs, isDeleted) {
|
||||
this.id = id;
|
||||
this.updatedAtMs = updatedAtMs;
|
||||
this.isDeleted = isDeleted;
|
||||
}
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
id: Type.String(),
|
||||
updatedAtMs: Type.Number(),
|
||||
isDeleted: Type.Boolean(),
|
||||
});
|
||||
|
||||
static fromJSON(json) {
|
||||
return new this(json.id, json.updatedAtMs, json.isDeleted);
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleSubscribableUpdate {
|
||||
static type = "event";
|
||||
static src = "controller";
|
||||
static dst = "control";
|
||||
static plugin = "// plugin_name //";
|
||||
static permission = "// plugin_name //.example.permission.subscribe";
|
||||
|
||||
constructor(updates) {
|
||||
this.updates = updates;
|
||||
}
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"updates": Type.Array(ExampleSubscribableValue.jsonSchema),
|
||||
});
|
||||
|
||||
static fromJSON(json) {
|
||||
return new this(json.updates.map(update => ExampleSubscribableValue.fromJSON(update)));
|
||||
}
|
||||
}// [] //
|
||||
|
||||
module.exports = {
|
||||
PluginExampleEvent,
|
||||
PluginExampleRequest,
|
||||
PluginExampleRequest,// [subscribable] //
|
||||
ExampleSubscribableValue,
|
||||
ExampleSubscribableUpdate,// [] //
|
||||
};
|
||||
@@ -1,18 +1,40 @@
|
||||
local clusterio_api = require("modules/clusterio/api")
|
||||
|
||||
--- Top level module table, contains event handlers and public methods
|
||||
local MyModule = {
|
||||
events = {},
|
||||
on_nth_tick = {},
|
||||
}
|
||||
|
||||
--- global is 'synced' between players, you should use your plugin name to avoid conflicts
|
||||
-- setupGlobalData should either be removed or called during clusterio_api.events.on_server_startup
|
||||
local globalData = {}
|
||||
local function setupGlobalData()
|
||||
if global["// plugin_name //"] == nil then
|
||||
global["// plugin_name //"] = {
|
||||
-- starting values go here
|
||||
}
|
||||
end
|
||||
globalData = global["// plugin_name //"]
|
||||
end
|
||||
|
||||
--- Public methods should be available though your top level module table
|
||||
function MyModule.foo()
|
||||
game.print("foo")
|
||||
end
|
||||
|
||||
--- Private methods should be local to the file, this will prevent others from calling it
|
||||
local function bar()
|
||||
game.print("bar")
|
||||
end
|
||||
|
||||
--- Clusterio provides a few custom events, on_server_startup is the most useful and should be used in place of on_load
|
||||
MyModule.events[clusterio_api.events.on_server_startup] = function(event)
|
||||
setupGlobalData()
|
||||
game.print(game.table_to_json(event))
|
||||
end
|
||||
|
||||
--- Factorio events are accessible through defines.events, you can have one handler per event per module
|
||||
MyModule.events[defines.events.on_player_crafted_item] = function(event)
|
||||
game.print(game.table_to_json(event))// [instance] //
|
||||
clusterio_api.send_json("// plugin_name //-plugin_example_ipc", {
|
||||
@@ -20,8 +42,11 @@ MyModule.events[defines.events.on_player_crafted_item] = function(event)
|
||||
})// [] //
|
||||
end
|
||||
|
||||
--- Nth tick is a special case that requires its own table, the index represents the time period between calls in ticks
|
||||
MyModule.on_nth_tick[300] = function()
|
||||
game.print(game.tick)
|
||||
bar()
|
||||
end
|
||||
|
||||
--- Always return the top level module table from control, this is how clusterio will access your event handlers
|
||||
return MyModule
|
||||
@@ -1,7 +1,8 @@
|
||||
local MyModule = require("./control")// [instance] //
|
||||
|
||||
-- Can contain anything you plan to use with send_rcon from functions, modules, or data
|
||||
--- Can contain anything you plan to use with send_rcon including functions, modules, or data
|
||||
-- luacheck: globals ipc_// plugin_name //
|
||||
ipc_// plugin_name // = MyModule// [] //
|
||||
|
||||
-- Can contain anything you want to allow other plugins to have access to, this example exposes the whole module
|
||||
--- Can contain anything you want to allow other plugins to have access to, this example exposes the whole module
|
||||
return MyModule
|
||||
@@ -1,4 +1,4 @@
|
||||
const { useContext, useEffect, useState } = require("react");
|
||||
const { useContext, useEffect, useState,/*/ [subscribable] /*/ useCallback, useSyncExternalStore,/*/ [] /*/ } = require("react");
|
||||
// const { } = require("antd");
|
||||
|
||||
const {
|
||||
@@ -6,17 +6,22 @@ const {
|
||||
} = require("@clusterio/web_ui");
|
||||
|
||||
const lib = require("@clusterio/lib");
|
||||
const { PluginExampleEvent, PluginExampleRequest } = require("../messages");
|
||||
const { PluginExampleEvent, PluginExampleRequest,/*/ [subscribable] /*/ ExampleSubscribableUpdate,/*/ [] /*/ } = require("../messages");
|
||||
|
||||
function MyTemplatePage() {
|
||||
let control = useContext(ControlContext);
|
||||
let control = useContext(ControlContext);// [subscribable] //
|
||||
const plugin = control.plugins.get("// plugin_name //");
|
||||
const [subscribableData, synced] = plugin.useSubscribableData();// [] //
|
||||
|
||||
return <PageLayout nav={[{ name: "// plugin_name //" }]}>
|
||||
<h2>// plugin_name //</h2>
|
||||
<h2>// plugin_name //</h2>// [subscribable] //
|
||||
Synced: {String(synced)} Data: {JSON.stringify([...subscribableData.values()])}// [] //
|
||||
</PageLayout>;
|
||||
}
|
||||
|
||||
class WebPlugin extends BaseWebPlugin {
|
||||
class WebPlugin extends BaseWebPlugin {// [subscribable] //
|
||||
subscribableData = new lib.EventSubscriber(ExampleSubscribableUpdate, this.control);
|
||||
// [] //
|
||||
async init() {
|
||||
this.pages = [
|
||||
{
|
||||
@@ -29,7 +34,13 @@ class WebPlugin extends BaseWebPlugin {
|
||||
|
||||
this.control.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
|
||||
this.control.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
|
||||
}
|
||||
}// [subscribable] //
|
||||
|
||||
useSubscribableData() {
|
||||
const control = useContext(ControlContext);
|
||||
const subscribe = useCallback((callback) => this.subscribableData.subscribe(callback), [control]);
|
||||
return useSyncExternalStore(subscribe, () => this.subscribableData.getSnapshot());
|
||||
}// [] //
|
||||
|
||||
async handlePluginExampleEvent(event) {
|
||||
this.logger.info(JSON.stringify(event));
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,11 +1,16 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
import { BaseControllerPlugin, InstanceInfo } from "@clusterio/controller";
|
||||
import { PluginExampleEvent, PluginExampleRequest } from "./messages";
|
||||
import { PluginExampleEvent, PluginExampleRequest,/*/ [subscribable] /*/ ExampleSubscribableUpdate, ExampleSubscribableValue/*/ [] /*/ } from "./messages";
|
||||
|
||||
export class ControllerPlugin extends BaseControllerPlugin {
|
||||
export class ControllerPlugin extends BaseControllerPlugin {// [subscribable] //
|
||||
exampleDatabase!: Map<string, ExampleSubscribableValue>;
|
||||
storageDirty = false;
|
||||
// [] //
|
||||
async init() {
|
||||
this.controller.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
|
||||
this.controller.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
|
||||
this.controller.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));// [subscribable] //
|
||||
this.controller.subscriptions.handle(ExampleSubscribableUpdate, this.handleExampleSubscription.bind(this));
|
||||
this.exampleDatabase = new Map();// [] //
|
||||
}
|
||||
|
||||
async onControllerConfigFieldChanged(field: string, curr: unknown, prev: unknown) {
|
||||
@@ -38,5 +43,12 @@ export class ControllerPlugin extends BaseControllerPlugin {
|
||||
myResponseString: request.myString,
|
||||
myResponseNumbers: request.myNumberArray,
|
||||
};
|
||||
}
|
||||
}// [subscribable] //
|
||||
|
||||
async handleExampleSubscription(request: lib.SubscriptionRequest) {
|
||||
const values = [...this.exampleDatabase.values()].filter(
|
||||
value => value.updatedAtMs > request.lastRequestTimeMs,
|
||||
);
|
||||
return values.length ? new ExampleSubscribableUpdate(values) : null;
|
||||
}// [] //
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as lib from "@clusterio/lib";
|
||||
|
||||
import { PluginExampleEvent, PluginExampleRequest } from "./messages";
|
||||
import * as Messages from "./messages";
|
||||
|
||||
lib.definePermission({
|
||||
name: "// plugin_name //.example.permission.event",
|
||||
@@ -12,7 +11,13 @@ lib.definePermission({
|
||||
name: "// plugin_name //.example.permission.request",
|
||||
title: "Example permission request",
|
||||
description: "My plugin's example permission that I forgot to remove",
|
||||
});// [web] //
|
||||
});// [subscribable] //
|
||||
|
||||
lib.definePermission({
|
||||
name: "// plugin_name //.example.permission.subscribe",
|
||||
title: "Example permission subscribe",
|
||||
description: "My plugin's example permission that I forgot to remove",
|
||||
});// [] //// [web] //
|
||||
|
||||
lib.definePermission({
|
||||
name: "// plugin_name //.page.view",
|
||||
@@ -40,7 +45,7 @@ export const plugin: lib.PluginDeclaration = {
|
||||
title: "// plugin_name //",
|
||||
description: "I didn't update my description",// [entry_points] //
|
||||
// entry_points //
|
||||
// [] //// [controller] //
|
||||
// [] //// [controller] //
|
||||
controllerConfigFields: {
|
||||
"// plugin_name //.myControllerField": {
|
||||
title: "My Controller Field",
|
||||
@@ -75,7 +80,8 @@ export const plugin: lib.PluginDeclaration = {
|
||||
},// [] //
|
||||
|
||||
messages: [
|
||||
PluginExampleEvent,
|
||||
PluginExampleRequest,
|
||||
Messages.PluginExampleEvent,
|
||||
Messages.PluginExampleRequest,// [subscribable] //
|
||||
Messages.ExampleSubscribableUpdate,// [] //
|
||||
],
|
||||
};
|
||||
@@ -52,4 +52,44 @@ export class PluginExampleRequest {
|
||||
"myResponseString": Type.String(),
|
||||
"myResponseNumbers": Type.Array(Type.Number()),
|
||||
}));
|
||||
}// [subscribable] //
|
||||
|
||||
export class ExampleSubscribableValue {
|
||||
constructor(
|
||||
public id: string,
|
||||
public updatedAtMs: number,
|
||||
public isDeleted: boolean,
|
||||
) {
|
||||
}
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
id: Type.String(),
|
||||
updatedAtMs: Type.Number(),
|
||||
isDeleted: Type.Boolean(),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(json.id, json.updatedAtMs, json.isDeleted);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExampleSubscribableUpdate {
|
||||
declare ["constructor"]: typeof ExampleSubscribableUpdate;
|
||||
static type = "event" as const;
|
||||
static src = "controller" as const;
|
||||
static dst = "control" as const;
|
||||
static plugin = "// plugin_name //" as const;
|
||||
static permission = "// plugin_name //.example.permission.subscribe";
|
||||
|
||||
constructor(
|
||||
public updates: ExampleSubscribableValue[],
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"updates": Type.Array(ExampleSubscribableValue.jsonSchema),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(json.updates.map(update => ExampleSubscribableValue.fromJSON(update)));
|
||||
}
|
||||
}// [] //// [] //
|
||||
@@ -1,18 +1,40 @@
|
||||
local clusterio_api = require("modules/clusterio/api")
|
||||
|
||||
--- Top level module table, contains event handlers and public methods
|
||||
local MyModule = {
|
||||
events = {},
|
||||
on_nth_tick = {},
|
||||
}
|
||||
|
||||
--- global is 'synced' between players, you should use your plugin name to avoid conflicts
|
||||
-- setupGlobalData should either be removed or called during clusterio_api.events.on_server_startup
|
||||
local globalData = {}
|
||||
local function setupGlobalData()
|
||||
if global["// plugin_name //"] == nil then
|
||||
global["// plugin_name //"] = {
|
||||
-- starting values go here
|
||||
}
|
||||
end
|
||||
globalData = global["// plugin_name //"]
|
||||
end
|
||||
|
||||
--- Public methods should be available though your top level module table
|
||||
function MyModule.foo()
|
||||
game.print("foo")
|
||||
end
|
||||
|
||||
--- Private methods should be local to the file, this will prevent others from calling it
|
||||
local function bar()
|
||||
game.print("bar")
|
||||
end
|
||||
|
||||
--- Clusterio provides a few custom events, on_server_startup is the most useful and should be used in place of on_load
|
||||
MyModule.events[clusterio_api.events.on_server_startup] = function(event)
|
||||
setupGlobalData()
|
||||
game.print(game.table_to_json(event))
|
||||
end
|
||||
|
||||
--- Factorio events are accessible through defines.events, you can have one handler per event per module
|
||||
MyModule.events[defines.events.on_player_crafted_item] = function(event)
|
||||
game.print(game.table_to_json(event))// [instance] //
|
||||
clusterio_api.send_json("// plugin_name //-plugin_example_ipc", {
|
||||
@@ -20,8 +42,11 @@ MyModule.events[defines.events.on_player_crafted_item] = function(event)
|
||||
})// [] //
|
||||
end
|
||||
|
||||
--- Nth tick is a special case that requires its own table, the index represents the time period between calls in ticks
|
||||
MyModule.on_nth_tick[300] = function()
|
||||
game.print(game.tick)
|
||||
bar()
|
||||
end
|
||||
|
||||
--- Always return the top level module table from control, this is how clusterio will access your event handlers
|
||||
return MyModule
|
||||
@@ -1,7 +1,8 @@
|
||||
local MyModule = require("./control")// [instance] //
|
||||
|
||||
-- Can contain anything you plan to use with send_rcon from functions, modules, or data
|
||||
--- Can contain anything you plan to use with send_rcon including functions, modules, or data
|
||||
-- luacheck: globals ipc_// plugin_name //
|
||||
ipc_// plugin_name // = MyModule// [] //
|
||||
|
||||
-- Can contain anything you want to allow other plugins to have access to, this example exposes the whole module
|
||||
--- Can contain anything you want to allow other plugins to have access to, this example exposes the whole module
|
||||
return MyModule
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import React, { useContext, useEffect, useState,/*/ [subscribable] /*/ useCallback, useSyncExternalStore,/*/ [] /*/ } from "react";
|
||||
// import { } from "antd";
|
||||
|
||||
import {
|
||||
@@ -6,17 +6,22 @@ import {
|
||||
} from "@clusterio/web_ui";
|
||||
|
||||
import * as lib from "@clusterio/lib";
|
||||
import { PluginExampleEvent, PluginExampleRequest } from "../messages";
|
||||
import { PluginExampleEvent, PluginExampleRequest,/*/ [subscribable] /*/ ExampleSubscribableUpdate,/*/ [] /*/ } from "../messages";
|
||||
|
||||
function MyTemplatePage() {
|
||||
let control = useContext(ControlContext);
|
||||
const control = useContext(ControlContext);// [subscribable] //
|
||||
const plugin = control.plugins.get("// plugin_name //") as WebPlugin;
|
||||
const [subscribableData, synced] = plugin.useSubscribableData();// [] //
|
||||
|
||||
return <PageLayout nav={[{ name: "// plugin_name //" }]}>
|
||||
<h2>// plugin_name //</h2>
|
||||
<h2>// plugin_name //</h2>// [subscribable] //
|
||||
Synced: {String(synced)} Data: {JSON.stringify([...subscribableData.values()])}// [] //
|
||||
</PageLayout>;
|
||||
}
|
||||
|
||||
export class WebPlugin extends BaseWebPlugin {
|
||||
export class WebPlugin extends BaseWebPlugin {// [subscribable] //
|
||||
subscribableData = new lib.EventSubscriber(ExampleSubscribableUpdate, this.control);
|
||||
// [] //
|
||||
async init() {
|
||||
this.pages = [
|
||||
{
|
||||
@@ -29,7 +34,13 @@ export class WebPlugin extends BaseWebPlugin {
|
||||
|
||||
this.control.handle(PluginExampleEvent, this.handlePluginExampleEvent.bind(this));
|
||||
this.control.handle(PluginExampleRequest, this.handlePluginExampleRequest.bind(this));
|
||||
}
|
||||
}// [subscribable] //
|
||||
|
||||
useSubscribableData() {
|
||||
const control = useContext(ControlContext);
|
||||
const subscribe = useCallback((callback: () => void) => this.subscribableData.subscribe(callback), [control]);
|
||||
return useSyncExternalStore(subscribe, () => this.subscribableData.getSnapshot());
|
||||
}// [] //
|
||||
|
||||
async handlePluginExampleEvent(event: PluginExampleEvent) {
|
||||
this.logger.info(JSON.stringify(event));
|
||||
|
||||
Reference in new issue
Block a user