From bfe119eaa34ec2dc1f4254e6dec0e62f2d0c5233 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Fri, 28 Jul 2023 01:46:25 +0200 Subject: [PATCH] Flatten lib namespace Move all functions and classes currently available through lib/name and libName to be under a single flat namespace in lib. This make reorganising the lib namespace much simpler as the location of symbols can move without breaking the consumers of lib. The multi-entrypoint design was already problematic for the web plugin system which couldn't effectively use it due to how webpack's shared module system is awkward to set up with multiple entrypoints per package. --- docs/contributing.md | 7 +- docs/writing-plugins.md | 24 +- packages/controller/controller.js | 58 ++- packages/controller/src/BaseConnection.js | 23 +- packages/controller/src/ControlConnection.js | 249 +++++------ packages/controller/src/Controller.js | 160 ++++--- packages/controller/src/ControllerRouter.js | 22 +- packages/controller/src/HostConnection.js | 54 ++- packages/controller/src/InstanceInfo.js | 2 +- packages/controller/src/UserManager.js | 17 +- packages/controller/src/WsServer.js | 32 +- packages/controller/src/WsServerConnector.js | 23 +- packages/controller/src/metrics.js | 4 +- packages/controller/src/routes.js | 43 +- packages/ctl/ctl.js | 70 ++- packages/ctl/src/commands.js | 423 +++++++++--------- packages/host/host.js | 48 +- packages/host/src/Host.js | 178 ++++---- packages/host/src/Instance.js | 139 +++--- packages/host/src/InstanceConnection.js | 11 +- packages/lib/ExponentialBackoff.js | 2 +- packages/lib/PlayerStats.js | 2 +- packages/lib/RateLimiter.js | 2 +- packages/lib/browser.js | 22 +- packages/lib/command.js | 16 +- packages/lib/config/classes.js | 32 +- packages/lib/config/definitions.js | 50 +-- packages/lib/data/ExportManifest.js | 2 +- packages/lib/data/ModInfo.js | 2 +- packages/lib/data/ModPack.js | 12 +- packages/lib/data/messages_controller.js | 22 +- packages/lib/data/messages_core.js | 70 +-- packages/lib/data/messages_host.js | 18 +- packages/lib/data/messages_instance.js | 94 ++-- packages/lib/data/messages_mod.js | 38 +- packages/lib/data/messages_user.js | 46 +- packages/lib/data/version.js | 6 +- packages/lib/database.js | 2 +- packages/lib/factorio/exchange_string.js | 6 +- packages/lib/factorio/export.js | 20 +- packages/lib/factorio/patch.js | 6 +- packages/lib/factorio/server.js | 14 +- packages/lib/helpers.js | 10 +- packages/lib/index.js | 52 ++- packages/lib/link/connectors.js | 22 +- packages/lib/link/link.js | 16 +- packages/lib/logging.js | 4 +- packages/lib/logging_utils.js | 12 +- packages/lib/plugin.js | 32 +- packages/lib/plugin_loader.js | 6 +- packages/lib/prometheus.js | 52 +-- packages/lib/shared_commands.js | 2 +- packages/lib/stream.js | 8 +- packages/lib/users.js | 16 +- packages/lib/zip_ops.js | 2 +- packages/web_ui/src/bootstrap.jsx | 12 +- packages/web_ui/src/components/App.jsx | 3 +- .../src/components/AssignInstanceModal.jsx | 4 +- .../src/components/ControllerConfigTree.jsx | 10 +- .../web_ui/src/components/CreateSaveModal.jsx | 8 +- packages/web_ui/src/components/HostsPage.jsx | 4 +- .../src/components/InstanceConfigTree.jsx | 10 +- .../web_ui/src/components/InstanceRcon.jsx | 4 +- .../src/components/InstanceViewPage.jsx | 10 +- .../web_ui/src/components/InstancesPage.jsx | 10 +- .../src/components/LoadScenarioModal.jsx | 8 +- packages/web_ui/src/components/LogConsole.jsx | 4 +- packages/web_ui/src/components/ModDetails.jsx | 4 +- .../web_ui/src/components/ModPackViewPage.jsx | 16 +- packages/web_ui/src/components/ModsPage.jsx | 20 +- .../web_ui/src/components/RoleViewPage.jsx | 12 +- packages/web_ui/src/components/RolesPage.jsx | 6 +- packages/web_ui/src/components/SavesList.jsx | 16 +- .../components/StartStopInstanceButton.jsx | 6 +- .../web_ui/src/components/UserViewPage.jsx | 22 +- packages/web_ui/src/components/UsersPage.jsx | 6 +- packages/web_ui/src/model/export_manifest.jsx | 4 +- packages/web_ui/src/model/host.jsx | 6 +- packages/web_ui/src/model/instance.jsx | 8 +- packages/web_ui/src/model/mod_pack.jsx | 8 +- packages/web_ui/src/model/mods.jsx | 7 +- packages/web_ui/src/model/saves.jsx | 6 +- packages/web_ui/src/model/user.jsx | 9 +- packages/web_ui/src/util/notify.jsx | 3 +- packages/web_ui/src/util/websocket.jsx | 48 +- plugins/global_chat/control.js | 9 +- plugins/global_chat/instance.js | 7 +- plugins/global_chat/test/plugin.js | 4 +- plugins/inventory_sync/controller.js | 7 +- plugins/inventory_sync/info.js | 8 +- plugins/inventory_sync/instance.js | 17 +- plugins/inventory_sync/web/index.jsx | 4 +- plugins/player_auth/controller.js | 11 +- plugins/player_auth/info.js | 4 +- plugins/player_auth/instance.js | 4 +- plugins/player_auth/test/plugin.js | 19 +- plugins/player_auth/web/index.jsx | 4 +- plugins/research_sync/controller.js | 9 +- plugins/research_sync/instance.js | 11 +- plugins/research_sync/messages.js | 6 +- plugins/statistics_exporter/info.js | 4 +- plugins/statistics_exporter/instance.js | 9 +- plugins/subspace_storage/controller.js | 15 +- plugins/subspace_storage/dole.js | 3 +- plugins/subspace_storage/info.js | 8 +- plugins/subspace_storage/instance.js | 13 +- plugins/subspace_storage/messages.js | 6 +- plugins/subspace_storage/web/index.jsx | 4 +- test/controller/HttpCloser.js | 1 - test/controller/routes.js | 2 +- test/host.js | 27 +- test/host/Instance.js | 28 +- test/integration/clusterio.js | 79 ++-- test/integration/export.js | 6 +- test/integration/index.js | 49 +- test/integration/patch.js | 6 +- test/integration/server.js | 13 +- test/lib/ExponentialBackoff.js | 2 +- test/lib/RateLimiter.js | 3 +- test/lib/command.js | 43 +- test/lib/config/classes.js | 40 +- test/lib/data/ModInfo.js | 9 +- test/lib/data/ModPack.js | 7 +- test/lib/database.js | 68 +-- test/lib/factorio/exchange_string.js | 16 +- test/lib/factorio/export.js | 6 +- test/lib/factorio/patch.js | 24 +- test/lib/factorio/server.js | 42 +- test/lib/file_ops.js | 30 +- test/lib/hash.js | 6 +- test/lib/helpers.js | 30 +- test/lib/ini.js | 24 +- test/lib/link/connector.js | 29 +- test/lib/link/link.js | 154 ++++--- test/lib/logging_utils.js | 39 +- test/lib/lua_tools.js | 16 +- test/lib/plugin.js | 12 +- test/lib/plugin_loader.js | 16 +- test/lib/prometheus.js | 2 +- test/lib/stream.js | 13 +- test/lib/users.js | 58 +-- test/lib/zip_ops.js | 2 +- test/mock.js | 29 +- 143 files changed, 1798 insertions(+), 1918 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index c007ee77..d8729a33 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -205,12 +205,13 @@ Fields in configs and messages sent over links uses lowercase_underscore. JavaScript files are named using lowercase_underscore for files that export multiple items. Files containing and exporting a single class should be named the same as the class in PascalCase. -Imported modules from the lib package are prefixed with lib to make them easier to distinguish, as the names tend to be very generic. +Relative imports in lib package are prefixed with lib to make them easier to distinguish, as the names tend to be very generic. E.g.: - const libLink = require("@clusterio/lib/link"); - const libLuaTools = require("@clusterio/lib/lua_tools"); + const libLink = require("./link"); + const libLuaTools = require("./lua_tools"); +Note that no sub-modules of the lib package is imported directly from the outside of it with the exception of `build_mod`. For lua code lowercase_underscore is used for everything. diff --git a/docs/writing-plugins.md b/docs/writing-plugins.md index 026efc5a..e0e3405e 100644 --- a/docs/writing-plugins.md +++ b/docs/writing-plugins.md @@ -49,7 +49,7 @@ Without it the plugin will not recognized by Clusterio. Here's an example of it: ```js -const { libLink } = require("@clusterio/lib"); // For messages +const lib = require("@clusterio/lib"); // For messages module.exports = { name: "foo_frobber", @@ -120,9 +120,9 @@ The plugin class should derive from its respective base class defined in `lib/pl For example, to define a ControllerPlugin class the following code can be used: ```js -const libPlugin = require("@clusterio/lib/plugin"); +const lib = require("@clusterio/lib"); -class ControllerPlugin extends libPlugin.BaseControllerPlugin { +class ControllerPlugin extends lib.BaseControllerPlugin { async init() { this.foo = 42; await this.startFrobnication(); @@ -206,9 +206,9 @@ You can take advantage of it by subclassing `PluginConfigGroup`, setting `defaul For example in info.js: ```js -const libConfig = require("@clusterio/lib/config"); +const lib = require("@clusterio/lib"); -class ControllerConfigGroup extends libConfig.PluginConfigGroup { } +class ControllerConfigGroup extends lib.PluginConfigGroup { } ControllerConfigGroup.defaultAccess = ["controller", "host", "control"]; ControllerConfigGroup.groupName = "foo_frobber"; ControllerConfigGroup.define({ @@ -333,7 +333,7 @@ The Event constructor takes an object of properties that define the event, for e ```js messages: { - startFrobnication: new libLink.Event({ + startFrobnication: new lib.Event({ type: "foo_frobber:start_frobnication", links: ["controller-host", "host-instance"], forwardTo: "instance", @@ -408,7 +408,7 @@ For example, the following could be defined in `info.js`: ```js messages: { - reportFrobnication: new libLink.Request({ + reportFrobnication: new lib.Request({ type: "foo_frobber:report_frobnication", links: ["controller-host", "host-instance"], forwardTo: "instance", @@ -530,7 +530,7 @@ In its simplest form collecting data from plugins consists of defining the metri For example: ```js -const { Counter } = require("@clusterio/lib/prometheus"); +const { Counter } = require("@clusterio/lib"); const fooMetric = new Counter( "clusterio_foo_frobber_foo_metric", "Measures the level of foo", @@ -546,7 +546,7 @@ It's recommended that plugin metrics follow `clusterio__ { yargs .command("create-admin ", "Create a cluster admin") @@ -262,10 +254,10 @@ async function initialize() { if (parameters.args.logLevel !== "none") { logger.add(new ConsoleTransport({ level: parameters.args.logLevel, - format: new libLoggingUtils.TerminalFormat(), + format: new lib.TerminalFormat(), })); } - libLoggingUtils.handleUnhandledErrors(logger); + lib.handleUnhandledErrors(logger); let command = parameters.args._[0]; if (command === "run") { @@ -285,19 +277,19 @@ async function initialize() { // If the command is plugin management we don't try to load plugins if (command === "plugin") { - await libSharedCommands.handlePluginCommand(parameters.args, pluginList, parameters.args.pluginList); + await lib.handlePluginCommand(parameters.args, pluginList, parameters.args.pluginList); return parameters; } logger.info("Loading Plugin info"); - parameters.pluginInfos = await libPluginLoader.loadPluginInfos(pluginList); - libLink.registerPluginMessages(parameters.pluginInfos); - libConfig.registerPluginConfigGroups(parameters.pluginInfos); - libConfig.finalizeConfigs(); + parameters.pluginInfos = await lib.loadPluginInfos(pluginList); + lib.registerPluginMessages(parameters.pluginInfos); + lib.registerPluginConfigGroups(parameters.pluginInfos); + lib.finalizeConfigs(); parameters.controllerConfigPath = parameters.args.config; logger.info(`Loading config from ${parameters.controllerConfigPath}`); - parameters.controllerConfig = new libConfig.ControllerConfig("controller"); + parameters.controllerConfig = new lib.ControllerConfig("controller"); try { await parameters.controllerConfig.load(JSON.parse(await fs.readFile(parameters.controllerConfigPath))); @@ -307,7 +299,7 @@ async function initialize() { await parameters.controllerConfig.init(); } else { - throw new libErrors.StartupError(`Failed to load ${parameters.controllerConfigPath}: ${err.message}`); + throw new lib.StartupError(`Failed to load ${parameters.controllerConfigPath}: ${err.message}`); } } @@ -316,13 +308,13 @@ async function initialize() { let asyncRandomBytes = util.promisify(crypto.randomBytes); let bytes = await asyncRandomBytes(256); parameters.controllerConfig.set("controller.auth_secret", bytes.toString("base64")); - await libFileOps.safeOutputFile( + await lib.safeOutputFile( parameters.controllerConfigPath, JSON.stringify(parameters.controllerConfig.serialize(), null, 4) ); } if (command === "config") { - await libSharedCommands.handleConfigCommand( + await lib.handleConfigCommand( parameters.args, parameters.controllerConfig, parameters.controllerConfigPath ); @@ -393,14 +385,14 @@ I version of clusterio. Expect things to break. I ` ); startup().catch(err => { - if (err instanceof libErrors.StartupError) { + if (err instanceof lib.StartupError) { logger.fatal(` +-------------------------------+ | Unable to to start controller | +-------------------------------+ ${err.stack}` ); - } else if (err instanceof libErrors.PluginError) { + } else if (err instanceof lib.PluginError) { logger.fatal(` ${err.pluginName} plugin threw an unexpected error during startup, please report it to the plugin author. diff --git a/packages/controller/src/BaseConnection.js b/packages/controller/src/BaseConnection.js index 40fddbba..73964d22 100644 --- a/packages/controller/src/BaseConnection.js +++ b/packages/controller/src/BaseConnection.js @@ -1,19 +1,16 @@ "use strict"; -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const libLink = require("@clusterio/lib/link"); -const { logger } = require("@clusterio/lib/logging"); -const libPlugin = require("@clusterio/lib/plugin"); +const lib = require("@clusterio/lib"); +const { logger } = lib; const ControllerRouter = require("./ControllerRouter"); /** * Base class for controller connections * - * @extends module:lib/link.Link + * @extends module:lib.Link * @alias module:controller/src/BaseConnection */ -class BaseConnection extends libLink.Link { +class BaseConnection extends lib.Link { constructor(connector, controller) { /** @member {module:controller/src/WsServerConnector} module:controller/src/BaseConnection#connector */ super(connector); @@ -24,15 +21,15 @@ class BaseConnection extends libLink.Link { for (let [Event, handler] of controller._registeredEvents) { this.handle(Event, handler); } for (let [Event, handler] of controller._snoopedEvents) { this.snoopEvent(Event, handler); } - this.handle(libData.ModPackGetRequest, this.handleModPackGetRequest.bind(this)); - this.handle(libData.ModPackGetDefaultRequest, this.handleModPackGetDefaultRequest.bind(this)); + this.handle(lib.ModPackGetRequest, this.handleModPackGetRequest.bind(this)); + this.handle(lib.ModPackGetDefaultRequest, this.handleModPackGetDefaultRequest.bind(this)); } async disconnect(code, reason) { try { await this.connector.disconnect(); } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { logger.error(`"Unexpected error preparing disconnect:\n${err.stack}`); } } @@ -51,7 +48,7 @@ class BaseConnection extends libLink.Link { let { id } = request; let modPack = this._controller.modPacks.get(id); if (!modPack) { - throw new libErrors.RequestError(`Mod pack with ID ${id} does not exist`); + throw new lib.RequestError(`Mod pack with ID ${id} does not exist`); } return modPack; } @@ -59,11 +56,11 @@ class BaseConnection extends libLink.Link { async handleModPackGetDefaultRequest() { let id = this._controller.config.get("controller.default_mod_pack_id"); if (id === null) { - throw new libErrors.RequestError("Default mod pack not set on controller"); + throw new lib.RequestError("Default mod pack not set on controller"); } let modPack = this._controller.modPacks.get(id); if (!modPack) { - throw new libErrors.RequestError(`Default mod pack configured (${id}) does not exist`); + throw new lib.RequestError(`Default mod pack configured (${id}) does not exist`); } return modPack; } diff --git a/packages/controller/src/ControlConnection.js b/packages/controller/src/ControlConnection.js index de677f07..d14bb5e7 100644 --- a/packages/controller/src/ControlConnection.js +++ b/packages/controller/src/ControlConnection.js @@ -3,22 +3,15 @@ const events = require("events"); const fs = require("fs-extra"); const path = require("path"); -const libConfig = require("@clusterio/lib/config"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const libHelpers = require("@clusterio/lib/helpers"); -const libLink = require("@clusterio/lib/link"); -const { logFilter, logger } = require("@clusterio/lib/logging"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); -const libPrometheus = require("@clusterio/lib/prometheus"); -const libUsers = require("@clusterio/lib/users"); +const lib = require("@clusterio/lib"); +const { logFilter, logger } = lib; const BaseConnection = require("./BaseConnection"); const routes = require("./routes"); const strcmp = new Intl.Collator(undefined, { numerice: "true", sensitivity: "base" }).compare; -const queryLogTime = new libPrometheus.Summary( +const queryLogTime = new lib.Summary( "clusterio_controller_query_log_duration_seconds", "Time in seconds log queries took to execute." ); @@ -39,7 +32,7 @@ class ControlConnection extends BaseConnection { /** * The user making this connection. - * @type {module:lib/users.User} + * @type {module:lib.User} */ this.user = user; @@ -103,75 +96,75 @@ class ControlConnection extends BaseConnection { }); } - this.handle(libData.ControllerConfigGetRequest, this.handleControllerConfigGetRequest.bind(this)); - this.handle(libData.ControllerConfigSetFieldRequest, this.handleControllerConfigSetFieldRequest.bind(this)); - this.handle(libData.ControllerConfigSetPropRequest, this.handleControllerConfigSetPropRequest.bind(this)); - this.handle(libData.HostListRequest, this.handleHostListRequest.bind(this)); - this.handle(libData.HostSetSubscriptionsRequest, this.handleHostSetSubscriptionsRequest.bind(this)); - this.handle(libData.HostGenerateTokenRequest, this.handleHostGenerateTokenRequest.bind(this)); - this.handle(libData.HostConfigCreateRequest, this.handleHostConfigCreateRequest.bind(this)); - this.handle(libData.InstanceDetailsGetRequest, this.handleInstanceDetailsGetRequest.bind(this)); - this.handle(libData.InstanceDetailsListRequest, this.handleInstanceDetailsListRequest.bind(this)); + this.handle(lib.ControllerConfigGetRequest, this.handleControllerConfigGetRequest.bind(this)); + this.handle(lib.ControllerConfigSetFieldRequest, this.handleControllerConfigSetFieldRequest.bind(this)); + this.handle(lib.ControllerConfigSetPropRequest, this.handleControllerConfigSetPropRequest.bind(this)); + this.handle(lib.HostListRequest, this.handleHostListRequest.bind(this)); + this.handle(lib.HostSetSubscriptionsRequest, this.handleHostSetSubscriptionsRequest.bind(this)); + this.handle(lib.HostGenerateTokenRequest, this.handleHostGenerateTokenRequest.bind(this)); + this.handle(lib.HostConfigCreateRequest, this.handleHostConfigCreateRequest.bind(this)); + this.handle(lib.InstanceDetailsGetRequest, this.handleInstanceDetailsGetRequest.bind(this)); + this.handle(lib.InstanceDetailsListRequest, this.handleInstanceDetailsListRequest.bind(this)); this.handle( - libData.InstanceDetailsSetSubscriptionsRequest, this.handleInstanceDetailsSetSubscriptionsRequest.bind(this) + lib.InstanceDetailsSetSubscriptionsRequest, this.handleInstanceDetailsSetSubscriptionsRequest.bind(this) ); - this.handle(libData.InstanceCreateRequest, this.handleInstanceCreateRequest.bind(this)); - this.handle(libData.InstanceDeleteRequest, this.handleInstanceDeleteRequest.bind(this)); - this.handle(libData.InstanceConfigGetRequest, this.handleInstanceConfigGetRequest.bind(this)); - this.handle(libData.InstanceConfigSetFieldRequest, this.handleInstanceConfigSetFieldRequest.bind(this)); - this.handle(libData.InstanceConfigSetPropRequest, this.handleInstanceConfigSetPropRequest.bind(this)); - this.handle(libData.InstanceAssignRequest, this.handleInstanceAssignRequest.bind(this)); + this.handle(lib.InstanceCreateRequest, this.handleInstanceCreateRequest.bind(this)); + this.handle(lib.InstanceDeleteRequest, this.handleInstanceDeleteRequest.bind(this)); + this.handle(lib.InstanceConfigGetRequest, this.handleInstanceConfigGetRequest.bind(this)); + this.handle(lib.InstanceConfigSetFieldRequest, this.handleInstanceConfigSetFieldRequest.bind(this)); + this.handle(lib.InstanceConfigSetPropRequest, this.handleInstanceConfigSetPropRequest.bind(this)); + this.handle(lib.InstanceAssignRequest, this.handleInstanceAssignRequest.bind(this)); this.handle( - libData.InstanceSetSaveListSubscriptionsRequest, + lib.InstanceSetSaveListSubscriptionsRequest, this.handleInstanceSetSaveListSubscriptionsRequest.bind(this) ); this.handle( - libData.InstanceRenameSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller) + lib.InstanceRenameSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller) ); - this.handle(libData.InstanceCopySaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller)); + this.handle(lib.InstanceCopySaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller)); this.handle( - libData.InstanceDeleteSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller) + lib.InstanceDeleteSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller) ); - this.handle(libData.InstanceDownloadSaveRequest, this.handleInstanceDownloadSaveRequest.bind(this)); - this.handle(libData.InstanceTransferSaveRequest, this.handleInstanceTransferSaveRequest.bind(this)); - this.handle(libData.ModPackListRequest, this.handleModPackListRequest.bind(this)); - this.handle(libData.ModPackSetSubscriptionsRequest, this.handleModPackSetSubscriptionsRequest.bind(this)); - this.handle(libData.ModPackCreateRequest, this.handleModPackCreateRequest.bind(this)); - this.handle(libData.ModPackUpdateRequest, this.handleModPackUpdateRequest.bind(this)); - this.handle(libData.ModPackDeleteRequest, this.handleModPackDeleteRequest.bind(this)); - this.handle(libData.ModGetRequest, this.handleModGetRequest.bind(this)); - this.handle(libData.ModListRequest, this.handleModListRequest.bind(this)); - this.handle(libData.ModSearchRequest, this.handleModSearchRequest.bind(this)); - this.handle(libData.ModSetSubscriptionsRequest, this.handleModSetSubscriptionsRequest.bind(this)); - this.handle(libData.ModDownloadRequest, this.handleModDownloadRequest.bind(this)); - this.handle(libData.ModDeleteRequest, this.handleModDeleteRequest.bind(this)); - this.handle(libData.LogSetSubscriptionsRequest, this.handleLogSetSubscriptionsRequest.bind(this)); - this.handle(libData.LogQueryRequest, this.handleLogQueryRequest.bind(this)); - this.handle(libData.PermissionListRequest, this.handlePermissionListRequest.bind(this)); - this.handle(libData.RoleListRequest, this.handleRoleListRequest.bind(this)); - this.handle(libData.RoleCreateRequest, this.handleRoleCreateRequest.bind(this)); - this.handle(libData.RoleUpdateRequest, this.handleRoleUpdateRequest.bind(this)); + this.handle(lib.InstanceDownloadSaveRequest, this.handleInstanceDownloadSaveRequest.bind(this)); + this.handle(lib.InstanceTransferSaveRequest, this.handleInstanceTransferSaveRequest.bind(this)); + this.handle(lib.ModPackListRequest, this.handleModPackListRequest.bind(this)); + this.handle(lib.ModPackSetSubscriptionsRequest, this.handleModPackSetSubscriptionsRequest.bind(this)); + this.handle(lib.ModPackCreateRequest, this.handleModPackCreateRequest.bind(this)); + this.handle(lib.ModPackUpdateRequest, this.handleModPackUpdateRequest.bind(this)); + this.handle(lib.ModPackDeleteRequest, this.handleModPackDeleteRequest.bind(this)); + this.handle(lib.ModGetRequest, this.handleModGetRequest.bind(this)); + this.handle(lib.ModListRequest, this.handleModListRequest.bind(this)); + this.handle(lib.ModSearchRequest, this.handleModSearchRequest.bind(this)); + this.handle(lib.ModSetSubscriptionsRequest, this.handleModSetSubscriptionsRequest.bind(this)); + this.handle(lib.ModDownloadRequest, this.handleModDownloadRequest.bind(this)); + this.handle(lib.ModDeleteRequest, this.handleModDeleteRequest.bind(this)); + this.handle(lib.LogSetSubscriptionsRequest, this.handleLogSetSubscriptionsRequest.bind(this)); + this.handle(lib.LogQueryRequest, this.handleLogQueryRequest.bind(this)); + this.handle(lib.PermissionListRequest, this.handlePermissionListRequest.bind(this)); + this.handle(lib.RoleListRequest, this.handleRoleListRequest.bind(this)); + this.handle(lib.RoleCreateRequest, this.handleRoleCreateRequest.bind(this)); + this.handle(lib.RoleUpdateRequest, this.handleRoleUpdateRequest.bind(this)); this.handle( - libData.RoleGrantDefaultPermissionsRequest, this.handleRoleGrantDefaultPermissionsRequest.bind(this) + lib.RoleGrantDefaultPermissionsRequest, this.handleRoleGrantDefaultPermissionsRequest.bind(this) ); - this.handle(libData.RoleDeleteRequest, this.handleRoleDeleteRequest.bind(this)); - this.handle(libData.UserGetRequest, this.handleUserGetRequest.bind(this)); - this.handle(libData.UserListRequest, this.handleUserListRequest.bind(this)); - this.handle(libData.UserSetSubscriptionsRequest, this.handleUserSetSubscriptionsRequest.bind(this)); - this.handle(libData.UserCreateRequest, this.handleUserCreateRequest.bind(this)); - this.handle(libData.UserRevokeTokenRequest, this.handleUserRevokeTokenRequest.bind(this)); - this.handle(libData.UserUpdateRolesRequest, this.handleUserUpdateRolesRequest.bind(this)); - this.handle(libData.UserSetAdminRequest, this.handleUserSetAdminRequest.bind(this)); - this.handle(libData.UserSetBannedRequest, this.handleUserSetBannedRequest.bind(this)); - this.handle(libData.UserSetWhitelistedRequest, this.handleUserSetWhitelistedRequest.bind(this)); - this.handle(libData.UserDeleteRequest, this.handleUserDeleteRequest.bind(this)); - this.handle(libData.DebugDumpWsRequest, this.handleDebugDumpWsRequest.bind(this)); + this.handle(lib.RoleDeleteRequest, this.handleRoleDeleteRequest.bind(this)); + this.handle(lib.UserGetRequest, this.handleUserGetRequest.bind(this)); + this.handle(lib.UserListRequest, this.handleUserListRequest.bind(this)); + this.handle(lib.UserSetSubscriptionsRequest, this.handleUserSetSubscriptionsRequest.bind(this)); + this.handle(lib.UserCreateRequest, this.handleUserCreateRequest.bind(this)); + this.handle(lib.UserRevokeTokenRequest, this.handleUserRevokeTokenRequest.bind(this)); + this.handle(lib.UserUpdateRolesRequest, this.handleUserUpdateRolesRequest.bind(this)); + this.handle(lib.UserSetAdminRequest, this.handleUserSetAdminRequest.bind(this)); + this.handle(lib.UserSetBannedRequest, this.handleUserSetBannedRequest.bind(this)); + this.handle(lib.UserSetWhitelistedRequest, this.handleUserSetWhitelistedRequest.bind(this)); + this.handle(lib.UserDeleteRequest, this.handleUserDeleteRequest.bind(this)); + this.handle(lib.DebugDumpWsRequest, this.handleDebugDumpWsRequest.bind(this)); } validateIngress(message) { let origin = this.connector.dst; if (origin.type !== message.src.type || origin.id !== message.src.id) { - throw new libErrors.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`); + throw new lib.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`); } } @@ -179,7 +172,7 @@ class ControlConnection extends BaseConnection { try { this.checkPermission(message, entry); } catch (err) { - this.connector.sendResponseError(new libData.ResponseError(err.message, err.code), message.src); + this.connector.sendResponseError(new lib.ResponseError(err.message, err.code), message.src); logger.audit(`Permission denied for ${message.name} by ${this.user.name} from ${this.connector.dst}`); throw err; } @@ -213,7 +206,7 @@ class ControlConnection extends BaseConnection { } async handleControllerConfigGetRequest() { - return new libData.RawConfig(this._controller.config.serialize("control")); + return new lib.RawConfig(this._controller.config.serialize("control")); } async handleControllerConfigSetFieldRequest(request) { @@ -228,7 +221,7 @@ class ControlConnection extends BaseConnection { async handleHostListRequest() { let list = []; for (let host of this._controller.hosts.values()) { - list.push(new libData.HostDetails( + list.push(new lib.HostDetails( host.agent, host.version, host.name, @@ -249,7 +242,7 @@ class ControlConnection extends BaseConnection { this.hostSubscriptions.all || this.hostSubscriptions.hostIds.includes(host.id) ) { - this.send(new libData.HostUpdateEvent(update)); + this.send(new lib.HostUpdateEvent(update)); } } @@ -262,7 +255,7 @@ class ControlConnection extends BaseConnection { } async handleHostConfigCreateRequest(request) { - let hostConfig = new libConfig.HostConfig("control"); + let hostConfig = new lib.HostConfig("control"); await hostConfig.init(); hostConfig.set("host.controller_url", this._controller.getControllerUrl()); @@ -276,13 +269,13 @@ class ControlConnection extends BaseConnection { this.user.checkPermission("core.host.generate_token"); hostConfig.set("host.controller_token", this._controller.generateHostToken(hostConfig.get("host.id"))); } - return new libData.RawConfig(hostConfig.serialize()); + return new lib.RawConfig(hostConfig.serialize()); } async handleInstanceDetailsGetRequest(request) { let instance = this._controller.getRequestInstance(request.instanceId); - return new libData.InstanceDetails( + return new lib.InstanceDetails( instance.config.get("instance.name"), instance.id, instance.config.get("instance.assigned_host"), @@ -294,7 +287,7 @@ class ControlConnection extends BaseConnection { async handleInstanceDetailsListRequest() { let list = []; for (let instance of this._controller.instances.values()) { - list.push(new libData.InstanceDetails( + list.push(new lib.InstanceDetails( instance.config.get("instance.name"), instance.id, instance.config.get("instance.assigned_host"), @@ -314,8 +307,8 @@ class ControlConnection extends BaseConnection { this.instanceSubscriptions.all || this.instanceSubscriptions.instanceIds.includes(instance.id) ) { - this.send(new libData.InstanceDetailsUpdateEvent( - new libData.InstanceDetails( + this.send(new lib.InstanceDetailsUpdateEvent( + new lib.InstanceDetails( instance.config.get("instance.name"), instance.id, instance.config.get("instance.assigned_host"), @@ -328,7 +321,7 @@ class ControlConnection extends BaseConnection { // XXX should probably add a hook for host reuqests? async handleInstanceCreateRequest(request) { - let instanceConfig = new libConfig.InstanceConfig("controller"); + let instanceConfig = new lib.InstanceConfig("controller"); await instanceConfig.load(request.config); await this._controller.instanceCreate(instanceConfig); } @@ -339,18 +332,18 @@ class ControlConnection extends BaseConnection { async handleInstanceConfigGetRequest(request) { let instance = this._controller.getRequestInstance(request.instanceId); - return new libData.InstanceConfigGetRequest.Response(instance.config.serialize("control")); + return new lib.InstanceConfigGetRequest.Response(instance.config.serialize("control")); } async handleInstanceConfigSetFieldRequest(request) { let instance = this._controller.getRequestInstance(request.instanceId); if (request.field === "instance.assigned_host") { - throw new libErrors.RequestError("instance.assigned_host must be set through the assign-host interface"); + throw new lib.RequestError("instance.assigned_host must be set through the assign-host interface"); } if (request.field === "instance.id") { // XXX is this worth implementing? It's race condition galore. - throw new libErrors.RequestError("Setting instance.id is not supported"); + throw new lib.RequestError("Setting instance.id is not supported"); } instance.config.set(request.field, request.value, "control"); @@ -377,7 +370,7 @@ class ControlConnection extends BaseConnection { this.saveListSubscriptions.all || this.saveListSubscriptions.instanceIds.includes(instanceId) ) { - this.send(new libData.InstanceSaveListUpdateEvent(instanceId, saves)); + this.send(new lib.InstanceSaveListUpdateEvent(instanceId, saves)); } } @@ -389,12 +382,12 @@ class ControlConnection extends BaseConnection { let ready = new Promise((resolve, reject) => { stream.events.on("source", resolve); stream.events.on("timeout", () => reject( - new libErrors.RequestError("Timed out establishing stream from host") + new lib.RequestError("Timed out establishing stream from host") )); }); ready.catch(() => {}); - await this._controller.sendToHostByInstanceId(new libData.InstancePushSaveRequest( + await this._controller.sendToHostByInstanceId(new lib.InstancePushSaveRequest( instanceId, stream.id, name, @@ -406,17 +399,17 @@ class ControlConnection extends BaseConnection { async handleInstanceTransferSaveRequest(request) { if (request.sourceInstanceId === request.targetInstanceId) { - throw new libErrors.RequestError("Source and target instance may not be the same"); + throw new lib.RequestError("Source and target instance may not be the same"); } let sourceInstance = this._controller.getRequestInstance(request.sourceInstanceId); let targetInstance = this._controller.getRequestInstance(request.targetInstanceId); let sourceHostId = sourceInstance.config.get("instance.assigned_host"); let targetHostId = targetInstance.config.get("instance.assigned_host"); if (sourceHostId === null) { - throw new libErrors.RequestError("Source instance is not assigned a host"); + throw new lib.RequestError("Source instance is not assigned a host"); } if (targetHostId === null) { - throw new libErrors.RequestError("Target instance is not assigned a host"); + throw new lib.RequestError("Target instance is not assigned a host"); } // Let host handle request if source and target is on the same host. @@ -427,12 +420,12 @@ class ControlConnection extends BaseConnection { // Check connectivity let sourceHostConnection = this._controller.wsServer.hostConnections.get(sourceHostId); if (!sourceHostConnection || sourceHostConnection.closing) { - throw new libErrors.RequestError("Source host is not connected to the controller"); + throw new lib.RequestError("Source host is not connected to the controller"); } let targetHostConnection = this._controller.wsServer.hostConnections.get(targetHostId); if (!targetHostConnection || targetHostConnection.closing) { - throw new libErrors.RequestError("Target host is not connected to the controller"); + throw new lib.RequestError("Target host is not connected to the controller"); } // Create stream to proxy from target to source @@ -441,7 +434,7 @@ class ControlConnection extends BaseConnection { if (stream.source) { stream.source.destroy(); } - stream.events.emit("error", new libErrors.RequestError("Timed out establishing transfer stream")); + stream.events.emit("error", new lib.RequestError("Timed out establishing transfer stream")); }); // Ignore errors if not listening for them to avoid crash. @@ -452,7 +445,7 @@ class ControlConnection extends BaseConnection { await Promise.all([ this._controller.sendTo( { hostId: sourceHostId }, - new libData.InstancePushSaveRequest(request.sourceInstanceId, stream.id, request.sourceName), + new lib.InstancePushSaveRequest(request.sourceInstanceId, stream.id, request.sourceName), ), events.once(stream.events, "source"), ]); @@ -460,14 +453,14 @@ class ControlConnection extends BaseConnection { // Establish pull from target host to stream and wait for completion. let storedName = await this._controller.sendTo( { hostId: targetHostId }, - new libData.InstancePullSaveRequest(request.targetInstanceId, stream.id, request.targetName), + new lib.InstancePullSaveRequest(request.targetInstanceId, stream.id, request.targetName), ); // Delete source save if this is not a copy if (!request.copy) { await this._controller.sendTo( { hostId: sourceHostId }, - new libData.InstanceDeleteSaveRequest(request.sourceInstanceId, request.sourceName), + new lib.InstanceDeleteSaveRequest(request.sourceInstanceId, request.sourceName), ); } @@ -485,7 +478,7 @@ class ControlConnection extends BaseConnection { async handleModPackCreateRequest(request) { let modPack = request.modPack; if (this._controller.modPacks.has(modPack.id)) { - throw new libErrors.RequestError(`Mod pack with ID ${modPack.id} already exist`); + throw new lib.RequestError(`Mod pack with ID ${modPack.id} already exist`); } this._controller.modPacks.set(modPack.id, modPack); this._controller.modPackUpdated(modPack); @@ -494,7 +487,7 @@ class ControlConnection extends BaseConnection { async handleModPackUpdateRequest(request) { let modPack = request.modPack; if (!this._controller.modPacks.has(modPack.id)) { - throw new libErrors.RequestError(`Mod pack with ID ${modPack.id} does not exist`); + throw new lib.RequestError(`Mod pack with ID ${modPack.id} does not exist`); } this._controller.modPacks.set(modPack.id, modPack); this._controller.modPackUpdated(modPack); @@ -504,7 +497,7 @@ class ControlConnection extends BaseConnection { let { id } = request; let modPack = this._controller.modPacks.get(id); if (!modPack) { - throw new libErrors.RequestError(`Mod pack with ID ${id} does not exist`); + throw new lib.RequestError(`Mod pack with ID ${id} does not exist`); } modPack.isDeleted = true; this._controller.modPacks.delete(id); @@ -516,7 +509,7 @@ class ControlConnection extends BaseConnection { this.modPackSubscriptions.all || this.modPackSubscriptions.modPackIds.includes(modPack.id) ) { - this.send(new libData.ModPackUpdateEvent(modPack)); + this.send(new lib.ModPackUpdateEvent(modPack)); } } @@ -525,7 +518,7 @@ class ControlConnection extends BaseConnection { let filename = `${name}_${version}.zip`; let mod = this._controller.mods.get(filename); if (!mod) { - throw new libErrors.RequestError(`Mod ${filename} does not exist`); + throw new lib.RequestError(`Mod ${filename} does not exist`); } return mod; } @@ -537,14 +530,14 @@ class ControlConnection extends BaseConnection { static termsMatchesMod(terms, mod) { for (let term of terms) { if (term.type === "word") { - if (!libHelpers.wordMatches(term, + if (!lib.wordMatches(term, mod.name, mod.version, mod.title, mod.author, mod.contact, mod.homepage, mod.description, mod.filename )) { return false; } } else if (term.type === "attribute") { - if (!libHelpers.wordMatches(term.value, mod[term.name])) { + if (!lib.wordMatches(term.value, mod[term.name])) { return false; } } @@ -553,7 +546,7 @@ class ControlConnection extends BaseConnection { } async handleModSearchRequest(request) { - let query = libHelpers.parseSearchString(request.query, { + let query = lib.parseSearchString(request.query, { name: "word", // version title: "word", @@ -601,7 +594,7 @@ class ControlConnection extends BaseConnection { author: (a, b) => strcmp(a.versions[0].author, b.versions[0].author), }; if (!Object.prototype.hasOwnProperty.call(sorters, sort)) { - throw new libErrors.RequestError(`Invalid value for sort: ${sort}`); + throw new lib.RequestError(`Invalid value for sort: ${sort}`); } resultList.sort(sorters[sort]); let order = request.sortOrder; @@ -631,7 +624,7 @@ class ControlConnection extends BaseConnection { let filename = `${name}_${version}.zip`; let mod = this._controller.mods.get(filename); if (!mod) { - throw new libErrors.RequestError(`Mod ${filename} does not exist`); + throw new lib.RequestError(`Mod ${filename} does not exist`); } let modPath = path.join(this._controller.config.get("controller.mods_directory"), mod.filename); @@ -658,7 +651,7 @@ class ControlConnection extends BaseConnection { this.modSubscriptions.all || this.modSubscriptions.modNames.includes(mod.name) ) { - this.send(new libData.ModUpdateEvent(mod)); + this.send(new lib.ModUpdateEvent(mod)); } } @@ -666,7 +659,7 @@ class ControlConnection extends BaseConnection { let { all, controller, hostIds, instanceIds } = this.logSubscriptions; if (all || controller || hostIds.length || instanceIds.length) { if (!this.logTransport) { - this.logTransport = new libLoggingUtils.LinkTransport({ link: this }); + this.logTransport = new lib.LinkTransport({ link: this }); this._controller.clusterLogger.add(this.logTransport); } this.logTransport.filter = logFilter(this.logSubscriptions); @@ -694,8 +687,8 @@ class ControlConnection extends BaseConnection { async handlePermissionListRequest() { let list = []; - for (let permission of libUsers.permissions.values()) { - list.push(new libData.RawPermission( + for (let permission of lib.permissions.values()) { + list.push(new lib.RawPermission( permission.name, permission.title, permission.description, @@ -707,7 +700,7 @@ class ControlConnection extends BaseConnection { async handleRoleListRequest() { let list = []; for (let role of this._controller.userManager.roles.values()) { - list.push(new libData.RawRole( + list.push(new lib.RawRole( role.id, role.name, role.description, @@ -722,7 +715,7 @@ class ControlConnection extends BaseConnection { // Start at 5 to leave space for future default roles let id = Math.max(5, lastId+1); - this._controller.userManager.roles.set(id, new libUsers.Role({ id, ...request })); + this._controller.userManager.roles.set(id, new lib.Role({ id, ...request })); return id; } @@ -730,7 +723,7 @@ class ControlConnection extends BaseConnection { let { id, name, description, permissions } = request; let role = this._controller.userManager.roles.get(id); if (!role) { - throw new libErrors.RequestError(`Role with ID ${id} does not exist`); + throw new lib.RequestError(`Role with ID ${id} does not exist`); } role.name = name; @@ -742,7 +735,7 @@ class ControlConnection extends BaseConnection { async handleRoleGrantDefaultPermissionsRequest(request) { let role = this._controller.userManager.roles.get(request.id); if (!role) { - throw new libErrors.RequestError(`Role with ID ${request.id} does not exist`); + throw new lib.RequestError(`Role with ID ${request.id} does not exist`); } role.grantDefaultPermissions(); @@ -753,7 +746,7 @@ class ControlConnection extends BaseConnection { let id = request.id; let role = this._controller.userManager.roles.get(id); if (!role) { - throw new libErrors.RequestError(`Role with ID ${id} does not exist`); + throw new lib.RequestError(`Role with ID ${id} does not exist`); } this._controller.userManager.roles.delete(id); @@ -767,10 +760,10 @@ class ControlConnection extends BaseConnection { let name = request.name; let user = this._controller.userManager.users.get(name); if (!user) { - throw new libErrors.RequestError(`User ${name} does not exist`); + throw new lib.RequestError(`User ${name} does not exist`); } - return new libData.RawUser( + return new lib.RawUser( user.name, [...user.roles].map(role => role.id), [...user.instances], @@ -787,7 +780,7 @@ class ControlConnection extends BaseConnection { async handleUserListRequest() { let list = []; for (let user of this._controller.userManager.users.values()) { - list.push(new libData.RawUser( + list.push(new lib.RawUser( user.name, [...user.roles].map(role => role.id), [...user.instances], @@ -812,8 +805,8 @@ class ControlConnection extends BaseConnection { this.userSubscriptions.all || this.userSubscriptions.names.includes(user.name) ) { - this.send(new libData.UserUpdateEvent( - new libData.RawUser( + this.send(new lib.UserUpdateEvent( + new lib.RawUser( user.name, [...user.roles].map(role => role.id), [...user.instances], @@ -837,7 +830,7 @@ class ControlConnection extends BaseConnection { async handleUserRevokeTokenRequest(request) { let user = this._controller.userManager.users.get(request.name); if (!user) { - throw new libErrors.RequestError(`User '${request.name}' does not exist`); + throw new lib.RequestError(`User '${request.name}' does not exist`); } if (user.name !== this.user.name) { this.user.checkPermission("core.user.revoke_other_token"); @@ -855,14 +848,14 @@ class ControlConnection extends BaseConnection { async handleUserUpdateRolesRequest(request) { let user = this._controller.userManager.users.get(request.name); if (!user) { - throw new libErrors.RequestError(`User '${request.name}' does not exist`); + throw new lib.RequestError(`User '${request.name}' does not exist`); } let resolvedRoles = new Set(); for (let roleId of request.roles) { let role = this._controller.userManager.roles.get(roleId); if (!role) { - throw new libErrors.RequestError(`Role with ID ${roleId} does not exist`); + throw new lib.RequestError(`Role with ID ${roleId} does not exist`); } resolvedRoles.add(role); @@ -881,13 +874,13 @@ class ControlConnection extends BaseConnection { this.user.checkPermission("core.user.create"); user = this._controller.userManager.createUser(name); } else { - throw new libErrors.RequestError(`User '${name}' does not exist`); + throw new lib.RequestError(`User '${name}' does not exist`); } } user.isAdmin = admin; this._controller.userUpdated(user); - this._controller.sendTo("allInstances", new libData.InstanceAdminlistUpdateEvent(name, admin)); + this._controller.sendTo("allInstances", new lib.InstanceAdminlistUpdateEvent(name, admin)); } async handleUserSetBannedRequest(request) { @@ -898,14 +891,14 @@ class ControlConnection extends BaseConnection { this.user.checkPermission("core.user.create"); user = this._controller.userManager.createUser(name); } else { - throw new libErrors.RequestError(`User '${name}' does not exist`); + throw new lib.RequestError(`User '${name}' does not exist`); } } user.isBanned = banned; user.banReason = reason; this._controller.userUpdated(user); - this._controller.sendTo("allInstances", new libData.InstanceBanlistUpdateEvent(name, banned, reason)); + this._controller.sendTo("allInstances", new lib.InstanceBanlistUpdateEvent(name, banned, reason)); } async handleUserSetWhitelistedRequest(request) { @@ -916,20 +909,20 @@ class ControlConnection extends BaseConnection { this.user.checkPermission("core.user.create"); user = this._controller.userManager.createUser(name); } else { - throw new libErrors.RequestError(`User '${name}' does not exist`); + throw new lib.RequestError(`User '${name}' does not exist`); } } user.isWhitelisted = whitelisted; this._controller.userUpdated(user); - this._controller.sendTo("allInstances", new libData.InstanceWhitelistUpdateEvent(name, whitelisted)); + this._controller.sendTo("allInstances", new lib.InstanceWhitelistUpdateEvent(name, whitelisted)); } async handleUserDeleteRequest(request) { let name = request.name; let user = this._controller.userManager.users.get(name); if (!user) { - throw new libErrors.RequestError(`User '${name}' does not exist`); + throw new lib.RequestError(`User '${name}' does not exist`); } user.isDeleted = true; @@ -937,20 +930,20 @@ class ControlConnection extends BaseConnection { this._controller.userUpdated(user); if (user.is_admin) { - this._controller.sendTo("allInstances", new libData.InstanceAdminlistUpdateEvent(name, false)); + this._controller.sendTo("allInstances", new lib.InstanceAdminlistUpdateEvent(name, false)); } if (user.is_whitelisted) { - this._controller.sendTo("allInstances", new libData.InstanceWhitelistUpdateEvent(name, false)); + this._controller.sendTo("allInstances", new lib.InstanceWhitelistUpdateEvent(name, false)); } if (user.is_banned) { - this._controller.sendTo("allInstances", new libData.InstanceBanlistUpdateEvent(name, false, "")); + this._controller.sendTo("allInstances", new lib.InstanceBanlistUpdateEvent(name, false, "")); } } async handleDebugDumpWsRequest(request) { this.ws_dumper = data => { if (this.connector.connected) { - this.send(new libData.DebugWsMessageEvent(data.direction, data.content)); + this.send(new lib.DebugWsMessageEvent(data.direction, data.content)); } }; this.connector._socket.clusterio_ignore_dump = true; diff --git a/packages/controller/src/Controller.js b/packages/controller/src/Controller.js index 6d9ecaed..6c84c135 100644 --- a/packages/controller/src/Controller.js +++ b/packages/controller/src/Controller.js @@ -9,16 +9,8 @@ const jwt = require("jsonwebtoken"); const path = require("path"); const stream = require("stream"); -const libConfig = require("@clusterio/lib/config"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libLink = require("@clusterio/lib/link"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); -const libPlugin = require("@clusterio/lib/plugin"); -const libPluginLoader = require("@clusterio/lib/plugin_loader"); -const libPrometheus = require("@clusterio/lib/prometheus"); -const { logger } = require("@clusterio/lib/logging"); +const lib = require("@clusterio/lib"); +const { logger } = lib; const HttpCloser = require("./HttpCloser"); const InstanceInfo = require("./InstanceInfo"); @@ -28,13 +20,13 @@ const UserManager = require("./UserManager"); const WsServer = require("./WsServer"); -const endpointDurationSummary = new libPrometheus.Summary( +const endpointDurationSummary = new lib.Summary( "clusterio_controller_http_endpoint_duration_seconds", "Time it took to respond to a an HTTP request", { labels: ["route"] } ); -const logSizeGauge = new libPrometheus.Gauge( +const logSizeGauge = new lib.Gauge( "clusterio_controller_log_bytes", "Size of all log files currently stored on the controller." ); @@ -54,7 +46,7 @@ class Controller { this.configPath = configPath; /** * Controller config. - * @type {module:lib/config.ControllerConfig} + * @type {module:lib.ControllerConfig} */ this.config = config; @@ -76,13 +68,13 @@ class Controller { /** * Mapping of mod pack id to mod pack - * @type {Map} + * @type {Map} */ this.modPacks = null; /** * Mapping of mod names to mod infos - * @type {Map} + * @type {Map} */ this.mods = null; @@ -98,7 +90,7 @@ class Controller { /** * Mapping of plugin name to loaded plugin - * @type {Map} + * @type {Map} */ this.plugins = new Map(); @@ -150,15 +142,15 @@ class Controller { */ async logSize() { return (await Promise.all([ - libFileOps.directorySize(path.join(this.logDirectory, "cluster")), - libFileOps.directorySize(path.join(this.logDirectory, "controller")), - libFileOps.directorySize(path.join(this.logDirectory, "host")), + lib.directorySize(path.join(this.logDirectory, "cluster")), + lib.directorySize(path.join(this.logDirectory, "controller")), + lib.directorySize(path.join(this.logDirectory, "host")), ])).reduce((a, v) => a + v, 0); } async _startInternal(args) { this.logDirectory = args.logDirectory; - this.clusterLogIndex = await libLoggingUtils.LogIndex.load(path.join(this.logDirectory, "cluster")); + this.clusterLogIndex = await lib.LogIndex.load(path.join(this.logDirectory, "cluster")); this.clusterLogBuildInterval = setInterval(() => { this.clusterLogIndex.buildIndex().catch( err => logger.error(`Error building cluster log index:\n${err.stack}`) @@ -181,7 +173,7 @@ class Controller { for (let name of args.devPlugin) { let info = this.pluginInfos.find(i => i.name === name); if (!info) { - throw new libErrors.StartupError(`No plugin named ${name}`); + throw new lib.StartupError(`No plugin named ${name}`); } let config = require(path.posix.join(info.requirePath, "webpack.config"))({}); devPlugins.set(name, webpackConfigs.length); @@ -210,7 +202,7 @@ class Controller { this.mods = await Controller.loadModInfos(modsDirectory); this.config.on("fieldChanged", (group, field, prev) => { - libPlugin.invokeHook(this.plugins, "onControllerConfigFieldChanged", group, field, prev); + lib.invokeHook(this.plugins, "onControllerConfigFieldChanged", group, field, prev); }); for (let instance of this.instances.values()) { this.addInstanceHooks(instance); @@ -230,7 +222,7 @@ class Controller { let tls_key = this.config.get("controller.tls_private_key"); if (httpsPort && (!tls_cert || !tls_key)) { - throw new libErrors.StartupError( + throw new lib.StartupError( "tls_certificate and tls_private_key must be configure in order to use https_port" ); } @@ -265,7 +257,7 @@ class Controller { privateKey = await fs.readFile(tls_key); } catch (err) { - throw new libErrors.StartupError( + throw new lib.StartupError( `Error loading ssl certificate: ${err.message}` ); } @@ -313,7 +305,7 @@ class Controller { } logger.info("Saving config"); - await libFileOps.safeOutputFile(this.configPath, JSON.stringify(this.config.serialize(), null, 4)); + await lib.safeOutputFile(this.configPath, JSON.stringify(this.config.serialize(), null, 4)); if (this.devMiddleware) { await new Promise((resolve, reject) => { this.devMiddleware.close(resolve); }); @@ -336,7 +328,7 @@ class Controller { await this.userManager.save(path.join(databaseDirectory, "users.json")); } - await libPlugin.invokeHook(this.plugins, "onShutdown"); + await lib.invokeHook(this.plugins, "onShutdown"); if (this.wsServer) { await this.wsServer.stop(); @@ -373,7 +365,7 @@ class Controller { } static async saveHosts(filePath, hosts) { - await libFileOps.safeOutputFile(filePath, JSON.stringify([...hosts.entries()], null, 4)); + await lib.safeOutputFile(filePath, JSON.stringify([...hosts.entries()], null, 4)); } static async loadInstances(filePath) { @@ -383,7 +375,7 @@ class Controller { try { let serialized = JSON.parse(await fs.readFile(filePath)); for (let serializedConfig of serialized) { - let instanceConfig = new libConfig.InstanceConfig("controller"); + let instanceConfig = new lib.InstanceConfig("controller"); await instanceConfig.load(serializedConfig); let status = instanceConfig.get("instance.assigned_host") === null ? "unassigned" : "unknown"; let instance = new InstanceInfo({ config: instanceConfig, status }); @@ -405,7 +397,7 @@ class Controller { serialized.push(instance.config.serialize()); } - await libFileOps.safeOutputFile(filePath, JSON.stringify(serialized, null, 4)); + await lib.safeOutputFile(filePath, JSON.stringify(serialized, null, 4)); } static async loadModPacks(filePath) { @@ -418,11 +410,11 @@ class Controller { } return new Map(); } - return new Map(json.map(e => [e.id, libData.ModPack.fromJSON(e)])); + return new Map(json.map(e => [e.id, lib.ModPack.fromJSON(e)])); } static async saveModPacks(filePath, modPacks) { - await libFileOps.safeOutputFile(filePath, JSON.stringify([...modPacks.values()], null, 4)); + await lib.safeOutputFile(filePath, JSON.stringify([...modPacks.values()], null, 4)); } static async loadModInfos(modsDirectory) { @@ -440,7 +432,7 @@ class Controller { logger.info(`Loading info for Mod ${entry.name}`); let modInfo; try { - modInfo = await libData.ModInfo.fromModFile(path.join(modsDirectory, entry.name)); + modInfo = await lib.ModInfo.fromModFile(path.join(modsDirectory, entry.name)); } catch (err) { logger.error(`Error loading mod ${entry.name}: ${err.message}`); continue; @@ -488,13 +480,13 @@ class Controller { /** * Query controller log * - * @param {module:lib/logging_utils~QueryLogFilter} filter - + * @param {module:lib~QueryLogFilter} filter - * Filter to limit entries with. Note that only the controller log can * be queried from this function. * @returns {Promise>} log entries matching the filter */ async queryControllerLog(filter) { - return await libLoggingUtils.queryLog( + return await lib.queryLog( path.join(this.logDirectory, "controller"), filter, ); } @@ -502,12 +494,12 @@ class Controller { /** * Query cluster log * - * @param {module:lib/logging_utils~QueryLogFilter} filter - + * @param {module:lib~QueryLogFilter} filter - * Filter to limit entries with. * @returns {Promise>} log entries matching the filter */ async queryClusterLog(filter) { - return await libLoggingUtils.queryLog( + return await lib.queryLog( path.join(this.logDirectory, "cluster"), filter, this.clusterLogIndex, ); } @@ -564,7 +556,7 @@ class Controller { } hostUpdated(host) { - let update = new libData.HostDetails( + let update = new lib.HostDetails( host.agent, host.version, host.name, @@ -587,12 +579,12 @@ class Controller { * * @param {number} instanceId - ID of instance to get. * @returns {object} instance - * @throws {module:lib/errors.RequestError} if the instance does not exist. + * @throws {module:lib.RequestError} if the instance does not exist. */ getRequestInstance(instanceId) { let instance = this.instances.get(instanceId); if (!instance) { - throw new libErrors.RequestError(`Instance with ID ${instanceId} does not exist`); + throw new lib.RequestError(`Instance with ID ${instanceId} does not exist`); } return instance; } @@ -604,20 +596,20 @@ class Controller { * creates an instance using that config in the cluster. * * @example - * let instanceConfig = new libConfig.InstanceConfig("controller"); + * let instanceConfig = new lib.InstanceConfig("controller"); * await instanceConfig.init(); * instanceConfig.set("instance.name", "My instance"); * let instance = await controller.instanceAssign(instanceConfig); * await controller.instanceAssign(instance.id, hostId); * - * @param {module:lib/config.InstanceConfig} instanceConfig - + * @param {module:lib.InstanceConfig} instanceConfig - * Config to base newly created instance on. * @returns {module:controller/src/InstanceInfo} The created instance */ async instanceCreate(instanceConfig) { let instanceId = instanceConfig.get("instance.id"); if (this.instances.has(instanceId)) { - throw new libErrors.RequestError(`Instance with ID ${instanceId} already exists`); + throw new lib.RequestError(`Instance with ID ${instanceId} already exists`); } // Add common settings for the Factorio server @@ -648,7 +640,7 @@ class Controller { let instance = new InstanceInfo({ config: instanceConfig, status: "unassigned" }); this.instances.set(instanceId, instance); - await libPlugin.invokeHook(this.plugins, "onInstanceStatusChanged", instance, null); + await lib.invokeHook(this.plugins, "onInstanceStatusChanged", instance, null); this.addInstanceHooks(instance); } @@ -678,7 +670,7 @@ class Controller { // target host be connected to the controller while doing the // assignment, but it is IMHO a better user experience if this // is the case. - throw new libErrors.RequestError("Target host is not connected to the controller"); + throw new lib.RequestError("Target host is not connected to the controller"); } } @@ -687,7 +679,7 @@ class Controller { if (currentAssignedHost !== null && hostId !== currentAssignedHost) { let oldHostConnection = this.wsServer.hostConnections.get(currentAssignedHost); if (oldHostConnection && !oldHostConnection.connector.closing) { - await oldHostConnection.send(new libData.InstanceUnassignInternalRequest(instanceId)); + await oldHostConnection.send(new lib.InstanceUnassignInternalRequest(instanceId)); } } @@ -695,7 +687,7 @@ class Controller { instance.config.set("instance.assigned_host", hostId); if (hostId !== null) { await newHostConnection.send( - new libData.InstanceAssignInternalRequest(instanceId, instance.config.serialize("host")) + new lib.InstanceAssignInternalRequest(instanceId, instance.config.serialize("host")) ); } else { instance.status = "unassigned"; @@ -715,14 +707,14 @@ class Controller { let instance = this.getRequestInstance(instanceId); let hostId = instance.config.get("instance.assigned_host"); if (hostId !== null) { - await this.sendTo({ hostId }, new libData.InstanceDeleteInternalRequest(instanceId)); + await this.sendTo({ hostId }, new lib.InstanceDeleteInternalRequest(instanceId)); } this.instances.delete(instanceId); let prev = instance.status; instance.status = "deleted"; this.instanceUpdated(instance); - await libPlugin.invokeHook(this.plugins, "onInstanceStatusChanged", instance, prev); + await lib.invokeHook(this.plugins, "onInstanceStatusChanged", instance, prev); } /** @@ -740,7 +732,7 @@ class Controller { let connection = this.wsServer.hostConnections.get(hostId); if (connection) { await connection.send( - new libData.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host")) + new lib.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host")) ); } } @@ -752,7 +744,7 @@ class Controller { this.instanceUpdated(instance); } - libPlugin.invokeHook(this.plugins, "onInstanceConfigFieldChanged", instance, group, field, prev); + lib.invokeHook(this.plugins, "onInstanceConfigFieldChanged", instance, group, field, prev); }); this.instanceUpdated(instance); @@ -786,7 +778,7 @@ class Controller { controlConnection.modPackUpdated(modPack); } - libPlugin.invokeHook(this.plugins, "onModPackUpdated", modPack); + lib.invokeHook(this.plugins, "onModPackUpdated", modPack); } modUpdated(mod) { @@ -798,7 +790,7 @@ class Controller { controlConnection.modUpdated(mod); } - libPlugin.invokeHook(this.plugins, "onModUpdated", mod); + lib.invokeHook(this.plugins, "onModUpdated", mod); } userUpdated(user) { @@ -814,13 +806,13 @@ class Controller { /** * Notify connected control clients under the given user that the * permissions for this user may have changed. - * @param {module:lib/users.User} user - User permisions updated for. + * @param {module:lib.User} user - User permisions updated for. */ userPermissionsUpdated(user) { for (let controlConnection of this.wsServer.controlConnections.values()) { if (controlConnection.user === user) { controlConnection.send( - new libData.AccountUpdateEvent([...user.roles].map(r => ({ + new lib.AccountUpdateEvent([...user.roles].map(r => ({ name: r.name, id: r.id, permissions: [...r.permissions], @@ -833,13 +825,13 @@ class Controller { /** * Notify connected control clients with the given role that the * permissions may have changed. - * @param {module:lib/users.Role} role - Role permisions updated for. + * @param {module:lib.Role} role - Role permisions updated for. */ rolePermissionsUpdated(role) { for (let controlConnection of this.wsServer.controlConnections.values()) { if (controlConnection.user.roles.has(role)) { controlConnection.send( - new libData.AccountUpdateEvent( + new lib.AccountUpdateEvent( [...controlConnection.user.roles].map(r => ({ name: r.name, id: r.id, @@ -864,10 +856,10 @@ class Controller { continue; } - let ControllerPluginClass = libPlugin.BaseControllerPlugin; + let ControllerPluginClass = lib.BaseControllerPlugin; try { if (pluginInfo.controllerEntrypoint) { - ControllerPluginClass = await libPluginLoader.loadControllerPluginClass(pluginInfo); + ControllerPluginClass = await lib.loadControllerPluginClass(pluginInfo); } let controllerPlugin = new ControllerPluginClass(pluginInfo, this, metrics, logger); @@ -875,7 +867,7 @@ class Controller { this.plugins.set(pluginInfo.name, controllerPlugin); } catch (err) { - throw new libErrors.PluginError(pluginInfo.name, err); + throw new lib.PluginError(pluginInfo.name, err); } logger.info(`Loaded plugin ${pluginInfo.name}`); @@ -899,7 +891,7 @@ class Controller { }); function wrapError(err) { - reject(new libErrors.StartupError( + reject(new lib.StartupError( `Server listening failed: ${err.message}` )); } @@ -982,7 +974,7 @@ class Controller { } handleRequest(Request, handler) { - if (!libLink.Link._requestsByClass.has(Request)) { + if (!lib.Link._requestsByClass.has(Request)) { throw new Error(`Unregistered Request class ${Request.name}`); } if (this._registeredRequests.has(Request)) { @@ -992,7 +984,7 @@ class Controller { } fallbackRequest(Request, handler) { - if (!libLink.Link._requestsByClass.has(Request)) { + if (!lib.Link._requestsByClass.has(Request)) { throw new Error(`Unregistered Request class ${Request.name}`); } if (this._fallbackedRequests.has(Request)) { @@ -1002,7 +994,7 @@ class Controller { } handleEvent(Event, handler) { - if (!libLink.Link._eventsByClass.has(Event)) { + if (!lib.Link._eventsByClass.has(Event)) { throw new Error(`Unregistered Event class ${Event.name}`); } if (this._registeredEvents.has(Event)) { @@ -1012,7 +1004,7 @@ class Controller { } snoopEvent(Event, handler) { - if (!libLink.Link._eventsByClass.has(Event)) { + if (!lib.Link._eventsByClass.has(Event)) { throw new Error(`Unregistered Event class ${Event.name}`); } if (this._snoopedEvents.has(Event)) { @@ -1026,16 +1018,16 @@ class Controller { * * Routes the given request or event to the given destination. The * destination argument supports address shorthands, see {@link - * module:lib/data.Address.fromShorthand} + * module:lib.Address.fromShorthand} * - * @param {*|module:lib/data.Address} address - Where to send it. + * @param {*|module:lib.Address} address - Where to send it. * @param {*} requestOrEvent - The request or event to send. * @returns {Promise<*>|undefined} * Promise that resolves to the response if a request was sent or * undefined if it was an event. */ sendTo(address, requestOrEvent) { - let dst = libData.Address.fromShorthand(address); + let dst = lib.Address.fromShorthand(address); if (requestOrEvent.constructor.type === "request") { return this.sendRequest(requestOrEvent, dst); } @@ -1047,30 +1039,30 @@ class Controller { async sendRequest(request, dst) { let connection; - if (dst.type === libData.Address.controller) { + if (dst.type === lib.Address.controller) { throw new Error("controller as dst is not supported."); - } else if (dst.type === libData.Address.control) { + } else if (dst.type === lib.Address.control) { connection = this.wsServer.controlConnections.get(dst.id); if (!connection) { - throw new libErrors.RequestError("Target control connection does not exist."); + throw new lib.RequestError("Target control connection does not exist."); } - } else if (dst.type === libData.Address.instance) { + } else if (dst.type === lib.Address.instance) { let instance = this.getRequestInstance(dst.id); let hostId = instance.config.get("instance.assigned_host"); if (hostId === null) { - throw new libErrors.RequestError("Instance is not assigned to a host"); + throw new lib.RequestError("Instance is not assigned to a host"); } connection = this.wsServer.hostConnections.get(hostId); if (!connection) { - throw new libErrors.RequestError("Host containing instance is not connected"); + throw new lib.RequestError("Host containing instance is not connected"); } - } else if (dst.type === libData.Address.host) { + } else if (dst.type === lib.Address.host) { connection = this.wsServer.hostConnections.get(dst.id); if (!connection) { - throw new libErrors.RequestError("Host is not connected"); + throw new lib.RequestError("Host is not connected"); } } else { @@ -1082,13 +1074,13 @@ class Controller { sendEvent(event, dst) { let connection; - if (dst.type === libData.Address.controller) { + if (dst.type === lib.Address.controller) { throw new Error("controller as dst is not supported."); - } else if (dst.type === libData.Address.control) { + } else if (dst.type === lib.Address.control) { connection = this.wsServer.controlConnections.get(dst.id); - } else if (dst.type === libData.Address.instance) { + } else if (dst.type === lib.Address.instance) { let instance = this.instances.get(dst.id); if (!instance) { return; @@ -1099,16 +1091,16 @@ class Controller { } connection = this.wsServer.hostConnections.get(hostId); - } else if (dst.type === libData.Address.host) { + } else if (dst.type === lib.Address.host) { connection = this.wsServer.hostConnections.get(dst.id); - } else if (dst.type === libData.Address.broadcast) { - if (dst.id === libData.Address.control) { + } else if (dst.type === lib.Address.broadcast) { + if (dst.id === lib.Address.control) { for (let controlConnection of this.wsServer.controlConnections.values()) { controlConnection.sendEvent(event, dst); } - } else if (dst.id === libData.Address.instance || dst.id === libData.Address.host) { + } else if (dst.id === lib.Address.instance || dst.id === lib.Address.host) { for (let hostConnection of this.wsServer.hostConnections.values()) { hostConnection.sendEvent(event, dst); } @@ -1141,11 +1133,11 @@ class Controller { let instance = this.getRequestInstance(request.instanceId); let hostId = instance.config.get("instance.assigned_host"); if (hostId === null) { - throw new libErrors.RequestError("Instance is not assigned to a host"); + throw new lib.RequestError("Instance is not assigned to a host"); } let connection = this.wsServer.hostConnections.get(hostId); if (!connection) { - throw new libErrors.RequestError("Host containing instance is not connected"); + throw new lib.RequestError("Host containing instance is not connected"); } return await connection.send(request); } diff --git a/packages/controller/src/ControllerRouter.js b/packages/controller/src/ControllerRouter.js index 8bc29fcb..1534bb2f 100644 --- a/packages/controller/src/ControllerRouter.js +++ b/packages/controller/src/ControllerRouter.js @@ -1,5 +1,5 @@ "use strict"; -const libData = require("@clusterio/lib/data"); +const lib = require("@clusterio/lib"); class ControllerRouter { /** @type {module:controller/src/Controller} */ @@ -20,8 +20,8 @@ class ControllerRouter { } /** - * @param {module:lib/link.Link} origin - Source link of the message. - * @param {module:lib/data.Message} message + * @param {module:lib.Link} origin - Source link of the message. + * @param {module:lib.Message} message * Link the message originated from. * @param {boolean} hasFallback - true if fallback handling is available. * @returns {boolean} true if the message was handled @@ -34,15 +34,15 @@ class ControllerRouter { let dst = message.dst; let nextHop; let msg; - if (dst.type === libData.Address.broadcast) { + if (dst.type === lib.Address.broadcast) { this.broadcastMessage(origin, message); return true; - } else if (dst.type === libData.Address.host) { + } else if (dst.type === lib.Address.host) { nextHop = this.controller.wsServer.hostConnections.get(dst.id); if (!nextHop) { msg = `Host ${dst.id} is offline`; } - } else if (dst.type === libData.Address.instance) { + } else if (dst.type === lib.Address.instance) { let instance = this.controller.instances.get(dst.id); if (!instance) { msg = `Instance ${dst.id} does not exist`; @@ -57,12 +57,12 @@ class ControllerRouter { } } } - } else if (dst.type === libData.Address.control) { + } else if (dst.type === lib.Address.control) { nextHop = this.controller.wsServer.controlConnections.get(dst.id); if (!nextHop) { msg = "Control connection does not exist"; } - } else if (dst.type === libData.Address.controller) { + } else if (dst.type === lib.Address.controller) { msg = `Unexpected message forwarded to ${dst}`; } @@ -77,7 +77,7 @@ class ControllerRouter { return false; } origin.connector.sendResponseError( - new libData.ResponseError(msg || "Unroutable destination"), message.src + new lib.ResponseError(msg || "Unroutable destination"), message.src ); return true; } @@ -100,13 +100,13 @@ class ControllerRouter { let dst = message.dst; if (message.type !== "event") { this.warnUnrouted(message, `Unexpected broadcast of ${message.type}`); - } else if (dst.id === libData.Address.host || dst.id === libData.Address.instance) { + } else if (dst.id === lib.Address.host || dst.id === lib.Address.instance) { for (let hostConnection of this.controller.wsServer.hostConnections.values()) { if (hostConnection !== origin) { hostConnection.connector.send(message); } } - } else if (dst.id === libData.Address.control) { + } else if (dst.id === lib.Address.control) { for (let controlConnection of this.controller.wsServer.controlConnections.values()) { if (controlConnection !== origin) { controlConnection.connector.send(message); diff --git a/packages/controller/src/HostConnection.js b/packages/controller/src/HostConnection.js index 232d7c7c..fdb88eed 100644 --- a/packages/controller/src/HostConnection.js +++ b/packages/controller/src/HostConnection.js @@ -1,10 +1,6 @@ "use strict"; -const libData = require("@clusterio/lib/data"); -const libConfig = require("@clusterio/lib/config"); -const libErrors = require("@clusterio/lib/errors"); -const { logger } = require("@clusterio/lib/logging"); -const libPlugin = require("@clusterio/lib/plugin"); -const PlayerStats = require("@clusterio/lib/PlayerStats"); +const lib = require("@clusterio/lib"); +const { logger, PlayerStats } = lib; const BaseConnection = require("./BaseConnection"); const InstanceInfo = require("./InstanceInfo"); @@ -55,36 +51,36 @@ class HostConnection extends BaseConnection { let prev = instance.status; instance.status = "unknown"; this._controller.instanceUpdated(instance); - libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev); + lib.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev); } }); - this.handle(libData.InstanceStatusChangedEvent, this.handleInstanceStatusChangedEvent.bind(this)); - this.handle(libData.InstancesUpdateRequest, this.handleInstancesUpdateRequest.bind(this)); - this.handle(libData.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this)); - this.handle(libData.LogMessageEvent, this.handleLogMessageEvent.bind(this)); - this.handle(libData.InstancePlayerUpdateEvent, this.handleInstancePlayerUpdateEvent.bind(this)); + this.handle(lib.InstanceStatusChangedEvent, this.handleInstanceStatusChangedEvent.bind(this)); + this.handle(lib.InstancesUpdateRequest, this.handleInstancesUpdateRequest.bind(this)); + this.handle(lib.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this)); + this.handle(lib.LogMessageEvent, this.handleLogMessageEvent.bind(this)); + this.handle(lib.InstancePlayerUpdateEvent, this.handleInstancePlayerUpdateEvent.bind(this)); } validateIngress(message) { let origin = this.connector.dst; switch (message.src.type) { - case libData.Address.control: - case libData.Address.controller: - throw new libErrors.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`); + case lib.Address.control: + case lib.Address.controller: + throw new lib.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`); - case libData.Address.host: + case lib.Address.host: if (message.src.id !== origin.id) { - throw new libErrors.InvalidMessage( + throw new lib.InvalidMessage( `Received message with invalid src ${message.src} from ${origin}` ); } break; - case libData.Address.instance: + case lib.Address.instance: let instance = this._controller.instances.get(message.src.id); if (!instance || instance.config.get("instance.assigned_host") !== this._id) { - throw new libErrors.InvalidMessage( + throw new lib.InvalidMessage( `Received message with invalid src ${message.src} from ${origin}` ); } @@ -120,7 +116,7 @@ class HostConnection extends BaseConnection { } async prepareDisconnect() { - await libPlugin.invokeHook(this._controller.plugins, "onPrepareHostDisconnect", this); + await lib.invokeHook(this._controller.plugins, "onPrepareHostDisconnect", this); return await super.prepareDisconnect(); } @@ -159,7 +155,7 @@ class HostConnection extends BaseConnection { instance.game_port = request.gamePort; logger.verbose(`Instance ${instance.config.get("instance.name")} State: ${instance.status}`); this._controller.instanceUpdated(instance); - await libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev); + await lib.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev); } async handleInstancesUpdateRequest(request) { @@ -167,14 +163,14 @@ class HostConnection extends BaseConnection { for (let instance of this._controller.instances.values()) { if (instance.config.get("instance.assigned_host") === this._id) { await this.send( - new libData.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host")) + new lib.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host")) ); } } // Assign instances the host has but controller does not for (let instanceData of request.instances) { - let instanceConfig = new libConfig.InstanceConfig("controller"); + let instanceConfig = new lib.InstanceConfig("controller"); await instanceConfig.load(instanceData.config, "host"); let controllerInstance = this._controller.instances.get(instanceConfig.get("instance.id")); @@ -182,7 +178,7 @@ class HostConnection extends BaseConnection { // Check if this instance is assigned somewhere else. if (controllerInstance.config.get("instance.assigned_host") !== this._id) { await this.send( - new libData.InstanceUnassignInternalRequest(instanceConfig.get("instance.id")) + new lib.InstanceUnassignInternalRequest(instanceConfig.get("instance.id")) ); continue; } @@ -193,7 +189,7 @@ class HostConnection extends BaseConnection { controllerInstance.status = instanceData.status; logger.verbose(`Instance ${instanceConfig.get("instance.name")} State: ${instanceData.status}`); this._controller.instanceUpdated(controllerInstance); - await libPlugin.invokeHook( + await lib.invokeHook( this._controller.plugins, "onInstanceStatusChanged", controllerInstance, prev ); } @@ -205,11 +201,11 @@ class HostConnection extends BaseConnection { this._controller.instances.set(instanceConfig.get("instance.id"), newInstance); this._controller.addInstanceHooks(newInstance); await this.send( - new libData.InstanceAssignInternalRequest( + new lib.InstanceAssignInternalRequest( instanceConfig.get("instance.id"), instanceConfig.serialize("host") ) ); - await libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", newInstance, null); + await lib.invokeHook(this._controller.plugins, "onInstanceStatusChanged", newInstance, null); } // Push lists to make sure they are in sync. @@ -229,7 +225,7 @@ class HostConnection extends BaseConnection { } } - await this.send(new libData.SyncUserListsEvent(adminlist, banlist, whitelist)); + await this.send(new lib.SyncUserListsEvent(adminlist, banlist, whitelist)); } async handleInstanceSaveListUpdateEvent(event) { @@ -261,7 +257,7 @@ class HostConnection extends BaseConnection { this._controller.userUpdated(user); let instance = this._controller.instances.get(instanceId); - await libPlugin.invokeHook(this._controller.plugins, "onPlayerEvent", instance, { + await lib.invokeHook(this._controller.plugins, "onPlayerEvent", instance, { type: event.type, name: event.name, reason: event.reason, diff --git a/packages/controller/src/InstanceInfo.js b/packages/controller/src/InstanceInfo.js index ef0cd66b..27bfdb5a 100644 --- a/packages/controller/src/InstanceInfo.js +++ b/packages/controller/src/InstanceInfo.js @@ -5,7 +5,7 @@ * @alias module:controller/src/InstanceInfo */ class InstanceInfo { - /** @type {module:lib/config.InstanceConfig} */ + /** @type {module:lib.InstanceConfig} */ config; /** diff --git a/packages/controller/src/UserManager.js b/packages/controller/src/UserManager.js index 883d1a4d..b40ca3bd 100644 --- a/packages/controller/src/UserManager.js +++ b/packages/controller/src/UserManager.js @@ -1,8 +1,7 @@ "use strict"; const fs = require("fs-extra"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libUsers = require("@clusterio/lib/users"); +const lib = require("@clusterio/lib"); /** * Manages users and roles @@ -21,12 +20,12 @@ class UserManager { try { let content = JSON.parse(await fs.readFile(filePath)); for (let serializedRole of content.roles) { - let role = new libUsers.Role(serializedRole); + let role = new lib.Role(serializedRole); loadedRoles.set(role.id, role); } for (let serializedUser of content.users) { - let user = new libUsers.User(serializedUser, loadedRoles); + let user = new lib.User(serializedUser, loadedRoles); loadedUsers.set(user.name, user); } @@ -36,8 +35,8 @@ class UserManager { } // Create default roles if loading failed - libUsers.ensureDefaultAdminRole(loadedRoles); - libUsers.ensureDefaultPlayerRole(loadedRoles); + lib.ensureDefaultAdminRole(loadedRoles); + lib.ensureDefaultPlayerRole(loadedRoles); } this.roles = loadedRoles; @@ -63,7 +62,7 @@ class UserManager { users: serializedUsers, roles: serializedRoles, }; - await libFileOps.safeOutputFile(filePath, JSON.stringify(serialized, null, 4)); + await lib.safeOutputFile(filePath, JSON.stringify(serialized, null, 4)); } /** @@ -72,7 +71,7 @@ class UserManager { * Creates a new user and add it to the user database. * * @param {string} name - Name of the user to create. - * @returns {module:lib/users.User} newly created user. + * @returns {module:lib.User} newly created user. */ createUser(name) { if (this.users.has(name)) { @@ -80,7 +79,7 @@ class UserManager { } let defaultRoleId = this._config.get("controller.default_role_id"); - let user = new libUsers.User({ name, roles: [defaultRoleId] }, this.roles); + let user = new lib.User({ name, roles: [defaultRoleId] }, this.roles); this.users.set(name, user); return user; } diff --git a/packages/controller/src/WsServer.js b/packages/controller/src/WsServer.js index 483fca5c..d14cba3d 100644 --- a/packages/controller/src/WsServer.js +++ b/packages/controller/src/WsServer.js @@ -2,10 +2,8 @@ const jwt = require("jsonwebtoken"); const WebSocket = require("ws"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const { logger } = require("@clusterio/lib/logging"); -const libPrometheus = require("@clusterio/lib/prometheus"); +const lib = require("@clusterio/lib"); +const { logger } = lib; const ControlConnection = require("./ControlConnection"); const packageVersion = require("../package").version; @@ -13,18 +11,18 @@ const HostConnection = require("./HostConnection"); const WsServerConnector = require("./WsServerConnector"); -const wsMessageCounter = new libPrometheus.Counter( +const wsMessageCounter = new lib.Counter( "clusterio_controller_websocket_message_total", "How many messages have been received over WebSocket on the controller", { labels: ["direction"] } ); -const wsConnectionsCounter = new libPrometheus.Counter( +const wsConnectionsCounter = new lib.Counter( "clusterio_controller_websocket_connections_total", "How many WebSocket connections have been initiated on the controller" ); -const wsRejectedConnectionsCounter = new libPrometheus.Counter( +const wsRejectedConnectionsCounter = new lib.Counter( "clusterio_controller_websocket_rejected_connections_total", "How many WebSocket connections have been rejected during the handshake on the controller" ); @@ -78,7 +76,7 @@ class WsServer { try { await task; } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { logger.warn(`Unexpected error disconnecting connector:\n${err.stack}`); } } @@ -123,7 +121,7 @@ class WsServer { loadedPlugins[name] = plugin.info.version; } - socket.send(JSON.stringify(new libData.MessageHello(new libData.HelloData(packageVersion, loadedPlugins)))); + socket.send(JSON.stringify(new lib.MessageHello(new lib.HelloData(packageVersion, loadedPlugins)))); this.attachHandler(socket, req); } @@ -160,8 +158,8 @@ ${err.stack}` let message; try { const json = JSON.parse(rawMessage); - libData.Message.validate(json); - message = libData.Message.fromJSON(json); + lib.Message.validate(json); + message = lib.Message.fromJSON(json); } catch (err) { logger.verbose(`WsServer | closing ${req.socket.remoteAddress} after receiving invalid message`); wsRejectedConnectionsCounter.inc(); @@ -239,7 +237,7 @@ ${err.stack}` return; } - let [connector, sessionToken] = this.createSession(new libData.Address(libData.Address.host, data.id)); + let [connector, sessionToken] = this.createSession(new lib.Address(lib.Address.host, data.id)); let connection = this.hostConnections.get(data.id); if (connection) { logger.verbose(`WsServer | disconnecting existing connection for host ${data.id}`); @@ -267,7 +265,7 @@ ${err.stack}` }); this.hostConnections.set(data.id, connection); this.controller.hostUpdated(this.controller.hosts.get(data.id)); - let src = new libData.Address(libData.Address.host, data.id); + let src = new lib.Address(lib.Address.host, data.id); connector.ready(socket, src, sessionToken); } @@ -298,7 +296,7 @@ ${err.stack}` let id = this.nextControlId; this.nextControlId += 1; - let [connector, sessionToken] = this.createSession(new libData.Address(libData.Address.control, id)); + let [connector, sessionToken] = this.createSession(new lib.Address(lib.Address.control, id)); logger.verbose(`WsServer | registered control ${id} from ${req.socket.remoteAddress}`); let connection = new ControlConnection(data, connector, this.controller, user, id); @@ -306,7 +304,7 @@ ${err.stack}` this.controlConnections.delete(id); }); this.controlConnections.set(id, connection); - let account = new libData.AccountDetails( + let account = new lib.AccountDetails( user.name, [...user.roles].map(r => ({ name: r.name, @@ -315,7 +313,7 @@ ${err.stack}` })) ); - let src = new libData.Address(libData.Address.control, id); + let src = new lib.Address(lib.Address.control, id); connector.ready(socket, src, sessionToken, account); } @@ -334,7 +332,7 @@ ${err.stack}` } } catch (err) { - socket.send(JSON.stringify(new libData.MessageInvalidate())); + socket.send(JSON.stringify(new lib.MessageInvalidate())); this.attachHandler(socket, req); return; } diff --git a/packages/controller/src/WsServerConnector.js b/packages/controller/src/WsServerConnector.js index 0b3fda8f..c0c4d0a1 100644 --- a/packages/controller/src/WsServerConnector.js +++ b/packages/controller/src/WsServerConnector.js @@ -1,20 +1,19 @@ "use strict"; const events = require("events"); -const libData = require("@clusterio/lib/data"); -const libLink = require("@clusterio/lib/link"); -const { logger } = require("@clusterio/lib/logging"); +const lib = require("@clusterio/lib"); +const { logger } = lib; /** * Connector for controller connections * - * @extends module:lib/link.WebSocketBaseConnector + * @extends module:lib.WebSocketBaseConnector * @alias module:controller/src/WsServerConnector */ -class WsServerConnector extends libLink.WebSocketBaseConnector { +class WsServerConnector extends lib.WebSocketBaseConnector { constructor(dst, sessionId, sessionTimeout, heartbeatInterval) { - super(new libData.Address(libData.Address.controller, 0), dst); + super(new lib.Address(lib.Address.controller, 0), dst); this._sessionTimeout = sessionTimeout; this._socket = null; @@ -40,16 +39,16 @@ class WsServerConnector extends libLink.WebSocketBaseConnector { * Sends the ready message over the socket to initiate the session. * * @param {Object} socket - WebSocket connection to client. - * @param {module:lib/data.Address} src - Source address for this link. + * @param {module:lib.Address} src - Source address for this link. * @param {string} sessionToken - * the session token to send to the client. - * @param {module:lib/data.AccountDetails=} account - + * @param {module:lib.AccountDetails=} account - * account data to provide to control connection */ ready(socket, src, sessionToken, account) { this._socket = socket; - this._sendInternal(new libData.MessageReady( - new libData.ReadyData( + this._sendInternal(new lib.MessageReady( + new lib.ReadyData( src, sessionToken, this._sessionTimeout, @@ -89,8 +88,8 @@ class WsServerConnector extends libLink.WebSocketBaseConnector { this._timeoutId = null; } - this._sendInternal(new libData.MessageContinue( - new libData.ContinueData(this._sessionTimeout, this._heartbeatInterval, this._lastReceivedSeq) + this._sendInternal(new lib.MessageContinue( + new lib.ContinueData(this._sessionTimeout, this._heartbeatInterval, this._lastReceivedSeq) )); this._state = "connected"; diff --git a/packages/controller/src/metrics.js b/packages/controller/src/metrics.js index 0706ec33..3107e294 100644 --- a/packages/controller/src/metrics.js +++ b/packages/controller/src/metrics.js @@ -1,9 +1,9 @@ // Shared metrics "use strict"; -const libPrometheus = require("@clusterio/lib/prometheus"); +const lib = require("@clusterio/lib"); const util = require("util"); -exports.endpointHitCounter = new libPrometheus.Counter( +exports.endpointHitCounter = new lib.Counter( "clusterio_controller_http_endpoint_hits_total", "How many requests a particular HTTP endpoint has gotten", { labels: ["route"], register: false } diff --git a/packages/controller/src/routes.js b/packages/controller/src/routes.js index 7f6a6ace..21c9aac7 100644 --- a/packages/controller/src/routes.js +++ b/packages/controller/src/routes.js @@ -9,15 +9,8 @@ const path = require("path"); const nodeStream = require("stream"); const util = require("util"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libHash = require("@clusterio/lib/hash"); -const libHelpers = require("@clusterio/lib/helpers"); -const libLink = require("@clusterio/lib/link"); -const libPlugin = require("@clusterio/lib/plugin"); -const libPrometheus = require("@clusterio/lib/prometheus"); -const { logger } = require("@clusterio/lib/logging"); +const lib = require("@clusterio/lib"); +const { logger } = lib; const finished = util.promisify(nodeStream.finished); @@ -40,7 +33,7 @@ function mergeSamples(destinationResult, sourceResult) { // Prometheus polling endpoint async function getMetrics(req, res, next) { let results = []; - let pluginResults = await libPlugin.invokeHook(req.app.locals.controller.plugins, "onMetrics"); + let pluginResults = await lib.invokeHook(req.app.locals.controller.plugins, "onMetrics"); for (let metricIterator of pluginResults) { for await (let metric of metricIterator) { results.push(metric); @@ -53,9 +46,9 @@ async function getMetrics(req, res, next) { if (!hostConnection.connected) { continue; } - requests.push(libHelpers.timeout( - hostConnection.send(new libData.HostMetricsRequest()).catch(err => { - if (!(err instanceof libErrors.SessionLost)) { + requests.push(lib.timeout( + hostConnection.send(new lib.HostMetricsRequest()).catch(err => { + if (!(err instanceof lib.SessionLost)) { logger.error(`Unexpected error gathering metrics from host:\n${err.stack}`); } return null; @@ -64,7 +57,7 @@ async function getMetrics(req, res, next) { )); } - for await (let result of await libPrometheus.defaultRegistry.collect()) { + for await (let result of await lib.defaultRegistry.collect()) { results.push(result); } @@ -87,12 +80,12 @@ async function getMetrics(req, res, next) { } for (let result of resultMap.values()) { - results.push(libPrometheus.deserializeResult(result)); + results.push(lib.deserializeResult(result)); } - let text = await libPrometheus.exposition(results); - res.set("Content-Type", libPrometheus.exposition.contentType); + let text = await lib.exposition(results); + res.set("Content-Type", lib.exposition.contentType); res.send(text); } @@ -227,12 +220,12 @@ async function uploadExport(req, res) { } let { name, ext } = path.posix.parse(filePath); - let hash = await libHash.hashStream(file.nodeStream()); + let hash = await lib.hashStream(file.nodeStream()); assets[name] = `${name}.${hash}${ext}`; - await libFileOps.safeOutputFile(path.join("static", `${name}.${hash}${ext}`), await file.async("nodebuffer")); + await lib.safeOutputFile(path.join("static", `${name}.${hash}${ext}`), await file.async("nodebuffer")); } - modPack.exportManifest = new libData.ExportManifest(assets); + modPack.exportManifest = new lib.ExportManifest(assets); modPack.fillDefaultSettings(settingPrototypes, logger); res.app.locals.controller.modPackUpdated(modPack); @@ -363,7 +356,7 @@ async function uploadSave(req, res) { try { let storedName = await Promise.race([ req.app.locals.controller.sendToHostByInstanceId( - new libData.InstancePullSaveRequest( + new lib.InstancePullSaveRequest( instanceId, proxyStream.id, filename, @@ -462,9 +455,9 @@ async function uploadSave(req, res) { function checkModName(name) { try { - libFileOps.checkFilename(name); + lib.checkFilename(name); } catch (err) { - throw new libErrors.RequestError(`Mod name ${err.message}`); + throw new lib.RequestError(`Mod name ${err.message}`); } } @@ -512,7 +505,7 @@ async function uploadMod(req, res) { break; } catch (err) { if (err.code === "EEXIST") { - tempFilename = await libFileOps.findUnusedName(modsDirectory, tempFilename, ".tmp.zip"); + tempFilename = await lib.findUnusedName(modsDirectory, tempFilename, ".tmp.zip"); } else { throw err; } @@ -521,7 +514,7 @@ async function uploadMod(req, res) { stream.pipe(writeStream); await finished(writeStream); - const modInfo = await libData.ModInfo.fromModFile(path.join(modsDirectory, tempFilename)); + const modInfo = await lib.ModInfo.fromModFile(path.join(modsDirectory, tempFilename)); await fs.rename(path.join(modsDirectory, tempFilename), path.join(modsDirectory, modInfo.filename)); req.app.locals.controller.mods.set(modInfo.filename, modInfo); req.app.locals.controller.modUpdated(modInfo); diff --git a/packages/ctl/ctl.js b/packages/ctl/ctl.js index 024f5f11..a699e22f 100755 --- a/packages/ctl/ctl.js +++ b/packages/ctl/ctl.js @@ -10,16 +10,8 @@ const yargs = require("yargs"); const version = require("./package").version; const setBlocking = require("set-blocking"); -const libLink = require("@clusterio/lib/link"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const libConfig = require("@clusterio/lib/config"); -const libPlugin = require("@clusterio/lib/plugin"); -const libPluginLoader = require("@clusterio/lib/plugin_loader"); -const libCommand = require("@clusterio/lib/command"); -const libSharedCommands = require("@clusterio/lib/shared_commands"); -const { ConsoleTransport, levels, logger } = require("@clusterio/lib/logging"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); +const lib = require("@clusterio/lib"); +const { ConsoleTransport, levels, logger } = lib; const commands = require("./src/commands"); @@ -28,7 +20,7 @@ const commands = require("./src/commands"); * Connector for control connection to controller * @private */ -class ControlConnector extends libLink.WebSocketClientConnector { +class ControlConnector extends lib.WebSocketClientConnector { constructor(url, maxReconnectDelay, tlsCa, token) { super(url, maxReconnectDelay, tlsCa); this._token = token; @@ -37,8 +29,8 @@ class ControlConnector extends libLink.WebSocketClientConnector { register() { logger.verbose("Connector | registering control"); this.sendHandshake( - new libData.MessageRegisterControl( - new libData.RegisterControlData( + new lib.MessageRegisterControl( + new lib.RegisterControlData( this._token, "clusterioctl", version, @@ -54,13 +46,13 @@ class ControlConnector extends libLink.WebSocketClientConnector { * Connects to the controller over WebSocket and sends commands to it. * @static */ -class Control extends libLink.Link { +class Control extends lib.Link { constructor(connector, controlConfig, tlsCa, controlPlugins) { super(connector); /** * Control config used for connecting to the controller. - * @type {module:lib/config.ControlConfig} + * @type {module:lib.ControlConfig} */ this.config = controlConfig; /** @@ -70,7 +62,7 @@ class Control extends libLink.Link { this.tlsCa = tlsCa; /** * Mapping of plugin names to their instance for loaded plugins. - * @type {Map} + * @type {Map} */ this.plugins = controlPlugins; @@ -80,8 +72,8 @@ class Control extends libLink.Link { */ this.keepOpen = false; - this.handle(libData.LogMessageEvent, this.handleLogMessageEvent.bind(this)); - this.handle(libData.DebugWsMessageEvent, this.handleDebugWsMessageEvent.bind(this)); + this.handle(lib.LogMessageEvent, this.handleLogMessageEvent.bind(this)); + this.handle(lib.DebugWsMessageEvent, this.handleDebugWsMessageEvent.bind(this)); } async setLogSubscriptions({ @@ -92,7 +84,7 @@ class Control extends libLink.Link { maxLevel = null, }) { await this.send( - new libData.LogSetSubscriptionsRequest( + new lib.LogSetSubscriptionsRequest( all, controller, hostIds, instanceIds, maxLevel, ) ); @@ -111,7 +103,7 @@ class Control extends libLink.Link { try { await this.connector.disconnect(); } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { throw err; } } @@ -119,10 +111,10 @@ class Control extends libLink.Link { } async function loadPlugins(pluginList) { - let pluginInfos = await libPluginLoader.loadPluginInfos(pluginList); - libLink.registerPluginMessages(pluginInfos); - libConfig.registerPluginConfigGroups(pluginInfos); - libConfig.finalizeConfigs(); + let pluginInfos = await lib.loadPluginInfos(pluginList); + lib.registerPluginMessages(pluginInfos); + lib.registerPluginConfigGroups(pluginInfos); + lib.finalizeConfigs(); let controlPlugins = new Map(); for (let pluginInfo of pluginInfos) { @@ -130,7 +122,7 @@ async function loadPlugins(pluginList) { continue; } - let ControlPluginClass = await libPluginLoader.loadControlPluginClass(pluginInfo); + let ControlPluginClass = await lib.loadControlPluginClass(pluginInfo); let controlPlugin = new ControlPluginClass(pluginInfo, logger); controlPlugins.set(pluginInfo.name, controlPlugin); await controlPlugin.init(); @@ -162,8 +154,8 @@ async function startControl() { default: "plugin-list.json", type: "string", }) - .command("plugin", "Manage available plugins", libSharedCommands.pluginCommand) - .command("control-config", "Manage Control config", libSharedCommands.configCommand) + .command("plugin", "Manage available plugins", lib.pluginCommand) + .command("control-config", "Manage Control config", lib.configCommand) .wrap(yargs.terminalWidth()) .help(false) // Disable help to avoid triggering it on the first parse. ; @@ -176,10 +168,10 @@ async function startControl() { new ConsoleTransport({ errorLevels: Object.keys(levels), level: args.logLevel, - format: new libLoggingUtils.TerminalFormat(), + format: new lib.TerminalFormat(), }) ); - libLoggingUtils.handleUnhandledErrors(logger); + lib.handleUnhandledErrors(logger); logger.verbose(`Loading available plugins from ${args.pluginList}`); let pluginList = new Map(); @@ -193,7 +185,7 @@ async function startControl() { // If the command is plugin management we don't try to load plugins if (args._[0] === "plugin") { - await libSharedCommands.handlePluginCommand(args, pluginList, args.pluginList); + await lib.handlePluginCommand(args, pluginList, args.pluginList); return; } @@ -211,7 +203,7 @@ async function startControl() { ; logger.verbose(`Loading config from ${args.config}`); - let controlConfig = new libConfig.ControlConfig("control"); + let controlConfig = new lib.ControlConfig("control"); try { await controlConfig.load(JSON.parse(await fs.readFile(args.config))); @@ -221,7 +213,7 @@ async function startControl() { await controlConfig.init(); } else { - throw new libErrors.StartupError(`Failed to load ${args.config}: ${err.message}`); + throw new lib.StartupError(`Failed to load ${args.config}: ${err.message}`); } } @@ -232,14 +224,14 @@ async function startControl() { // Handle the control-config command before trying to connect. if (args._[0] === "control-config") { - await libSharedCommands.handleConfigCommand(args, controlConfig, args.config); + await lib.handleConfigCommand(args, controlConfig, args.config); return; } // Determine which command is being executed. let commandPath = [...args._]; let targetCommand = rootCommands; - while (commandPath.length && targetCommand instanceof libCommand.CommandTree) { + while (commandPath.length && targetCommand instanceof lib.CommandTree) { targetCommand = targetCommand.get(commandPath.shift()); } @@ -266,8 +258,8 @@ async function startControl() { try { await controlConnector.connect(); } catch (err) { - if (err instanceof libErrors.AuthenticationFailed) { - throw new libErrors.StartupError(err.message); + if (err instanceof lib.AuthenticationFailed) { + throw new lib.StartupError(err.message); } throw err; } @@ -287,11 +279,11 @@ async function startControl() { } catch (err) { control.keepOpen = false; - if (err instanceof libErrors.CommandError) { + if (err instanceof lib.CommandError) { logger.error(`Error running command: ${err.message}`); process.exitCode = 1; - } else if (err instanceof libErrors.RequestError) { + } else if (err instanceof lib.RequestError) { logger.error(`Error sending request:\n${err.stack}`); process.exitCode = 1; @@ -321,7 +313,7 @@ I version of clusterio. Expect things to break. I ` ); startControl().catch(err => { - if (!(err instanceof libErrors.StartupError)) { + if (!(err instanceof lib.StartupError)) { logger.fatal(` +------------------------------------------------------------+ | Unexpected error occured while starting control, please | diff --git a/packages/ctl/src/commands.js b/packages/ctl/src/commands.js index c4c908bb..35e675be 100644 --- a/packages/ctl/src/commands.js +++ b/packages/ctl/src/commands.js @@ -10,15 +10,8 @@ const child_process = require("child_process"); const stream = require("stream"); const util = require("util"); -const libErrors = require("@clusterio/lib/errors"); -const libConfig = require("@clusterio/lib/config"); -const libCommand = require("@clusterio/lib/command"); -const libData = require("@clusterio/lib/data"); -const { ConsoleTransport, levels, logger } = require("@clusterio/lib/logging"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); -const libHelpers = require("@clusterio/lib/helpers"); -const libFactorio = require("@clusterio/lib/factorio"); -const libFileOps = require("@clusterio/lib/file_ops"); +const lib = require("@clusterio/lib"); +const { ConsoleTransport, levels, logger } = lib; const finished = util.promisify(stream.finished); @@ -83,14 +76,14 @@ async function serializedConfigToString(serializedConfig, configGroup, disallowe return allConfigElements; } -const controllerCommands = new libCommand.CommandTree({ name: "controller", description: "Controller management" }); -const controllerConfigCommands = new libCommand.CommandTree({ +const controllerCommands = new lib.CommandTree({ name: "controller", description: "Controller management" }); +const controllerConfigCommands = new lib.CommandTree({ name: "config", alias: ["c"], description: "controller config management", }); -controllerConfigCommands.add(new libCommand.Command({ +controllerConfigCommands.add(new lib.Command({ definition: ["list", "List controller configuration"], handler: async function(args, control) { - let response = await control.send(new libData.ControllerConfigGetRequest()); + let response = await control.send(new lib.ControllerConfigGetRequest()); for (let group of response.serializedConfig.groups) { for (let [name, value] of Object.entries(group.fields)) { @@ -100,7 +93,7 @@ controllerConfigCommands.add(new libCommand.Command({ }, })); -controllerConfigCommands.add(new libCommand.Command({ +controllerConfigCommands.add(new lib.Command({ definition: ["set [value]", "Set field in controller config", (yargs) => { yargs.positional("field", { describe: "Field to set", type: "string" }); yargs.positional("value", { describe: "Value to set", type: "string" }); @@ -110,15 +103,15 @@ controllerConfigCommands.add(new libCommand.Command({ }], handler: async function(args, control) { if (args.stdin) { - args.value = (await libHelpers.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); + args.value = (await lib.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); } else if (args.value === undefined) { args.value = ""; } - await control.send(new libData.ControllerConfigSetFieldRequest(args.field, args.value)); + await control.send(new lib.ControllerConfigSetFieldRequest(args.field, args.value)); }, })); -controllerConfigCommands.add(new libCommand.Command({ +controllerConfigCommands.add(new lib.Command({ definition: ["set-prop [value]", "Set property of field in controller config", (yargs) => { yargs.positional("field", { describe: "Field to set", type: "string" }); yargs.positional("prop", { describe: "Property to set", type: "string" }); @@ -129,7 +122,7 @@ controllerConfigCommands.add(new libCommand.Command({ }], handler: async function(args, control) { if (args.stdin) { - args.value = (await libHelpers.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); + args.value = (await lib.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); } let value; try { @@ -139,14 +132,14 @@ controllerConfigCommands.add(new libCommand.Command({ } catch (err) { // See note for the instance version of set-prop if (args.stdin || /^(\[.*]|{.*}|".*")$/.test(args.value)) { - throw new libErrors.CommandError(`In parsing value '${args.value}': ${err.message}`); + throw new lib.CommandError(`In parsing value '${args.value}': ${err.message}`); } value = args.value; } - await control.send(new libData.ControllerConfigSetPropRequest(args.field, args.prop, value)); + await control.send(new lib.ControllerConfigSetPropRequest(args.field, args.prop, value)); }, })); -controllerConfigCommands.add(new libCommand.Command({ +controllerConfigCommands.add(new lib.Command({ definition: ["edit [editor]", "Edit controller configuration", (yargs) => { yargs.positional("editor", { describe: "Editor to use", @@ -156,14 +149,14 @@ controllerConfigCommands.add(new libCommand.Command({ }], handler: async function(args, control) { let response = await control.send(new ControllerConfigGetRequest()); - let tmpFile = await libFileOps.getTempFile("ctl-", "-tmp", os.tmpdir()); + let tmpFile = await lib.getTempFile("ctl-", "-tmp", os.tmpdir()); let editor = await getEditor(args.editor); if (editor === -1) { - throw new libErrors.CommandError(`No editor avalible. Checked CLI input, EDITOR and VISUAL env vars + throw new lib.CommandError(`No editor avalible. Checked CLI input, EDITOR and VISUAL env vars Try "ctl controller config edit "`); } let allConfigElements = await serializedConfigToString( - response.serializedConfig, libConfig.ControllerConfig, {} + response.serializedConfig, lib.ControllerConfig, {} ); await fs.writeFile(tmpFile, allConfigElements, (err) => { if (err) { @@ -211,10 +204,10 @@ controllerConfigCommands.add(new libCommand.Command({ controllerCommands.add(controllerConfigCommands); -const controllerPluginCommands = new libCommand.CommandTree({ +const controllerPluginCommands = new lib.CommandTree({ name: "plugin", alias: ["p"], description: "controller plugin inspection", }); -controllerPluginCommands.add(new libCommand.Command({ +controllerPluginCommands.add(new lib.Command({ definition: ["list", "List plugins on controller"], handler: async function(args, control) { let url = new URL(control.config.get("control.controller_url")); @@ -230,27 +223,27 @@ controllerPluginCommands.add(new libCommand.Command({ controllerCommands.add(controllerPluginCommands); -const hostCommands = new libCommand.CommandTree({ name: "host", description: "Host management" }); -hostCommands.add(new libCommand.Command({ +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) { - let hosts = await control.send(new libData.HostListRequest()); + let hosts = await control.send(new lib.HostListRequest()); print(asTable(hosts)); }, })); -hostCommands.add(new libCommand.Command({ +hostCommands.add(new lib.Command({ definition: ["generate-token", "Generate token for a host", (yargs) => { yargs.option("id", { type: "number", nargs: 1, describe: "Host id" }); }], handler: async function(args, control) { let hostId = typeof args.id === "number" ? args.id : null; - let response = await control.send(new libData.HostGenerateTokenRequest(hostId)); + let response = await control.send(new lib.HostGenerateTokenRequest(hostId)); print(response.token); }, })); -hostCommands.add(new libCommand.Command({ +hostCommands.add(new lib.Command({ definition: ["create-config", "Create host config", (yargs) => { yargs.option("id", { type: "number", nargs: 1, describe: "Host id", default: null }); yargs.option("name", { type: "string", nargs: 1, describe: "Host name", default: null }); @@ -263,7 +256,7 @@ hostCommands.add(new libCommand.Command({ }], handler: async function(args, control) { let rawConfig = await control.send( - new libData.HostConfigCreateRequest(args.id, args.name, args.generateToken) + new lib.HostConfigCreateRequest(args.id, args.name, args.generateToken) ); let content = JSON.stringify(rawConfig.serializedConfig, null, 4); @@ -275,7 +268,7 @@ hostCommands.add(new libCommand.Command({ await fs.outputFile(args.output, content, { flag: "wx" }); } catch (err) { if (err.code === "EEXIST") { - throw new libErrors.CommandError(`File ${args.output} already exists`); + throw new lib.CommandError(`File ${args.output} already exists`); } throw err; } @@ -284,18 +277,18 @@ hostCommands.add(new libCommand.Command({ })); -const instanceCommands = new libCommand.CommandTree({ +const instanceCommands = new lib.CommandTree({ name: "instance", alias: ["i"], description: "Instance management", }); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: [["list", "l"], "List instances known to the controller"], handler: async function(args, control) { - let list = await control.send(new libData.InstanceDetailsListRequest()); + let list = await control.send(new lib.InstanceDetailsListRequest()); print(asTable(list)); }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["create ", "Create an instance", (yargs) => { // XXX TODO: set any specific options? yargs.positional("name", { describe: "Instance name", type: "string" }); @@ -304,27 +297,27 @@ instanceCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceConfig = new libConfig.InstanceConfig("control"); + let instanceConfig = new lib.InstanceConfig("control"); await instanceConfig.init(); if (args.id) { instanceConfig.set("instance.id", args.id); } instanceConfig.set("instance.name", args.name); let serializedConfig = instanceConfig.serialize("controller"); - await control.send(new libData.InstanceCreateRequest(serializedConfig)); + await control.send(new lib.InstanceCreateRequest(serializedConfig)); }, })); -const instanceConfigCommands = new libCommand.CommandTree({ +const instanceConfigCommands = new lib.CommandTree({ name: "config", alias: ["c"], description: "Instance config management", }); -instanceConfigCommands.add(new libCommand.Command({ +instanceConfigCommands.add(new lib.Command({ definition: ["list ", "List configuration for an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to list config for", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - let response = await control.send(new libData.InstanceConfigGetRequest(instanceId)); + let instanceId = await lib.resolveInstance(control, args.instance); + let response = await control.send(new lib.InstanceConfigGetRequest(instanceId)); for (let group of response.config.groups) { for (let [name, value] of Object.entries(group.fields)) { @@ -334,7 +327,7 @@ instanceConfigCommands.add(new libCommand.Command({ }, })); -instanceConfigCommands.add(new libCommand.Command({ +instanceConfigCommands.add(new lib.Command({ definition: ["set [value]", "Set field in instance config", (yargs) => { yargs.positional("instance", { describe: "Instance to set config on", type: "string" }); yargs.positional("field", { describe: "Field to set", type: "string" }); @@ -344,17 +337,17 @@ instanceConfigCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); if (args.stdin) { - args.value = (await libHelpers.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); + args.value = (await lib.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); } else if (args.value === undefined) { args.value = ""; } - await control.send(new libData.InstanceConfigSetFieldRequest(instanceId, args.field, args.value)); + await control.send(new lib.InstanceConfigSetFieldRequest(instanceId, args.field, args.value)); }, })); -instanceConfigCommands.add(new libCommand.Command({ +instanceConfigCommands.add(new lib.Command({ definition: ["set-prop [value]", "Set property of field in instance config", (yargs) => { yargs.positional("instance", { describe: "Instance to set config on", type: "string" }); yargs.positional("field", { describe: "Field to set", type: "string" }); @@ -365,9 +358,9 @@ instanceConfigCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); if (args.stdin) { - args.value = (await libHelpers.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); + args.value = (await lib.readStream(process.stdin)).toString().replace(/\r?\n$/, ""); } let value; try { @@ -392,15 +385,15 @@ instanceConfigCommands.add(new libCommand.Command({ // bash + npx : '""That'\''s a \" quote""' // bash + npx -s sh : "'\"\"That'\\''s a \\\" quote\"\"'" if (args.stdin || /^(\[.*]|{.*}|".*")$/.test(args.value)) { - throw new libErrors.CommandError(`In parsing value '${args.value}': ${err.message}`); + throw new lib.CommandError(`In parsing value '${args.value}': ${err.message}`); } value = args.value; } - await control.send(new libData.InstanceConfigSetPropRequest(instanceId, args.field, args.prop, value)); + await control.send(new lib.InstanceConfigSetPropRequest(instanceId, args.field, args.prop, value)); }, })); -instanceConfigCommands.add(new libCommand.Command({ +instanceConfigCommands.add(new lib.Command({ definition: ["edit [editor]", "Edit instance configuration", (yargs) => { yargs.positional("instance", { describe: "Instance to set config on", type: "string" }); yargs.positional("editor", { @@ -410,18 +403,18 @@ instanceConfigCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - let response = await control.send(new libData.InstanceConfigGetRequest(instanceId)); - let tmpFile = await libFileOps.getTempFile("ctl-", "-tmp", os.tmpdir()); + let instanceId = await lib.resolveInstance(control, args.instance); + let response = await control.send(new lib.InstanceConfigGetRequest(instanceId)); + let tmpFile = await lib.getTempFile("ctl-", "-tmp", os.tmpdir()); let editor = await getEditor(args.editor); if (editor === -1) { - throw new libErrors.CommandError(`No editor avalible. Checked CLI input, EDITOR and VISUAL env vars + throw new lib.CommandError(`No editor avalible. Checked CLI input, EDITOR and VISUAL env vars Try "ctl controller config edit "`); } let disallowedList = {"instance.id": 0, "instance.assigned_host": 0, "factorio.settings": 0}; let allConfigElements = await serializedConfigToString( response.serializedConfig, - libConfig.InstanceConfig, + lib.InstanceConfig, disallowedList ); await fs.writeFile(tmpFile, allConfigElements, (err) => { @@ -443,7 +436,7 @@ instanceConfigCommands.add(new libCommand.Command({ for (let index in final) { if (index in final) { try { - await control.send(new libData.InstanceConfigSetField( + await control.send(new lib.InstanceConfigSetField( instanceId, index, final[index], @@ -474,15 +467,15 @@ instanceConfigCommands.add(new libCommand.Command({ })); instanceCommands.add(instanceConfigCommands); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["assign [host]", "Assign instance to a host", (yargs) => { yargs.positional("instance", { describe: "Instance to assign", type: "string" }); yargs.positional("host", { describe: "Host to assign to or unassign if none", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - let hostId = args.host ? await libCommand.resolveHost(control, args.host) : null; - await control.send(new libData.InstanceAssignRequest(instanceId, hostId)); + let instanceId = await lib.resolveInstance(control, args.instance); + let hostId = args.host ? await lib.resolveHost(control, args.host) : null; + await control.send(new lib.InstanceAssignRequest(instanceId, hostId)); }, })); @@ -491,7 +484,7 @@ async function loadMapSettings(args) { let mapGenSettings = null; let mapSettings = null; if (args.mapExchangeString) { - let parsed = libFactorio.readMapExchangeString(args.mapExchangeString); + let parsed = lib.readMapExchangeString(args.mapExchangeString); mapGenSettings = parsed.map_gen_settings; mapSettings = parsed.map_settings; } @@ -509,16 +502,16 @@ async function loadMapSettings(args) { }; } -const instanceSaveCommands = new libCommand.CommandTree({ +const instanceSaveCommands = new lib.CommandTree({ name: "save", alias: ["s"], description: "Instance save management", }); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["list ", "list saves on an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to list saves on", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - let saves = await control.sendTo({ instanceId }, new libData.InstanceListSavesRequest()); + let instanceId = await lib.resolveInstance(control, args.instance); + let saves = await control.sendTo({ instanceId }, new lib.InstanceListSavesRequest()); for (let entry of saves) { entry.mtime = new Date(entry.mtimeMs).toLocaleString(); delete entry.mtimeMs; @@ -527,7 +520,7 @@ instanceSaveCommands.add(new libCommand.Command({ }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["create [name]", "Create a new save on an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to create on", type: "string" }); yargs.positional("name", { describe: "Name of save to create.", type: "string", default: "world.zip" }); @@ -539,41 +532,41 @@ instanceSaveCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); let { seed, mapGenSettings, mapSettings } = await loadMapSettings(args); await control.setLogSubscriptions({ instanceIds: [instanceId] }); await control.sendTo( { instanceId }, - new libData.InstanceCreateSaveRequest(args.name, seed, mapGenSettings, mapSettings), + new lib.InstanceCreateSaveRequest(args.name, seed, mapGenSettings, mapSettings), ); }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["rename ", "Rename a save on an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to rename save on", type: "string" }); yargs.positional("old-name", { describe: "Old name of save.", type: "string" }); yargs.positional("new-name", { describe: "New name of save.", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - await control.send(new libData.InstanceRenameSaveRequest(instanceId, args.oldName, args.newName)); + let instanceId = await lib.resolveInstance(control, args.instance); + await control.send(new lib.InstanceRenameSaveRequest(instanceId, args.oldName, args.newName)); }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["copy ", "Copy a save on an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to copy save on", type: "string" }); yargs.positional("source", { describe: "Save to copy.", type: "string" }); yargs.positional("destination", { describe: "Name of copy.", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - await control.send(new libData.InstanceCopySaveRequest(instanceId, args.source, args.destination)); + let instanceId = await lib.resolveInstance(control, args.instance); + await control.send(new lib.InstanceCopySaveRequest(instanceId, args.source, args.destination)); }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["upload ", "Upload a save to an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to upload to", type: "string" }); yargs.positional("filepath", { describe: "Path to save to upload", type: "string" }); @@ -584,12 +577,12 @@ instanceSaveCommands.add(new libCommand.Command({ handler: async function(args, control) { let filename = args.name || path.basename(args.filepath); if (!filename.endsWith(".zip")) { - throw new libErrors.CommandError("Save name must end with .zip"); + throw new lib.CommandError("Save name must end with .zip"); } // phin doesn't support streaming requests :( let content = await fs.readFile(args.filepath); - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); let url = new URL(control.config.get("control.controller_url")); url.pathname += "api/upload-save"; url.searchParams.append("instance_id", instanceId); @@ -619,12 +612,12 @@ instanceSaveCommands.add(new libCommand.Command({ } if ((result.body.errors || []).length || (result.body.request_errors || []).length) { - throw new libErrors.CommandError("Uploading save failed"); + throw new lib.CommandError("Uploading save failed"); } }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: [ "transfer [target-save]", "Transfer a save between instances", @@ -639,10 +632,10 @@ instanceSaveCommands.add(new libCommand.Command({ }, ], handler: async function(args, control) { - let sourceInstanceId = await libCommand.resolveInstance(control, args.sourceInstance); - let targetInstanceId = await libCommand.resolveInstance(control, args.targetInstance); + let sourceInstanceId = await lib.resolveInstance(control, args.sourceInstance); + let targetInstanceId = await lib.resolveInstance(control, args.targetInstance); let storedName = await control.send( - new libData.InstanceTransferSaveRequest( + new lib.InstanceTransferSaveRequest( sourceInstanceId, args.sourceSave, targetInstanceId, @@ -654,14 +647,14 @@ instanceSaveCommands.add(new libCommand.Command({ }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["download ", "Download a save from an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to download save from", type: "string" }); yargs.positional("save", { describe: "Save to download", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - let streamId = await control.send(new libData.InstanceDownloadSaveRequest(instanceId, args.save)); + let instanceId = await lib.resolveInstance(control, args.instance); + let streamId = await control.send(new lib.InstanceDownloadSaveRequest(instanceId, args.save)); let url = new URL(control.config.get("control.controller_url")); url.pathname += `api/stream/${streamId}`; @@ -680,7 +673,7 @@ instanceSaveCommands.add(new libCommand.Command({ break; } catch (err) { if (err.code === "EEXIST") { - tempFilename = await libFileOps.findUnusedName(".", tempFilename, ".tmp.zip"); + tempFilename = await lib.findUnusedName(".", tempFilename, ".tmp.zip"); } else { throw err; } @@ -689,48 +682,48 @@ instanceSaveCommands.add(new libCommand.Command({ response.pipe(writeStream); await finished(writeStream); - let filename = await libFileOps.findUnusedName(".", args.save, ".zip"); + let filename = await lib.findUnusedName(".", args.save, ".zip"); await fs.rename(tempFilename, filename); logger.info(`Downloaded ${args.save}${args.save === filename ? "" : ` as ${filename}`}`); }, })); -instanceSaveCommands.add(new libCommand.Command({ +instanceSaveCommands.add(new lib.Command({ definition: ["delete ", "Delete a save from an instance", (yargs) => { yargs.positional("instance", { describe: "Instance to delete save from", type: "string" }); yargs.positional("save", { describe: "Save to delete", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - await control.send(new libData.InstanceDeleteSaveRequest(instanceId, args.save)); + let instanceId = await lib.resolveInstance(control, args.instance); + await control.send(new lib.InstanceDeleteSaveRequest(instanceId, args.save)); }, })); instanceCommands.add(instanceSaveCommands); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["export-data ", "Export item icons and locale from instance", (yargs) => { yargs.positional("instance", { describe: "Instance to export from", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); await control.setLogSubscriptions({ instanceIds: [instanceId] }); - await control.sendTo({ instanceId }, new libData.InstanceExportDataRequest()); + await control.sendTo({ instanceId }, new lib.InstanceExportDataRequest()); }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["extract-players ", "Extract players from running save into the cluster.", (yargs) => { yargs.positional("instance", { describe: "Instance to extract players and online time from", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); await control.setLogSubscriptions({ instanceIds: [instanceId] }); - await control.sendTo({ instanceId }, new libData.InstanceExtractPlayersRequest()); + await control.sendTo({ instanceId }, new lib.InstanceExtractPlayersRequest()); }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["start ", "Start instance", (yargs) => { yargs.positional("instance", { describe: "Instance to start", type: "string" }); yargs.options({ @@ -739,14 +732,14 @@ instanceCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); await control.setLogSubscriptions({ instanceIds: [instanceId] }); - await control.sendTo({ instanceId }, new libData.InstanceStartRequest(args.save)); + await control.sendTo({ instanceId }, new lib.InstanceStartRequest(args.save)); control.keepOpen = args.keepOpen; }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["load-scenario ", "Start instance by loading a scenario", (yargs) => { yargs.positional("instance", { describe: "Instance to start", type: "string" }); yargs.positional("scenario", { describe: "Scenario to load", type: "string" }); @@ -759,58 +752,58 @@ instanceCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); await control.setLogSubscriptions({ instanceIds: [instanceId] }); let { seed, mapGenSettings, mapSettings } = await loadMapSettings(args); await control.sendTo( { instanceId }, - new libData.InstanceLoadScenarioRequest(args.scenario, seed, mapGenSettings, mapSettings), + new lib.InstanceLoadScenarioRequest(args.scenario, seed, mapGenSettings, mapSettings), ); control.keepOpen = args.keepOpen; }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["stop ", "Stop instance", (yargs) => { yargs.positional("instance", { describe: "Instance to stop", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); await control.setLogSubscriptions({ instanceIds: [instanceId] }); - await control.sendTo({ instanceId }, new libData.InstanceStopRequest(args.save)); + await control.sendTo({ instanceId }, new lib.InstanceStopRequest(args.save)); }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["kill ", "Kill instance", (yargs) => { yargs.positional("instance", { describe: "Instance to kill", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); + let instanceId = await lib.resolveInstance(control, args.instance); await control.setLogSubscriptions({ instanceIds: [instanceId] }); - await control.sendTo({ instanceId }, new libData.InstanceKillRequest(args.save)); + await control.sendTo({ instanceId }, new lib.InstanceKillRequest(args.save)); }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["delete ", "Delete instance", (yargs) => { yargs.positional("instance", { describe: "Instance to delete", type: "string" }); }], handler: async function(args, control) { - let instanceId = await libCommand.resolveInstance(control, args.instance); - await control.send(new libData.InstanceDeleteRequest(instanceId)); + let instanceId = await lib.resolveInstance(control, args.instance); + await control.send(new lib.InstanceDeleteRequest(instanceId)); }, })); -instanceCommands.add(new libCommand.Command({ +instanceCommands.add(new lib.Command({ definition: ["send-rcon ", "Send RCON command", (yargs) => { yargs.positional("instance", { describe: "Instance to send to", type: "string" }); yargs.positional("command", { describe: "command to send", type: "string" }); }], handler: async function(args, control) { let result = await control.sendTo( - { instanceId: await libCommand.resolveInstance(control, args.instance) }, - new libData.InstanceSendRconRequest(args.command), + { instanceId: await lib.resolveInstance(control, args.instance) }, + new lib.InstanceSendRconRequest(args.command), ); // Factorio includes a newline in its response output. @@ -818,17 +811,17 @@ instanceCommands.add(new libCommand.Command({ }, })); -const modPackCommands = new libCommand.CommandTree({ name: "mod-pack", description: "Mod Pack" }); -modPackCommands.add(new libCommand.Command({ +const modPackCommands = new lib.CommandTree({ name: "mod-pack", description: "Mod Pack" }); +modPackCommands.add(new lib.Command({ definition: ["show ", "Show details of mod pack", (yargs) => { yargs.positional("mod-pack", { describe: "Mod pack to show", type: "string" }); }], handler: async function(args, control) { let mods = new Map( - (await control.send(new libData.ModListRequest())).map(m => [`${m.name}_${m.version}`, m]) + (await control.send(new lib.ModListRequest())).map(m => [`${m.name}_${m.version}`, m]) ); let modPack = await control.send( - new libData.ModPackGetRequest(await libCommand.resolveModPack(control, args.modPack)) + new lib.ModPackGetRequest(await lib.resolveModPack(control, args.modPack)) ); for (let [field, value] of Object.entries(modPack)) { @@ -866,10 +859,10 @@ modPackCommands.add(new libCommand.Command({ }, })); -modPackCommands.add(new libCommand.Command({ +modPackCommands.add(new lib.Command({ definition: [["list", "l"], "List mod packs in the cluster"], handler: async function(args, control) { - let modPacks = await control.send(new libData.ModPackListRequest()); + 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)) { @@ -887,7 +880,7 @@ function setModPackSettings(modPack, args) { for (let i = 0; i + 2 < settings.length; i += 3) { const [scope, name, value] = settings.slice(i, i + 3); if (!["startup", "runtime-global", "runtime-per-user"].includes(scope)) { - throw new libErrors.CommandError( + throw new lib.CommandError( `Setting scope must be one of startup, runtime-gloabl, or runtime-per-user, not ${scope}` ); } @@ -897,7 +890,7 @@ function setModPackSettings(modPack, args) { doSettings(args.boolSetting || [], value => { if (!["true", "false"].includes(value)) { - throw new libErrors.CommandError(`boolean value must be one of true or false, not ${value}`); + throw new lib.CommandError(`boolean value must be one of true or false, not ${value}`); } return value === "true"; }); @@ -905,14 +898,14 @@ function setModPackSettings(modPack, args) { // eslint-disable-next-line radix let number = Number.parseInt(value); if (isNaN(number)) { - throw new libErrors.CommandError(`int value must be an integer, not ${value}`); + throw new lib.CommandError(`int value must be an integer, not ${value}`); } return number; }); doSettings(args.doubleSetting || [], value => { let number = Number.parseFloat(value); if (isNaN(number)) { - throw new libErrors.CommandError(`double value must be a number, not ${value}`); + throw new lib.CommandError(`double value must be a number, not ${value}`); } return number; }); @@ -923,13 +916,13 @@ function setModPackMods(modPack, mods) { for (let mod of mods || []) { const [name, version, sha1] = mod.split(":"); if (!version) { - throw new libErrors.CommandError("Added mod must be formatted as name:version or name:version:sha1"); + throw new lib.CommandError("Added mod must be formatted as name:version or name:version:sha1"); } if (!/^\d+\.\d+\.\d+$/.test(version)) { - throw new libErrors.CommandError("version must match the format digit.digit.digit"); + throw new lib.CommandError("version must match the format digit.digit.digit"); } if (sha1 && !/^[0-9a-f]{40}$/.test(sha1)) { - throw new libErrors.CommandError("sha1 must be a 40 digit lower case hex string"); + throw new lib.CommandError("sha1 must be a 40 digit lower case hex string"); } modPack.mods.set(name, { name, enabled: true, version, sha1 }); } @@ -938,13 +931,13 @@ function setModPackMods(modPack, mods) { function setModPackModsEnabled(modPack, mods, enabled) { for (let mod of mods || []) { if (!modPack.mods.has(mod)) { - throw new libErrors.CommandError(`Mod named ${mod} does not exist in the mod pack`); + throw new lib.CommandError(`Mod named ${mod} does not exist in the mod pack`); } modPack.mods.get(mod).enabled = enabled; } } -modPackCommands.add(new libCommand.Command({ +modPackCommands.add(new lib.Command({ definition: ["create ", "Create mod pack", (yargs) => { yargs.positional("name", { describe: "Name of mod pack to create", type: "string" }); yargs.positional("factorio-version", { describe: "Version of factorio the mod pack is for", type: "string" }); @@ -959,47 +952,47 @@ modPackCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - const modPack = libData.ModPack.fromJSON({}); + const modPack = lib.ModPack.fromJSON({}); modPack.name = args.name; if (args.description) { modPack.description = args.description; } if (args.factorioVersion) { if (!/^\d+\.\d+\.\d+?$/.test(args.factorioVersion)) { - throw new libErrors.CommandError("factorio-version must match the format digit.digit.digit"); + throw new lib.CommandError("factorio-version must match the format digit.digit.digit"); } modPack.factorioVersion = args.factorioVersion; } setModPackMods(modPack, args.mods); setModPackModsEnabled(modPack, args.disabledMods, false); setModPackSettings(modPack, args); - await control.send(new libData.ModPackCreateRequest(modPack)); + await control.send(new lib.ModPackCreateRequest(modPack)); print(`Created mod pack ${modPack.name} (${modPack.id})`); }, })); -modPackCommands.add(new libCommand.Command({ +modPackCommands.add(new lib.Command({ definition: ["import ", "Import mod pack string", (yargs) => { yargs.positional("string", { describe: "Mod pack string to import", type: "string" }); }], handler: async function(args, control) { - const modPack = libData.ModPack.fromModPackString(args.string); - await control.send(new libData.ModPackCreateRequest(modPack)); + const modPack = lib.ModPack.fromModPackString(args.string); + await control.send(new lib.ModPackCreateRequest(modPack)); print(`Created mod pack ${modPack.name} (${modPack.id})`); }, })); -modPackCommands.add(new libCommand.Command({ +modPackCommands.add(new lib.Command({ definition: ["export ", "Export mod pack string", (yargs) => { yargs.positional("string", { describe: "Mod pack to export", type: "string" }); }], handler: async function(args, control) { const modPack = await control.send( - new libData.ModPackGetRequest(await libCommand.resolveModPack(control, args.modPack)) + new lib.ModPackGetRequest(await lib.resolveModPack(control, args.modPack)) ); print(modPack.toModPackString()); }, })); -modPackCommands.add(new libCommand.Command({ +modPackCommands.add(new lib.Command({ definition: ["edit ", "Edit mod pack", (yargs) => { yargs.positional("mod-pack", { describe: "Mod pack to remove from", type: "string" }); yargs.options({ @@ -1019,14 +1012,14 @@ modPackCommands.add(new libCommand.Command({ }], handler: async function(args, control) { const modPack = await control.send( - new libData.ModPackGetRequest(await libCommand.resolveModPack(control, args.modPack)) + new lib.ModPackGetRequest(await lib.resolveModPack(control, args.modPack)) ); if (args.name) { modPack.name = args.name; } if (args.description) { modPack.description = args.description; } if (args.factorioVersion) { if (!/^\d+\.\d+\.\d+?$/.test(args.factorioVersion)) { - throw new libErrors.CommandError("factorio-version must match the format digit.digit.digit"); + throw new lib.CommandError("factorio-version must match the format digit.digit.digit"); } modPack.factorioVersion = args.factorioVersion; } @@ -1047,7 +1040,7 @@ modPackCommands.add(new libCommand.Command({ for (let i = 0; i + 1 < args.removeSetting.length; i += 2) { const [scope, name] = settings.slice(i, i + 2); if (!["startup", "runtime-global", "runtime-per-user"].includes(scope)) { - throw new libErrors.CommandError( + throw new lib.CommandError( `Setting scope must be one of startup, runtime-gloabl, or runtime-per-user, not ${scope}` ); } @@ -1058,28 +1051,28 @@ modPackCommands.add(new libCommand.Command({ } } } - await control.send(new libData.ModPackUpdateRequest(modPack)); + await control.send(new lib.ModPackUpdateRequest(modPack)); }, })); -modPackCommands.add(new libCommand.Command({ +modPackCommands.add(new lib.Command({ definition: ["delete ", "Delete mod pack", (yargs) => { yargs.positional("mod-pack", { describe: "Mod pack to delete", type: "string" }); }], handler: async function(args, control) { - const id = await libCommand.resolveModPack(control, args.modPack); - await control.send(new libData.ModPackDeleteRequest(id)); + const id = await lib.resolveModPack(control, args.modPack); + await control.send(new lib.ModPackDeleteRequest(id)); }, })); -const modCommands = new libCommand.CommandTree({ name: "mod", description: "Manage uploaded mods" }); -modCommands.add(new libCommand.Command({ +const modCommands = new lib.CommandTree({ name: "mod", description: "Manage uploaded mods" }); +modCommands.add(new lib.Command({ definition: ["show ", "Show details for a mod stored in the cluster", (yargs) => { yargs.positional("name", { describe: "Mod name to show details for", type: "string" }); yargs.positional("mod-version", { describe: "Version of the mod", type: "string" }); }], handler: async function(args, control) { - let modInfo = await control.send(new libData.ModGetRequest(args.name, args.modVersion)); + let modInfo = await control.send(new lib.ModGetRequest(args.name, args.modVersion)); for (let [field, value] of Object.entries(modInfo)) { if (value instanceof Array) { print(`${field}:`); @@ -1093,7 +1086,7 @@ modCommands.add(new libCommand.Command({ }, })); -modCommands.add(new libCommand.Command({ +modCommands.add(new lib.Command({ definition: [["list", "l"], "List mods stored in the cluster", (yargs) => { yargs.options({ "fields": { @@ -1105,7 +1098,7 @@ modCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let mods = await control.send(new libData.ModListRequest()); + let mods = await control.send(new lib.ModListRequest()); if (!args.fields.includes("all")) { for (let entry of mods) { for (let field of Object.keys(entry)) { @@ -1119,7 +1112,7 @@ modCommands.add(new libCommand.Command({ }, })); -modCommands.add(new libCommand.Command({ +modCommands.add(new lib.Command({ definition: ["search [query]", "Search mods stored in the cluster", (yargs) => { yargs.positional("factorio-version", { describe: "Major version of Factorio to search for", type: "string" }); yargs.positional("query", { describe: "Search query", type: "string", default: "" }); @@ -1152,7 +1145,7 @@ modCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let response = await control.send(new libData.ModSearchRequest( + let response = await control.send(new lib.ModSearchRequest( args.query, args.factorioVersion, args.page, @@ -1178,14 +1171,14 @@ modCommands.add(new libCommand.Command({ }, })); -modCommands.add(new libCommand.Command({ +modCommands.add(new lib.Command({ definition: ["upload ", "Upload mod to the cluster", (yargs) => { yargs.positional("file", { describe: "File to upload", type: "string" }); }], handler: async function(args, control) { let filename = path.basename(args.file); if (!filename.endsWith(".zip")) { - throw new libErrors.CommandError("Mod filename must end with .zip"); + throw new lib.CommandError("Mod filename must end with .zip"); } // phin doesn't support streaming requests :( let content = await fs.readFile(args.file); @@ -1214,23 +1207,23 @@ modCommands.add(new libCommand.Command({ } if (result.body.mods && result.body.mods.length) { - const mod = libData.ModInfo.fromJSON(result.body.mods[0]); + const mod = lib.ModInfo.fromJSON(result.body.mods[0]); logger.info(`Successfully uploaded ${mod.filename}`); } if ((result.body.errors || []).length || (result.body.request_errors || []).length) { - throw new libErrors.CommandError("Uploading mod failed"); + throw new lib.CommandError("Uploading mod failed"); } }, })); -modCommands.add(new libCommand.Command({ +modCommands.add(new lib.Command({ definition: ["download ", "Download a mod from the cluster", (yargs) => { yargs.positional("name", { describe: "Internal name of mod to download", type: "string" }); yargs.positional("mod-version", { describe: "Version of mod to download", type: "string" }); }], handler: async function(args, control) { - let streamId = await control.send(new libData.ModDownloadRequest(args.name, args.modVersion)); + let streamId = await control.send(new lib.ModDownloadRequest(args.name, args.modVersion)); let url = new URL(control.config.get("control.controller_url")); url.pathname += `api/stream/${streamId}`; @@ -1250,7 +1243,7 @@ modCommands.add(new libCommand.Command({ break; } catch (err) { if (err.code === "EEXIST") { - tempFilename = await libFileOps.findUnusedName(".", tempFilename, ".tmp.zip"); + tempFilename = await lib.findUnusedName(".", tempFilename, ".tmp.zip"); } else { throw err; } @@ -1264,36 +1257,36 @@ modCommands.add(new libCommand.Command({ }, })); -modCommands.add(new libCommand.Command({ +modCommands.add(new lib.Command({ definition: ["delete ", "Delete a mod stored in the cluster", (yargs) => { yargs.positional("name", { describe: "Name of mod to delete", type: "string" }); yargs.positional("mod-version", { describe: "Version of mod to delete", type: "string" }); }], handler: async function(args, control) { - await control.send(new libData.ModDeleteRequest(args.name, args.modVersion)); + await control.send(new lib.ModDeleteRequest(args.name, args.modVersion)); }, })); -const permissionCommands = new libCommand.CommandTree({ name: "permission", description: "Permission inspection" }); -permissionCommands.add(new libCommand.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) { - let permissions = await control.send(new libData.PermissionListRequest()); + let permissions = await control.send(new lib.PermissionListRequest()); print(asTable(permissions)); }, })); -const roleCommands = new libCommand.CommandTree({ name: "role", description: "Role management" }); -roleCommands.add(new libCommand.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) { - let roles = await control.send(new libData.RoleListRequest()); + let roles = await control.send(new lib.RoleListRequest()); print(asTable(roles)); }, })); -roleCommands.add(new libCommand.Command({ +roleCommands.add(new lib.Command({ definition: ["create ", "Create a new role", (yargs) => { yargs.positional("name", { describe: "Name of role to create", type: "string" }); yargs.options({ @@ -1302,7 +1295,7 @@ roleCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let id = await control.send(new libData.RoleCreateRequest( + let id = await control.send(new lib.RoleCreateRequest( args.name, args.description, args.permissions, @@ -1311,7 +1304,7 @@ roleCommands.add(new libCommand.Command({ }, })); -roleCommands.add(new libCommand.Command({ +roleCommands.add(new lib.Command({ definition: ["edit ", "Edit existing role", (yargs) => { yargs.positional("role", { describe: "Role to edit", type: "string" }); yargs.options({ @@ -1326,7 +1319,7 @@ roleCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let role = await libCommand.retrieveRole(control, args.role); + let role = await lib.retrieveRole(control, args.role); if (args.name !== undefined) { role.name = args.name; @@ -1347,27 +1340,27 @@ roleCommands.add(new libCommand.Command({ if (args.setPerms !== undefined) { role.permissions = args.setPerms; } - await control.send(new libData.RoleUpdateRequest(role.id, role.name, role.description, role.permissions)); + await control.send(new lib.RoleUpdateRequest(role.id, role.name, role.description, role.permissions)); if (args.grantDefault) { - await control.send(new libData.RoleGrantDefaultPermissionsRequest(role.id)); + await control.send(new lib.RoleGrantDefaultPermissionsRequest(role.id)); } }, })); -roleCommands.add(new libCommand.Command({ +roleCommands.add(new lib.Command({ definition: ["delete ", "Delete role", (yargs) => { yargs.positional("role", { describe: "Role to delete", type: "string" }); }], handler: async function(args, control) { - let role = await libCommand.retrieveRole(control, args.role); - await control.send(new libData.RoleDeleteRequest(role.id)); + let role = await lib.retrieveRole(control, args.role); + await control.send(new lib.RoleDeleteRequest(role.id)); }, })); -const userCommands = new libCommand.CommandTree({ name: "user", alias: ["u"], description: "User management" }); -userCommands.add(new libCommand.Command({ +const userCommands = new lib.CommandTree({ name: "user", alias: ["u"], description: "User management" }); +userCommands.add(new lib.Command({ definition: ["show ", "Show details for one user", (yargs) => { yargs.positional("name", { decribe: "Name of user to show", type: "string" }); yargs.options({ @@ -1375,7 +1368,7 @@ userCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let user = await control.send(new libData.UserGetRequest(args.name)); + let user = await control.send(new lib.UserGetRequest(args.name)); Object.assign(user, user.playerStats); delete user.playerStats; let instanceStats = user.instanceStats; @@ -1383,7 +1376,7 @@ userCommands.add(new libCommand.Command({ print(asTable(Object.entries(user).map(([property, value]) => ({ property, value })))); if (args.instanceStats) { - let instances = await control.send(new libData.InstanceDetailsListRequest()); + let instances = await control.send(new lib.InstanceDetailsListRequest()); function instanceName(id) { let instance = instances.find(i => i.id === id); if (instance) { @@ -1400,7 +1393,7 @@ userCommands.add(new libCommand.Command({ }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: [["list", "l"], "List user in the cluster", (yargs) => { yargs.options({ "stats": { describe: "include user stats", nargs: 0, type: "boolean", default: false }, @@ -1408,7 +1401,7 @@ userCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - let users = await control.send(new libData.UserListRequest()); + let users = await control.send(new lib.UserListRequest()); for (let user of users) { if (args.stats) { Object.assign(user, user.playerStats); @@ -1427,25 +1420,25 @@ userCommands.add(new libCommand.Command({ }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["create ", "Create a user", (yargs) => { yargs.positional("name", { describe: "Name of user to create", type: "string" }); }], handler: async function(args, control) { - await control.send(new libData.UserCreateRequest(args.name)); + await control.send(new lib.UserCreateRequest(args.name)); }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["revoke-token ", "Revoke token for user", (yargs) => { yargs.positional("name", { describe: "Name of user to revoke token for", type: "string" }); }], handler: async function(args, control) { - await control.send(new libData.UserRevokeTokenRequest(args.name)); + await control.send(new lib.UserRevokeTokenRequest(args.name)); }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["set-admin ", "Promote or demote a user to admin", (yargs) => { yargs.positional("user", { describe: "Name of user set admin status for", type: "string" }); yargs.options({ @@ -1454,11 +1447,11 @@ userCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - await control.send(new libData.UserSetAdminRequest(args.user, args.create, !args.revoke)); + await control.send(new lib.UserSetAdminRequest(args.user, args.create, !args.revoke)); }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["set-whitelisted ", "Add or remove user from the whitelist", (yargs) => { yargs.positional("user", { describe: "Name of user to set whitelist status for", type: "string" }); yargs.options({ @@ -1467,11 +1460,11 @@ userCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - await control.send(new libData.UserSetWhitelistedRequest(args.user, args.create, !args.remove)); + await control.send(new lib.UserSetWhitelistedRequest(args.user, args.create, !args.remove)); }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["set-banned ", "Ban or pardon user from banlist", (yargs) => { yargs.positional("user", { describe: "Name of user to set ban status for", type: "string" }); yargs.options({ @@ -1481,17 +1474,17 @@ userCommands.add(new libCommand.Command({ }); }], handler: async function(args, control) { - await control.send(new libData.UserSetBannedRequest(args.user, args.create, !args.pardon, args.reason)); + await control.send(new lib.UserSetBannedRequest(args.user, args.create, !args.pardon, args.reason)); }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["set-roles [roles...]", "Replace user roles", (yargs) => { yargs.positional("user", { describe: "Name of user to change roles for", type: "string" }); yargs.positional("roles", { describe: "roles to assign", type: "string" }); }], handler: async function(args, control) { - let roles = await control.send(new libData.RoleListRequest()); + let roles = await control.send(new lib.RoleListRequest()); let resolvedRoles = []; for (let roleName of args.roles) { @@ -1510,26 +1503,26 @@ userCommands.add(new libCommand.Command({ } if (!found) { - throw new libErrors.CommandError(`No role named ${roleName}`); + throw new lib.CommandError(`No role named ${roleName}`); } } } - await control.send(new libData.UserUpdateRolesRequest(args.user, resolvedRoles)); + await control.send(new lib.UserUpdateRolesRequest(args.user, resolvedRoles)); }, })); -userCommands.add(new libCommand.Command({ +userCommands.add(new lib.Command({ definition: ["delete ", "Delete user", (yargs) => { yargs.positional("user", { describe: "Name of user to delete", type: "string" }); }], handler: async function(args, control) { - await control.send(new libData.UserDeleteRequest(args.user)); + await control.send(new lib.UserDeleteRequest(args.user)); }, })); -const logCommands = new libCommand.CommandTree({ name: "log", description: "Log inspection" }); -logCommands.add(new libCommand.Command({ +const logCommands = new lib.CommandTree({ name: "log", description: "Log inspection" }); +logCommands.add(new lib.Command({ definition: ["follow", "follow cluster log", (yargs) => { yargs.options({ "all": { describe: "Follow the whole cluster log", nargs: 0, type: "boolean", default: false }, @@ -1544,14 +1537,14 @@ logCommands.add(new libCommand.Command({ process.exitCode = 1; return; } - let instanceIds = args.instance ? [await libCommand.resolveInstance(control, args.instance)] : []; - let hostIds = args.host ? [await libCommand.resolveHost(control, args.host)] : []; + let instanceIds = args.instance ? [await lib.resolveInstance(control, args.instance)] : []; + let hostIds = args.host ? [await lib.resolveHost(control, args.host)] : []; await control.setLogSubscriptions({ all: args.all, controller: args.controller, hostIds, instanceIds }); control.keepOpen = true; }, })); -logCommands.add(new libCommand.Command({ +logCommands.add(new lib.Command({ definition: ["query", "Query cluster log", (yargs) => { yargs.options({ "all": { describe: "Query the whole cluster log", nargs: 0, type: "boolean", default: false }, @@ -1569,9 +1562,9 @@ logCommands.add(new libCommand.Command({ process.exitCode = 1; return; } - let instanceIds = args.instance ? [await libCommand.resolveInstance(control, args.instance)] : []; - let hostIds = args.host ? [await libCommand.resolveHost(control, args.host)] : []; - let result = await control.send(new libData.LogQueryRequest( + let instanceIds = args.instance ? [await lib.resolveInstance(control, args.instance)] : []; + let hostIds = args.host ? [await lib.resolveHost(control, args.host)] : []; + let result = await control.send(new lib.LogQueryRequest( args.all, args.controller, hostIds, @@ -1588,7 +1581,7 @@ logCommands.add(new libCommand.Command({ let stdoutLogger = winston.createLogger({ level: "verbose", levels, - format: new libLoggingUtils.TerminalFormat({ showTimestamp: true }), + format: new lib.TerminalFormat({ showTimestamp: true }), transports: [ new ConsoleTransport({ errorLevels: [], warnLevels: [] }), ], @@ -1599,17 +1592,17 @@ logCommands.add(new libCommand.Command({ }, })); -const debugCommands = new libCommand.CommandTree({ name: "debug", description: "Debugging utilities" }); -debugCommands.add(new libCommand.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", (yargs) => { }], handler: async function(args, control) { - await control.send(new libData.DebugDumpWsRequest()); + await control.send(new lib.DebugDumpWsRequest()); control.keepOpen = true; }, })); async function registerCommands(controlPlugins, yargs) { - const rootCommands = new libCommand.CommandTree({ name: "clusterioctl", description: "Manage cluster" }); + const rootCommands = new lib.CommandTree({ name: "clusterioctl", description: "Manage cluster" }); rootCommands.add(controllerCommands); rootCommands.add(hostCommands); rootCommands.add(instanceCommands); diff --git a/packages/host/host.js b/packages/host/host.js index 679e926b..d5239f09 100755 --- a/packages/host/host.js +++ b/packages/host/host.js @@ -22,19 +22,13 @@ const winston = require("winston"); require("winston-daily-rotate-file"); // internal libraries -const libData = require("@clusterio/lib/data"); -const libLink = require("@clusterio/lib/link"); -const libPluginLoader = require("@clusterio/lib/plugin_loader"); -const libErrors = require("@clusterio/lib/errors"); -const libConfig = require("@clusterio/lib/config"); -const libSharedCommands = require("@clusterio/lib/shared_commands"); -const { ConsoleTransport, FilteredTransport, levels, logger } = require("@clusterio/lib/logging"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); +const lib = require("@clusterio/lib"); +const { ConsoleTransport, levels, logger } = lib; const Host = require("./src/Host"); -class HostConnector extends libLink.WebSocketClientConnector { +class HostConnector extends lib.WebSocketClientConnector { constructor(hostConfig, tlsCa, pluginInfos) { super( hostConfig.get("host.controller_url"), @@ -53,8 +47,8 @@ class HostConnector extends libLink.WebSocketClientConnector { } this.sendHandshake( - new libData.MessageRegisterHost( - new libData.RegisterHostData( + new lib.MessageRegisterHost( + new lib.RegisterHostData( this.hostConfig.get("host.controller_token"), "Clusterio Host", version, @@ -99,8 +93,8 @@ async function startHost() { default: "plugin-list.json", type: "string", }) - .command("plugin", "Manage available plugins", libSharedCommands.pluginCommand) - .command("config", "Manage Host config", libSharedCommands.configCommand) + .command("plugin", "Manage available plugins", lib.pluginCommand) + .command("config", "Manage Host config", lib.configCommand) .command("run", "Run host") .demandCommand(1, "You need to specify a command to run") .strict() @@ -116,11 +110,11 @@ async function startHost() { if (args.logLevel !== "none") { logger.add(new ConsoleTransport({ level: args.logLevel, - format: new libLoggingUtils.TerminalFormat(), + format: new lib.TerminalFormat(), filter: info => info.instance_id === undefined, })); } - libLoggingUtils.handleUnhandledErrors(logger); + lib.handleUnhandledErrors(logger); let command = args._[0]; if (command === "run") { @@ -139,18 +133,18 @@ async function startHost() { // If the command is plugin management we don't try to load plugins if (command === "plugin") { - await libSharedCommands.handlePluginCommand(args, pluginList, args.pluginList); + await lib.handlePluginCommand(args, pluginList, args.pluginList); return; } logger.info("Loading Plugin info"); - let pluginInfos = await libPluginLoader.loadPluginInfos(pluginList); - libLink.registerPluginMessages(pluginInfos); - libConfig.registerPluginConfigGroups(pluginInfos); - libConfig.finalizeConfigs(); + let pluginInfos = await lib.loadPluginInfos(pluginList); + lib.registerPluginMessages(pluginInfos); + lib.registerPluginConfigGroups(pluginInfos); + lib.finalizeConfigs(); logger.info(`Loading config from ${args.config}`); - let hostConfig = new libConfig.HostConfig("host"); + let hostConfig = new lib.HostConfig("host"); try { await hostConfig.load(JSON.parse(await fs.readFile(args.config))); @@ -160,12 +154,12 @@ async function startHost() { await hostConfig.init(); } else { - throw new libErrors.StartupError(`Failed to load ${args.config}: ${err.message}`); + throw new lib.StartupError(`Failed to load ${args.config}: ${err.message}`); } } if (command === "config") { - await libSharedCommands.handleConfigCommand(args, hostConfig, args.config); + await lib.handleConfigCommand(args, hostConfig, args.config); return; } @@ -242,7 +236,7 @@ async function startHost() { }); hostConnector.once("connect", () => { - logger.add(new libLoggingUtils.LinkTransport({ link: host })); + logger.add(new lib.LinkTransport({ link: host })); }); await hostConnector.connect(); @@ -259,10 +253,10 @@ I version of clusterio. Expect things to break. I ` ); startHost().catch(err => { - if (err instanceof libErrors.AuthenticationFailed) { + if (err instanceof lib.AuthenticationFailed) { logger.fatal(err.message); - } else if (err instanceof libErrors.StartupError) { + } else if (err instanceof lib.StartupError) { logger.fatal(` +----------------------------------+ | Unable to to start clusteriohost | @@ -270,7 +264,7 @@ I version of clusterio. Expect things to break. I ${err.stack}` ); - } else if (err instanceof libErrors.PluginError) { + } else if (err instanceof lib.PluginError) { logger.fatal(` ${err.pluginName} plugin threw an unexpected error during startup, please report it to the plugin author. diff --git a/packages/host/src/Host.js b/packages/host/src/Host.js index b616820e..c92ddc0b 100644 --- a/packages/host/src/Host.js +++ b/packages/host/src/Host.js @@ -1,7 +1,6 @@ "use strict"; const fs = require("fs-extra"); const path = require("path"); -const yargs = require("yargs"); const events = require("events"); const pidusage = require("pidusage"); const setBlocking = require("set-blocking"); @@ -10,15 +9,8 @@ const stream = require("stream"); const util = require("util"); // internal libraries -const libData = require("@clusterio/lib/data"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libLink = require("@clusterio/lib/link"); -const libPlugin = require("@clusterio/lib/plugin"); -const libErrors = require("@clusterio/lib/errors"); -const libPrometheus = require("@clusterio/lib/prometheus"); -const libConfig = require("@clusterio/lib/config"); -const { logger } = require("@clusterio/lib/logging"); -const libHelpers = require("@clusterio/lib/helpers"); +const lib = require("@clusterio/lib"); +const { logger } = lib; const Instance = require("./Instance"); const InstanceConnection = require("./InstanceConnection"); @@ -28,9 +20,9 @@ const finished = util.promisify(stream.finished); function checkRequestSaveName(name) { try { - libFileOps.checkFilename(name); + lib.checkFilename(name); } catch (err) { - throw new libErrors.RequestError(`Save name ${err.message}`); + throw new lib.RequestError(`Save name ${err.message}`); } } @@ -50,7 +42,7 @@ async function discoverInstances(instancesDir) { let instanceInfos = new Map(); for (let entry of await fs.readdir(instancesDir, { withFileTypes: true })) { if (entry.isDirectory()) { - let instanceConfig = new libConfig.InstanceConfig("host"); + let instanceConfig = new lib.InstanceConfig("host"); let configPath = path.join(instancesDir, entry.name, "instance.json"); try { @@ -82,14 +74,14 @@ async function discoverInstances(instancesDir) { } const instanceStartingMessages = new Set([ - libData.InstanceStartRequest.name, - libData.InstanceLoadScenarioRequest.name, - libData.InstanceCreateSaveRequest.name, - libData.InstanceExportDataRequest.name, + lib.InstanceStartRequest.name, + lib.InstanceLoadScenarioRequest.name, + lib.InstanceCreateSaveRequest.name, + lib.InstanceExportDataRequest.name, ]); class HostRouter { - /** @type {module:lib/host/src/Host} */ + /** @type {module:host/src/Host} */ host; constructor(host) { @@ -99,9 +91,9 @@ class HostRouter { /** * Forward a message to the next hop towards its destination. * - * @param {module:lib/link.Link} origin - + * @param {module:lib.Link} origin - * Link the message originated from. - * @param {module:lib/data.Message} message - Message to process. + * @param {module:lib.Message} message - Message to process. * @param {boolean} hasFallback - is fallback available * @returns {boolean} true if the message was handled, false if fallback * is requested @@ -110,17 +102,17 @@ class HostRouter { let dst = message.dst; let nextHop; let msg; - if (dst.type === libData.Address.broadcast) { + if (dst.type === lib.Address.broadcast) { this.broadcastMessage(origin, message); return true; } else if ( - dst.type === libData.Address.controller - || dst.type === libData.Address.control - || dst.type === libData.Address.host && dst.id !== this.host.config.get("host.id") - || dst.type === libData.Address.instance && !this.host.instanceInfos.has(dst.id) + dst.type === lib.Address.controller + || dst.type === lib.Address.control + || dst.type === lib.Address.host && dst.id !== this.host.config.get("host.id") + || dst.type === lib.Address.instance && !this.host.instanceInfos.has(dst.id) ) { nextHop = this.host; - } else if (dst.type === libData.Address.instance && this.host.instanceInfos.has(dst.id)) { + } else if (dst.type === lib.Address.instance && this.host.instanceInfos.has(dst.id)) { nextHop = this.host.instanceConnections.get(dst.id); } @@ -130,17 +122,17 @@ class HostRouter { } if (message.type === "request") { - if (dst.type === libData.Address.instance && instanceStartingMessages.has(message.name)) { + if (dst.type === lib.Address.instance && instanceStartingMessages.has(message.name)) { this.wakeInstance(origin, message, nextHop); return true; } else if (!nextHop) { - if (dst.type === libData.Address.instance) { + if (dst.type === lib.Address.instance) { if (hasFallback) { return false; } origin.connector.sendResponseError( - new libData.ResponseError("Instance is not running."), message.src + new lib.ResponseError("Instance is not running."), message.src ); } return true; @@ -163,7 +155,7 @@ class HostRouter { let dst = message.dst; if (message.type !== "event") { this.warnUnrouted(message, `Unexpected broadcast of ${message.type}`); - } else if (dst.id === libData.Address.host || dst.id === libData.Address.instance) { + } else if (dst.id === lib.Address.host || dst.id === lib.Address.instance) { for (let instanceConnection of this.host.instanceConnections.values()) { if (instanceConnection !== origin) { instanceConnection.connector.send(message); @@ -172,7 +164,7 @@ class HostRouter { if (this.host !== origin) { this.host.connector.send(message); } - } else if (dst.id === libData.Address.control) { + } else if (dst.id === lib.Address.control) { if (this.host !== origin) { this.host.connector.send(message); } else { @@ -187,13 +179,13 @@ class HostRouter { let dst = message.dst; if (nextHop) { origin.connector.sendResponseError( - new libData.ResponseError("Instance is already running."), message.src + new lib.ResponseError("Instance is already running."), message.src ); return; } if (this.host._shuttingDown) { origin.connector.sendResponseError( - new libData.ResponseError("Host is shutting down."), message.src + new lib.ResponseError("Host is shutting down."), message.src ); return; } @@ -203,7 +195,7 @@ class HostRouter { }).catch(err => { logger.error(`Error starting instance:\n${err.stack}`, this.host.instanceLogMeta(dst.id)); origin.connector.sendResponseError( - new libData.ResponseError(err.message, err.code, err.stack), message.src + new lib.ResponseError(err.message, err.code, err.stack), message.src ); }); } @@ -218,7 +210,7 @@ class HostRouter { } catch (err) { if (message.type === "request") { origin.connector.sendResponseError( - new libData.ResponseError(err.message, err.code, err.stack), message.src + new lib.ResponseError(err.message, err.code, err.stack), message.src ); } logger.warn(`Failed to deliver ${message.name || "message"} (${message.type}): ${err.message}`); @@ -238,7 +230,7 @@ class HostRouter { * Connects to the controller over the WebSocket and manages intsances. * @alias module:host/src/Host */ -class Host extends libLink.Link { +class Host extends lib.Link { constructor(connector, hostConfig, tlsCa, pluginInfos) { super(connector); @@ -275,7 +267,7 @@ class Host extends libLink.Link { } this.updateInstances().catch((err) => { - if (err instanceof libErrors.SessionLost) { + if (err instanceof lib.SessionLost) { return undefined; } @@ -304,41 +296,41 @@ class Host extends libLink.Link { for (let event of ["connect", "drop", "resume", "close"]) { this.connector.on(event, () => { - let message = new libData.ControllerConnectionEvent(event); + let message = new lib.ControllerConnectionEvent(event); for (let instanceConnection of this.instanceConnections.values()) { instanceConnection.send(message); } }); } - this.handle(libData.SyncUserListsEvent, this.handleSyncUserListsEvent.bind(this)); - this.snoopEvent(libData.InstanceAdminlistUpdateEvent, this.handleAdminlistUpdateEvent.bind(this)); - this.snoopEvent(libData.InstanceBanlistUpdateEvent, this.handleBanlistUpdateEvent.bind(this)); - this.snoopEvent(libData.InstanceWhitelistUpdateEvent, this.handleWhitelistUpdateEvent.bind(this)); - this.handle(libData.InstanceAssignInternalRequest, this.handleInstanceAssignInternalRequest.bind(this)); - this.handle(libData.InstanceUnassignInternalRequest, this.handleInstanceUnassignInternalRequest.bind(this)); - this.handle(libData.HostMetricsRequest, this.handleHostMetricsRequest.bind(this)); - this.fallbackRequest(libData.InstanceListSavesRequest, this.fallbackInstanceListSavesRequest.bind(this)); - this.handle(libData.InstanceRenameSaveRequest, this.handleInstanceRenameSaveRequest.bind(this)); - this.handle(libData.InstanceCopySaveRequest, this.handleInstanceCopySaveRequest.bind(this)); - this.handle(libData.InstanceTransferSaveRequest, this.handleInstanceTransferSaveRequest.bind(this)); - this.handle(libData.InstanceDeleteSaveRequest, this.handleInstanceDeleteSaveRequest.bind(this)); - this.handle(libData.InstancePullSaveRequest, this.handleInstancePullSaveRequest.bind(this)); - this.handle(libData.InstancePushSaveRequest, this.handleInstancePushSaveRequest.bind(this)); - this.handle(libData.InstanceDeleteInternalRequest, this.handleInstanceDeleteInternalRequest.bind(this)); + this.handle(lib.SyncUserListsEvent, this.handleSyncUserListsEvent.bind(this)); + this.snoopEvent(lib.InstanceAdminlistUpdateEvent, this.handleAdminlistUpdateEvent.bind(this)); + this.snoopEvent(lib.InstanceBanlistUpdateEvent, this.handleBanlistUpdateEvent.bind(this)); + this.snoopEvent(lib.InstanceWhitelistUpdateEvent, this.handleWhitelistUpdateEvent.bind(this)); + this.handle(lib.InstanceAssignInternalRequest, this.handleInstanceAssignInternalRequest.bind(this)); + this.handle(lib.InstanceUnassignInternalRequest, this.handleInstanceUnassignInternalRequest.bind(this)); + this.handle(lib.HostMetricsRequest, this.handleHostMetricsRequest.bind(this)); + this.fallbackRequest(lib.InstanceListSavesRequest, this.fallbackInstanceListSavesRequest.bind(this)); + this.handle(lib.InstanceRenameSaveRequest, this.handleInstanceRenameSaveRequest.bind(this)); + this.handle(lib.InstanceCopySaveRequest, this.handleInstanceCopySaveRequest.bind(this)); + this.handle(lib.InstanceTransferSaveRequest, this.handleInstanceTransferSaveRequest.bind(this)); + this.handle(lib.InstanceDeleteSaveRequest, this.handleInstanceDeleteSaveRequest.bind(this)); + this.handle(lib.InstancePullSaveRequest, this.handleInstancePullSaveRequest.bind(this)); + this.handle(lib.InstancePushSaveRequest, this.handleInstancePushSaveRequest.bind(this)); + this.handle(lib.InstanceDeleteInternalRequest, this.handleInstanceDeleteInternalRequest.bind(this)); } async _createNewInstanceDir(name) { - name = libFileOps.cleanFilename(name); + name = lib.cleanFilename(name); try { - libFileOps.checkFilename(name); + lib.checkFilename(name); } catch (err) { throw new Error(`Instance folder was unepectedly invalid: name ${err.message}`); } let instancesDir = this.config.get("host.instances_directory"); for (let i = 0; i < 10; i++) { // Limit attempts in case this is somehow an infinite loop - let candidateDir = path.join(instancesDir, await libFileOps.findUnusedName(instancesDir, name)); + let candidateDir = path.join(instancesDir, await lib.findUnusedName(instancesDir, name)); try { await fs.mkdir(candidateDir); } catch (err) { @@ -377,8 +369,8 @@ class Host extends libLink.Link { } }; - updateList(this.adminlist, request.adminlist, libData.InstanceAdminlistUpdateEvent); - updateList(this.whitelist, request.whitelist, libData.InstanceWhitelistUpdateEvent); + updateList(this.adminlist, request.adminlist, lib.InstanceAdminlistUpdateEvent); + updateList(this.whitelist, request.whitelist, lib.InstanceWhitelistUpdateEvent); let addedOrChanged = new Map(request.banlist); let removed = new Set(this.banlist.keys()); @@ -391,12 +383,12 @@ class Host extends libLink.Link { for (let [name, reason] of addedOrChanged) { this.banlist.set(name, reason); - this.broadcastEventToInstance(new libData.InstanceBanlistUpdateEvent(name, true, reason)); + this.broadcastEventToInstance(new lib.InstanceBanlistUpdateEvent(name, true, reason)); } for (let name of removed) { this.banlist.delete(name); - this.broadcastEventToInstance(new libData.InstanceBanlistUpdateEvent(name, false, "")); + this.broadcastEventToInstance(new lib.InstanceBanlistUpdateEvent(name, false, "")); } } @@ -440,7 +432,7 @@ class Host extends libLink.Link { instanceInfo.config.update(config, true, "controller"); } else { - let instanceConfig = new libConfig.InstanceConfig("host"); + let instanceConfig = new lib.InstanceConfig("host"); await instanceConfig.load(config, "controller"); let instanceDir = await this._createNewInstanceDir(instanceConfig.get("instance.name")); @@ -464,7 +456,7 @@ class Host extends libLink.Link { // request for all the instances it knows should be on this host. let instanceConnection = this.instanceConnections.get(instanceId); this.send( - new libData.InstanceStatusChangedEvent( + new lib.InstanceStatusChangedEvent( instanceId, instanceConnection ? instanceConnection.status : "stopped", null ) ); @@ -474,7 +466,7 @@ class Host extends libLink.Link { _warning: "Changes to this file will be overwritten by the controller's copy.", ...instanceInfo.config.serialize(), }; - await libFileOps.safeOutputFile( + await lib.safeOutputFile( path.join(instanceInfo.path, "instance.json"), JSON.stringify(warnedOutput, null, 4) ); @@ -486,7 +478,7 @@ class Host extends libLink.Link { if (instanceInfo) { let instanceConnection = this.instanceConnections.get(instanceId); if (instanceConnection && ["starting", "running"].includes(instanceConnection.status)) { - await instanceConnection.send(new libData.InstanceStopRequest()); + await instanceConnection.send(new lib.InstanceStopRequest()); } this.instanceInfos.delete(instanceId); @@ -505,7 +497,7 @@ class Host extends libLink.Link { getRequestInstanceInfo(instanceId) { let instanceInfo = this.instanceInfos.get(instanceId); if (!instanceInfo) { - throw new libErrors.RequestError(`Instance with ID ${instanceId} does not exist`); + throw new lib.RequestError(`Instance with ID ${instanceId} does not exist`); } return instanceInfo; } @@ -519,12 +511,12 @@ class Host extends libLink.Link { async _connectInstance(instanceId) { let instanceInfo = this.getRequestInstanceInfo(instanceId); if (this.instanceConnections.has(instanceId)) { - throw new libErrors.RequestError(`Instance with ID ${instanceId} is running`); + throw new lib.RequestError(`Instance with ID ${instanceId} is running`); } - let hostAddress = new libData.Address(libData.Address.host, this.id); - let instanceAddress = new libData.Address(libData.Address.instance, instanceId); - let [connectionClient, connectionServer] = libLink.VirtualConnector.makePair(instanceAddress, hostAddress); + let hostAddress = new lib.Address(lib.Address.host, this.id); + let instanceAddress = new lib.Address(lib.Address.instance, instanceId); + let [connectionClient, connectionServer] = lib.VirtualConnector.makePair(instanceAddress, hostAddress); let instanceConnection = new InstanceConnection(connectionServer, this, instanceId); let instance = new Instance( this, connectionClient, instanceInfo.path, this.config.get("host.factorio_directory"), instanceInfo.config @@ -539,7 +531,7 @@ class Host extends libLink.Link { async handleHostMetricsRequest() { let requests = []; for (let instanceConnection of this.instanceConnections.values()) { - requests.push(instanceConnection.send(new libData.InstanceMetricsRequest())); + requests.push(instanceConnection.send(new lib.InstanceMetricsRequest())); } let results = []; @@ -547,15 +539,15 @@ class Host extends libLink.Link { results.push(...response.results); } - for await (let result of libPrometheus.defaultRegistry.collect()) { + for await (let result of lib.defaultRegistry.collect()) { if (result.metric.name.startsWith("process_")) { - results.push(libPrometheus.serializeResult(result, { + results.push(lib.serializeResult(result, { addLabels: { "host_id": String(this.config.get("host.id")) }, metricName: result.metric.name.replace("process_", "clusterio_host_"), })); } else { - results.push(libPrometheus.serializeResult(result)); + results.push(lib.serializeResult(result)); } } @@ -580,7 +572,7 @@ class Host extends libLink.Link { ); } catch (err) { if (err.code === "ENOENT") { - throw new libErrors.RequestError(`${oldName} does not exist`); + throw new lib.RequestError(`${oldName} does not exist`); } throw err; } @@ -600,7 +592,7 @@ class Host extends libLink.Link { ); } catch (err) { if (err.code === "ENOENT") { - throw new libErrors.RequestError(`${source} does not exist`); + throw new lib.RequestError(`${source} does not exist`); } throw err; } @@ -616,7 +608,7 @@ class Host extends libLink.Link { // For consistency with remote transfer initiated through pullSave the // target is renamed if it already exists. - targetName = await libFileOps.findUnusedName( + targetName = await lib.findUnusedName( path.join(targetInstanceInfo.path, "saves"), targetName, ".zip" ); @@ -636,7 +628,7 @@ class Host extends libLink.Link { } } catch (err) { if (err.code === "ENOENT") { - throw new libErrors.RequestError(`${sourceName} does not exist`); + throw new lib.RequestError(`${sourceName} does not exist`); } throw err; } @@ -650,12 +642,12 @@ class Host extends libLink.Link { let instanceConnection = this.instanceConnections.get(instanceId); let saveList; if (instanceConnection) { - saveList = await instanceConnection.send(new libData.InstanceListSavesRequest()); + saveList = await instanceConnection.send(new lib.InstanceListSavesRequest()); } else { saveList = await Instance.listSaves(savesDir, null); } - this.send(new libData.InstanceSaveListUpdateEvent(instanceId, saveList)); + this.send(new lib.InstanceSaveListUpdateEvent(instanceId, saveList)); } async handleInstanceDeleteSaveRequest(request) { @@ -667,7 +659,7 @@ class Host extends libLink.Link { await fs.unlink(path.join(instanceInfo.path, "saves", name)); } catch (err) { if (err.code === "ENOENT") { - throw new libErrors.RequestError(`${name} does not exist`); + throw new lib.RequestError(`${name} does not exist`); } throw err; } @@ -688,8 +680,8 @@ class Host extends libLink.Link { }); if (response.statusCode !== 200) { - let content = await libHelpers.readStream(response); - throw new libErrors.RequestError(`Stream returned ${response.statusCode}: ${content.toString()}`); + let content = await lib.readStream(response); + throw new lib.RequestError(`Stream returned ${response.statusCode}: ${content.toString()}`); } let savesDir = path.join(instanceInfo.path, "saves"); @@ -702,7 +694,7 @@ class Host extends libLink.Link { break; } catch (err) { if (err.code === "EEXIST") { - tempFilename = await libFileOps.findUnusedName(savesDir, tempFilename, ".tmp.zip"); + tempFilename = await lib.findUnusedName(savesDir, tempFilename, ".tmp.zip"); } else { throw err; } @@ -711,7 +703,7 @@ class Host extends libLink.Link { response.pipe(writeStream); await finished(writeStream); - name = await libFileOps.findUnusedName(savesDir, name, ".zip"); + name = await lib.findUnusedName(savesDir, name, ".zip"); await fs.rename(path.join(savesDir, tempFilename), path.join(savesDir, name)); await this.sendSaveListUpdate(instanceId, savesDir); @@ -729,7 +721,7 @@ class Host extends libLink.Link { content = await fs.readFile(path.join(instanceInfo.path, "saves", name)); } catch (err) { if (err.code === "ENOENT") { - throw new libErrors.RequestError(`${name} does not exist`); + throw new lib.RequestError(`${name} does not exist`); } throw err; } @@ -747,18 +739,18 @@ class Host extends libLink.Link { async stopInstance(instanceId) { let instanceConnection = this.instanceConnections.get(instanceId); - await instanceConnection.send(new libData.InstanceStopRequest()); + await instanceConnection.send(new lib.InstanceStopRequest()); } async handleInstanceDeleteInternalRequest(request) { let instanceId = request.instanceId; if (this.instanceConnections.has(instanceId)) { - throw new libErrors.RequestError(`Instance with ID ${instanceId} is running`); + throw new lib.RequestError(`Instance with ID ${instanceId} is running`); } let instanceInfo = this.discoveredInstanceInfos.get(instanceId); if (!instanceInfo) { - throw new libErrors.RequestError(`Instance with ID ${instanceId} does not exist`); + throw new lib.RequestError(`Instance with ID ${instanceId} does not exist`); } this.discoveredInstanceInfos.delete(instanceId); @@ -777,12 +769,12 @@ class Host extends libLink.Link { let list = []; for (let [instanceId, instanceInfo] of this.discoveredInstanceInfos) { let instanceConnection = this.instanceConnections.get(instanceId); - list.push(new libData.RawInstanceInfo( + list.push(new lib.RawInstanceInfo( instanceInfo.config.serialize("controller"), instanceConnection ? instanceConnection.status : "stopped", )); } - await this.send(new libData.InstancesUpdateRequest(list)); + await this.send(new lib.InstancesUpdateRequest(list)); // Handle configured auto startup instances if (this._startup) { @@ -792,7 +784,7 @@ class Host extends libLink.Link { if (instanceInfo.config.get("instance.auto_start")) { try { let instanceConnection = await this._connectInstance(instanceId); - await instanceConnection.send(new libData.InstanceStartRequest(null)); + await instanceConnection.send(new lib.InstanceStartRequest(null)); } catch (err) { logger.error( `Error during auto startup for ${instanceInfo.config.get("instance.name")}:\n${err.stack}`, @@ -806,7 +798,7 @@ class Host extends libLink.Link { async prepareDisconnect() { for (let instanceConnection of this.instanceConnections.values()) { - await instanceConnection.send(new libData.PrepareControllerDisconnectRequest()); + await instanceConnection.send(new lib.PrepareControllerDisconnectRequest()); } this._disconnecting = true; return await super.prepareDisconnect(); @@ -832,7 +824,7 @@ class Host extends libLink.Link { try { await this.connector.disconnect(); } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { logger.error(`Unexpected error preparing disconnect:\n${err.stack}`); } } diff --git a/packages/host/src/Instance.js b/packages/host/src/Instance.js index d4e2b8aa..f5458808 100644 --- a/packages/host/src/Instance.js +++ b/packages/host/src/Instance.js @@ -6,47 +6,38 @@ const phin = require("phin"); const util = require("util"); // internal libraries -const libData = require("@clusterio/lib/data"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libFactorio = require("@clusterio/lib/factorio"); -const libLink = require("@clusterio/lib/link"); -const PlayerStats = require("@clusterio/lib/PlayerStats"); -const libPlugin = require("@clusterio/lib/plugin"); -const libPluginLoader = require("@clusterio/lib/plugin_loader"); -const libErrors = require("@clusterio/lib/errors"); -const libPrometheus = require("@clusterio/lib/prometheus"); -const libLuaTools = require("@clusterio/lib/lua_tools"); -const libLogging = require("@clusterio/lib/logging"); +const lib = require("@clusterio/lib"); +const { PlayerStats } = lib; -const instanceRconCommandDuration = new libPrometheus.Histogram( +const instanceRconCommandDuration = new lib.Histogram( "clusterio_instance_rcon_command_duration_seconds", "Histogram of the RCON command duration from request to response.", { labels: ["instance_id"] } ); -const instanceRconCommandSize = new libPrometheus.Histogram( +const instanceRconCommandSize = new lib.Histogram( "clusterio_instance_rcon_command_size_bytes", "Histogram of the RCON command sizes that are sent.", { labels: ["instance_id", "plugin"], - buckets: libPrometheus.Histogram.exponential(16, 2, 12), + buckets: lib.Histogram.exponential(16, 2, 12), } ); -const instanceFactorioCpuTime = new libPrometheus.Gauge( +const instanceFactorioCpuTime = new lib.Gauge( "clusterio_instance_factorio_cpu_time_total", "Factorio CPU time spent in seconds.", { labels: ["instance_id"] } ); -const instanceFactorioMemoryUsage = new libPrometheus.Gauge( +const instanceFactorioMemoryUsage = new lib.Gauge( "clusterio_instance_factorio_resident_memory_bytes", "Factorio resident memory size in bytes.", { labels: ["instance_id"] } ); -const instanceFactorioAutosaveSize = new libPrometheus.Gauge( +const instanceFactorioAutosaveSize = new lib.Gauge( "clusterio_instance_factorio_autosave_bytes", "Size of Factorio server autosave in bytes.", { labels: ["instance_id"] } @@ -100,7 +91,7 @@ const serverSettingsActions = { * Keeps track of the runtime parameters of an instance * @alias module:host/src/Instance */ -class Instance extends libLink.Link { +class Instance extends lib.Link { constructor(host, connector, dir, factorioDir, instanceConfig) { super(connector); this._host = host; @@ -115,13 +106,13 @@ class Instance extends libLink.Link { */ this.id = this.config.get("instance.id"); - this.logger = libLogging.logger.child({ + this.logger = lib.logger.child({ instance_id: this.id, instance_name: this.name, }); this._configFieldChanged = (group, field, prev) => { - let hook = () => libPlugin.invokeHook(this.plugins, "onInstanceConfigFieldChanged", group, field, prev); + let hook = () => lib.invokeHook(this.plugins, "onInstanceConfigFieldChanged", group, field, prev); if (group.name === "factorio" && field === "settings") { this.updateFactorioSettings(group.get(field), prev).finally(hook); @@ -152,18 +143,18 @@ class Instance extends libLink.Link { // Valid statuses are stopped, starting, running, stopping, creating_save and exporting_data. this._status = "stopped"; this._loadedSave = null; - this.server = new libFactorio.FactorioServer( + this.server = new lib.FactorioServer( factorioDir, this._dir, serverOptions ); this.server.on("output", (parsed, line) => { this.logger.log("server", { message: line, instance_id: this.id, parsed }); - libPlugin.invokeHook(this.plugins, "onOutput", parsed, line); + lib.invokeHook(this.plugins, "onOutput", parsed, line); }); this.server.on("error", err => { - if (err instanceof libErrors.EnvironmentError) { + if (err instanceof lib.EnvironmentError) { this.logger.error(err.message); } else { this.logger.error(`${this.name}:\n${err.stack}`); @@ -192,13 +183,13 @@ class Instance extends libLink.Link { /** * Mod pack currently running on this instance - * @type {module:lib/data.ModPack} + * @type {module:lib.ModPack} */ this.activeModPack = undefined; /** * Per player statistics recorded by this instance. - * @type {Map} + * @type {Map} */ this.playerStats = new Map(); @@ -211,23 +202,23 @@ class Instance extends libLink.Link { this._hadPlayersOnline = false; this._playerAutosaveSlot = 1; - this.handle(libData.InstanceExtractPlayersRequest, this.handleInstanceExtractPlayersRequest.bind(this)); - this.handle(libData.InstanceAdminlistUpdateEvent, this.handleInstanceAdminlistUpdateEvent.bind(this)); - this.handle(libData.InstanceBanlistUpdateEvent, this.handleInstanceBanlistUpdateEvent.bind(this)); - this.handle(libData.InstanceWhitelistUpdateEvent, this.handleInstanceWhitelistUpdateEvent.bind(this)); - this.handle(libData.ControllerConnectionEvent, this.handleControllerConnectionEvent.bind(this)); + this.handle(lib.InstanceExtractPlayersRequest, this.handleInstanceExtractPlayersRequest.bind(this)); + this.handle(lib.InstanceAdminlistUpdateEvent, this.handleInstanceAdminlistUpdateEvent.bind(this)); + this.handle(lib.InstanceBanlistUpdateEvent, this.handleInstanceBanlistUpdateEvent.bind(this)); + this.handle(lib.InstanceWhitelistUpdateEvent, this.handleInstanceWhitelistUpdateEvent.bind(this)); + this.handle(lib.ControllerConnectionEvent, this.handleControllerConnectionEvent.bind(this)); this.handle( - libData.PrepareControllerDisconnectRequest, this.handlePrepareControllerDisconnectRequest.bind(this) + lib.PrepareControllerDisconnectRequest, this.handlePrepareControllerDisconnectRequest.bind(this) ); - this.handle(libData.InstanceMetricsRequest, this.handleInstanceMetricsRequest.bind(this)); - this.handle(libData.InstanceStartRequest, this.handleInstanceStartRequest.bind(this)); - this.handle(libData.InstanceLoadScenarioRequest, this.handleInstanceLoadScenarioRequest.bind(this)); - this.handle(libData.InstanceListSavesRequest, this.handleInstanceListSavesRequest.bind(this)); - this.handle(libData.InstanceCreateSaveRequest, this.handleInstanceCreateSaveRequest.bind(this)); - this.handle(libData.InstanceExportDataRequest, this.handleInstanceExportDataRequest.bind(this)); - this.handle(libData.InstanceStopRequest, this.handleInstanceStopRequest.bind(this)); - this.handle(libData.InstanceKillRequest, this.handleInstanceKillRequest.bind(this)); - this.handle(libData.InstanceSendRconRequest, this.handleInstanceSendRconRequest.bind(this)); + this.handle(lib.InstanceMetricsRequest, this.handleInstanceMetricsRequest.bind(this)); + this.handle(lib.InstanceStartRequest, this.handleInstanceStartRequest.bind(this)); + this.handle(lib.InstanceLoadScenarioRequest, this.handleInstanceLoadScenarioRequest.bind(this)); + this.handle(lib.InstanceListSavesRequest, this.handleInstanceListSavesRequest.bind(this)); + this.handle(lib.InstanceCreateSaveRequest, this.handleInstanceCreateSaveRequest.bind(this)); + this.handle(lib.InstanceExportDataRequest, this.handleInstanceExportDataRequest.bind(this)); + this.handle(lib.InstanceStopRequest, this.handleInstanceStopRequest.bind(this)); + this.handle(lib.InstanceKillRequest, this.handleInstanceKillRequest.bind(this)); + this.handle(lib.InstanceSendRconRequest, this.handleInstanceSendRconRequest.bind(this)); } _watchPlayerJoinsByChat() { @@ -303,8 +294,8 @@ class Instance extends libLink.Link { name, stats, }; - this.sendTo("controller", new libData.InstancePlayerUpdateEvent("join", name, undefined, stats)); - libPlugin.invokeHook(this.plugins, "onPlayerEvent", event); + this.sendTo("controller", new lib.InstancePlayerUpdateEvent("join", name, undefined, stats)); + lib.invokeHook(this.plugins, "onPlayerEvent", event); } _recordPlayerLeave(name, reason) { @@ -325,8 +316,8 @@ class Instance extends libLink.Link { reason, stats, }; - this.sendTo("controller", new libData.InstancePlayerUpdateEvent("leave", name, reason, stats)); - libPlugin.invokeHook(this.plugins, "onPlayerEvent", event); + this.sendTo("controller", new lib.InstancePlayerUpdateEvent("leave", name, reason, stats)); + lib.invokeHook(this.plugins, "onPlayerEvent", event); } async handleInstanceExtractPlayersRequest() { @@ -353,8 +344,8 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); name, stats: stats.toJSON(), }; - this.sendTo("controller", new libData.InstancePlayerUpdateEvent("import", name, undefined, stats)); - libPlugin.invokeHook(this.plugins, "onPlayerEvent", event); + this.sendTo("controller", new lib.InstancePlayerUpdateEvent("import", name, undefined, stats)); + lib.invokeHook(this.plugins, "onPlayerEvent", event); count += 1; } this.logger.info(`Extracted data for ${count} player(s)`); @@ -374,7 +365,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); static async listSaves(savesDir, loadedSave) { let defaultSave = null; if (loadedSave === null) { - defaultSave = await libFileOps.getNewestFile( + defaultSave = await lib.getNewestFile( savesDir, (name) => !name.endsWith(".tmp.zip") ); } @@ -391,7 +382,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); type = "special"; } - list.push(new libData.SaveDetails( + list.push(new lib.SaveDetails( type, name, stat.size, @@ -407,7 +398,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); async sendSaveListUpdate() { this.sendTo( "controller", - new libData.InstanceSaveListUpdateEvent( + new lib.InstanceSaveListUpdateEvent( this.id, await Instance.listSaves(this.path("saves"), this._loadedSave), ), @@ -440,7 +431,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); this._status = status; this.sendTo( "controller", - new libData.InstanceStatusChangedEvent( + new lib.InstanceStatusChangedEvent( this.id, status, this.server && this.server.gamePort || this.config.get("factorio.game_port") || null, @@ -467,9 +458,9 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); clearTimeout(this._playerCheckInterval); // Clear metrics this instance is exporting - for (let collector of libPrometheus.defaultRegistry.collectors) { + for (let collector of lib.defaultRegistry.collectors) { if ( - collector instanceof libPrometheus.ValueCollector + collector instanceof lib.ValueCollector && collector.metric.labels.includes("instance_id") ) { collector.removeAll({ instance_id: String(this.id) }); @@ -489,7 +480,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); async _loadPlugin(pluginInfo, host) { let pluginLoadStarted = Date.now(); - let InstancePluginClass = await libPluginLoader.loadInstancePluginClass(pluginInfo); + let InstancePluginClass = await lib.loadInstancePluginClass(pluginInfo); let instancePlugin = new InstancePluginClass(pluginInfo, this, host); this.plugins.set(pluginInfo.name, instancePlugin); await instancePlugin.init(); @@ -516,7 +507,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); players: [...this.playerStats], player_autosave_slot: this._playerAutosaveSlot, }, null, 4); - await libFileOps.safeOutputFile(this.path("instance-stats.json"), content); + await lib.safeOutputFile(this.path("instance-stats.json"), content); } async init(pluginInfos) { @@ -553,7 +544,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); for (let [name, plugin] of this.plugins) { plugins[name] = plugin.info.version; } - this.send(new libData.InstanceInitialisedEvent(plugins)); + this.send(new lib.InstanceInitialisedEvent(plugins)); } /** @@ -588,7 +579,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); */ async writeServerSettings() { let serverSettings = await this.resolveServerSettings(this.config.get("factorio.settings")); - await libFileOps.safeOutputFile( + await lib.safeOutputFile( this.server.writePath("server-settings.json"), JSON.stringify(serverSettings, null, 4) ); @@ -625,9 +616,9 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); const modPackId = this.config.get("factorio.mod_pack"); let modPack; if (modPackId === null) { - modPack = await this.sendTo("controller", new libData.ModPackGetDefaultRequest()); + modPack = await this.sendTo("controller", new lib.ModPackGetDefaultRequest()); } else { - modPack = await this.sendTo("controller", new libData.ModPackGetRequest(modPackId)); + modPack = await this.sendTo("controller", new lib.ModPackGetRequest(modPackId)); } this.activeModPack = modPack; @@ -691,7 +682,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); if (this.config.get("factorio.sync_adminlist")) { this.logger.verbose("Writing server-adminlist.json"); - libFileOps.safeOutputFile( + lib.safeOutputFile( this.server.writePath("server-adminlist.json"), JSON.stringify([...this._host.adminlist], null, 4) ); @@ -699,7 +690,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); if (this.config.get("factorio.sync_banlist")) { this.logger.verbose("Writing server-banlist.json"); - libFileOps.safeOutputFile( + lib.safeOutputFile( this.server.writePath("server-banlist.json"), JSON.stringify([...this._host.banlist].map( ([username, reason]) => ({ username, reason }) @@ -709,7 +700,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); if (this.config.get("factorio.sync_whitelist")) { this.logger.verbose("Writing server-whitelist.json"); - libFileOps.safeOutputFile( + lib.safeOutputFile( this.server.writePath("server-whitelist.json"), JSON.stringify([...this._host.whitelist], null, 4) ); @@ -731,7 +722,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); async prepareSave(saveName) { // Use latest save if no save was specified if (saveName === undefined) { - saveName = await libFileOps.getNewestFile( + saveName = await lib.getNewestFile( this.path("saves"), (name) => !name.endsWith(".tmp.zip") ); } @@ -832,7 +823,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); } } - await libFactorio.patch(this.path("saves", saveName), [...modules.values()]); + await lib.patch(this.path("saves", saveName), [...modules.values()]); return saveName; } @@ -860,7 +851,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); } await this.sendSaveListUpdate(); - await libPlugin.invokeHook(this.plugins, "onStart"); + await lib.invokeHook(this.plugins, "onStart"); this.notifyStatus("running"); } @@ -885,7 +876,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); await this.server.startScenario(scenario, seed, mapGenSettings, mapSettings); this._watchPlayerJoinsByChat(); - await libPlugin.invokeHook(this.plugins, "onStart"); + await lib.invokeHook(this.plugins, "onStart"); this.notifyStatus("running"); } @@ -894,7 +885,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); * Update instance information on the Factorio side */ async updateInstanceData() { - let name = libLuaTools.escapeString(this.name); + let name = lib.escapeString(this.name); await this.sendRcon(`/sc clusterio_private.update_instance(${this.id}, "${name}")`, true); } @@ -973,7 +964,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); // XXX this needs more thought to it if (this.server._state === "running") { - await libPlugin.invokeHook(this.plugins, "onStop"); + await lib.invokeHook(this.plugins, "onStop"); await this.server.stop(); await this.sendSaveListUpdate(); } @@ -987,20 +978,20 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); } async handleControllerConnectionEvent(event) { - await libPlugin.invokeHook(this.plugins, "onControllerConnectionEvent", event.event); + await lib.invokeHook(this.plugins, "onControllerConnectionEvent", event.event); } async handlePrepareControllerDisconnectRequest() { - await libPlugin.invokeHook(this.plugins, "onPrepareControllerDisconnect"); + await lib.invokeHook(this.plugins, "onPrepareControllerDisconnect"); } async handleInstanceMetricsRequest() { let results = []; if (!["stopped", "stopping"].includes(this._status)) { - let pluginResults = await libPlugin.invokeHook(this.plugins, "onMetrics"); + let pluginResults = await lib.invokeHook(this.plugins, "onMetrics"); for (let metricIterator of pluginResults) { for await (let metric of metricIterator) { - results.push(libPrometheus.serializeResult(metric)); + results.push(lib.serializeResult(metric)); } } } @@ -1012,7 +1003,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); instanceFactorioMemoryUsage.labels(String(this.id)).set(stats.memory); } - return new libData.InstanceMetricsRequest.Response(results); + return new lib.InstanceMetricsRequest.Response(results); } async handleInstanceStartRequest(request) { @@ -1037,7 +1028,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); async handleInstanceLoadScenarioRequest(request) { if (this.config.get("factorio.enable_save_patching")) { this.notifyExit(); - throw new libErrors.RequestError("Load scenario cannot be used with save patching enabled"); + throw new lib.RequestError("Load scenario cannot be used with save patching enabled"); } try { @@ -1091,7 +1082,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); this.logger.info("Exporting data ....."); await this.syncMods(); - let zip = await libFactorio.exportData(this.server); + let zip = await lib.exportData(this.server); let content = await zip.generateAsync({ type: "nodebuffer" }); let url = new URL(this._host.config.get("host.controller_url")); diff --git a/packages/host/src/InstanceConnection.js b/packages/host/src/InstanceConnection.js index 223863fa..d404c3bf 100644 --- a/packages/host/src/InstanceConnection.js +++ b/packages/host/src/InstanceConnection.js @@ -1,11 +1,8 @@ "use strict"; -const libData = require("@clusterio/lib/data"); -const libLink = require("@clusterio/lib/link"); -const libPlugin = require("@clusterio/lib/plugin"); -const libErrors = require("@clusterio/lib/errors"); +const lib = require("@clusterio/lib"); -class InstanceConnection extends libLink.Link { +class InstanceConnection extends lib.Link { constructor(connector, host, instanceId) { super(connector); this.host = host; @@ -14,8 +11,8 @@ class InstanceConnection extends libLink.Link { this.plugins = new Map(); this.status = "stopped"; - this.handle(libData.InstanceInitialisedEvent, this.handleInstanceInitialisedEvent.bind(this)); - this.snoopEvent(libData.InstanceStatusChangedEvent, this.snoopInstanceStatusChangedEvent.bind(this)); + this.handle(lib.InstanceInitialisedEvent, this.handleInstanceInitialisedEvent.bind(this)); + this.snoopEvent(lib.InstanceStatusChangedEvent, this.snoopInstanceStatusChangedEvent.bind(this)); } async broadcastEventToInstance(message, event) { diff --git a/packages/lib/ExponentialBackoff.js b/packages/lib/ExponentialBackoff.js index f8c30516..5af3033f 100644 --- a/packages/lib/ExponentialBackoff.js +++ b/packages/lib/ExponentialBackoff.js @@ -15,7 +15,7 @@ * `base` if more time than the value for `reset` has passed between two * invocations of delay. * - * @alias module:lib/ExponentialBackoff + * @alias module:lib.ExponentialBackoff */ class ExponentialBackoff { /** diff --git a/packages/lib/PlayerStats.js b/packages/lib/PlayerStats.js index c13fa1cb..1c7c873b 100644 --- a/packages/lib/PlayerStats.js +++ b/packages/lib/PlayerStats.js @@ -2,7 +2,7 @@ /** * Stastics collected about a player. - * @alias module:lib/PlayerStats + * @alias module:lib.PlayerStats */ class PlayerStats { /** diff --git a/packages/lib/RateLimiter.js b/packages/lib/RateLimiter.js index 9d19e770..7a82d0c1 100644 --- a/packages/lib/RateLimiter.js +++ b/packages/lib/RateLimiter.js @@ -19,7 +19,7 @@ * // and one more time 1 second later for 99 other activations that were * // exceeding the rate limit. * } - * @alias module:lib/RateLimiter + * @alias module:lib.RateLimiter */ class RateLimiter { /** diff --git a/packages/lib/browser.js b/packages/lib/browser.js index 20866a72..c5256437 100644 --- a/packages/lib/browser.js +++ b/packages/lib/browser.js @@ -1,13 +1,15 @@ -export { default as libConfig } from "./config"; -export { default as libData } from "./data"; -export { default as libErrors } from "./errors"; -export { default as libFactorio } from "./factorio/exchange_string"; -export { default as libHelpers } from "./helpers"; -export { default as libLink } from "./link"; -export { default as libLogging } from "./logging"; -export { default as libPlugin } from "./plugin"; -export { default as libSchema } from "./schema"; -export { default as libUsers } from "./users"; +export * from "./config"; +export * from "./data"; +export * from "./errors"; +export * from "./factorio/exchange_string"; +export * from "./helpers"; +export * from "./ini"; +export * from "./link"; +export * from "./logging"; +export * from "./plugin"; +export * from "./schema"; +export * from "./users"; export { default as ExponentialBackoff } from "./ExponentialBackoff"; +export { default as PlayerStats } from "./PlayerStats"; export { default as RateLimiter } from "./RateLimiter"; diff --git a/packages/lib/command.js b/packages/lib/command.js index 59eea880..972f6969 100644 --- a/packages/lib/command.js +++ b/packages/lib/command.js @@ -52,10 +52,10 @@ class Command { /** * A node in the command tree that can hold commands and sub trees * - * Container which can contain {@link module:lib/command.Command}s and other + * Container which can contain {@link module:lib.Command}s and other * CommandTrees. This is used by clusterioctl to hold the full tree of * available commands, you may extend this tree by using a control plugin, - * see {@link module:lib/plugin.BaseControlPlugin#addCommands} + * see {@link module:lib.BaseControlPlugin#addCommands} * * @static */ @@ -83,7 +83,7 @@ class CommandTree { /** * Add a command or command tree to this tree * - * @param {module:lib/command.Command|module:lib/command.CommandTree} command - + * @param {module:lib.Command|module:lib.CommandTree} command - * The command to add to this command tree. */ add(command) { @@ -104,7 +104,7 @@ class CommandTree { * * @param {string} name - * The name of the command or command tree to retrieve. - * @return {?module:lib/command.Command|module:lib/command.CommandTree} + * @return {?module:lib.Command|module:lib.CommandTree} * The command to add to this command tree. */ get(name) { @@ -141,7 +141,7 @@ class CommandTree { * Resolves a string with either an host name or an id into an integer with * the host ID. * - * @param {module:lib/link.Link} client - link to controller to query host on. + * @param {module:lib.Link} client - link to controller to query host on. * @param {string} hostName - string with name or id of host. * @returns {Promise} host ID. * @static @@ -173,7 +173,7 @@ async function resolveHost(client, hostName) { * Resolves a string with either an instance name or an id into an integer * with the instance ID. * - * @param {module:lib/link.Link} client - link to controller to query instance on. + * @param {module:lib.Link} client - link to controller to query instance on. * @param {string} instanceName - string with name or id of instance. * @returns {Promise} instance ID. * @static @@ -205,7 +205,7 @@ async function resolveInstance(client, instanceName) { * Resolevs a string with either a mod pack name or an id into an integer * with the mod pack ID. * - * @param {module:lib/link.Link} client - + * @param {module:lib.Link} client - * link to controller to query mod pack on. * @param {string} modPackName - string with name or id of mod pack. * @returns {Promise} mod pack ID. @@ -238,7 +238,7 @@ async function resolveModPack(client, modPackName) { * Resolves a string with either a role name or an id into an object * representing the role. * - * @param {module:lib/link.Link} client - link to controller to query role on. + * @param {module:lib.Link} client - link to controller to query role on. * @param {string} roleName - string with name or id of role. * @returns {Promise} Role info. * @static diff --git a/packages/lib/config/classes.js b/packages/lib/config/classes.js index ac1591b0..1855b584 100644 --- a/packages/lib/config/classes.js +++ b/packages/lib/config/classes.js @@ -14,7 +14,7 @@ const { basicType } = require("../helpers"); * does not permitt this access is done. * * @extends Error - * @memberof module:lib/config + * @memberof module:lib */ class InvalidAccess extends Error { }; @@ -25,7 +25,7 @@ class InvalidAccess extends Error { }; * field. * * @extends Error - * @memberof module:lib/config + * @memberof module:lib */ class InvalidValue extends Error { }; @@ -36,7 +36,7 @@ class InvalidValue extends Error { }; * attempted to be accessed. * * @extends Error - * @memberof module:lib/config + * @memberof module:lib */ class InvalidField extends Error { }; @@ -51,7 +51,7 @@ class InvalidField extends Error { }; * @param {string} separator - Separator to split string by. * @param {string} string - String to split * @returns {Array} string split on separator. - * @memberof module:lib/config + * @memberof module:lib * @private * @inner */ @@ -77,7 +77,7 @@ function splitOn(separator, string) { * * @extends events.EventEmitter * - * @memberof module:lib/config + * @memberof module:lib */ class Config extends events.EventEmitter { /** @@ -236,7 +236,7 @@ class Config extends events.EventEmitter { * Get the config group instance with the given name * * @param {string} name - Name of group to get. - * @returns {module:lib/config.ConfigGroup} config group. + * @returns {module:lib.ConfigGroup} config group. */ group(name) { if (!this._initialized) { @@ -287,7 +287,7 @@ class Config extends events.EventEmitter { * Adds the ConfigGroup to this config as a group that will get * initialized, loaded and serialized with this config class. * - * @param {module:lib/config.ConfigGroup} group - class to register. + * @param {module:lib.ConfigGroup} group - class to register. */ static registerGroup(group) { this._initSubclass(); @@ -317,7 +317,7 @@ class Config extends events.EventEmitter { * loading a config with invalid values will result in those being replaced * by the innitial value for those fields. * - * @memberof module:lib/config + * @memberof module:lib */ class ConfigGroup { /** @@ -326,7 +326,7 @@ class ConfigGroup { * After the creation of the new config group you have to call * either .init() or .load() on it in order to fully initialize it. * - * @param {module:lib/config.Config} config - + * @param {module:lib.Config} config - * Parent config for this group instance. */ constructor(config) { @@ -345,7 +345,7 @@ class ConfigGroup { * @param {object} def - definition for for the field to check. * @param {string} remote - location of remote access to check for. * @param {boolean} error - throw on failure to pass check. - * @throws {module:lib/config.InvalidAccess} + * @throws {module:lib.InvalidAccess} * if access is not granted and error is true. * @returns {boolean} true if access is granted * @private @@ -456,8 +456,8 @@ class ConfigGroup { * @param {string} name - Name of field to set. * @param {*} value - Value to set for field. * @param {string=} location - Location used for access control. - * @throws {module:lib/config.InvalidField} if field is not defined. - * @throws {module:lib/config.InvalidValue} if value is not allowed for the field. + * @throws {module:lib.InvalidField} if field is not defined. + * @throws {module:lib.InvalidValue} if value is not allowed for the field. */ set(name, value, location = this.config.location) { let def = this.constructor._definitions.get(name); @@ -524,8 +524,8 @@ class ConfigGroup { * @param {string} prop - Name of property to set on field. * @param {*} value - the value to set the property to. * @param {string=} location - Location used for access control. - * @throws {module:lib/config.InvalidField} if field is not defined. - * @throws {module:lib/config.InvalidValue} if field is not an object. + * @throws {module:lib.InvalidField} if field is not defined. + * @throws {module:lib.InvalidValue} if field is not an object. */ setProp(name, prop, value, location = this.config.location) { let def = this.constructor._definitions.get(name); @@ -829,8 +829,8 @@ class ConfigGroup { * plugins. This is currently only the enabled field. It is otherwise * identical to the ConfigGroup class. * - * @extends module:lib/config.ConfigGroup - * @memberof module:lib/config + * @extends module:lib.ConfigGroup + * @memberof module:lib */ class PluginConfigGroup extends ConfigGroup { static _initSubclass() { diff --git a/packages/lib/config/definitions.js b/packages/lib/config/definitions.js index 7eb683c5..a21bf40b 100644 --- a/packages/lib/config/definitions.js +++ b/packages/lib/config/definitions.js @@ -5,9 +5,9 @@ const classes = require("./classes"); /** - * Controller config group for {@link module:lib/config.ControllerConfig} - * @extends module:lib/config.ConfigGroup - * @memberof module:lib/config + * Controller config group for {@link module:lib.ControllerConfig} + * @extends module:lib.ConfigGroup + * @memberof module:lib */ class ControllerGroup extends classes.ConfigGroup { } ControllerGroup.defaultAccess = ["controller", "host", "control"]; @@ -140,17 +140,17 @@ ControllerGroup.finalize(); /** * Controller Config class - * @extends module:lib/config.Config - * @memberof module:lib/config + * @extends module:lib.Config + * @memberof module:lib */ class ControllerConfig extends classes.Config { } ControllerConfig.registerGroup(ControllerGroup); /** - * Host config group for {@link module:lib/config.HostConfig} - * @extends module:lib/config.ConfigGroup - * @memberof module:lib/config + * Host config group for {@link module:lib.HostConfig} + * @extends module:lib.ConfigGroup + * @memberof module:lib */ class HostGroup extends classes.ConfigGroup {} HostGroup.defaultAccess = ["controller", "host", "control"]; @@ -232,17 +232,17 @@ HostGroup.finalize(); /** * Host Config class - * @extends module:lib/config.Config - * @memberof module:lib/config + * @extends module:lib.Config + * @memberof module:lib */ class HostConfig extends classes.Config { } HostConfig.registerGroup(HostGroup); /** - * Instance config group for {@link module:lib/config.InstanceConfig} - * @extends module:lib/config.ConfigGroup - * @memberof module:lib/config + * Instance config group for {@link module:lib.InstanceConfig} + * @extends module:lib.ConfigGroup + * @memberof module:lib */ class InstanceGroup extends classes.ConfigGroup { } InstanceGroup.defaultAccess = ["controller", "host", "control"]; @@ -272,9 +272,9 @@ InstanceGroup.define({ InstanceGroup.finalize(); /** - * Factorio config group for {@link module:lib/config.InstanceConfig} - * @extends module:lib/config.ConfigGroup - * @memberof module:lib/config + * Factorio config group for {@link module:lib.InstanceConfig} + * @extends module:lib.ConfigGroup + * @memberof module:lib */ class FactorioGroup extends classes.ConfigGroup { } FactorioGroup.defaultAccess = ["controller", "host", "control"]; @@ -398,8 +398,8 @@ FactorioGroup.finalize(); /** * Instance config class - * @extends module:lib/config.Config - * @memberof module:lib/config + * @extends module:lib.Config + * @memberof module:lib */ class InstanceConfig extends classes.Config { } InstanceConfig.registerGroup(InstanceGroup); @@ -407,9 +407,9 @@ InstanceConfig.registerGroup(FactorioGroup); /** - * Control config group for {@link module:lib/config.ControlConfig} - * @extends module:lib/config.ConfigGroup - * @memberof module:lib/config + * Control config group for {@link module:lib.ControlConfig} + * @extends module:lib.ConfigGroup + * @memberof module:lib */ class ControlGroup extends classes.ConfigGroup {} ControlGroup.defaultAccess = ["control"]; @@ -443,8 +443,8 @@ ControlGroup.finalize(); /** * Control config class - * @extends module:lib/config.Config - * @memberof module:lib/config + * @extends module:lib.Config + * @memberof module:lib */ class ControlConfig extends classes.Config { } ControlConfig.registerGroup(ControlGroup); @@ -468,7 +468,7 @@ function validateGroup(pluginInfo, groupName) { * Registers the config groups for the provided plugin infos * * @param {Array} pluginInfos - Array of plugin info objects. - * @memberof module:lib/config + * @memberof module:lib */ function registerPluginConfigGroups(pluginInfos) { for (let pluginInfo of pluginInfos) { @@ -503,7 +503,7 @@ function registerPluginConfigGroups(pluginInfos) { /** * Lock configs from adding more groups and make them usable * - * @memberof module:lib/config + * @memberof module:lib */ function finalizeConfigs() { ControllerConfig.finalize(); diff --git a/packages/lib/data/ExportManifest.js b/packages/lib/data/ExportManifest.js index dcc226a2..9e52a725 100644 --- a/packages/lib/data/ExportManifest.js +++ b/packages/lib/data/ExportManifest.js @@ -5,7 +5,7 @@ * * Tracks files stored on disk for data that extracted from Factorio using a * given mod pack. - * @alias module:lib/data.ExportManifest + * @alias module:lib.ExportManifest */ class ExportManifest { diff --git a/packages/lib/data/ModInfo.js b/packages/lib/data/ModInfo.js index 83cc175f..8ad802d1 100644 --- a/packages/lib/data/ModInfo.js +++ b/packages/lib/data/ModInfo.js @@ -15,7 +15,7 @@ const { integerModVersion, integerFactorioVersion, modVersionRegExp } = require( * * See https://wiki.factorio.com/Tutorial:Mod_structure#info.json for * details of the invidiual fields sourced from info.json. - * @alias module:lib/data.ModInfo + * @alias module:lib.ModInfo */ class ModInfo { /** diff --git a/packages/lib/data/ModPack.js b/packages/lib/data/ModPack.js index f574b524..de4335f8 100644 --- a/packages/lib/data/ModPack.js +++ b/packages/lib/data/ModPack.js @@ -9,7 +9,7 @@ const { integerFactorioVersion } = require("./version"); /** * A setting for a mod. - * @typedef {object} module:lib/data.ModPack~ModSetting + * @typedef {object} module:lib.ModPack~ModSetting * @property {boolean|number|string} value - Value of the given mod setting. */ const ModSettingJsonSchema = { @@ -28,7 +28,7 @@ const ModSettingsJsonSchema = { /** * A mod in a mod pack - * @typedef {object} module:lib/data.ModPack~ModRecord + * @typedef {object} module:lib.ModPack~ModRecord * @property {string} name - name of the mod. * @property {boolean} enabled - if mod is to be loaded. * @property {string} version - version of the mod. @@ -49,7 +49,7 @@ const ModRecordJsonSchema = { * Factorio Mod Pack * * Tracks mods and settings for a collection of Factorio mods. - * @alias module:lib/data.ModPack + * @alias module:lib.ModPack */ class ModPack { /** @@ -86,13 +86,13 @@ class ModPack { /** * Mods included in this mod pack - * @type {Map} + * @type {Map} */ mods = new Map(); /** * Mod settings for this mod pack - * @type {Object>=} + * @type {Object>=} */ settings = { "startup": new Map(), @@ -102,7 +102,7 @@ class ModPack { /** * Mapping to files containing exported data for this modpack - * @type {module:lib/data.ExportManifest|undefined} + * @type {module:lib.ExportManifest|undefined} */ exportManifest; diff --git a/packages/lib/data/messages_controller.js b/packages/lib/data/messages_controller.js index 0280320f..5fb97303 100644 --- a/packages/lib/data/messages_controller.js +++ b/packages/lib/data/messages_controller.js @@ -2,7 +2,7 @@ const { JsonString } = require("./composites"); // TODO: remove after config refactor -/** @memberof module:lib/data */ +/** @memberof module:lib */ class RawConfig { /** @type {object} */ serializedConfig; @@ -24,7 +24,7 @@ class RawConfig { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ControllerConfigGetRequest { static type = "request"; static src = "control"; @@ -33,7 +33,7 @@ class ControllerConfigGetRequest { static Response = RawConfig; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ControllerConfigSetFieldRequest { static type = "request"; static src = "control"; @@ -64,7 +64,7 @@ class ControllerConfigSetFieldRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ControllerConfigSetPropRequest { static type = "request"; static src = "control"; @@ -99,7 +99,7 @@ class ControllerConfigSetPropRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class HostGenerateTokenRequest { static type = "request"; static src = "control"; @@ -128,7 +128,7 @@ class HostGenerateTokenRequest { static Response = JsonString; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class HostConfigCreateRequest { static type = "request"; static src = "control"; @@ -165,7 +165,7 @@ class HostConfigCreateRequest { static Response = RawConfig; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class LogSetSubscriptionsRequest { static type = "request"; static src = "control"; @@ -214,7 +214,7 @@ class LogSetSubscriptionsRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class LogQueryRequest { static type = "request"; static src = "control"; @@ -298,7 +298,7 @@ LogQueryRequest.Response = class Response { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class LogMessageEvent { static type = "event"; static src = ["host", "controller"]; @@ -331,7 +331,7 @@ class LogMessageEvent { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class DebugDumpWsRequest { static type = "request"; static src = "control"; @@ -339,7 +339,7 @@ class DebugDumpWsRequest { static permission = "core.debug.dump_ws"; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class DebugWsMessageEvent { static type = "event"; static src = "controller"; diff --git a/packages/lib/data/messages_core.js b/packages/lib/data/messages_core.js index 1bd925c6..14e090f9 100644 --- a/packages/lib/data/messages_core.js +++ b/packages/lib/data/messages_core.js @@ -2,7 +2,7 @@ const libSchema = require("../schema"); -/** @memberof module:lib/data */ +/** @memberof module:lib */ class Address { /** Controller address */ static controller = 0; @@ -44,9 +44,9 @@ class Address { * `"allHosts"`: new Address(Address.broadcast, Address.host) * `"allInstances"`: new Address(Address.broadcast, Address.instance) * `"allControls"`: new Address(Address.broadcast, Address.control) - * @param {module:lib/data.Address|string|object} shorthand - + * @param {module:lib.Address|string|object} shorthand - * Shorthand to translate with. - * @returns {module:lib/data.Address} Translated address. + * @returns {module:lib.Address} Translated address. */ static fromShorthand(shorthand) { if (shorthand instanceof Address) { return shorthand; } @@ -107,7 +107,7 @@ class Address { /** * Returns true if this address targets the given destination - * @param {module:lib/Data.Address} dst - Destination to check + * @param {module:lib.Address} dst - Destination to check * @returns {boolean} true if this address is addressed to the given destination */ addressedTo(dst) { @@ -129,7 +129,7 @@ class Address { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class Message { /** @type {string} */ type; @@ -161,7 +161,7 @@ class Message { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class HelloData { /** @type {string} */ version; @@ -190,9 +190,9 @@ class HelloData { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageHello extends Message { - /** @type {module:lib/data.HelloData} */ + /** @type {module:lib.HelloData} */ data; constructor(data) { @@ -214,7 +214,7 @@ class MessageHello extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class RegisterHostData { /** @type {string} */ token; @@ -263,9 +263,9 @@ class RegisterHostData { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageRegisterHost extends Message { - /** @type {module:lib/data.RegisterHostData} */ + /** @type {module:lib.RegisterHostData} */ data; constructor(data) { @@ -287,7 +287,7 @@ class MessageRegisterHost extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class RegisterControlData { /** @type {string} */ token; @@ -317,9 +317,9 @@ class RegisterControlData { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageRegisterControl extends Message { - /** @type {module:lib/data.RegisterControlData} */ + /** @type {module:lib.RegisterControlData} */ data; constructor(data) { @@ -341,7 +341,7 @@ class MessageRegisterControl extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class AccountDetails { /** @type {string} */ name; @@ -381,9 +381,9 @@ class AccountDetails { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ReadyData { - /** @type {module:lib/data.Address} */ + /** @type {module:lib.Address} */ src; /** @type {string} */ sessionToken; @@ -427,9 +427,9 @@ class ReadyData { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageReady extends Message { - /** @type {module:lib/data.ReadyData} */ + /** @type {module:lib.ReadyData} */ data; constructor(data) { @@ -451,7 +451,7 @@ class MessageReady extends Message { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ResumeData { /** @type {string} */ sessionToken; @@ -478,9 +478,9 @@ class ResumeData { } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageResume extends Message { - /** @type {module:lib/data.ResumeData} */ + /** @type {module:lib.ResumeData} */ data; constructor(data) { @@ -502,7 +502,7 @@ class MessageResume extends Message { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ContinueData { /** @type {number} */ sessionTimeout; @@ -532,9 +532,9 @@ class ContinueData { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageContinue extends Message { - /** @type {module:lib/data.ContinueData} */ + /** @type {module:lib.ContinueData} */ data; constructor(data) { @@ -556,7 +556,7 @@ class MessageContinue extends Message { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageInvalidate extends Message { constructor() { super("invalidate"); @@ -574,7 +574,7 @@ class MessageInvalidate extends Message { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageHeartbeat extends Message { /** @type {integer|undefined} */ seq; @@ -598,7 +598,7 @@ class MessageHeartbeat extends Message { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageRequest extends Message { /** @type {number} */ seq; @@ -644,7 +644,7 @@ class MessageRequest extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageResponse extends Message { /** @type {number} */ seq; @@ -685,7 +685,7 @@ class MessageResponse extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ResponseError { /** @type {string} */ message; @@ -715,7 +715,7 @@ class ResponseError { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageResponseError extends Message { /** @type {number} */ seq; @@ -723,7 +723,7 @@ class MessageResponseError extends Message { src; /** @type {Address} */ dst; - /** @type {module:lib/data.ResponseError} */ + /** @type {module:lib.ResponseError} */ data; constructor(seq, src, dst, data) { @@ -756,7 +756,7 @@ class MessageResponseError extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageEvent extends Message { /** @type {number} */ seq; @@ -802,7 +802,7 @@ class MessageEvent extends Message { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class MessageDisconnect extends Message { /** @type {string} */ data; @@ -853,7 +853,7 @@ Message.jsonSchema = { }; Message.validate = libSchema.compile(Message.jsonSchema); -/** @memberof module:lib/data */ +/** @memberof module:lib */ class PingRequest { static type = "request"; static src = ["controller", "host", "control"]; diff --git a/packages/lib/data/messages_host.js b/packages/lib/data/messages_host.js index fe91ed68..d9d50174 100644 --- a/packages/lib/data/messages_host.js +++ b/packages/lib/data/messages_host.js @@ -2,7 +2,7 @@ const { jsonArray } = require("./composites"); -/** @memberof module:lib/data */ +/** @memberof module:lib */ class HostDetails { /** @type {string} */ agent; @@ -44,7 +44,7 @@ class HostDetails { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class HostListRequest { static type = "request"; static src = "control"; @@ -53,7 +53,7 @@ class HostListRequest { static Response = jsonArray(HostDetails); } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class HostSetSubscriptionsRequest { static type = "request"; static src = "control"; @@ -88,13 +88,13 @@ class HostSetSubscriptionsRequest { } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class HostUpdateEvent { static type = "event"; static src = "controller"; static dst = "control"; - /** @type {module:lib/data.HostDetails} */ + /** @type {module:lib.HostDetails} */ update; constructor(update) { @@ -114,7 +114,7 @@ class HostUpdateEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class HostMetricsRequest { static type = "request"; static src = "controller"; @@ -143,7 +143,7 @@ HostMetricsRequest.Response = class Response { // TODO: Use JSON class pattern i } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ControllerConnectionEvent { static type = "event"; static src = "host"; @@ -169,14 +169,14 @@ class ControllerConnectionEvent { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class PrepareControllerDisconnectRequest { static type = "request"; static src = "host"; static dst = "instance"; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class SyncUserListsEvent { static type = "event"; static src = "controller"; diff --git a/packages/lib/data/messages_instance.js b/packages/lib/data/messages_instance.js index d7bbaf0c..311bf0cf 100644 --- a/packages/lib/data/messages_instance.js +++ b/packages/lib/data/messages_instance.js @@ -2,7 +2,7 @@ const PlayerStats = require("../PlayerStats"); const { JsonString, jsonArray } = require("./composites"); -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDetails { /** @type {string} */ name; @@ -43,7 +43,7 @@ class InstanceDetails { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDetailsGetRequest { static type = "request"; static src = "control"; @@ -72,7 +72,7 @@ class InstanceDetailsGetRequest { static Response = InstanceDetails; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDetailsListRequest { static type = "request"; static src = "control"; @@ -81,7 +81,7 @@ class InstanceDetailsListRequest { static Response = jsonArray(InstanceDetails); }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDetailsSetSubscriptionsRequest { static type = "request"; static src = "control"; @@ -115,13 +115,13 @@ class InstanceDetailsSetSubscriptionsRequest { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDetailsUpdateEvent { static type = "event"; static src = "controller"; static dst = "control"; - /** @type {module:lib/data.InstanceDetails} */ + /** @type {module:lib.InstanceDetails} */ details; constructor(details) { @@ -139,7 +139,7 @@ class InstanceDetailsUpdateEvent { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceCreateRequest { static type = "request"; static src = "control"; @@ -167,7 +167,7 @@ class InstanceCreateRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceConfigGetRequest { static type = "request"; static src = "control"; @@ -215,7 +215,7 @@ InstanceConfigGetRequest.Response = class Response { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceConfigSetFieldRequest { static type = "request"; static src = "control"; @@ -250,7 +250,7 @@ class InstanceConfigSetFieldRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceConfigSetPropRequest { static type = "request"; static src = "control"; @@ -291,7 +291,7 @@ class InstanceConfigSetPropRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceAssignRequest { static type = "request"; static src = "control"; @@ -322,7 +322,7 @@ class InstanceAssignRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceMetricsRequest { static type = "request"; static src = "host"; @@ -351,7 +351,7 @@ InstanceMetricsRequest.Response = class Response { // TODO: Use JSON class patte } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceStartRequest { static type = "request"; static src = ["control", "controller"]; @@ -377,7 +377,7 @@ class InstanceStartRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class SaveDetails { /** @type {string} */ type; @@ -419,7 +419,7 @@ class SaveDetails { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceListSavesRequest { static type = "request"; static src = "control"; @@ -428,7 +428,7 @@ class InstanceListSavesRequest { static Response = jsonArray(SaveDetails); } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceSetSaveListSubscriptionsRequest { static type = "request"; static src = "control"; @@ -462,7 +462,7 @@ class InstanceSetSaveListSubscriptionsRequest { } }; -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceSaveListUpdateEvent { static type = "event"; static src = ["instance", "host", "controller"]; @@ -470,7 +470,7 @@ class InstanceSaveListUpdateEvent { /** @type {number} */ instanceId; - /** @type {module:lib/data.SaveDetails} */ + /** @type {module:lib.SaveDetails} */ saves; constructor(instanceId, saves) { @@ -495,7 +495,7 @@ class InstanceSaveListUpdateEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceCreateSaveRequest { static type = "request"; static src = "control"; @@ -534,7 +534,7 @@ class InstanceCreateSaveRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceRenameSaveRequest { static type = "request"; static src = ["control", "controller"]; @@ -569,7 +569,7 @@ class InstanceRenameSaveRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceCopySaveRequest { static type = "request"; static src = ["control", "controller"]; @@ -604,7 +604,7 @@ class InstanceCopySaveRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDeleteSaveRequest { static type = "request"; static src = ["control", "controller"]; @@ -635,7 +635,7 @@ class InstanceDeleteSaveRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDownloadSaveRequest { static type = "request"; static src = "control"; @@ -668,7 +668,7 @@ class InstanceDownloadSaveRequest { static Response = JsonString; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceTransferSaveRequest { static type = "request"; static src = ["control", "controller"]; @@ -724,7 +724,7 @@ class InstanceTransferSaveRequest { } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstancePullSaveRequest { static type = "request"; static src = "controller"; @@ -760,7 +760,7 @@ class InstancePullSaveRequest { static Response = JsonString; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstancePushSaveRequest { static type = "request"; static src = "controller"; @@ -794,7 +794,7 @@ class InstancePushSaveRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceLoadScenarioRequest { static type = "request"; static src = "control"; @@ -833,7 +833,7 @@ class InstanceLoadScenarioRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceExportDataRequest { static type = "request"; static src = "control"; @@ -841,7 +841,7 @@ class InstanceExportDataRequest { static permission = "core.instance.export_data"; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceExtractPlayersRequest { static type = "request"; static src = "control"; @@ -849,7 +849,7 @@ class InstanceExtractPlayersRequest { static permission = "core.instance.extract_players"; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceStopRequest { static type = "request"; static src = "control"; @@ -857,7 +857,7 @@ class InstanceStopRequest { static permission = "core.instance.stop"; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceKillRequest { static type = "request"; static src = "control"; @@ -865,7 +865,7 @@ class InstanceKillRequest { static permission = "core.instance.kill"; } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDeleteRequest { static type = "request"; static src = "control"; @@ -892,7 +892,7 @@ class InstanceDeleteRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDeleteInternalRequest { static type = "request"; static src = "controller"; @@ -918,7 +918,7 @@ class InstanceDeleteInternalRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceSendRconRequest { static type = "request"; static src = "control"; @@ -948,7 +948,7 @@ class InstanceSendRconRequest { } // TODO remove this after config refactor -/** @memberof module:lib/data */ +/** @memberof module:lib */ class RawInstanceInfo { /** @type {object} */ config; @@ -977,13 +977,13 @@ class RawInstanceInfo { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstancesUpdateRequest { static type = "request"; static src = "host"; static dst = "controller"; - /** @type {Array} */ + /** @type {Array} */ instances; constructor(instances) { @@ -1004,7 +1004,7 @@ class InstancesUpdateRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceAssignInternalRequest { static type = "request"; static src = "controller"; @@ -1035,7 +1035,7 @@ class InstanceAssignInternalRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceUnassignInternalRequest { static type = "request"; static src = "controller"; @@ -1061,7 +1061,7 @@ class InstanceUnassignInternalRequest { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceInitialisedEvent { static type = "event"; static src = "instance"; @@ -1090,7 +1090,7 @@ class InstanceInitialisedEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceStatusChangedEvent { static type = "event"; static src = ["instance", "host"]; @@ -1129,13 +1129,13 @@ class InstanceStatusChangedEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceDetailsChangedEvent { static type = "event"; static src = "instance"; static dst = "controller"; - /** @type {module:lib/data.InstanceDetails} */ + /** @type {module:lib.InstanceDetails} */ details; constructor(details) { @@ -1149,7 +1149,7 @@ class InstanceDetailsChangedEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceBanlistUpdateEvent { static type = "event"; static src = "controller"; @@ -1185,7 +1185,7 @@ class InstanceBanlistUpdateEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceAdminlistUpdateEvent { static type = "event"; static src = "controller"; @@ -1216,7 +1216,7 @@ class InstanceAdminlistUpdateEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstanceWhitelistUpdateEvent { static type = "event"; static src = "controller"; @@ -1247,7 +1247,7 @@ class InstanceWhitelistUpdateEvent { } } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class InstancePlayerUpdateEvent { static type = "event"; static src = "instance"; diff --git a/packages/lib/data/messages_mod.js b/packages/lib/data/messages_mod.js index da311226..7f4d34de 100644 --- a/packages/lib/data/messages_mod.js +++ b/packages/lib/data/messages_mod.js @@ -4,7 +4,7 @@ const ModInfo = require("./ModInfo"); const { jsonArray, JsonString } = require("./composites"); -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackGetRequest { static type = "request"; static src = ["instance", "control"]; @@ -33,7 +33,7 @@ class ModPackGetRequest { static Response = ModPack; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackGetDefaultRequest { static type = "request"; static src = ["instance", "control"]; @@ -42,7 +42,7 @@ class ModPackGetDefaultRequest { static Response = ModPack; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackListRequest { static type = "request"; static src = "control"; @@ -51,14 +51,14 @@ class ModPackListRequest { static Response = jsonArray(ModPack); } -/** @memberof module:lib/data */ +/** @memberof module:lib */ class ModPackCreateRequest { static type = "request"; static src = "control"; static dst = "controller"; static permission = "core.mod_pack.create"; - /** @type {module:lib/data.ModPack} */ + /** @type {module:lib.ModPack} */ modPack; constructor(modPack) { @@ -78,14 +78,14 @@ class ModPackCreateRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackUpdateRequest { static type = "request"; static src = "control"; static dst = "controller"; static permission = "core.mod_pack.update"; - /** @type {module:lib/data.ModPack} */ + /** @type {module:lib.ModPack} */ modPack; constructor(modPack) { @@ -105,7 +105,7 @@ class ModPackUpdateRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackDeleteRequest { static type = "request"; static src = "control"; @@ -132,7 +132,7 @@ class ModPackDeleteRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackSetSubscriptionsRequest { static type = "request"; static src = "control"; @@ -166,7 +166,7 @@ class ModPackSetSubscriptionsRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModGetRequest { static type = "request"; static src = "control"; @@ -199,7 +199,7 @@ class ModGetRequest { static Response = ModInfo; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModListRequest { static type = "request"; static src = "control"; @@ -208,7 +208,7 @@ class ModListRequest { static Response = jsonArray(ModInfo); } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModSearchRequest { static type = "request"; static src = "control"; @@ -305,7 +305,7 @@ ModSearchRequest.Response = class Response { } }; -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModSetSubscriptionsRequest { static type = "request"; static src = "control"; @@ -339,7 +339,7 @@ class ModSetSubscriptionsRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModDownloadRequest { static type = "request"; static src = "control"; @@ -372,7 +372,7 @@ class ModDownloadRequest { static Response = JsonString; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModDeleteRequest { static type = "request"; static src = "control"; @@ -403,13 +403,13 @@ class ModDeleteRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModPackUpdateEvent { static type = "event"; static src = "controller"; static dst = "control"; - /** @type {module:lib/data.ModPack} */ + /** @type {module:lib.ModPack} */ modPack; constructor(modPack) { @@ -429,13 +429,13 @@ class ModPackUpdateEvent { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class ModUpdateEvent { static type = "event"; static src = "controller"; static dst = "control"; - /** @type {module:lib/data.ModInfo} */ + /** @type {module:lib.ModInfo} */ mod; constructor(mod) { diff --git a/packages/lib/data/messages_user.js b/packages/lib/data/messages_user.js index c651ed95..47bc1ff3 100644 --- a/packages/lib/data/messages_user.js +++ b/packages/lib/data/messages_user.js @@ -2,7 +2,7 @@ const PlayerStats = require("../PlayerStats"); const { jsonArray, JsonNumber } = require("./composites"); -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RawPermission { // TODO refactor into lib/user.Permission /** @type {string} */ name; @@ -32,7 +32,7 @@ class RawPermission { // TODO refactor into lib/user.Permission } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class PermissionListRequest { static type = "request"; static src = "control"; @@ -77,7 +77,7 @@ class RawRole { // TODO refactor into lib/user.Role } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RoleListRequest { static type = "request"; static src = "control"; @@ -86,7 +86,7 @@ class RoleListRequest { static Response = jsonArray(RawRole); } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RoleCreateRequest { static type = "request"; static src = "control"; @@ -126,7 +126,7 @@ class RoleCreateRequest { static Response = JsonNumber; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RoleUpdateRequest { static type = "request"; static src = "control"; @@ -168,7 +168,7 @@ class RoleUpdateRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RoleGrantDefaultPermissionsRequest { static type = "request"; static src = "control"; @@ -195,7 +195,7 @@ class RoleGrantDefaultPermissionsRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RoleDeleteRequest { static type = "request"; static src = "control"; @@ -222,7 +222,7 @@ class RoleDeleteRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class RawUser { // TODO refactor into lib/user.User /** @type {string} */ name; @@ -240,9 +240,9 @@ class RawUser { // TODO refactor into lib/user.User banReason; /** @type {boolean|undefined} */ isDeleted; - /** @type {module:lib/PlayerStats} */ + /** @type {module:lib.PlayerStats} */ playerStats; - /** @type {Map|undefined} */ + /** @type {Map|undefined} */ instanceStats; constructor( @@ -321,7 +321,7 @@ class RawUser { // TODO refactor into lib/user.User } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserGetRequest { static type = "request"; static src = "control"; @@ -350,7 +350,7 @@ class UserGetRequest { static Response = RawUser; } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserListRequest { static type = "request"; static src = "control"; @@ -359,7 +359,7 @@ class UserListRequest { static Response = jsonArray(RawUser); } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserSetSubscriptionsRequest { static type = "request"; static src = "control"; @@ -393,7 +393,7 @@ class UserSetSubscriptionsRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserCreateRequest { static type = "request"; static src = "control"; @@ -420,7 +420,7 @@ class UserCreateRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserRevokeTokenRequest { static type = "request"; static src = "control"; @@ -447,7 +447,7 @@ class UserRevokeTokenRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserUpdateRolesRequest { static type = "request"; static src = "control"; @@ -481,7 +481,7 @@ class UserUpdateRolesRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserSetAdminRequest { static type = "request"; static src = "control"; @@ -516,7 +516,7 @@ class UserSetAdminRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserSetWhitelistedRequest { static type = "request"; static src = "control"; @@ -551,7 +551,7 @@ class UserSetWhitelistedRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserSetBannedRequest { static type = "request"; static src = "control"; @@ -590,7 +590,7 @@ class UserSetBannedRequest { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserDeleteRequest { static type = "request"; static src = "control"; @@ -618,7 +618,7 @@ class UserDeleteRequest { } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class AccountUpdateEvent { static type = "event"; static src = "controller"; @@ -657,13 +657,13 @@ class AccountUpdateEvent { } } -/* @memberof module:lib/data */ +/* @memberof module:lib */ class UserUpdateEvent { static type = "event"; static src = "controller"; static dst = "control"; - /** @type {module:lib/data.RawUser} */ + /** @type {module:lib.RawUser} */ user; constructor(user) { diff --git a/packages/lib/data/version.js b/packages/lib/data/version.js index 32706c04..c20f44db 100644 --- a/packages/lib/data/version.js +++ b/packages/lib/data/version.js @@ -9,7 +9,7 @@ * number of leading zeros in them. * @param {string} version - string representation of version. * @returns {number} numeric representation. - * @alias module:lib/data.integerModVersion + * @alias module:lib.integerModVersion */ function integerModVersion(version) { const [major, minor, sub] = version.split(".").map(n => Number.parseInt(n, 10)); @@ -23,7 +23,7 @@ function integerModVersion(version) { * number of leading zeros in them. * @param {string} version - string representation of version. * @returns {number} numeric representation. - * @alias module:lib/data.integerFactorioVersion + * @alias module:lib.integerFactorioVersion */ function integerFactorioVersion(version) { const [main, major, minor] = version.split(".").map(n => Number.parseInt(n, 10)); @@ -33,7 +33,7 @@ function integerFactorioVersion(version) { /** * Matches valid mod versions. * @type {RegExp} - * @alias module:lib/data.modVersionRegExp + * @alias module:lib.modVersionRegExp */ const modVersionRegExp = /^\d+\.\d+\.\d+$/; diff --git a/packages/lib/database.js b/packages/lib/database.js index 61c63528..4c2b8520 100644 --- a/packages/lib/database.js +++ b/packages/lib/database.js @@ -170,7 +170,7 @@ class ItemDatabase { * Create a new item database * * @param {object|undefined} serialized - An object from a previous call to - * {@link module:lib/database~ItemDatabase#serialize} to restore the + * {@link module:libbase~ItemDatabase#serialize} to restore the * database from. An empty database will be created if this parameter * is left undefined. */ diff --git a/packages/lib/factorio/exchange_string.js b/packages/lib/factorio/exchange_string.js index 52698c0f..a4373356 100644 --- a/packages/lib/factorio/exchange_string.js +++ b/packages/lib/factorio/exchange_string.js @@ -324,7 +324,7 @@ function readMapSettings(state) { } /** - * @typedef {object} module:lib/factorio.MapExchangeResult + * @typedef {object} module:lib.MapExchangeResult * @property {array} version - * Version of Factorio the string was created with. * @property {object} map_gen_settings - @@ -344,8 +344,8 @@ function readMapSettings(state) { * save to set the map gen settings and the map settings for the save. * * @param {string} exchangeString - Max Exchange String to parse. - * @returns {module:lib/factorio.MapExchangeResult} Parsed result. - * @memberof module:lib/factorio + * @returns {module:lib.MapExchangeResult} Parsed result. + * @memberof module:lib */ function readMapExchangeString(exchangeString) { exchangeString = exchangeString.replace(/[ \t\n\r]+/g, ""); diff --git a/packages/lib/factorio/export.js b/packages/lib/factorio/export.js index b26be51c..9bd03b80 100644 --- a/packages/lib/factorio/export.js +++ b/packages/lib/factorio/export.js @@ -16,9 +16,9 @@ const libZipOps = require("../zip_ops"); * the server given, with dependencies generated for all the mods present in * the server's mods folder. * - * @param {module:lib/factorio.FactorioServer} server - + * @param {module:lib.FactorioServer} server - * The server to generate the export mod for. - * @memberof module:lib/factorio + * @memberof module:lib */ async function generateExportMod(server) { let dependencies = []; @@ -63,12 +63,12 @@ async function loadZip(server, modVersions, mod) { /** * Load the given Factorio file path into a Buffer * - * @param {module:lib/factorio.FactorioServer} server - + * @param {module:lib.FactorioServer} server - * The server to load the file from. * @param {Map} modVersions - Mapping of mod to version used. * @param {string} modPath - Factorio style path to the file to load. * @returns {Promise} The content of the file or null if not found. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -250,14 +250,14 @@ function filterItems(prototypes) { * Assembles and packs the icons for the item prototypes given into a single * spritesheet and json file with meta data. * - * @param {module:lib/factorio.FactorioServer} server - + * @param {module:lib.FactorioServer} server - * The server to generate the export mod for. * @param {Map} modVersions - * Mapping of mod name to versions to get icons from. * @param {Array} items - Array of item prototypes. * @return {Promise<{itemSheet: Jimp, itemData: Map}>} * Item spritesheet and metadata. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -321,14 +321,14 @@ async function exportItems(server, modVersions, items) { * Parses and merges all the locales for the all the mods given through * `modVersions` and `modOrder`. * - * @param {module:lib/factorio.FactorioServer} server - + * @param {module:lib.FactorioServer} server - * The server to export the locale from. * @param {Map} modVersions - * Mapping of mod name to version to export locale from. * @param {Array} modOrder - Load order of the mods. * @param {string} languageCode - Language to export locale for. * @returns {Promise>} merged locale information - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -377,10 +377,10 @@ async function exportLocale(server, modVersions, modOrder, languageCode) { /** * Export the locale and item icons for the given factorio server * - * @param {module:lib/factorio.FactorioServer} server - + * @param {module:lib.FactorioServer} server - * The server to export the data from. * @returns {Promise} zip file with exported data. - * @memberof module:lib/factorio + * @memberof module:lib */ async function exportData(server) { await generateExportMod(server); diff --git a/packages/lib/factorio/patch.js b/packages/lib/factorio/patch.js index 8e0c6a0f..9fe53860 100644 --- a/packages/lib/factorio/patch.js +++ b/packages/lib/factorio/patch.js @@ -27,7 +27,7 @@ const knownScenarios = { * * @param {Object} patchInfo - The patch info files's json content * @returns {string} Generated control.lua code. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -77,7 +77,7 @@ function generateLoader(patchInfo) { * their dependents. Throws an error if this is not possible. * * @param {Array} modules - Array of modules to reorder - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -175,7 +175,7 @@ function reorderDependencies(modules) { * * @param {string} savePath - Path to the Factorio save to patch. * @param {Array} modules - Description of the modules to patch. - * @memberof module:lib/factorio + * @memberof module:lib */ async function patch(savePath, modules) { let zip = await JSZip.loadAsync(await fs.readFile(savePath)); diff --git a/packages/lib/factorio/server.js b/packages/lib/factorio/server.js index d6d07345..c51f7610 100644 --- a/packages/lib/factorio/server.js +++ b/packages/lib/factorio/server.js @@ -21,7 +21,7 @@ const { LineSplitter } = require("../stream"); * reading the changelog.txt in it. * * @param {string} changelogPath - Path to changelog.txt. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -55,7 +55,7 @@ async function getVersion(changelogPath) { * @param {string} a - Version to compare. * @param {string} b - Version to compare. * @returns {number} 1 if a < b, 0 if a = b and -1 if a > b. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -87,7 +87,7 @@ function versionOrder(a, b) { * Version to look for, supports the special value "latest" for the * latest version available. * @returns {Promise} Array with path to data dir and version found. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -145,7 +145,7 @@ async function findVersion(factorioDir, targetVersion) { * RFC 6335. * * @return {number} a number in the range 49152 to 65535. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -164,7 +164,7 @@ function randomDynamicPort() { * * @param {number} length - the length of the password to generate. * @return {Promise} password of the given length - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -207,7 +207,7 @@ async function generatePassword(length) { * @param {string} source - Passed into the output structure as source * * @returns {object} - An object with interpeted data. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ @@ -412,7 +412,7 @@ const outputHeuristics = [ * - save-finished - invoked when the server has finished a manual save * - exit - invoked when the sterver has exited * @extends events.EventEmitter - * @memberof module:lib/factorio + * @memberof module:lib */ class FactorioServer extends events.EventEmitter { /** diff --git a/packages/lib/helpers.js b/packages/lib/helpers.js index 9069a198..5104f74a 100644 --- a/packages/lib/helpers.js +++ b/packages/lib/helpers.js @@ -210,18 +210,18 @@ function wordMatches(word, ...texts) { } /** - * @typedef {object} module:lib/helpers~ParsedTerm + * @typedef {object} module:lib~ParsedTerm * @property {string} type - Type of term, either attribute or word. * @property {string=} name - attribute only: Name of attribute. * @property {boolean=} exclude - word only: exclude results with this word. - * @property {string | module:lib/helpers.ParsedTerm} value - + * @property {string | module:lib.ParsedTerm} value - * Parsed value of this term. Is a string if type is word, and a * ParsedTerm if type is attribute. */ /** - * @typedef {object} module:lib/helpers~ParsedSearch - * @property {Array} terms - + * @typedef {object} module:lib~ParsedSearch + * @property {Array} terms - * Parsed result of search terms. * @property {Array} issues - * Issues detected while parsing the seach string. @@ -248,7 +248,7 @@ function wordMatches(word, ...texts) { * @param {Object} attributes - * Recognized attributes and their format. Currently only word is * supported. - * @returns {module:lib/helpers~ParsedSearch} parsed terms of the search. + * @returns {module:lib~ParsedSearch} parsed terms of the search. * @static */ function parseSearchString(input, attributes = {}) { diff --git a/packages/lib/index.js b/packages/lib/index.js index a642c629..7e282a20 100644 --- a/packages/lib/index.js +++ b/packages/lib/index.js @@ -1,3 +1,7 @@ +/** + * Shared library for Clusterio + * @module lib + */ "use strict"; const libBuildMod = require("./build_mod"); const libCommand = require("./command"); @@ -9,6 +13,7 @@ const libFactorio = require("./factorio"); const libFileOps = require("./file_ops"); const libHash = require("./hash"); const libHelpers = require("./helpers"); +const libIni = require("./ini"); const libLink = require("./link"); const libLogging = require("./logging"); const libLoggingUtils = require("./logging_utils"); @@ -18,36 +23,41 @@ const libPluginLoader = require("./plugin_loader"); const libPrometheus = require("./prometheus"); const libSchema = require("./schema"); const libSharedCommands = require("./shared_commands"); +const libStream = require("./stream"); const libUsers = require("./users"); const libZipOps = require("./zip_ops"); const ExponentialBackoff = require("./ExponentialBackoff"); +const PlayerStats = require("./PlayerStats"); const RateLimiter = require("./RateLimiter"); module.exports = { - libBuildMod, - libCommand, - libConfig, - libData, - libDatabase, - libErrors, - libFactorio, - libFileOps, - libHash, - libHelpers, - libLink, - libLogging, - libLoggingUtils, - libLuaTools, - libPlugin, - libPluginLoader, - libPrometheus, - libSchema, - libSharedCommands, - libUsers, - libZipOps, + ...libBuildMod, + ...libCommand, + ...libConfig, + ...libData, + ...libDatabase, + ...libErrors, + ...libFactorio, + ...libFileOps, + ...libHash, + ...libHelpers, + ...libIni, + ...libLink, + ...libLogging, + ...libLoggingUtils, + ...libLuaTools, + ...libPlugin, + ...libPluginLoader, + ...libPrometheus, + ...libSchema, + ...libSharedCommands, + ...libStream, + ...libUsers, + ...libZipOps, ExponentialBackoff, + PlayerStats, RateLimiter, }; diff --git a/packages/lib/link/connectors.js b/packages/lib/link/connectors.js index 7f4ed270..1afad7e2 100644 --- a/packages/lib/link/connectors.js +++ b/packages/lib/link/connectors.js @@ -15,7 +15,7 @@ const ExponentialBackoff = require("../ExponentialBackoff"); * Base connector for links * * @extends events.EventEmitter - * @memberof module:lib/link + * @memberof module:lib */ class BaseConnector extends events.EventEmitter { constructor(src, dst) { @@ -76,8 +76,8 @@ class BaseConnector extends events.EventEmitter { /** * Base connector for links * - * @extends module:lib/link.BaseConnector - * @memberof module:lib/link + * @extends module:lib.BaseConnector + * @memberof module:lib */ class WebSocketBaseConnector extends BaseConnector { constructor(src, dst) { @@ -231,7 +231,7 @@ class WebSocketBaseConnector extends BaseConnector { * This is a low level method that should only be used for implementing * links. See sendTo for sending requests and events. * - * @param {module:lib/data.Message} message - Message to send. + * @param {module:lib.Message} message - Message to send. */ send(message) { if (!["connected", "resuming"].includes(this._state)) { @@ -313,8 +313,8 @@ class WebSocketBaseConnector extends BaseConnector { /** * Connector for controller clients * - * @extends module:lib/link.WebSocketBaseConnector - * @memberof module:lib/link + * @extends module:lib.WebSocketBaseConnector + * @memberof module:lib */ class WebSocketClientConnector extends WebSocketBaseConnector { constructor(url, maxReconnectDelay, tlsCa = null) { @@ -360,7 +360,7 @@ class WebSocketClientConnector extends WebSocketBaseConnector { * Used in the register function in order to send the handshake messages * over the WebSocket. * - * @param {module:lib/data.Message} message - Message to send. + * @param {module:lib.Message} message - Message to send. */ sendHandshake(message) { this._check("connecting", "resuming"); @@ -647,7 +647,7 @@ class WebSocketClientConnector extends WebSocketBaseConnector { * Connector for in-memory local links * * @extends events.EventEmitter - * @memberof module:lib/link + * @memberof module:lib */ class VirtualConnector extends BaseConnector { constructor(src, dst) { @@ -662,8 +662,8 @@ class VirtualConnector extends BaseConnector { * Creates two virtual connectors that are liked to each othes such that * a message sent on one is received by the other. * - * @param {module:lib/data.Address} src - Source for obverse connector - * @param {module:lib/data.Address} dst - destination for obverse connector + * @param {module:lib.Address} src - Source for obverse connector + * @param {module:lib.Address} dst - destination for obverse connector * @returns {Array} two virtuarl connectors. */ static makePair(src, dst) { @@ -677,7 +677,7 @@ class VirtualConnector extends BaseConnector { /** * Send a message to the other end of the connector * - * @param {module:lib/data.Message} message - Message type to send. + * @param {module:lib.Message} message - Message type to send. */ send(message) { this.other.emit("message", message); diff --git a/packages/lib/link/link.js b/packages/lib/link/link.js index 54c33afe..758c524c 100644 --- a/packages/lib/link/link.js +++ b/packages/lib/link/link.js @@ -17,7 +17,7 @@ const { dataClasses } = require("./messages"); /** * Common interface for server and client connections * - * @memberof module:lib/link + * @memberof module:lib */ class Link { constructor(connector) { @@ -95,8 +95,8 @@ class Link { * Validates and invokes the handler and/or waiters for a message that has * been received. An unhandled message is considered to be an error. * - * @param {module:lib/data.Message} message - Message to process. - * @throws {module:lib/errors.InvalidMessage} if the message is invalid or not handled. + * @param {module:lib.Message} message - Message to process. + * @throws {module:lib.InvalidMessage} if the message is invalid or not handled. */ _processMessage(message) { if (!["request", "response", "responseError", "event"].includes(message.type)) { @@ -149,8 +149,8 @@ class Link { * * Should be overridden by sub-classes to validate messages received. * - * @param {module:lib/data.Message} message - Message to check. - * @throws {module:lib/errors.InvalidMessage} if the message is invalid. + * @param {module:lib.Message} message - Message to check. + * @throws {module:lib.InvalidMessage} if the message is invalid. */ validateIngress(message) { } @@ -222,9 +222,9 @@ class Link { * Called when an request or event is received by a control connector. * Should be overridden by sub-classes to validate messages received. * - * @param {module:lib/data.Message} message - Message to check. + * @param {module:lib.Message} message - Message to check. * @param {object} entry - Request or Event entry for this Message. - * @throws {module:lib/errors.PermissionError} if unauthorized. + * @throws {module:lib.PermissionError} if unauthorized. */ validatePermission(message, entry) { } @@ -380,7 +380,7 @@ class Link { /** * Send a request or event to the given address * - * @param {*|module:lib/data.Address} destination - Where to send it + * @param {*|module:lib.Address} destination - Where to send it * @param {*} requestOrEvent - Request or event to send * @returns {Promise<*>|undefined} * Promise that resolves to the response if a request was sent or diff --git a/packages/lib/logging.js b/packages/lib/logging.js index 56c9a729..98aeb928 100644 --- a/packages/lib/logging.js +++ b/packages/lib/logging.js @@ -84,7 +84,7 @@ class WebConsoleFormat { /** * Filter object for logs - * @typedef {Object} module:lib/logging~LogFilter + * @typedef {Object} module:lib~LogFilter * @property {string} [maxLevel] - * Maximum log level to include. Higher levels are more verbose. * @property {boolean} [all] - @@ -101,7 +101,7 @@ class WebConsoleFormat { /** * Create log filter by level and source. * - * @param {module:lib/logging~LogFilter} filter - + * @param {module:lib~LogFilter} filter - * Filter to filter log entries by. * @returns {function(object): boolean} * filter returning true for log entries that match it. diff --git a/packages/lib/logging_utils.js b/packages/lib/logging_utils.js index dea8baee..c45a961d 100644 --- a/packages/lib/logging_utils.js +++ b/packages/lib/logging_utils.js @@ -188,10 +188,10 @@ class LogIndex { * * Loads index.json from the given log directy expecting it to contain * data about previously indexed files saved with {@link - * module:lib/logging_utils.LogIndex#save}. + * module:lib.LogIndex#save}. * * @param {string} logDirectory - Path to directory to load from. - * @returns {Promise} loaded or created log index. + * @returns {Promise} loaded or created log index. */ static async load(logDirectory) { try { @@ -275,7 +275,7 @@ class LogIndex { * * @param {string} file - * Name of file in the log directory to check for. - * @param {module:lib/logging~LogFilter} filter - + * @param {module:lib~LogFilter} filter - * Filter to check index if file contains entries for. * @returns {boolean} * true if the file may contain entries included by the filter. @@ -314,7 +314,7 @@ class LogIndex { /** * Filter object for querying logs - * @typedef {Object} module:lib/logging_utils~QueryLogFilter + * @typedef {Object} module:lib~QueryLogFilter * @property {number} [limit=100] - Maximum number of entries to return. * @property {string} [order="asc"] - * Return entries in ascending ("asc") date order or desceding ("desc") @@ -336,9 +336,9 @@ class LogIndex { * Query log directory * * @param {string} logDirectory - path to directory with logs. - * @param {module:lib/logging_utils~QueryLogFilter} filter - + * @param {module:lib~QueryLogFilter} filter - * Filter to limit logs by. - * @param {module:lib/logging_utils.LogIndex=} index - + * @param {module:lib.LogIndex=} index - * Index to speed up query with. * @returns {Promise>} log entries matching the filter */ diff --git a/packages/lib/plugin.js b/packages/lib/plugin.js index eebfd072..48e22cbb 100644 --- a/packages/lib/plugin.js +++ b/packages/lib/plugin.js @@ -9,10 +9,10 @@ const helpers = require("./helpers"); /** * Conceptual base for controller and instance plugins. * @typedef { - * module:lib/plugin.BaseControllerPlugin - * |module:lib/plugin.BaseInstancePlugin - * |module:lib/plugin.BaseControlPlugin - * } module:lib/plugin.BasePlugin + * module:lib.BaseControllerPlugin + * |module:lib.BaseInstancePlugin + * |module:lib.BaseControlPlugin + * } module:lib.BasePlugin */ /** @@ -77,7 +77,7 @@ class BaseInstancePlugin { * Invoked after the value of the config field given by `field` has * changed. * - * @param {module:lib/config.ConfigGroup} group - + * @param {module:lib.ConfigGroup} group - * The group who's field got changed. * @param {string} field - Name of the field that changed. * @param {*} prev - The previous value of the field. @@ -366,7 +366,7 @@ class BaseControllerPlugin { * Invoked after the value of the config field given by `field` has * changed on the controller. * - * @param {module:lib/config.ConfigGroup} group - + * @param {module:lib.ConfigGroup} group - * The group who's field got changed. * @param {string} field - Name of the field that changed. * @param {*} prev - The previous value of the field. @@ -381,7 +381,7 @@ class BaseControllerPlugin { * * @param {module:controller/src/InstanceInfo} instance - * The instance the config changed on. - * @param {module:lib/config.ConfigGroup} group - + * @param {module:lib.ConfigGroup} group - * The group who's field got changed. * @param {string} field - Name of the field that changed. * @param {*} prev - The previous value of the field. @@ -504,7 +504,7 @@ class BaseControllerPlugin { * If the mod pack has been deleted its `.isDeleted` property will be * true. * - * @param {module:lib/data.ModPack} modPack - Mod pack that updated. + * @param {module:lib.ModPack} modPack - Mod pack that updated. */ async onModPackUpdated(modPack) { } @@ -516,7 +516,7 @@ class BaseControllerPlugin { * * If a mod has been deleted its `.isDeleted` property will be true. * - * @param {module:lib/data.ModInfo} mod - Mod that updated. + * @param {module:lib.ModInfo} mod - Mod that updated. */ async onModUpdated(mod) { } @@ -601,9 +601,9 @@ class BaseControlPlugin { * * Invoked by clusterioctl to let plugins add commands. `rootCommand` is * the top level command node which the plugin should add its own {@link - * module:lib/command.CommandTree} to. + * module:lib.CommandTree} to. * - * @param {module:lib/command.CommandTree} rootCommand - + * @param {module:lib.CommandTree} rootCommand - * Root of the clusterioctl command tree. */ async addCommands(rootCommand) { } @@ -612,7 +612,7 @@ class BaseControlPlugin { /** * Plugin supplied login form - * @typedef {Object} module:lib/plugin~LoginForm + * @typedef {Object} module:lib~LoginForm * @property {string} name - * Internal name of the login form, this should start with the * plugin name followed by a dot. @@ -627,7 +627,7 @@ class BaseControlPlugin { /** * Plugin supplied pages - * @typedef {Object} module:lib/plugin~Page + * @typedef {Object} module:lib~Page * @property {string} path - URL path to this page. * @property {string=} sidebarPath - * If present and this path matches one of the pages in the sidebar it @@ -669,7 +669,7 @@ class BaseWebPlugin { /** * Control link to the controller, not available until the * connect event in onControllerConnectionEvent is signaled. - * @type {?module:lib/link.Link} + * @type {?module:lib.Link} */ this.control = null; @@ -685,14 +685,14 @@ class BaseWebPlugin { /** * List of login forms provided by this plugin * - * @type {Array} + * @type {Array} */ this.loginForms = []; /** * List of pages provided by this plugin * - * @type {Array} + * @type {Array} */ this.pages = []; diff --git a/packages/lib/plugin_loader.js b/packages/lib/plugin_loader.js index e831e5db..e97d7541 100644 --- a/packages/lib/plugin_loader.js +++ b/packages/lib/plugin_loader.js @@ -77,7 +77,7 @@ function loadPluginClass(entrypointName, className, pluginClass, pluginInfo) { * * @param {Object} pluginInfo - * Plugin info object returned from {@link - * module:lib/plugin_loader.loadPluginInfos} to load class from. + * module:lib.loadPluginInfos} to load class from. * @returns {Promise} plugin class * @static */ @@ -90,7 +90,7 @@ async function loadControllerPluginClass(pluginInfo) { * * @param {Object} pluginInfo - * Plugin info object returned from {@link - * module:lib/plugin_loader.loadPluginInfos} to load class from. + * module:lib.loadPluginInfos} to load class from. * @returns {Promise} plugin class * @static */ @@ -103,7 +103,7 @@ async function loadInstancePluginClass(pluginInfo) { * * @param {Object} pluginInfo - * Plugin info object returned from {@link - * module:lib/plugin_loader.loadPluginInfos} to load class from. + * module:lib.loadPluginInfos} to load class from. * @returns {Promise} plugin class * @static */ diff --git a/packages/lib/prometheus.js b/packages/lib/prometheus.js index aa96efa9..7a69f391 100644 --- a/packages/lib/prometheus.js +++ b/packages/lib/prometheus.js @@ -7,13 +7,13 @@ * metric collections in prom-client. * * The ordinary use case of instrumenting a code base should be covered by - * {@link module:lib/prometheus.Counter}, {@link - * module:lib/prometheus.Gauge}, {@link module:lib/prometheus.Histogram} and - * {@link module:lib/prometheus.exposition}. See documentation for each of + * {@link module:lib.Counter}, {@link + * module:lib.Gauge}, {@link module:lib.Histogram} and + * {@link module:lib.exposition}. See documentation for each of * the listed interfaces for more information. * * @example - * const { Counter, exposition } = require("@clusterio/lib/prometheus"); + * const { Counter, exposition } = require("@clusterio/lib"); * * // Collectors are by default registered to the default collector regitry. * const totalRequests = new Counter( @@ -42,9 +42,9 @@ "use strict"; /** - * Result from collecting a {@link module:lib/prometheus.Collector} + * Result from collecting a {@link module:lib.Collector} * @typedef {Object} CollectorResult - * @property {module:lib/prometheus.Metric} metric - + * @property {module:lib.Metric} metric - * Metric collected. * @property {Map>} samples - * Mapping of metric suffix to mapping of label keys to values @@ -165,7 +165,7 @@ class Metric { /** * The default registry which collectors are regististered to. - * @type {module:lib/prometheus.CollectorRegistry} + * @type {module:lib.CollectorRegistry} * @static */ let defaultRegistry; @@ -176,7 +176,7 @@ let defaultRegistry; * This servers mostly as a conceptual base for all collectors, the only * feature implemented here is registring to the default registry on * construction. If you want to implement a custom collector you most - * likely want to base it on {@link module:lib/prometheus.LabeledCollector} + * likely want to base it on {@link module:lib.LabeledCollector} * instead. * * @static @@ -197,7 +197,7 @@ class Collector { /** * Retrieve metric data from this collctor. * - * Called by {@link module:lib/prometheus.CollectorRegistry} to gather + * Called by {@link module:lib.CollectorRegistry} to gather * the metric data this Collector exports. * * @returns {*} Async iterator of {@link CollectorResult}. @@ -318,7 +318,7 @@ function removeMatchingLabels(mapping, labels) { * set is a child to the collector that can be retrieved with the .labels() * method. * - * @extends module:lib/prometheus.Collector + * @extends module:lib.Collector * @static */ class LabeledCollector extends Collector { @@ -341,7 +341,7 @@ class LabeledCollector extends Collector { * collected. The collector being collected is passed as the * argument. * @param { - * function(module:lib/prometheus.LabeledCollector,string) + * function(module:lib.LabeledCollector,string) * } childClass - * Constructor taking instance of collector and label key as * arguments and returns a child instance. @@ -461,7 +461,7 @@ class LabeledCollector extends Collector { /** * Base class for implementing single value per label collectors * - * @extends module:lib/prometheus.LabeledCollector + * @extends module:lib.LabeledCollector * @static */ class ValueCollector extends LabeledCollector { @@ -485,8 +485,8 @@ class ValueCollector extends LabeledCollector { * argument. * @param { * function( - * new:module:lib/prometheus.ValueCollectorChild, - * module:lib/prometheus.LabeledCollector, + * new:module:lib.ValueCollectorChild, + * module:lib.LabeledCollector, * string * ) * } childClass - @@ -555,7 +555,7 @@ class ValueCollectorChild { /** * Child counter holding the value for a single label set. - * @extends module:lib/prometheus~ValueCollectorChild + * @extends module:lib~ValueCollectorChild */ class CounterChild extends ValueCollectorChild { /** @@ -597,7 +597,7 @@ class CounterChild extends ValueCollectorChild { * * The `totalRequests` counter will register with the default registry and * provided exposition is set up (see {@link - * module:lib/prometheus.exposition}) the counter will be exported to + * module:lib.exposition}) the counter will be exported to * Prometheus starting out with a value of 0. And that is all there is to * it. * @@ -652,7 +652,7 @@ class CounterChild extends ValueCollectorChild { * labels you actually need as resource usage for a metric increases * exponentially with the number of labels used. * - * @extends module:lib/prometheus.ValueCollector + * @extends module:lib.ValueCollector * @static */ class Counter extends ValueCollector { @@ -689,7 +689,7 @@ class Counter extends ValueCollector { /** * Child gauge holding the value for a single label set. - * @extends module:lib/prometheus~ValueCollectorChild + * @extends module:lib~ValueCollectorChild */ class GaugeChild extends ValueCollectorChild { /** @@ -771,7 +771,7 @@ class GaugeChild extends ValueCollectorChild { * * The `activeRequests` gauge will register with the default registry and * provided exposition is set up (see {@link - * module:lib/prometheus.exposition}) the gauge will be exported to + * module:lib.exposition}) the gauge will be exported to * Prometheus starting out with a value of 0. * * Sometimes keeping track of the value measured is impractical or @@ -842,7 +842,7 @@ class GaugeChild extends ValueCollectorChild { * labels you actually need as resource usage for a metric increases * exponentially with the number of labels used. * - * @extends module:lib/prometheus.ValueCollector + * @extends module:lib.ValueCollector * @static */ class Gauge extends ValueCollector { @@ -1637,7 +1637,7 @@ async function* expositionLines(resultsIterator) { * @param {*} resultsIterator - * Asynchronously itreable of {@link CollectorResult} results to create * exposition for. Defaults to collecting results from {@link - * module:lib/prometheus.defaultRegistry}. + * module:lib.defaultRegistry}. * @returns {string} Prometheus exposition. * * @property {string} exposition.contentType @@ -1658,10 +1658,10 @@ exposition.contentType = "text/plain; version=0.0.4"; /** * Serialize CollectorResult into a plain object * - * Converts a {@link module:lib/prometheus~CollectorResult} into a plain + * Converts a {@link module:lib~CollectorResult} into a plain * object form that can be stringified to JSON. * - * @param {module:lib/prometheus~CollectorResult} result - + * @param {module:lib~CollectorResult} result - * Result to serialize into plain object form. * @param {Object} options - Options for controlling the serialization. * @param {string} options.addLabels - @@ -1724,10 +1724,10 @@ function serializeResult(result, options = {}) { /** * Deserialize CollectorResult from plain object * - * Reverse counterpart to {@link module:lib/prometheus.serializeResult}. + * Reverse counterpart to {@link module:lib.serializeResult}. * * @param {Object} serializedResult - Previously serialized result object. - * @returns {module:lib/prometheus~CollectorResult} deserialized result. + * @returns {module:lib~CollectorResult} deserialized result. * @static */ function deserializeResult(serializedResult) { @@ -1748,7 +1748,7 @@ function deserializeResult(serializedResult) { /** * Default collectors provided by this library - * @type {Object} + * @type {Object} */ let defaultCollectors = {}; defaultCollectors.processCpuSecondsTotal = new Gauge( diff --git a/packages/lib/shared_commands.js b/packages/lib/shared_commands.js index d09ba5df..c641d1df 100644 --- a/packages/lib/shared_commands.js +++ b/packages/lib/shared_commands.js @@ -120,7 +120,7 @@ function configCommand(yargs) { * Handle the actions that are made available by configCommand. * * @param {Object} args - yargs args object. - * @param {module:lib/config.Config} instance - Config instance. + * @param {module:lib.Config} instance - Config instance. * @param {string} configPath - Path to configuration file. */ async function handleConfigCommand(args, instance, configPath) { diff --git a/packages/lib/stream.js b/packages/lib/stream.js index 98787397..a05180a9 100644 --- a/packages/lib/stream.js +++ b/packages/lib/stream.js @@ -16,7 +16,7 @@ const stream = require("stream"); * let fileStream = fs.createReadStream(path); * fileStream.pipe(lineStream); * - * @memberof module:lib/stream + * @memberof module:lib */ class LineSplitter extends stream.Transform { constructor(options) { @@ -63,7 +63,7 @@ class LineSplitter extends stream.Transform { * Transform splitting a reverse stream into lines * * Splits up a reverse stream of chunks created by {@link - * module:lib/stream.createReverseReadStream} by newlines and passes on the + * module:lib.createReverseReadStream} by newlines and passes on the * lines one by one in reverse order removing the line feed and optional * carriage return from the lines. * @@ -73,7 +73,7 @@ class LineSplitter extends stream.Transform { * let revFileStream = await libStream.createReverseReadStream(path); * revFileStream.pipe(revLineStream); * - * @memberof module:lib/stream + * @memberof module:lib */ class ReverseLineSplitter extends stream.Transform { constructor(options) { @@ -141,7 +141,7 @@ class ReverseLineSplitter extends stream.Transform { * @param {object} options - * Options to pass to fs.createReadStream. Values passed for `fd` and * `fs` will be ignored. - * @memberof module:lib/stream + * @memberof module:lib */ async function createReverseReadStream(path, options) { const fileFd = await fs.open(path, "r"); diff --git a/packages/lib/users.js b/packages/lib/users.js index 0d9f90d4..b13ec9b2 100644 --- a/packages/lib/users.js +++ b/packages/lib/users.js @@ -100,8 +100,8 @@ class Role { * * Ensures the role with id 0 exisits and has the core.admin permission. * - * @param {Map} roles - role storage to modify. - * @returns {module:lib/permission.Role} the default admin role + * @param {Map} roles - role storage to modify. + * @returns {module:lib.Role} the default admin role * @static */ function ensureDefaultAdminRole(roles) { @@ -121,7 +121,7 @@ function ensureDefaultAdminRole(roles) { * assigned by default. Note that this may not be the same role as the one * that is assigned to new users by default. * - * @param {Map} roles - role storage to modify. + * @param {Map} roles - role storage to modify. * @static */ function ensureDefaultPlayerRole(roles) { @@ -186,7 +186,7 @@ class User { /** * Roles this user has - * @type {Set} + * @type {Set} */ this.roles = new Set(); if (serializedUser.roles) { @@ -200,7 +200,7 @@ class User { /** * Per instance statistics for the player this user account is tied to. - * @type {Map} + * @type {Map} */ this.instanceStats = new Map( (serializedUser.instance_stats ? serializedUser.instance_stats : []).map( @@ -210,7 +210,7 @@ class User { /** * Combined statistics for the player this user account is tied to. - * @type {module:lib/PlayerStats} + * @type {module:lib.PlayerStats} */ this.playerStats = this._calculatePlayerStats(); @@ -286,7 +286,7 @@ class User { * * @param {string} permission - The permission to check for. * @throws {Error} If the given permission does not exist. - * @throws {module:lib/errors.PermissionError} if the user does noh have the given permission. + * @throws {module:lib.PermissionError} if the user does noh have the given permission. */ checkPermission(permission) { if (!permissions.has(permission)) { @@ -336,7 +336,7 @@ class User { } /** * Set of users currently online in the cluster. - * @type {module:lib/users.User} + * @type {module:lib.User} */ User.onlineUsers = new Set(); diff --git a/packages/lib/zip_ops.js b/packages/lib/zip_ops.js index f05c09b5..39cb1bb0 100644 --- a/packages/lib/zip_ops.js +++ b/packages/lib/zip_ops.js @@ -8,7 +8,7 @@ * * @param {JSZip} zip - Zip to search through. * @returns {string} name of the root folder. - * @memberof module:lib/factorio + * @memberof module:lib * @private * @inner */ diff --git a/packages/web_ui/src/bootstrap.jsx b/packages/web_ui/src/bootstrap.jsx index c0861fda..bf2fa5b8 100644 --- a/packages/web_ui/src/bootstrap.jsx +++ b/packages/web_ui/src/bootstrap.jsx @@ -3,12 +3,12 @@ import "./index.css"; import React from "react"; import { createRoot } from "react-dom/client"; -import { libConfig, libLink, libLogging, libPlugin } from "@clusterio/lib"; -const { ConsoleTransport, WebConsoleFormat, logger } = libLogging; +import * as lib from "@clusterio/lib"; import App from "./components/App"; import { Control, ControlConnector } from "./util/websocket"; +const { ConsoleTransport, WebConsoleFormat, logger } = lib; async function loadScript(url) { let script = document.createElement("script"); @@ -73,7 +73,7 @@ async function loadPlugins(pluginInfos) { continue; } try { - let WebPluginClass = libPlugin.BaseWebPlugin; + let WebPluginClass = lib.BaseWebPlugin; if (pluginInfo.webEntrypoint) { let webModule = (await pluginInfo.container.get(pluginInfo.webEntrypoint))(); if (!webModule.WebPlugin) { @@ -102,9 +102,9 @@ export default async function bootstrap() { format: new WebConsoleFormat(), })); let pluginInfos = await loadPluginInfos(); - libLink.registerPluginMessages(pluginInfos); - libConfig.registerPluginConfigGroups(pluginInfos); - libConfig.finalizeConfigs(); + lib.registerPluginMessages(pluginInfos); + lib.registerPluginConfigGroups(pluginInfos); + lib.finalizeConfigs(); let plugins = await loadPlugins(pluginInfos); let wsUrl = new URL(window.webRoot, document.location); diff --git a/packages/web_ui/src/components/App.jsx b/packages/web_ui/src/components/App.jsx index 5422c9f4..2c573d46 100644 --- a/packages/web_ui/src/components/App.jsx +++ b/packages/web_ui/src/components/App.jsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import { BrowserRouter } from "react-router-dom"; -import { libLogging } from "@clusterio/lib"; +import { logger } from "@clusterio/lib"; import ErrorBoundary from "./ErrorBoundary"; import SiteLayout from "./SiteLayout"; @@ -11,7 +11,6 @@ import LoginForm from "./LoginForm"; import { Card, ConfigProvider, Spin, Typography, theme } from "antd"; const { Paragraph } = Typography; -const { logger } = libLogging; function ErrorCard(props) { diff --git a/packages/web_ui/src/components/AssignInstanceModal.jsx b/packages/web_ui/src/components/AssignInstanceModal.jsx index 05049f41..4fc8109c 100644 --- a/packages/web_ui/src/components/AssignInstanceModal.jsx +++ b/packages/web_ui/src/components/AssignInstanceModal.jsx @@ -1,7 +1,7 @@ import React, { useContext, useState } from "react"; import { Button, Form, Modal, Select, Typography } from "antd"; -import { libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import ControlContext from "./ControlContext"; import { notifyErrorHandler } from "../util/notify"; @@ -30,7 +30,7 @@ export default function AssignInstanceModal(props) { setApplying(true); control.send( - new libData.InstanceAssignRequest(props.id, hostId) + new lib.InstanceAssignRequest(props.id, hostId) ).then(() => { setOpen(false); if (props.onFinish) { diff --git a/packages/web_ui/src/components/ControllerConfigTree.jsx b/packages/web_ui/src/components/ControllerConfigTree.jsx index 40dd7947..b95c71d5 100644 --- a/packages/web_ui/src/components/ControllerConfigTree.jsx +++ b/packages/web_ui/src/components/ControllerConfigTree.jsx @@ -1,6 +1,6 @@ import React, { useContext } from "react"; -import { libConfig, libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import BaseConfigTree from "./BaseConfigTree"; import ControlContext from "./ControlContext"; @@ -10,12 +10,12 @@ export default function ControllerConfigTree(props) { let control = useContext(ControlContext); async function retrieveConfig() { - let result = await control.send(new libData.ControllerConfigGetRequest()); + let result = await control.send(new lib.ControllerConfigGetRequest()); return result.serializedConfig; } async function setField(field, value) { - await control.send(new libData.ControllerConfigSetFieldRequest( + await control.send(new lib.ControllerConfigSetFieldRequest( field, String(value), )); @@ -29,11 +29,11 @@ export default function ControllerConfigTree(props) { return; } } - await control.send(new libData.ControllerConfigSetPropRequest(field, prop, value)); + await control.send(new lib.ControllerConfigSetPropRequest(field, prop, value)); } return { form.resetFields(); setOpen(false); @@ -68,7 +68,7 @@ export default function CreateSaveModal(props) { let exchangeString = form.getFieldValue("exchangeString"); let result; try { - result = libFactorio.readMapExchangeString(exchangeString); + result = lib.readMapExchangeString(exchangeString); } catch (err) { form.setFields([{ name: "exchangeString", errors: [err.message] }]); return; diff --git a/packages/web_ui/src/components/HostsPage.jsx b/packages/web_ui/src/components/HostsPage.jsx index e1df0228..636bffb1 100644 --- a/packages/web_ui/src/components/HostsPage.jsx +++ b/packages/web_ui/src/components/HostsPage.jsx @@ -3,7 +3,7 @@ import { useNavigate } from "react-router-dom"; import { Button, Form, InputNumber, Modal, Table, Tag, Typography } from "antd"; import CopyOutlined from "@ant-design/icons/lib/icons/CopyOutlined"; -import { libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import { useAccount } from "../model/account"; import ControlContext from "./ControlContext"; @@ -47,7 +47,7 @@ function GenerateHostTokenButton(props) { form.setFields([{ name: "hostId", errors: [] }]); } - let newToken = await control.send(new libData.HostGenerateTokenRequest(id)); + let newToken = await control.send(new lib.HostGenerateTokenRequest(id)); setToken(newToken); setHostId(id); } diff --git a/packages/web_ui/src/components/InstanceConfigTree.jsx b/packages/web_ui/src/components/InstanceConfigTree.jsx index 74afaa31..54e30485 100644 --- a/packages/web_ui/src/components/InstanceConfigTree.jsx +++ b/packages/web_ui/src/components/InstanceConfigTree.jsx @@ -1,6 +1,6 @@ import React, { useContext } from "react"; -import { libConfig, libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import BaseConfigTree from "./BaseConfigTree"; import ControlContext from "./ControlContext"; @@ -10,12 +10,12 @@ export default function InstanceConfigTree(props) { let control = useContext(ControlContext); async function retrieveConfig() { - let result = await control.send(new libData.InstanceConfigGetRequest(props.id)); + let result = await control.send(new lib.InstanceConfigGetRequest(props.id)); return result.config; } async function setField(field, value) { - await control.send(new libData.InstanceConfigSetFieldRequest(props.id, field, value)); + await control.send(new lib.InstanceConfigSetFieldRequest(props.id, field, value)); } async function setProp(field, prop, value) { @@ -26,11 +26,11 @@ export default function InstanceConfigTree(props) { return; } } - await control.send(new libData.InstanceConfigSetPropRequest(props.id, field, prop, value)); + await control.send(new lib.InstanceConfigSetPropRequest(props.id, field, prop, value)); } return { @@ -144,13 +144,13 @@ export default function InstanceViewPage(props) { } else if (key === "extract") { control.sendTo( { instanceId }, - new libData.InstanceExtractPlayersRequest(), + new lib.InstanceExtractPlayersRequest(), ).catch(notifyErrorHandler("Error extracting player data")); } else if (key === "kill") { control.sendTo( { instanceId }, - new libData.InstanceKillRequest(), + new lib.InstanceKillRequest(), ).catch(notifyErrorHandler("Error killing instance")); } else if (key === "delete") { @@ -161,7 +161,7 @@ export default function InstanceViewPage(props) { okButtonProps: { danger: true }, onOk: () => { control.send( - new libData.InstanceDeleteRequest(instanceId) + new lib.InstanceDeleteRequest(instanceId) ).then(() => { navigate("/instances"); }).catch(notifyErrorHandler("Error deleting instance")); diff --git a/packages/web_ui/src/components/InstancesPage.jsx b/packages/web_ui/src/components/InstancesPage.jsx index 36b764cf..1e4822c8 100644 --- a/packages/web_ui/src/components/InstancesPage.jsx +++ b/packages/web_ui/src/components/InstancesPage.jsx @@ -2,7 +2,7 @@ import React, { useContext, useState } from "react"; import { useNavigate } from "react-router-dom"; import { Button, Form, Input, Modal } from "antd"; -import { libConfig, libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import { useAccount } from "../model/account"; import ControlContext from "./ControlContext"; @@ -26,11 +26,11 @@ function CreateInstanceButton(props) { return; } - let instanceConfig = new libConfig.InstanceConfig("control"); + let instanceConfig = new lib.InstanceConfig("control"); await instanceConfig.init(); instanceConfig.set("instance.name", values.instanceName); let serializedConfig = instanceConfig.serialize("controller"); - await control.send(new libData.InstanceCreateRequest(serializedConfig)); + await control.send(new lib.InstanceCreateRequest(serializedConfig)); setOpen(false); navigate(`/instances/${instanceConfig.get("instance.id")}/view`); } @@ -73,7 +73,7 @@ export default function InstancesPage() { && @@ -269,7 +269,7 @@ export default function UserViewPage() { type={banReasonDirty ? "primary" : "default"} onClick={() => { control.send( - new libData.UserSetBannedRequest( + new lib.UserSetBannedRequest( userName, false, true, form.getFieldValue("banReason") ) ).then(() => { diff --git a/packages/web_ui/src/components/UsersPage.jsx b/packages/web_ui/src/components/UsersPage.jsx index 457b0ef2..bb2a1367 100644 --- a/packages/web_ui/src/components/UsersPage.jsx +++ b/packages/web_ui/src/components/UsersPage.jsx @@ -2,7 +2,7 @@ import React, { useEffect, useContext, useState } from "react"; import { useNavigate } from "react-router-dom"; import { Button, Form, Input, Modal, Space, Table, Tag } from "antd"; -import { libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import { useAccount } from "../model/account"; import ControlContext from "./ControlContext"; @@ -29,7 +29,7 @@ function CreateUserButton() { return; } - await control.send(new libData.UserCreateRequest(values.userName)); + await control.send(new lib.UserCreateRequest(values.userName)); setOpen(false); navigate(`/users/${values.userName}/view`); } @@ -65,7 +65,7 @@ export default function UsersPage() { let [roles, setRoles] = useState(new Map()); useEffect(() => { - control.send(new libData.RoleListRequest()).then(newRoles => { + control.send(new lib.RoleListRequest()).then(newRoles => { setRoles(new Map(newRoles.map(role => [role.id, role]))); }).catch(() => { // ignore diff --git a/packages/web_ui/src/model/export_manifest.jsx b/packages/web_ui/src/model/export_manifest.jsx index 4f6a6219..67a6008b 100644 --- a/packages/web_ui/src/model/export_manifest.jsx +++ b/packages/web_ui/src/model/export_manifest.jsx @@ -1,6 +1,6 @@ import { useEffect, useContext, useState } from "react"; -import { libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import ControlContext from "../components/ControlContext"; @@ -11,7 +11,7 @@ export function useExportManifest() { let [exportManifest, setExportManifest] = useState(exportManifestCache || emptyCache); useEffect(() => { async function load() { - let modPack = await control.send(new libData.ModPackGetDefaultRequest()); + let modPack = await control.send(new lib.ModPackGetDefaultRequest()); if (modPack.exportManifest) { exportManifestCache = modPack.exportManifest; setExportManifest(exportManifestCache); diff --git a/packages/web_ui/src/model/host.jsx b/packages/web_ui/src/model/host.jsx index 3ab37961..398d0512 100644 --- a/packages/web_ui/src/model/host.jsx +++ b/packages/web_ui/src/model/host.jsx @@ -1,7 +1,7 @@ import { useEffect, useContext, useState } from "react"; import ControlContext from "../components/ControlContext"; -import { libData } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; export function useHost(id) { @@ -10,7 +10,7 @@ export function useHost(id) { function updateHost() { // XXX optimize by requesting only the host in question - control.send(new libData.HostListRequest()).then(hosts => { + control.send(new lib.HostListRequest()).then(hosts => { let match = hosts.find(i => i.id === id); if (!match) { setHost({ missing: true }); @@ -45,7 +45,7 @@ export function useHostList() { let [hostList, setHostList] = useState([]); function updateHostList() { - control.send(new libData.HostListRequest()).then(hosts => { + control.send(new lib.HostListRequest()).then(hosts => { setHostList(hosts); }); } diff --git a/packages/web_ui/src/model/instance.jsx b/packages/web_ui/src/model/instance.jsx index f0f337f8..ccbf587f 100644 --- a/packages/web_ui/src/model/instance.jsx +++ b/packages/web_ui/src/model/instance.jsx @@ -1,16 +1,16 @@ import { useEffect, useContext, useState } from "react"; import ControlContext from "../components/ControlContext"; -import { libData, libLogging } from "@clusterio/lib"; -const { logger } = libLogging; +import * as lib from "@clusterio/lib"; +const { logger } = lib; export function useInstance(id) { let control = useContext(ControlContext); let [instance, setInstance] = useState({ loading: true }); function updateInstance() { - control.send(new libData.InstanceDetailsGetRequest(id)).then(updatedInstance => { + control.send(new lib.InstanceDetailsGetRequest(id)).then(updatedInstance => { setInstance({ ...updatedInstance, present: true }); }).catch(err => { logger.error(`Failed to get instance: ${err}`); @@ -44,7 +44,7 @@ export function useInstanceList() { let [instanceList, setInstanceList] = useState([]); function updateInstanceList() { - control.send(new libData.InstanceDetailsListRequest()).then(instances => { + control.send(new lib.InstanceDetailsListRequest()).then(instances => { setInstanceList(instances); }).catch(err => { logger.error(`Failed to list instances:\n${err}`); diff --git a/packages/web_ui/src/model/mod_pack.jsx b/packages/web_ui/src/model/mod_pack.jsx index 2eb8b491..a5d08810 100644 --- a/packages/web_ui/src/model/mod_pack.jsx +++ b/packages/web_ui/src/model/mod_pack.jsx @@ -1,17 +1,17 @@ import { useContext, useEffect, useState } from "react"; -import { libData, libLogging } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import ControlContext from "../components/ControlContext"; -const { logger } = libLogging; +const { logger } = lib; export function useModPack(id) { let control = useContext(ControlContext); let [modPack, setModPack] = useState({ loading: true }); function updateModPack() { - control.send(new libData.ModPackGetRequest(id)).then(updatedModPack => { + control.send(new lib.ModPackGetRequest(id)).then(updatedModPack => { setModPack(updatedModPack); }).catch(err => { logger.error(`Failed to get mod pack: ${err}`); @@ -40,7 +40,7 @@ export function useModPackList() { let [modPackList, setModPackList] = useState([]); function updateModPackList() { - control.send(new libData.ModPackListRequest()).then(modPacks => { + control.send(new lib.ModPackListRequest()).then(modPacks => { setModPackList(modPacks); }).catch(err => { logger.error(`Failed to list mod packs:\n${err}`); diff --git a/packages/web_ui/src/model/mods.jsx b/packages/web_ui/src/model/mods.jsx index ee633a70..5e0f8569 100644 --- a/packages/web_ui/src/model/mods.jsx +++ b/packages/web_ui/src/model/mods.jsx @@ -1,18 +1,17 @@ import { useContext, useEffect, useState } from "react"; -import { libData, libLogging } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import ControlContext from "../components/ControlContext"; -const { logger } = libLogging; - +const { logger } = lib; export function useModList() { let control = useContext(ControlContext); let [modList, setModList] = useState([]); function updateModList() { - control.send(new libData.ModListRequest()).then(mods => { + control.send(new lib.ModListRequest()).then(mods => { setModList(mods); }).catch(err => { logger.error(`Failed to list mods:\n${err}`); diff --git a/packages/web_ui/src/model/saves.jsx b/packages/web_ui/src/model/saves.jsx index 51596d39..12489e3d 100644 --- a/packages/web_ui/src/model/saves.jsx +++ b/packages/web_ui/src/model/saves.jsx @@ -1,16 +1,16 @@ import { useEffect, useContext, useState } from "react"; import ControlContext from "../components/ControlContext"; -import { libData, libLogging } from "@clusterio/lib"; -const { logger } = libLogging; +import * as lib from "@clusterio/lib"; +const { logger } = lib; export function useSaves(instanceId) { let control = useContext(ControlContext); let [saves, setSaves] = useState([]); function updateSaves() { - control.sendTo({ instanceId }, new libData.InstanceListSavesRequest()).then(updatedSaves => { + control.sendTo({ instanceId }, new lib.InstanceListSavesRequest()).then(updatedSaves => { setSaves(updatedSaves); }).catch(err => { logger.error(`Failed to list instance saves: ${err}`); diff --git a/packages/web_ui/src/model/user.jsx b/packages/web_ui/src/model/user.jsx index 019ce6bd..709152df 100644 --- a/packages/web_ui/src/model/user.jsx +++ b/packages/web_ui/src/model/user.jsx @@ -2,8 +2,9 @@ import React, { useEffect, useContext, useState } from "react"; import { Tag } from "antd"; import ControlContext from "../components/ControlContext"; -import { libData, libLogging } from "@clusterio/lib"; -const { logger } = libLogging; +import * as lib from "@clusterio/lib"; + +const { logger } = lib; function calculateLastSeen(user, instanceId) { let stats; @@ -56,7 +57,7 @@ export function useUser(name) { let [user, setUser] = useState({ loading: true }); function updateUser() { - control.send(new libData.UserGetRequest(name)).then(updatedUser => { + control.send(new lib.UserGetRequest(name)).then(updatedUser => { setUser({ ...updatedUser, present: true }); }).catch(err => { logger.error(`Failed to get user: ${err}`); @@ -90,7 +91,7 @@ export function useUserList() { let [userList, setUserList] = useState([]); function updateUserList() { - control.send(new libData.UserListRequest()).then(users => { + control.send(new lib.UserListRequest()).then(users => { setUserList(users); }).catch(err => { logger.error(`Failed to list users:\n${err}`); diff --git a/packages/web_ui/src/util/notify.jsx b/packages/web_ui/src/util/notify.jsx index 420ff83f..86bc79f5 100644 --- a/packages/web_ui/src/util/notify.jsx +++ b/packages/web_ui/src/util/notify.jsx @@ -1,6 +1,5 @@ import { notification } from "antd"; -import { libLogging } from "@clusterio/lib"; -const { logger } = libLogging; +import { logger } from "@clusterio/lib"; export default function notify(message, type = "info", description = undefined) { diff --git a/packages/web_ui/src/util/websocket.jsx b/packages/web_ui/src/util/websocket.jsx index 7a4f4b9f..3f06a68c 100644 --- a/packages/web_ui/src/util/websocket.jsx +++ b/packages/web_ui/src/util/websocket.jsx @@ -1,13 +1,13 @@ -import { libData, libErrors, libLink, libLogging, libPlugin } from "@clusterio/lib"; -const { logFilter, logger } = libLogging; +import * as lib from "@clusterio/lib"; import packageJson from "../../package.json"; +const { logFilter, logger } = lib; /** * Connector for control connection to controller * @private */ -export class ControlConnector extends libLink.WebSocketClientConnector { +export class ControlConnector extends lib.WebSocketClientConnector { constructor(url, maxReconnectDelay) { super(url, maxReconnectDelay); this.token = null; @@ -20,8 +20,8 @@ export class ControlConnector extends libLink.WebSocketClientConnector { logger.verbose("Connector | registering control"); this.sendHandshake( - new libData.MessageRegisterControl( - new libData.RegisterControlData( + new lib.MessageRegisterControl( + new lib.RegisterControlData( this.token, "Clusterio Web UI", packageJson.version, @@ -37,13 +37,13 @@ export class ControlConnector extends libLink.WebSocketClientConnector { * Connects to the controller over WebSocket and sends commands to it. * @static */ -export class Control extends libLink.Link { +export class Control extends lib.Link { constructor(connector, plugins) { super(connector); /** * Mapping of plugin names to their instance for loaded plugins. - * @type {Map} + * @type {Map} */ this.plugins = plugins; for (let plugin of plugins.values()) { @@ -118,15 +118,15 @@ export class Control extends libLink.Link { }); } - this.handle(libData.AccountUpdateEvent, this.handleAccountUpdateEvent.bind(this)); - this.handle(libData.HostUpdateEvent, this.handleHostUpdateEvent.bind(this)); - this.handle(libData.InstanceDetailsUpdateEvent, this.handleInstanceDetailsUpdateEvent.bind(this)); - this.handle(libData.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this)); - this.handle(libData.ModPackUpdateEvent, this.handleModPackUpdateEvent.bind(this)); - this.handle(libData.ModUpdateEvent, this.handleModUpdateEvent.bind(this)); - this.handle(libData.UserUpdateEvent, this.handleUserUpdateEvent.bind(this)); - this.handle(libData.LogMessageEvent, this.handleLogMessageEvent.bind(this)); - this.handle(libData.DebugWsMessageEvent, this.handleDebugWsMessageEvent.bind(this)); + this.handle(lib.AccountUpdateEvent, this.handleAccountUpdateEvent.bind(this)); + this.handle(lib.HostUpdateEvent, this.handleHostUpdateEvent.bind(this)); + this.handle(lib.InstanceDetailsUpdateEvent, this.handleInstanceDetailsUpdateEvent.bind(this)); + this.handle(lib.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this)); + this.handle(lib.ModPackUpdateEvent, this.handleModPackUpdateEvent.bind(this)); + this.handle(lib.ModUpdateEvent, this.handleModUpdateEvent.bind(this)); + this.handle(lib.UserUpdateEvent, this.handleUserUpdateEvent.bind(this)); + this.handle(lib.LogMessageEvent, this.handleLogMessageEvent.bind(this)); + this.handle(lib.DebugWsMessageEvent, this.handleDebugWsMessageEvent.bind(this)); } async handleAccountUpdateEvent(event) { @@ -206,7 +206,7 @@ export class Control extends libLink.Link { return; } - await this.send(new libData.HostSetSubscriptionsRequest( + await this.send(new lib.HostSetSubscriptionsRequest( this.hostUpdateHandlers.has(null), [...this.hostUpdateHandlers.keys()].filter(e => e !== null), )); @@ -263,7 +263,7 @@ export class Control extends libLink.Link { return; } - await this.send(new libData.InstanceDetailsSetSubscriptionsRequest( + await this.send(new lib.InstanceDetailsSetSubscriptionsRequest( this.instanceUpdateHandlers.has(null), [...this.instanceUpdateHandlers.keys()].filter(e => e !== null), )); @@ -317,7 +317,7 @@ export class Control extends libLink.Link { return; } - await this.send(new libData.InstanceSetSaveListSubscriptionsRequest( + await this.send(new lib.InstanceSetSaveListSubscriptionsRequest( false, [...this.saveListUpdateHandlers.keys()], )); @@ -375,7 +375,7 @@ export class Control extends libLink.Link { return; } - await this.send(new libData.ModPackSetSubscriptionsRequest( + await this.send(new lib.ModPackSetSubscriptionsRequest( this.modPackUpdateHandlers.has(null), [...this.modPackUpdateHandlers.keys()].filter(k => k !== null), )); @@ -433,7 +433,7 @@ export class Control extends libLink.Link { return; } - await this.send(new libData.ModSetSubscriptionsRequest( + await this.send(new lib.ModSetSubscriptionsRequest( this.modUpdateHandlers.has(null), [...this.modUpdateHandlers.keys()].filter(k => k !== null), )); @@ -490,7 +490,7 @@ export class Control extends libLink.Link { return; } - await this.send(new libData.UserSetSubscriptionsRequest( + await this.send(new lib.UserSetSubscriptionsRequest( this.userUpdateHandlers.has(null), [...this.userUpdateHandlers.keys()].filter(e => e !== null), )); @@ -565,7 +565,7 @@ export class Control extends libLink.Link { } } - await this.send(new libData.LogSetSubscriptionsRequest(all, controller, hostIds, instanceIds, null)); + await this.send(new lib.LogSetSubscriptionsRequest(all, controller, hostIds, instanceIds, null)); } async handleDebugWsMessageEvent(message) { @@ -577,7 +577,7 @@ export class Control extends libLink.Link { try { await this.connector.disconnect(); } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { throw err; } } diff --git a/plugins/global_chat/control.js b/plugins/global_chat/control.js index 62cd5b5c..c2ffad66 100644 --- a/plugins/global_chat/control.js +++ b/plugins/global_chat/control.js @@ -1,13 +1,12 @@ "use strict"; -const libPlugin = require("@clusterio/lib/plugin"); +const { BaseControlPlugin, CommandTree, Command } = require("@clusterio/lib"); const { ChatEvent } = require("./messages"); -const libCommand = require("@clusterio/lib/command"); -const globalChatCommands = new libCommand.CommandTree({ +const globalChatCommands = new CommandTree({ name: "global-chat", description: "Global Chat plugin commands", }); -globalChatCommands.add(new libCommand.Command({ +globalChatCommands.add(new Command({ definition: ["shout ", "Send message to all instances", (yargs) => { yargs.positional("message", { describe: "message to send", type: "string" }); }], @@ -16,7 +15,7 @@ globalChatCommands.add(new libCommand.Command({ }, })); -class ControlPlugin extends libPlugin.BaseControlPlugin { +class ControlPlugin extends BaseControlPlugin { async addCommands(rootCommand) { rootCommand.add(globalChatCommands); } diff --git a/plugins/global_chat/instance.js b/plugins/global_chat/instance.js index c7e35b57..4eaea8ac 100644 --- a/plugins/global_chat/instance.js +++ b/plugins/global_chat/instance.js @@ -2,8 +2,7 @@ * @module */ "use strict"; -const libPlugin = require("@clusterio/lib/plugin"); -const libLuaTools = require("@clusterio/lib/lua_tools"); +const lib = require("@clusterio/lib"); const { ChatEvent } = require("./messages"); @@ -17,7 +16,7 @@ function removeTags(content) { return content.replace(/(\[gps=-?\d+,-?\d+\]|\[train=\d+\])/g, ""); } -class InstancePlugin extends libPlugin.BaseInstancePlugin { +class InstancePlugin extends lib.BaseInstancePlugin { async init() { this.messageQueue = []; this.instance.handle(ChatEvent, this.handleChatEvent.bind(this)); @@ -35,7 +34,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { async handleChatEvent(event) { // TODO check if cross server chat is enabled let content = `[${event.instanceName}] ${removeTags(event.content)}`; - await this.sendRcon(`/sc game.print('${libLuaTools.escapeString(content)}')`, true); + await this.sendRcon(`/sc game.print('${lib.escapeString(content)}')`, true); } sendChat(message) { diff --git a/plugins/global_chat/test/plugin.js b/plugins/global_chat/test/plugin.js index 4b147d92..e0ac9522 100644 --- a/plugins/global_chat/test/plugin.js +++ b/plugins/global_chat/test/plugin.js @@ -1,6 +1,6 @@ "use strict"; const assert = require("assert").strict; -const libLink = require("@clusterio/lib/link"); +const lib = require("@clusterio/lib"); const mock = require("../../../test/mock"); const lines = require("../../../test/lib/factorio/lines"); @@ -26,7 +26,7 @@ describe("global_chat plugin", function() { let instancePlugin; before(async function() { - libLink.Link.register(ChatEvent); + lib.Link.register(ChatEvent); instancePlugin = new instance.InstancePlugin(info, new mock.MockInstance(), new mock.MockHost()); await instancePlugin.init(); }); diff --git a/plugins/inventory_sync/controller.js b/plugins/inventory_sync/controller.js index 34cc2bb0..ee7834a1 100644 --- a/plugins/inventory_sync/controller.js +++ b/plugins/inventory_sync/controller.js @@ -2,8 +2,7 @@ const fs = require("fs-extra"); const path = require("path"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libPlugin = require("@clusterio/lib/plugin"); +const lib = require("@clusterio/lib"); const { AcquireRequest, @@ -34,11 +33,11 @@ async function saveDatabase(controllerConfig, playerDatastore, logger) { let file = path.resolve(controllerConfig.get("controller.database_directory"), "inventories.json"); logger.verbose(`writing ${file}`); let content = JSON.stringify(Array.from(playerDatastore)); - await libFileOps.safeOutputFile(file, content); + await lib.safeOutputFile(file, content); } } -class ControllerPlugin extends libPlugin.BaseControllerPlugin { +class ControllerPlugin extends lib.BaseControllerPlugin { async init() { this.acquiredPlayers = new Map(); this.playerDatastore = await loadDatabase(this.controller.config, this.logger); diff --git a/plugins/inventory_sync/info.js b/plugins/inventory_sync/info.js index 9b341fcd..30544da5 100644 --- a/plugins/inventory_sync/info.js +++ b/plugins/inventory_sync/info.js @@ -1,8 +1,8 @@ "use strict"; -const { libConfig, libUsers } = require("@clusterio/lib"); +const lib = require("@clusterio/lib"); let messages = require("./messages"); -class ControllerConfigGroup extends libConfig.PluginConfigGroup { } +class ControllerConfigGroup extends lib.PluginConfigGroup { } ControllerConfigGroup.defaultAccess = ["controller", "host", "control"]; ControllerConfigGroup.groupName = "inventory_sync"; ControllerConfigGroup.define({ @@ -22,7 +22,7 @@ ControllerConfigGroup.define({ }); ControllerConfigGroup.finalize(); -class InstanceConfigGroup extends libConfig.PluginConfigGroup { } +class InstanceConfigGroup extends lib.PluginConfigGroup { } InstanceConfigGroup.defaultAccess = ["controller", "host", "control"]; InstanceConfigGroup.groupName = "inventory_sync"; InstanceConfigGroup.define({ @@ -34,7 +34,7 @@ InstanceConfigGroup.define({ }); InstanceConfigGroup.finalize(); -libUsers.definePermission({ +lib.definePermission({ name: "inventory_sync.inventory.view", title: "View player inventories", description: "View player inventories", diff --git a/plugins/inventory_sync/instance.js b/plugins/inventory_sync/instance.js index 8447a670..9a696a71 100644 --- a/plugins/inventory_sync/instance.js +++ b/plugins/inventory_sync/instance.js @@ -2,16 +2,13 @@ * @module */ "use strict"; -const libErrors = require("@clusterio/lib/errors"); -const libPlugin = require("@clusterio/lib/plugin"); -const libLuaTools = require("@clusterio/lib/lua_tools"); +const lib = require("@clusterio/lib"); const { AcquireRequest, ReleaseRequest, UploadRequest, DownloadRequest, - DatabaseStatsRequest, } = require("./messages"); /** @@ -24,7 +21,7 @@ function chunkify(chunkSize, string) { return string.match(new RegExp(`.{1,${chunkSize}}`, "g")); } -class InstancePlugin extends libPlugin.BaseInstancePlugin { +class InstancePlugin extends lib.BaseInstancePlugin { async init() { this.playersToRelease = new Set(); this.disconnecting = false; @@ -82,14 +79,14 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { message: acquireResponse.message, }; } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { this.logger.error(`Unexpected error sending aquire request:\n${err.stack}`); response.message = err.message; } } } - let json = libLuaTools.escapeString(JSON.stringify(response)); + let json = lib.escapeString(JSON.stringify(response)); await this.sendRcon(`/sc inventory_sync.acquire_response("${json}")`, true); } @@ -101,7 +98,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { try { await this.instance.sendTo("controller", new ReleaseRequest(this.instance.id, request.player_name)); } catch (err) { - if (err instanceof libErrors.SessionLost) { + if (err instanceof lib.SessionLost) { this.playersToRelease.set(request.player_name); } else { this.logger.error(`Unexpected error releasing player ${request.player_name}:\n${err.stack}`); @@ -122,7 +119,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { ); } catch (err) { - if (!(err instanceof libErrors.SessionLost)) { + if (!(err instanceof lib.SessionLost)) { this.logger.error(`Unexpected error uploading inventory for ${player_data.name}:\n${err.stack}`); } return; @@ -149,7 +146,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { this.logger.verbose(`Sending inventory for ${playerName} in ${chunks.length} chunks`); for (let i = 0; i < chunks.length; i++) { // this.logger.verbose(`Sending chunk ${i+1} of ${chunks.length}`) - const chunk = libLuaTools.escapeString(chunks[i]); + const chunk = lib.escapeString(chunks[i]); await this.sendRcon( `/sc inventory_sync.download_inventory('${playerName}','${chunk}',${i + 1},${chunks.length})`, true diff --git a/plugins/inventory_sync/web/index.jsx b/plugins/inventory_sync/web/index.jsx index 5cfe9030..d3c9218f 100644 --- a/plugins/inventory_sync/web/index.jsx +++ b/plugins/inventory_sync/web/index.jsx @@ -1,6 +1,6 @@ import React, { useContext, useEffect, useState } from "react"; -import { libPlugin } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import { PageLayout, ControlContext } from "@clusterio/web_ui"; import { DatabaseStatsRequest } from "../messages"; @@ -28,7 +28,7 @@ function InventoryPage() { ; } -export class WebPlugin extends libPlugin.BaseWebPlugin { +export class WebPlugin extends lib.BaseWebPlugin { async init() { this.pages = [ { diff --git a/plugins/player_auth/controller.js b/plugins/player_auth/controller.js index aab1ad2c..95d63fc2 100644 --- a/plugins/player_auth/controller.js +++ b/plugins/player_auth/controller.js @@ -7,9 +7,8 @@ const express = require("express"); const util = require("util"); const jwt = require("jsonwebtoken"); -const libPlugin = require("@clusterio/lib/plugin"); -const libErrors = require("@clusterio/lib/errors"); -const { basicType } = require("@clusterio/lib/helpers"); +const lib = require("@clusterio/lib"); +const { basicType } = lib; const { FetchPlayerCodeRequest, SetVerifyCodeRequest } = require("./messages"); @@ -30,7 +29,7 @@ async function generateCode(length) { } -class ControllerPlugin extends libPlugin.BaseControllerPlugin { +class ControllerPlugin extends lib.BaseControllerPlugin { async init() { // Store of validation attempts by players this.players = new Map(); @@ -174,12 +173,12 @@ class ControllerPlugin extends libPlugin.BaseControllerPlugin { async handleSetVerifyCodeRequest(request) { let { player, verifyCode } = request; if (!this.players.has(player)) { - throw new libErrors.RequestError("invalid player"); + throw new lib.RequestError("invalid player"); } let entry = this.players.get(player); if (entry.expires < Date.now()) { - throw new libErrors.RequestError("invalid player"); + throw new lib.RequestError("invalid player"); } entry.verifyCode = verifyCode; diff --git a/plugins/player_auth/info.js b/plugins/player_auth/info.js index ebe16f55..9de9094c 100644 --- a/plugins/player_auth/info.js +++ b/plugins/player_auth/info.js @@ -1,9 +1,9 @@ "use strict"; -let { libConfig } = require("@clusterio/lib"); +const lib = require("@clusterio/lib"); let messages = require("./messages"); -class ControllerConfigGroup extends libConfig.PluginConfigGroup {} +class ControllerConfigGroup extends lib.PluginConfigGroup {} ControllerConfigGroup.defaultAccess = ["controller", "host", "control"]; ControllerConfigGroup.groupName = "player_auth"; ControllerConfigGroup.define({ diff --git a/plugins/player_auth/instance.js b/plugins/player_auth/instance.js index 3f0b5f43..ffb740ce 100644 --- a/plugins/player_auth/instance.js +++ b/plugins/player_auth/instance.js @@ -2,12 +2,12 @@ * @module */ "use strict"; -const libPlugin = require("@clusterio/lib/plugin"); +const lib = require("@clusterio/lib"); const { FetchPlayerCodeRequest, SetVerifyCodeRequest } = require("./messages"); -class InstancePlugin extends libPlugin.BaseInstancePlugin { +class InstancePlugin extends lib.BaseInstancePlugin { async init() { if (!this.instance.config.get("factorio.enable_save_patching")) { throw new Error("player_auth plugin requires save patching."); diff --git a/plugins/player_auth/test/plugin.js b/plugins/player_auth/test/plugin.js index f764a049..d55d12ac 100644 --- a/plugins/player_auth/test/plugin.js +++ b/plugins/player_auth/test/plugin.js @@ -9,8 +9,7 @@ const controller = require("../controller"); const instance = require("../instance"); const info = require("../info"); const { FetchPlayerCodeRequest, SetVerifyCodeRequest } = require("../messages"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); +const lib = require("@clusterio/lib"); describe("player_auth", function() { @@ -312,7 +311,7 @@ describe("player_auth", function() { controllerPlugin.handleSetVerifyCodeRequest( new SetVerifyCodeRequest("invalid", "invalid") ), - new libErrors.RequestError("invalid player") + new lib.RequestError("invalid player") ); }); it("should throw if player code has expired", async function() { @@ -322,7 +321,7 @@ describe("player_auth", function() { controllerPlugin.handleSetVerifyCodeRequest( new SetVerifyCodeRequest("expired", "expired") ), - new libErrors.RequestError("invalid player") + new lib.RequestError("invalid player") ); }); }); @@ -379,8 +378,8 @@ describe("player_auth", function() { instancePlugin.instance.server.reset(); instancePlugin.instance.connector.once("send", message => { instancePlugin.instance.connector.emit("message", - new libData.MessageResponseError(1, message.dst, message.src, - new libData.ResponseError("controller error") + new lib.MessageResponseError(1, message.dst, message.src, + new lib.ResponseError("controller error") ) ); }); @@ -392,7 +391,7 @@ describe("player_auth", function() { instancePlugin.instance.server.reset(); instancePlugin.instance.connector.once("send", message => { instancePlugin.instance.connector.emit("message", - new libData.MessageResponse(1, message.dst, message.src, + new lib.MessageResponse(1, message.dst, message.src, new FetchPlayerCodeRequest.Response("code", "controller-url") ) ); @@ -407,7 +406,7 @@ describe("player_auth", function() { instancePlugin.instance.server.reset(); instancePlugin.instance.connector.once("send", message => { instancePlugin.instance.connector.emit("message", - new libData.MessageResponse(1, message.dst, message.src) + new lib.MessageResponse(1, message.dst, message.src) ); }); await instancePlugin.handleEvent( @@ -420,8 +419,8 @@ describe("player_auth", function() { instancePlugin.instance.server.reset(); instancePlugin.instance.connector.once("send", message => { instancePlugin.instance.connector.emit("message", - new libData.MessageResponseError(1, message.dst, message.src, - new libData.ResponseError("controller error") + new lib.MessageResponseError(1, message.dst, message.src, + new lib.ResponseError("controller error") ) ); }); diff --git a/plugins/player_auth/web/index.jsx b/plugins/player_auth/web/index.jsx index 6ea302a2..0ad8fb62 100644 --- a/plugins/player_auth/web/index.jsx +++ b/plugins/player_auth/web/index.jsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; -import { libPlugin } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import { notifyErrorHandler } from "@clusterio/web_ui"; import { Button, Form, Input, Spin, Typography } from "antd"; @@ -146,7 +146,7 @@ function LoginForm(props) { } -export class WebPlugin extends libPlugin.BaseWebPlugin { +export class WebPlugin extends lib.BaseWebPlugin { async init() { this.logger.info("Player Auth init"); this.loginForms = [{ diff --git a/plugins/research_sync/controller.js b/plugins/research_sync/controller.js index 4a71d4fd..dc82ead3 100644 --- a/plugins/research_sync/controller.js +++ b/plugins/research_sync/controller.js @@ -2,9 +2,8 @@ const fs = require("fs-extra"); const path = require("path"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libPlugin = require("@clusterio/lib/plugin"); -const RateLimiter = require("@clusterio/lib/RateLimiter"); +const lib = require("@clusterio/lib"); +const { RateLimiter } = lib; const { ContributionEvent, @@ -34,10 +33,10 @@ async function loadTechnologies(controllerConfig, logger) { async function saveTechnologies(controllerConfig, technologies, logger) { let filePath = path.join(controllerConfig.get("controller.database_directory"), "technologies.json"); logger.verbose(`writing ${filePath}`); - await libFileOps.safeOutputFile(filePath, JSON.stringify([...technologies.entries()], null, 4)); + await lib.safeOutputFile(filePath, JSON.stringify([...technologies.entries()], null, 4)); } -class ControllerPlugin extends libPlugin.BaseControllerPlugin { +class ControllerPlugin extends lib.BaseControllerPlugin { async init() { this.technologies = await loadTechnologies(this.controller.config, this.logger); this.progressRateLimiter = new RateLimiter({ diff --git a/plugins/research_sync/instance.js b/plugins/research_sync/instance.js index 5089c408..9529ff10 100644 --- a/plugins/research_sync/instance.js +++ b/plugins/research_sync/instance.js @@ -1,6 +1,5 @@ "use strict"; -const libPlugin = require("@clusterio/lib/plugin"); -const libLuaTools = require("@clusterio/lib/lua_tools"); +const lib = require("@clusterio/lib"); const { ContributionEvent, ProgressEvent, @@ -10,7 +9,7 @@ const { } = require("./messages"); -class InstancePlugin extends libPlugin.BaseInstancePlugin { +class InstancePlugin extends lib.BaseInstancePlugin { unexpectedError(err) { this.logger.error(`Unexpected error:\n${err.stack}`); } @@ -40,7 +39,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { if (!this.syncStarted || !["starting", "running"].includes(this.instance.status)) { return; } - let techsJson = libLuaTools.escapeString(JSON.stringify(event.technologies)); + let techsJson = lib.escapeString(JSON.stringify(event.technologies)); await this.sendOrderedRcon(`/sc research_sync.update_progress("${techsJson}")`, true); } @@ -54,7 +53,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { } let { name, level } = event; await this.sendOrderedRcon( - `/sc research_sync.research_technology("${libLuaTools.escapeString(name)}", ${level})`, true + `/sc research_sync.research_technology("${lib.escapeString(name)}", ${level})`, true ); } @@ -89,7 +88,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { } if (techsToSync.length) { - let syncJson = libLuaTools.escapeString(JSON.stringify(techsToSync)); + let syncJson = lib.escapeString(JSON.stringify(techsToSync)); await this.sendOrderedRcon(`/sc research_sync.sync_technologies("${syncJson}")`, true); } } diff --git a/plugins/research_sync/messages.js b/plugins/research_sync/messages.js index c131021e..7e37ec05 100644 --- a/plugins/research_sync/messages.js +++ b/plugins/research_sync/messages.js @@ -1,5 +1,5 @@ "use strict"; -const { libData } = require("@clusterio/lib"); +const lib = require("@clusterio/lib"); class ContributionEvent { static type = "event"; @@ -41,7 +41,7 @@ class ProgressEvent { static dst = "instance"; static plugin = "research_sync"; - /** @type {Array<>} */ + /** @type {Array} */ technologies; constructor(technologies) { @@ -167,7 +167,7 @@ class SyncTechnologiesRequest { return new this(json.map(e => Technology.fromJSON(e))); } - static Response = libData.jsonArray(Technology); + static Response = lib.jsonArray(Technology); } module.exports = { diff --git a/plugins/statistics_exporter/info.js b/plugins/statistics_exporter/info.js index 8b424049..14f60bee 100644 --- a/plugins/statistics_exporter/info.js +++ b/plugins/statistics_exporter/info.js @@ -1,7 +1,7 @@ "use strict"; -const { libConfig } = require("@clusterio/lib"); +const lib = require("@clusterio/lib"); -class InstanceConfigGroup extends libConfig.PluginConfigGroup {} +class InstanceConfigGroup extends lib.PluginConfigGroup {} InstanceConfigGroup.defaultAccess = ["controller", "host", "control"]; InstanceConfigGroup.groupName = "statistics_exporter"; InstanceConfigGroup.define({ diff --git a/plugins/statistics_exporter/instance.js b/plugins/statistics_exporter/instance.js index 5643acbe..5c9d699f 100644 --- a/plugins/statistics_exporter/instance.js +++ b/plugins/statistics_exporter/instance.js @@ -1,7 +1,6 @@ "use strict"; -const libPlugin = require("@clusterio/lib/plugin"); -const { Gauge } = require("@clusterio/lib/prometheus"); -const libHelpers = require("@clusterio/lib/helpers"); +const lib = require("@clusterio/lib"); +const { Gauge } = lib; const instancePlayerCount = new Gauge( @@ -37,7 +36,7 @@ function setForceFlowStatistic(instanceId, forceName, statisticName, direction, } -class InstancePlugin extends libPlugin.BaseInstancePlugin { +class InstancePlugin extends lib.BaseInstancePlugin { async init() { if (!this.instance.config.get("factorio.enable_save_patching")) { throw new Error("statistics_exporter plugin requires save patching."); @@ -86,7 +85,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { // stream is overloaded. Should the timeout be exceeded the // previous values for the metrics will end up being sent to controller. let timeout = this.instance.config.get("statistics_exporter.command_timeout") * 1000; - await libHelpers.timeout(this.gatherMetrics(), timeout); + await lib.timeout(this.gatherMetrics(), timeout); } } diff --git a/plugins/subspace_storage/controller.js b/plugins/subspace_storage/controller.js index ed8dd86a..823b7566 100644 --- a/plugins/subspace_storage/controller.js +++ b/plugins/subspace_storage/controller.js @@ -2,11 +2,8 @@ const fs = require("fs-extra"); const path = require("path"); -const libDatabase = require("@clusterio/lib/database"); -const libFileOps = require("@clusterio/lib/file_ops"); -const libPlugin = require("@clusterio/lib/plugin"); -const { Counter, Gauge } = require("@clusterio/lib/prometheus"); -const RateLimiter = require("@clusterio/lib/RateLimiter"); +const lib = require("@clusterio/lib"); +const { Counter, Gauge, RateLimiter } = lib; const routes = require("./routes"); const dole = require("./dole"); @@ -43,12 +40,12 @@ async function loadDatabase(config, logger) { logger.verbose(`Loading ${itemsPath}`); try { let content = await fs.readFile(itemsPath); - return new libDatabase.ItemDatabase(JSON.parse(content)); + return new lib.ItemDatabase(JSON.parse(content)); } catch (err) { if (err.code === "ENOENT") { logger.verbose("Creating new item database"); - return new libDatabase.ItemDatabase(); + return new lib.ItemDatabase(); } throw err; } @@ -59,13 +56,13 @@ async function saveDatabase(controllerConfig, items, logger) { let file = path.resolve(controllerConfig.get("controller.database_directory"), "items.json"); logger.verbose(`writing ${file}`); let content = JSON.stringify(items.serialize()); - await libFileOps.safeOutputFile(file, content); + await lib.safeOutputFile(file, content); } else if (items) { logger.error(`Item database too large, not saving (${items.size})`); } } -class ControllerPlugin extends libPlugin.BaseControllerPlugin { +class ControllerPlugin extends lib.BaseControllerPlugin { async init() { this.items = await loadDatabase(this.controller.config, this.logger); diff --git a/plugins/subspace_storage/dole.js b/plugins/subspace_storage/dole.js index a247e765..142530f3 100644 --- a/plugins/subspace_storage/dole.js +++ b/plugins/subspace_storage/dole.js @@ -1,7 +1,8 @@ "use strict"; const doleNN = require("./dole_nn_base"); -const { Gauge } = require("@clusterio/lib/prometheus"); +const lib = require("@clusterio/lib"); +const { Gauge } = lib; const prometheusNNDoleGauge = new Gauge( diff --git a/plugins/subspace_storage/info.js b/plugins/subspace_storage/info.js index 394bb4e9..828ed69a 100644 --- a/plugins/subspace_storage/info.js +++ b/plugins/subspace_storage/info.js @@ -1,8 +1,8 @@ "use strict"; -const { libConfig, libUsers } = require("@clusterio/lib"); +const lib = require("@clusterio/lib"); const messages = require("./messages"); -class ControllerConfigGroup extends libConfig.PluginConfigGroup {} +class ControllerConfigGroup extends lib.PluginConfigGroup {} ControllerConfigGroup.defaultAccess = ["controller", "host", "control"]; ControllerConfigGroup.groupName = "subspace_storage"; ControllerConfigGroup.define({ @@ -29,7 +29,7 @@ ControllerConfigGroup.define({ }); ControllerConfigGroup.finalize(); -class InstanceConfigGroup extends libConfig.PluginConfigGroup {} +class InstanceConfigGroup extends lib.PluginConfigGroup {} InstanceConfigGroup.defaultAccess = ["controller", "host", "control"]; InstanceConfigGroup.groupName = "subspace_storage"; InstanceConfigGroup.define({ @@ -41,7 +41,7 @@ InstanceConfigGroup.define({ }); InstanceConfigGroup.finalize(); -libUsers.definePermission({ +lib.definePermission({ name: "subspace_storage.storage.view", title: "View Subspace Storage", description: "View the items and fluids stored in the shared subspace.", diff --git a/plugins/subspace_storage/instance.js b/plugins/subspace_storage/instance.js index 2864f761..41b826db 100644 --- a/plugins/subspace_storage/instance.js +++ b/plugins/subspace_storage/instance.js @@ -1,17 +1,14 @@ "use strict"; -const libPlugin = require("@clusterio/lib/plugin"); -const libLuaTools = require("@clusterio/lib/lua_tools"); +const lib = require("@clusterio/lib"); const { - Item, PlaceEvent, RemoveRequest, GetStorageRequest, UpdateStorageEvent, - SetStorageSubscriptionRequest, } = require("./messages"); -class InstancePlugin extends libPlugin.BaseInstancePlugin { +class InstancePlugin extends lib.BaseInstancePlugin { unexpectedError(err) { this.logger.error(`Unexpected error:\n${err.stack}`); } @@ -46,7 +43,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { let items = await this.instance.sendTo("controller", new GetStorageRequest()); // TODO Diff with dump of invdata produce minimal command to sync - let itemsJson = libLuaTools.escapeString(JSON.stringify(items)); + let itemsJson = lib.escapeString(JSON.stringify(items)); await this.sendRcon(`/sc __subspace_storage__ UpdateInvData("${itemsJson}", true)`, true); } @@ -93,7 +90,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { this.logger.verbose(JSON.stringify(items)); } - let itemsJson = libLuaTools.escapeString(JSON.stringify(items)); + let itemsJson = lib.escapeString(JSON.stringify(items)); await this.sendRcon(`/sc __subspace_storage__ Import("${itemsJson}")`, true); } @@ -107,7 +104,7 @@ class InstancePlugin extends libPlugin.BaseInstancePlugin { // XXX this should be moved to instance/clusterio api items.push(["signal-unixtime", Math.floor(Date.now()/1000)]); - let itemsJson = libLuaTools.escapeString(JSON.stringify(items)); + let itemsJson = lib.escapeString(JSON.stringify(items)); let task = this.sendRcon(`/sc __subspace_storage__ UpdateInvData("${itemsJson}")`, true); this.pendingTasks.add(task); task.finally(() => { this.pendingTasks.delete(task); }); diff --git a/plugins/subspace_storage/messages.js b/plugins/subspace_storage/messages.js index 44a8ec8b..b27332eb 100644 --- a/plugins/subspace_storage/messages.js +++ b/plugins/subspace_storage/messages.js @@ -1,5 +1,5 @@ "use strict"; -const { libData } = require("@clusterio/lib"); +const lib = require("@clusterio/lib"); class Item { /** @type {string} */ @@ -89,7 +89,7 @@ class RemoveRequest { return new this(json.items); } - static Response = libData.jsonArray(Item); + static Response = lib.jsonArray(Item); } class GetStorageRequest { @@ -98,7 +98,7 @@ class GetStorageRequest { static dst = "controller"; static plugin = "subspace_storage"; static permission = "subspace_storage.storage.view"; - static Response = libData.jsonArray(Item); + static Response = lib.jsonArray(Item); } class UpdateStorageEvent { diff --git a/plugins/subspace_storage/web/index.jsx b/plugins/subspace_storage/web/index.jsx index aa1aa2b1..4121d995 100644 --- a/plugins/subspace_storage/web/index.jsx +++ b/plugins/subspace_storage/web/index.jsx @@ -1,7 +1,7 @@ import React, { useContext, useEffect, useState } from "react"; import { Input, Table, Typography } from "antd"; -import { libPlugin } from "@clusterio/lib"; +import * as lib from "@clusterio/lib"; import { notifyErrorHandler, useItemMetadata, useLocale, PageLayout, ControlContext } from "@clusterio/web_ui"; import { GetStorageRequest, SetStorageSubscriptionRequest } from "../messages"; @@ -114,7 +114,7 @@ function StoragePage() { ; } -export class WebPlugin extends libPlugin.BaseWebPlugin { +export class WebPlugin extends lib.BaseWebPlugin { async init() { this.pages = [ { diff --git a/test/controller/HttpCloser.js b/test/controller/HttpCloser.js index 77e89e5e..3dca01c5 100644 --- a/test/controller/HttpCloser.js +++ b/test/controller/HttpCloser.js @@ -7,7 +7,6 @@ const util = require("util"); const phin = require("phin"); -const { wait } = require("@clusterio/lib/helpers"); const HttpCloser = require("@clusterio/controller/src/HttpCloser"); // Time to wait during async operations to ensure they happened in order. diff --git a/test/controller/routes.js b/test/controller/routes.js index d5779cd5..0a5ec99a 100644 --- a/test/controller/routes.js +++ b/test/controller/routes.js @@ -6,7 +6,7 @@ const jwt = require("jsonwebtoken"); const http = require("http"); const phin = require("phin"); -const { wait } = require("@clusterio/lib/helpers"); +const { wait } = require("@clusterio/lib"); const routes = require("@clusterio/controller/src/routes"); const mock = require("../mock"); diff --git a/test/host.js b/test/host.js index 675ea203..0b3eddd0 100644 --- a/test/host.js +++ b/test/host.js @@ -2,13 +2,12 @@ const assert = require("assert").strict; const path = require("path"); -const libConfig = require("@clusterio/lib/config"); -const libData = require("@clusterio/lib/data"); +const lib = require("@clusterio/lib"); const Host = require("@clusterio/host/src/Host"); describe("Host testing", function() { before(function() { - libConfig.InstanceConfig.finalize(); + lib.InstanceConfig.finalize(); }); describe("discoverInstances()", function() { @@ -16,7 +15,7 @@ describe("Host testing", function() { let instancePath = path.join("test", "file", "instances"); let instanceInfos = await Host._discoverInstances(instancePath); - let referenceConfig = new libConfig.InstanceConfig("host"); + let referenceConfig = new lib.InstanceConfig("host"); await referenceConfig.init(); referenceConfig.set("instance.id", 1); referenceConfig.set("instance.name", "test"); @@ -45,7 +44,7 @@ describe("Host testing", function() { handleSyncUserListsEvent: Host.prototype.handleSyncUserListsEvent, syncLists(adminlist, banlist, whitelist) { return this.handleSyncUserListsEvent( - new libData.SyncUserListsEvent(adminlist, banlist, whitelist) + new lib.SyncUserListsEvent(adminlist, banlist, whitelist) ); }, }; @@ -56,8 +55,8 @@ describe("Host testing", function() { await mockHost.syncLists(["admin1", "admin2"], [], []); assert.deepEqual(mockHost.broadcasts, [ - new libData.InstanceAdminlistUpdateEvent("admin1", true), - new libData.InstanceAdminlistUpdateEvent("admin2", true), + new lib.InstanceAdminlistUpdateEvent("admin1", true), + new lib.InstanceAdminlistUpdateEvent("admin2", true), ]); }); @@ -65,7 +64,7 @@ describe("Host testing", function() { mockHost.adminlist.add("admin1").add("admin2"); await mockHost.syncLists(["admin1"], [], []); assert.deepEqual(mockHost.broadcasts, [ - new libData.InstanceAdminlistUpdateEvent("admin2", false), + new lib.InstanceAdminlistUpdateEvent("admin2", false), ]); }); @@ -74,8 +73,8 @@ describe("Host testing", function() { await mockHost.syncLists([], [], ["player1", "player2"]); assert.deepEqual(mockHost.broadcasts, [ - new libData.InstanceWhitelistUpdateEvent("player1", true), - new libData.InstanceWhitelistUpdateEvent("player2", true), + new lib.InstanceWhitelistUpdateEvent("player1", true), + new lib.InstanceWhitelistUpdateEvent("player2", true), ]); }); @@ -84,7 +83,7 @@ describe("Host testing", function() { await mockHost.syncLists([], [], ["player1"]); assert.deepEqual(mockHost.broadcasts, [ - new libData.InstanceWhitelistUpdateEvent("player2", false), + new lib.InstanceWhitelistUpdateEvent("player2", false), ]); }); @@ -93,8 +92,8 @@ describe("Host testing", function() { await mockHost.syncLists([], [["badie1", "greifing"], ["badie2", "annoying"]], []); assert.deepEqual(mockHost.broadcasts, [ - new libData.InstanceBanlistUpdateEvent("badie1", true, "greifing"), - new libData.InstanceBanlistUpdateEvent("badie2", true, "annoying"), + new lib.InstanceBanlistUpdateEvent("badie1", true, "greifing"), + new lib.InstanceBanlistUpdateEvent("badie2", true, "annoying"), ]); }); @@ -103,7 +102,7 @@ describe("Host testing", function() { await mockHost.syncLists([], [["badie1", "greifing"]], []); assert.deepEqual(mockHost.broadcasts, [ - new libData.InstanceBanlistUpdateEvent("badie2", false, ""), + new lib.InstanceBanlistUpdateEvent("badie2", false, ""), ]); }); }); diff --git a/test/host/Instance.js b/test/host/Instance.js index 224a4927..bc4e99fc 100644 --- a/test/host/Instance.js +++ b/test/host/Instance.js @@ -2,19 +2,17 @@ const assert = require("assert").strict; const path = require("path"); -const libConfig = require("@clusterio/lib/config"); -const libData = require("@clusterio/lib/data"); -const { wait } = require("@clusterio/lib/helpers"); -const PlayerStats = require("@clusterio/lib/PlayerStats"); +const lib = require("@clusterio/lib"); +const { PlayerStats, wait } = lib; const Instance = require("@clusterio/host/src/Instance"); const { MockConnector, MockServer } = require("../mock"); -const addr = libData.Address.fromShorthand; +const addr = lib.Address.fromShorthand; describe("class Instance", function() { before(function() { - libConfig.InstanceConfig.finalize(); + lib.InstanceConfig.finalize(); }); let src; @@ -22,7 +20,7 @@ describe("class Instance", function() { let instance; let connector; beforeEach(async function() { - let instanceConfig = new libConfig.InstanceConfig("host"); + let instanceConfig = new lib.InstanceConfig("host"); await instanceConfig.init(); instanceConfig.set("instance.name", "foo"); src = addr({ instanceId: instanceConfig.get("instance.id") }); @@ -64,9 +62,9 @@ describe("class Instance", function() { let stats = instance.playerStats.get("player"); assert.deepEqual( connector.sentMessages[0], - new libData.MessageEvent( + new lib.MessageEvent( 1, src, addr("controller"), "InstancePlayerUpdateEvent", - new libData.InstancePlayerUpdateEvent( + new lib.InstancePlayerUpdateEvent( "join", "player", undefined, new PlayerStats({ join_count: 1, @@ -109,9 +107,9 @@ describe("class Instance", function() { let stats = instance.playerStats.get("player"); assert.deepEqual( connector.sentMessages[1], - new libData.MessageEvent( + new lib.MessageEvent( 2, src, addr("controller"), "InstancePlayerUpdateEvent", - new libData.InstancePlayerUpdateEvent( + new lib.InstancePlayerUpdateEvent( "leave", "player", "quit", new PlayerStats({ join_count: 1, @@ -159,9 +157,9 @@ describe("class Instance", function() { let stats = instance.playerStats.get("foo"); assert.deepEqual( connector.sentMessages[1], - new libData.MessageEvent( + new lib.MessageEvent( 2, src, addr("controller"), "InstancePlayerUpdateEvent", - new libData.InstancePlayerUpdateEvent( + new lib.InstancePlayerUpdateEvent( "join", "foo", undefined, new PlayerStats({ join_count: 1, @@ -180,9 +178,9 @@ describe("class Instance", function() { let stats = instance.playerStats.get("player"); assert.deepEqual( connector.sentMessages[1], - new libData.MessageEvent( + new lib.MessageEvent( 2, src, addr("controller"), "InstancePlayerUpdateEvent", - new libData.InstancePlayerUpdateEvent( + new lib.InstancePlayerUpdateEvent( "leave", "player", "quit", new PlayerStats({ join_count: 1, diff --git a/test/integration/clusterio.js b/test/integration/clusterio.js index cb4f1744..8e01758d 100644 --- a/test/integration/clusterio.js +++ b/test/integration/clusterio.js @@ -6,12 +6,9 @@ const path = require("path"); const events = require("events"); const phin = require("phin"); +const lib = require("@clusterio/lib"); const libBuildMod = require("@clusterio/lib/build_mod"); -const libData = require("@clusterio/lib/data"); -const libHash = require("@clusterio/lib/hash"); -const libLink = require("@clusterio/lib/link"); -const libUsers = require("@clusterio/lib/users"); -const { wait } = require("@clusterio/lib/helpers"); +const { wait } = lib; const testStrings = require("../lib/factorio/test_strings"); const { @@ -21,7 +18,7 @@ const { async function getInstances() { - let instances = await getControl().send(new libData.InstanceDetailsListRequest()); + let instances = await getControl().send(new lib.InstanceDetailsListRequest()); return new Map(instances.map(instance => [instance.id, instance])); } @@ -45,11 +42,11 @@ async function uploadSave(instanceId, name, content) { } async function deleteSave(instanceId, save) { - await getControl().send(new libData.InstanceDeleteSaveRequest(instanceId, save)); + await getControl().send(new lib.InstanceDeleteSaveRequest(instanceId, save)); } async function getUsers() { - let users = await getControl().send(new libData.UserListRequest()); + let users = await getControl().send(new lib.UserListRequest()); return new Map(users.map(user => [user.name, user])); } @@ -95,12 +92,12 @@ describe("Integration of Clusterio", function() { describe("queryLogRequestHandler", function() { it("should honnor the limit", async function() { - let result = await getControl().send(new libData.LogQueryRequest(true, false, [], [], null, 10, "asc")); + let result = await getControl().send(new lib.LogQueryRequest(true, false, [], [], null, 10, "asc")); assert.equal(result.log.length, 10); }); it("should return entries by order", async function() { - let first = await getControl().send(new libData.LogQueryRequest(true, false, [], [], null, 1, "asc")); - let last = await getControl().send(new libData.LogQueryRequest(true, false, [], [], null, 1, "desc")); + let first = await getControl().send(new lib.LogQueryRequest(true, false, [], [], null, 1, "asc")); + let last = await getControl().send(new lib.LogQueryRequest(true, false, [], [], null, 1, "desc")); assert(first.log[0].timestamp < last.log[0].timestamp, "first log entry happened after last"); }); }); @@ -165,7 +162,7 @@ describe("Integration of Clusterio", function() { assert(sawConnected, "No host update with status connected was sent"); assert(sawDisconnected, "No host update with status disconnected was sent"); - let result = await getControl().send(new libData.HostListRequest()); + let result = await getControl().send(new lib.HostListRequest()); let hosts = new Map(result.map(instance => [instance.id, instance])); assert(hosts.has(5), "Host list was not updated"); }); @@ -178,7 +175,7 @@ describe("Integration of Clusterio", function() { await execCtl("controller config list"); }); it("should not leak auth_secret", async function() { - let result = await getControl().send(new libData.ControllerConfigGetRequest()); + let result = await getControl().send(new lib.ControllerConfigGetRequest()); let done = false; for (let group of result.serializedConfig.groups) { if (group.name === "controller") { @@ -193,7 +190,7 @@ describe("Integration of Clusterio", function() { describe("controller config set", function() { it("sets given config option", async function() { await execCtl('controller config set controller.name "Test Cluster"'); - let result = await getControl().send(new libData.ControllerConfigGetRequest()); + let result = await getControl().send(new lib.ControllerConfigGetRequest()); let done = false; for (let group of result.serializedConfig.groups) { if (group.name === "controller") { @@ -289,7 +286,7 @@ describe("Integration of Clusterio", function() { let exportPath = path.join("temp", "test", "static"); await fs.remove(exportPath); await execCtl("instance export-data test"); - let modPack = await getControl().send(new libData.ModPackGetDefaultRequest()); + let modPack = await getControl().send(new lib.ModPackGetDefaultRequest()); let assets = modPack.exportManifest.assets; assert(Object.keys(assets).length > 1, "Export assets is empty"); for (let key of ["settings", "prototypes", "item-metadata", "item-spritesheet", "locale"]) { @@ -338,7 +335,7 @@ describe("Integration of Clusterio", function() { let savesDir = path.join("temp", "test", "instances", "test", "saves"); await fs.copy(path.join(savesDir, "world.zip"), path.join(savesDir, "_autosave1.zip")); await execCtl("instance start test"); - let saves = await getControl().sendTo({ instanceId: 44 }, new libData.InstanceListSavesRequest()); + let saves = await getControl().sendTo({ instanceId: 44 }, new lib.InstanceListSavesRequest()); let running = saves.find(s => s.loaded); assert(running.name !== "_autosave1.zip"); }); @@ -349,7 +346,7 @@ describe("Integration of Clusterio", function() { slowTest(this); await execCtl("instance send-rcon test technobabble"); let { log } = await getControl().send( - new libData.LogQueryRequest(false, false, [], [44], null, 10, "desc") + new lib.LogQueryRequest(false, false, [], [44], null, 10, "desc") ); assert(log.some(info => /technobabble/.test(info.message)), "Command was not sent"); }); @@ -461,14 +458,14 @@ describe("Integration of Clusterio", function() { describe("user set-admin/whitelisted/banned", function() { async function getUser(name) { - return await getControl().send(new libData.UserGetRequest(name)); + return await getControl().send(new lib.UserGetRequest(name)); } let lists = [["admin", "isAdmin"], ["whitelisted", "isWhitelisted"], ["banned", "isBanned"]]; it("should add and remove the given user to the list", async function() { slowTest(this); getControl().userUpdates = []; - await getControl().send(new libData.UserCreateRequest("list_test")); + await getControl().send(new lib.UserCreateRequest("list_test")); let user = (await getUsers()).get("list_test"); for (let [listName, prop] of lists) { assert.equal(user[prop], false, `unexpected ${listName} status`); @@ -806,7 +803,7 @@ describe("Integration of Clusterio", function() { describe("mod-pack create", function() { it("should create a mod-pack", async function() { await execCtl("mod-pack create empty-pack 1.1.0"); - let modPacks = await getControl().send(new libData.ModPackListRequest()); + let modPacks = await getControl().send(new lib.ModPackListRequest()); assert(modPacks.some(modPack => modPack.name === "empty-pack"), "created pack is not in the list"); }); it("should allow setting all fields", async function() { @@ -819,10 +816,10 @@ describe("Integration of Clusterio", function() { "--double-setting runtime-global MyDouble 12.25 " + "--string-setting runtime-per-user MyString a-string" ); - let modPacks = await getControl().send(new libData.ModPackListRequest()); + let modPacks = await getControl().send(new lib.ModPackListRequest()); let modPack = modPacks.find(entry => entry.name === "full-pack"); assert(modPack, "created mod pack not found"); - let reference = libData.ModPack.fromJSON({}); + let reference = lib.ModPack.fromJSON({}); reference.id = modPack.id; reference.name = "full-pack"; reference.description = "Description"; @@ -851,7 +848,7 @@ describe("Integration of Clusterio", function() { describe("mod-pack import/export", function() { it("should should roundtrip a mod-pack", async function() { slowTest(this); - let reference = libData.ModPack.fromJSON({}); + let reference = lib.ModPack.fromJSON({}); reference.name = "imported-pack"; reference.description = "Description"; reference.factorioVersion = "0.17.59"; @@ -862,7 +859,7 @@ describe("Integration of Clusterio", function() { reference.settings["runtime-per-user"].set("MyString", { value: "a-string" }); await execCtl(`mod-pack import ${reference.toModPackString()}`); const result = await execCtl("mod-pack export imported-pack"); - const roundtrip = libData.ModPack.fromModPackString(result.stdout.trim()); + const roundtrip = lib.ModPack.fromModPackString(result.stdout.trim()); roundtrip.id = reference.id; assert.deepEqual(roundtrip, reference); }); @@ -871,7 +868,7 @@ describe("Integration of Clusterio", function() { describe("mod-pack edit", function() { it("runs", async function() { await execCtl("mod-pack edit full-pack --factorio-version 1.2.0"); - let modPacks = await getControl().send(new libData.ModPackListRequest()); + let modPacks = await getControl().send(new lib.ModPackListRequest()); let modPack = modPacks.find(entry => entry.name === "full-pack"); assert(modPack, "created mod pack not found"); assert.equal(modPack.factorioVersion, "1.2.0"); @@ -881,7 +878,7 @@ describe("Integration of Clusterio", function() { describe("mod-pack delete", function() { it("deletes the pack", async function() { await execCtl("mod-pack delete full-pack"); - let modPacks = await getControl().send(new libData.ModPackListRequest()); + let modPacks = await getControl().send(new lib.ModPackListRequest()); let modPack = modPacks.find(entry => entry.name === "full-pack"); assert(!modPack, "mod pack not deleted"); }); @@ -906,7 +903,7 @@ describe("Integration of Clusterio", function() { describe("mod show", function() { it("gives details of a mod", async function() { let result = await execCtl("mod show empty_mod 1.0.0"); - let hash = await libHash.hashFile(path.join("temp", "test", "mods", "empty_mod_1.0.0.zip")); + let hash = await lib.hashFile(path.join("temp", "test", "mods", "empty_mod_1.0.0.zip")); let stat = await fs.stat(path.join("temp", "test", "mods", "empty_mod_1.0.0.zip")); assert.equal( result.stdout, @@ -997,11 +994,11 @@ describe("Integration of Clusterio", function() { it("should create the given role", async function() { let args = "--description \"A temp role\" --permissions core.control.connect"; await execCtl(`role create temp ${args}`); - let roles = await getControl().send(new libData.RoleListRequest()); + let roles = await getControl().send(new lib.RoleListRequest()); let tempRole = roles.find(role => role.name === "temp"); assert.deepEqual( tempRole, - new libData.RawRole(5, "temp", "A temp role", ["core.control.connect"]) + new lib.RawRole(5, "temp", "A temp role", ["core.control.connect"]) ); }); }); @@ -1010,29 +1007,29 @@ describe("Integration of Clusterio", function() { it("should modify the given role", async function() { let args = "--name new --description \"A new role\" --set-perms"; await execCtl(`role edit temp ${args}`); - let roles = await getControl().send(new libData.RoleListRequest()); + let roles = await getControl().send(new lib.RoleListRequest()); let newRole = roles.find(role => role.name === "new"); - assert.deepEqual(newRole, new libData.RawRole(5, "new", "A new role", [])); + assert.deepEqual(newRole, new lib.RawRole(5, "new", "A new role", [])); }); it("should add permissions with --add-perms", async function() { let args = "--name new --add-perms core.host.list core.instance.list"; await execCtl(`role edit new ${args}`); - let roles = await getControl().send(new libData.RoleListRequest()); + let roles = await getControl().send(new lib.RoleListRequest()); let newRole = roles.find(role => role.name === "new"); assert.deepEqual(newRole.permissions, ["core.host.list", "core.instance.list"]); }); it("should remove permissions with --remove-perms", async function() { let args = "--name new --remove-perms core.host.list"; await execCtl(`role edit new ${args}`); - let roles = await getControl().send(new libData.RoleListRequest()); + let roles = await getControl().send(new lib.RoleListRequest()); let newRole = roles.find(role => role.name === "new"); assert.deepEqual(newRole.permissions, ["core.instance.list"]); }); it("should grant default permissions with --grant-default", async function() { await execCtl("role edit new --grant-default"); - let roles = await getControl().send(new libData.RoleListRequest()); + let roles = await getControl().send(new lib.RoleListRequest()); let newRole = roles.find(role => role.name === "new"); - let defaultPermissions = [...libUsers.permissions.values()] + let defaultPermissions = [...lib.permissions.values()] .filter(p => p.grantByDefault) .map(p => p.name) ; @@ -1043,7 +1040,7 @@ describe("Integration of Clusterio", function() { describe("role delete", function() { it("should delete the given role", async function() { await execCtl("role delete new"); - let roles = await getControl().send(new libData.RoleListRequest()); + let roles = await getControl().send(new lib.RoleListRequest()); let newRole = roles.find(role => role.name === "new"); assert(!newRole, "Role was not deleted"); }); @@ -1059,7 +1056,7 @@ describe("Integration of Clusterio", function() { it("should create the given user", async function() { getControl().userUpdates = []; await execCtl("user create temp"); - let users = await getControl().send(new libData.UserListRequest()); + let users = await getControl().send(new lib.UserListRequest()); let tempUser = users.find(user => user.name === "temp"); assert(tempUser, "user was not created"); assert.equal(getControl().userUpdates.length, 1); @@ -1070,7 +1067,7 @@ describe("Integration of Clusterio", function() { describe("user revoke-token", function() { it("should kick existing sessions for the user", async function() { slowTest(this); - await getControl().send(new libData.UserCreateRequest("revokee")); + await getControl().send(new lib.UserCreateRequest("revokee")); let tlsCa = await fs.readFile("test/file/tls/cert.pem"); let connector = new TestControlConnector(url, 2, tlsCa); connector.token = jwt.sign( @@ -1091,7 +1088,7 @@ describe("Integration of Clusterio", function() { it("should set the roles on the user", async function() { getControl().userUpdates = []; await execCtl('user set-roles temp "Cluster Admin"'); - let users = await getControl().send(new libData.UserListRequest()); + let users = await getControl().send(new lib.UserListRequest()); let tempUser = users.find(user => user.name === "temp"); assert.deepEqual(tempUser.roles, [0]); assert.equal(getControl().userUpdates.length, 1); @@ -1110,7 +1107,7 @@ describe("Integration of Clusterio", function() { await connector.connect(); await assert.rejects( - tempControl.send(new libData.UserCreateRequest("notallowed")), + tempControl.send(new lib.UserCreateRequest("notallowed")), new Error("Permission denied") ); @@ -1127,7 +1124,7 @@ describe("Integration of Clusterio", function() { it("should delete the user", async function() { getControl().userUpdates = []; await execCtl("user delete temp"); - let users = await getControl().send(new libData.UserListRequest()); + let users = await getControl().send(new lib.UserListRequest()); let tempUser = users.find(user => user.name === "temp"); assert(!tempUser, "user was note deleted"); assert.equal(getControl().userUpdates.length, 1); diff --git a/test/integration/export.js b/test/integration/export.js index dccfbb10..d15dc22e 100644 --- a/test/integration/export.js +++ b/test/integration/export.js @@ -2,17 +2,17 @@ const assert = require("assert").strict; const path = require("path"); -const libFactorio = require("@clusterio/lib/factorio"); +const lib = require("@clusterio/lib"); describe("Integration of lib/factorio/export", function() { describe("exportLocale()", function() { it("returns a nested Map with base game locale information", async function() { let writePath = path.join("temp", "test", "server"); - let testServer = new libFactorio.FactorioServer("factorio", writePath, {}); + let testServer = new lib.FactorioServer("factorio", writePath, {}); await testServer.init(); - let locale = await libFactorio._exportLocale(testServer, new Map(), ["base"], "en"); + let locale = await lib._exportLocale(testServer, new Map(), ["base"], "en"); assert(locale instanceof Map, "locale is not a map"); assert.equal(locale.get("entity-name.fish"), "Fish"); diff --git a/test/integration/index.js b/test/integration/index.js index a950f7ce..61150a2d 100644 --- a/test/integration/index.js +++ b/test/integration/index.js @@ -8,11 +8,8 @@ const phin = require("phin"); const util = require("util"); const events = require("events"); -const libData = require("@clusterio/lib/data"); -const libLink = require("@clusterio/lib/link"); -const { LineSplitter } = require("@clusterio/lib/stream"); -const { ConsoleTransport, logger } = require("@clusterio/lib/logging"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); +const lib = require("@clusterio/lib"); +const { LineSplitter, ConsoleTransport, logger } = lib; // Make sure permissions from plugins are loaded require("../../plugins/global_chat/info"); @@ -22,7 +19,7 @@ require("../../plugins/statistics_exporter/info"); require("../../plugins/subspace_storage/info"); -class TestControl extends libLink.Link { +class TestControl extends lib.Link { constructor(connector, subscribe = true) { super(connector); this.hostUpdates = []; @@ -37,29 +34,29 @@ class TestControl extends libLink.Link { return; } this.send( - new libData.HostSetSubscriptionsRequest(true, []) + new lib.HostSetSubscriptionsRequest(true, []) ).catch(err => logger.error(`Error setting host subscriptions:\n${err.stack}`)); this.send( - new libData.InstanceDetailsSetSubscriptionsRequest(true, []) + new lib.InstanceDetailsSetSubscriptionsRequest(true, []) ).catch(err => logger.error(`Error setting instance subscriptions:\n${err.stack}`)); this.send( - new libData.InstanceSetSaveListSubscriptionsRequest(true, []) + new lib.InstanceSetSaveListSubscriptionsRequest(true, []) ).catch(err => logger.error(`Error setting save list subscriptions:\n${err.stack}`)); this.send( - new libData.ModSetSubscriptionsRequest(true, []) + new lib.ModSetSubscriptionsRequest(true, []) ).catch(err => logger.error(`Error setting mod subscriptions:\n${err.stack}`)); this.send( - new libData.UserSetSubscriptionsRequest(true, []) + new lib.UserSetSubscriptionsRequest(true, []) ).catch(err => logger.error(`Error setting user subscriptions:\n${err.stack}`)); }); - this.handle(libData.AccountUpdateEvent); - this.handle(libData.HostUpdateEvent, this.handleHostUpdateEvent.bind(this)); - this.handle(libData.InstanceDetailsUpdateEvent, this.handleInstanceDetailsUpdateEvent.bind(this)); - this.handle(libData.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this)); - this.handle(libData.ModUpdateEvent, this.handleModUpdateEvent.bind(this)); - this.handle(libData.ModPackUpdateEvent, this.handleModPackUpdateEvent.bind(this)); - this.handle(libData.UserUpdateEvent, this.handleUserUpdateEvent.bind(this)); + this.handle(lib.AccountUpdateEvent); + this.handle(lib.HostUpdateEvent, this.handleHostUpdateEvent.bind(this)); + this.handle(lib.InstanceDetailsUpdateEvent, this.handleInstanceDetailsUpdateEvent.bind(this)); + this.handle(lib.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this)); + this.handle(lib.ModUpdateEvent, this.handleModUpdateEvent.bind(this)); + this.handle(lib.ModPackUpdateEvent, this.handleModPackUpdateEvent.bind(this)); + this.handle(lib.UserUpdateEvent, this.handleUserUpdateEvent.bind(this)); } async handleHostUpdateEvent(event) { @@ -87,11 +84,11 @@ class TestControl extends libLink.Link { } } -class TestControlConnector extends libLink.WebSocketClientConnector { +class TestControlConnector extends lib.WebSocketClientConnector { register() { this.sendHandshake( - new libData.MessageRegisterControl( - new libData.RegisterControlData( + new lib.MessageRegisterControl( + new lib.RegisterControlData( this.token, "clusterioctl", "test", @@ -150,7 +147,7 @@ async function execCtl(...args) { } async function sendRcon(instanceId, command) { - return await control.sendTo({ instanceId }, new libData.InstanceSendRconRequest(command)); + return await control.sendTo({ instanceId }, new lib.InstanceSendRconRequest(command)); } function getControl() { @@ -183,7 +180,7 @@ before(async function() { // Some integration tests may cause log events logger.add(new ConsoleTransport({ level: "info", - format: new libLoggingUtils.TerminalFormat(), + format: new lib.TerminalFormat(), })); await fs.remove(databaseDir); @@ -228,16 +225,16 @@ before(async function() { control = new TestControl(controlConnector); await controlConnector.connect(); - const testPack = libData.ModPack.fromJSON({}); + const testPack = lib.ModPack.fromJSON({}); testPack.id = 12; testPack.name = "subspace_storage-pack"; testPack.factorioVersion = "1.1.0"; testPack.mods.set("clusterio_lib", { name: "clusterio_lib", enabled: true, version: "0.1.2" }); testPack.mods.set("subspace_storage", { name: "subspace_storage", enabled: true, version: "1.99.8" }); - await control.sendTo("controller", new libData.ModPackCreateRequest(testPack)); + await control.sendTo("controller", new lib.ModPackCreateRequest(testPack)); await control.sendTo( "controller", - new libData.ControllerConfigSetFieldRequest("controller.default_mod_pack_id", "12"), + new lib.ControllerConfigSetFieldRequest("controller.default_mod_pack_id", "12"), ); }); diff --git a/test/integration/patch.js b/test/integration/patch.js index 74d3c849..8e9a926c 100644 --- a/test/integration/patch.js +++ b/test/integration/patch.js @@ -4,7 +4,7 @@ const fs = require("fs-extra"); const JSZip = require("jszip"); const path = require("path"); -const libFactorio = require("@clusterio/lib/factorio"); +const lib = require("@clusterio/lib"); const { slowTest } = require("./index"); @@ -17,7 +17,7 @@ describe("Integration of lib/factorio/patch", function() { let savePath = path.join("temp", "test", "integration", "saves", "test.zip"); it("should patch a freeplay game", async function() { slowTest(this); - await libFactorio.patch(savePath, [{ + await lib.patch(savePath, [{ name: "test", version: "1.0.0", dependencies: {}, @@ -39,7 +39,7 @@ describe("Integration of lib/factorio/patch", function() { }); it("should remove old modules in a save", async function() { slowTest(this); - await libFactorio.patch(savePath, []); + await lib.patch(savePath, []); let zip = await JSZip.loadAsync(await fs.readFile(savePath)); assert.equal(zip.file("test/modules/test/test.lua"), null); }); diff --git a/test/integration/server.js b/test/integration/server.js index b4f1adb6..e820c6be 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -4,9 +4,8 @@ const events = require("events"); const fs = require("fs-extra"); const path = require("path"); -const libFactorio = require("@clusterio/lib/factorio"); -const libErrors = require("@clusterio/lib/errors"); -const { logger } = require("@clusterio/lib/logging"); +const lib = require("@clusterio/lib"); +const { logger } = lib; const { slowTest } = require("./index"); @@ -14,7 +13,7 @@ const { slowTest } = require("./index"); describe("Integration of lib/factorio/server", function() { describe("_getVersion()", function() { it("should get a version from factorio's changelog.txt", async function() { - let version = await libFactorio._getVersion(path.join("factorio", "data", "changelog.txt")); + let version = await lib._getVersion(path.join("factorio", "data", "changelog.txt")); if (!/^\d+\.\d+\.\d+$/.test(version)) { assert.fail(`Detected version '${version}' does not followed the format x.y.z`); } @@ -23,7 +22,7 @@ describe("Integration of lib/factorio/server", function() { describe("class FactorioServer", function() { let writePath = path.join("temp", "test", "integration"); - let server = new libFactorio.FactorioServer("factorio", writePath, {}); + let server = new lib.FactorioServer("factorio", writePath, {}); let logFile; before(async function() { @@ -231,7 +230,7 @@ describe("Integration of lib/factorio/server", function() { await assert.rejects( startPromise, - new libErrors.EnvironmentError( + new lib.EnvironmentError( "Factorio server was unexpectedly killed, is the system low on memory?" ) ); @@ -243,7 +242,7 @@ describe("Integration of lib/factorio/server", function() { await assert.rejects( server.start("does-not-exist.zip"), - new libErrors.EnvironmentError("Factorio server unexpectedly shut down with code 1") + new lib.EnvironmentError("Factorio server unexpectedly shut down with code 1") ); }); }); diff --git a/test/lib/ExponentialBackoff.js b/test/lib/ExponentialBackoff.js index 222e0383..790b1afa 100644 --- a/test/lib/ExponentialBackoff.js +++ b/test/lib/ExponentialBackoff.js @@ -1,7 +1,7 @@ "use strict"; const assert = require("assert").strict; -const ExponentialBackoff = require("@clusterio/lib/ExponentialBackoff"); +const { ExponentialBackoff } = require("@clusterio/lib"); describe("lib/ExponentialBackoff", function() { describe("class ExponentialBackoff", function() { diff --git a/test/lib/RateLimiter.js b/test/lib/RateLimiter.js index d7448d3f..f778d869 100644 --- a/test/lib/RateLimiter.js +++ b/test/lib/RateLimiter.js @@ -1,8 +1,7 @@ "use strict"; const assert = require("assert").strict; -const { wait } = require("@clusterio/lib/helpers"); -const RateLimiter = require("@clusterio/lib/RateLimiter"); +const { RateLimiter, wait } = require("@clusterio/lib"); describe("lib/RateLimiter", function() { diff --git a/test/lib/command.js b/test/lib/command.js index 38d6f635..a78adf02 100644 --- a/test/lib/command.js +++ b/test/lib/command.js @@ -1,70 +1,67 @@ "use strict"; const assert = require("assert").strict; -const libCommand = require("@clusterio/lib/command"); -const libData = require("@clusterio/lib/data"); -const libErrors = require("@clusterio/lib/errors"); -const libLink = require("@clusterio/lib/link"); +const lib = require("@clusterio/lib"); const mock = require("../mock"); -const addr = libData.Address.fromShorthand; +const addr = lib.Address.fromShorthand; describe("lib/command", function() { - let testRole = libData.RawRole.fromJSON({ id: 28, name: "Test Role", description: "Test", permissions: [] }); + let testRole = lib.RawRole.fromJSON({ id: 28, name: "Test Role", description: "Test", permissions: [] }); - let [controlConnector, controllerConnector] = libLink.VirtualConnector.makePair( + let [controlConnector, controllerConnector] = lib.VirtualConnector.makePair( addr({ controlId: 1}), addr("controller") ); let testControl = new mock.MockControl(controlConnector); - let testController = new libLink.Link(controllerConnector); + let testController = new lib.Link(controllerConnector); testController.handle( - libData.HostListRequest, () => [new libData.HostDetails("test", "0.1", "Test Host", 11, false)] + lib.HostListRequest, () => [new lib.HostDetails("test", "0.1", "Test Host", 11, false)] ); testController.handle( - libData.InstanceDetailsListRequest, () => [new libData.InstanceDetails("Test Instance", 57, 4, null, "stopped")] + lib.InstanceDetailsListRequest, () => [new lib.InstanceDetails("Test Instance", 57, 4, null, "stopped")] ); - testController.handle(libData.RoleListRequest, () => [testRole]); + testController.handle(lib.RoleListRequest, () => [testRole]); describe("resolveHost", function() { it("should pass an integer like string back", async function() { - assert.equal(await libCommand.resolveHost(null, "123"), 123); + assert.equal(await lib.resolveHost(null, "123"), 123); }); it("should resolve a host name with the controller", async function() { - assert.equal(await libCommand.resolveHost(testControl, "Test Host"), 11); + assert.equal(await lib.resolveHost(testControl, "Test Host"), 11); }); it("should throw if host is not found", async function() { await assert.rejects( - libCommand.resolveHost(testControl, "invalid"), - new libErrors.CommandError("No host named invalid") + lib.resolveHost(testControl, "invalid"), + new lib.CommandError("No host named invalid") ); }); }); describe("resolveInstance", function() { it("should pass an integer like string back", async function() { - assert.equal(await libCommand.resolveInstance(null, "123"), 123); + assert.equal(await lib.resolveInstance(null, "123"), 123); }); it("should resolve an instance name with the controller", async function() { - assert.equal(await libCommand.resolveInstance(testControl, "Test Instance"), 57); + assert.equal(await lib.resolveInstance(testControl, "Test Instance"), 57); }); it("should throw if instance is not found", async function() { await assert.rejects( - libCommand.resolveInstance(testControl, "invalid"), - new libErrors.CommandError("No instance named invalid") + lib.resolveInstance(testControl, "invalid"), + new lib.CommandError("No instance named invalid") ); }); }); describe("retrieveRole", function() { it("should retrieve a role by id from an integer like string", async function() { - assert.deepEqual(await libCommand.retrieveRole(testControl, "28"), testRole); + assert.deepEqual(await lib.retrieveRole(testControl, "28"), testRole); }); it("should retrieve a role by name from a string", async function() { - assert.deepEqual(await libCommand.retrieveRole(testControl, "Test Role"), testRole); + assert.deepEqual(await lib.retrieveRole(testControl, "Test Role"), testRole); }); it("should throw if role is not found", async function() { await assert.rejects( - libCommand.retrieveRole(testControl, "invalid"), - new libErrors.CommandError("No role named invalid") + lib.retrieveRole(testControl, "invalid"), + new lib.CommandError("No role named invalid") ); }); }); diff --git a/test/lib/config/classes.js b/test/lib/config/classes.js index 23a2a292..b0c10523 100644 --- a/test/lib/config/classes.js +++ b/test/lib/config/classes.js @@ -1,5 +1,5 @@ "use strict"; -const classes = require("@clusterio/lib/config/classes"); +const lib = require("@clusterio/lib"); const assert = require("assert").strict; const events = require("events"); @@ -8,12 +8,12 @@ describe("lib/config/classes", function() { describe("ConfigGroup", function() { let mockConfig = new events.EventEmitter(); mockConfig.location = "local"; - class TestGroup extends classes.ConfigGroup { } + class TestGroup extends lib.ConfigGroup { } TestGroup.defaultAccess = ["local", "remote"]; TestGroup.groupName = "test_group"; describe(".define()", function() { it("should throw if groupName is not set", function() { - class NoGroupName extends classes.ConfigGroup { } + class NoGroupName extends lib.ConfigGroup { } assert.throws( () => NoGroupName.define({ name: "a", type: "string", optional: true }), new Error("Expected ConfigGroup class NoGroupName to have the groupName property set to a string") @@ -68,7 +68,7 @@ describe("lib/config/classes", function() { } }); it("should throw on defaultAccess not set", function() { - class NoAccessGroup extends classes.ConfigGroup { } + class NoAccessGroup extends lib.ConfigGroup { } NoAccessGroup.groupName = "no_access"; assert.throws( () => NoAccessGroup.define({ name: "a", type: "string", optional: true }), @@ -134,7 +134,7 @@ describe("lib/config/classes", function() { describe(".finalize()", function() { it("should throw if groupName is not set", function() { - class NoGroupName extends classes.ConfigGroup { } + class NoGroupName extends lib.ConfigGroup { } assert.throws( () => NoGroupName.finalize(), new Error("Expected ConfigGroup class NoGroupName to have the groupName property set to a string") @@ -360,7 +360,7 @@ describe("lib/config/classes", function() { it("should throw if field is inaccessible", function() { assert.throws( () => testInstance.get("priv", "remote"), - new classes.InvalidAccess("Field 'priv' is not accessible from remote") + new lib.InvalidAccess("Field 'priv' is not accessible from remote") ); }); }); @@ -375,14 +375,14 @@ describe("lib/config/classes", function() { it("should throw if field does not exist", function() { assert.throws( () => testInstance.set("bar", 1), - new classes.InvalidField("No field named 'bar'") + new lib.InvalidField("No field named 'bar'") ); }); it("should throw if field is inaccesible", function() { assert.throws( () => testInstance.set("priv", "bad", "remote"), - new classes.InvalidAccess("Field 'priv' is not accessible from remote") + new lib.InvalidAccess("Field 'priv' is not accessible from remote") ); }); @@ -430,7 +430,7 @@ describe("lib/config/classes", function() { assert.throws( () => testInstance.set("bool", "blah"), - new classes.InvalidValue("Expected type of bool to be boolean, not string") + new lib.InvalidValue("Expected type of bool to be boolean, not string") ); }); @@ -449,7 +449,7 @@ describe("lib/config/classes", function() { assert.throws( () => testInstance.set("func", "blah"), - new classes.InvalidValue("Expected type of func to be number, not string") + new lib.InvalidValue("Expected type of func to be number, not string") ); }); @@ -465,7 +465,7 @@ describe("lib/config/classes", function() { } assert.throws( () => testInstance.set("json", "blah"), - new classes.InvalidValue(`Error parsing value for json: ${errMsg}`) + new lib.InvalidValue(`Error parsing value for json: ${errMsg}`) ); }); }); @@ -482,21 +482,21 @@ describe("lib/config/classes", function() { it("should throw if field does not exist", function() { assert.throws( () => testInstance.setProp("bar", 1), - new classes.InvalidField("No field named 'bar'") + new lib.InvalidField("No field named 'bar'") ); }); it("should throw if field is inaccesible", function() { assert.throws( () => testInstance.setProp("priv", "prop", "bad", "remote"), - new classes.InvalidAccess("Field 'priv' is not accessible from remote") + new lib.InvalidAccess("Field 'priv' is not accessible from remote") ); }); it("should throw if field is not an object", function() { assert.throws( () => testInstance.setProp("enum", "prop", "a"), - new classes.InvalidField("Cannot set property on non-object field 'enum'") + new lib.InvalidField("Cannot set property on non-object field 'enum'") ); }); @@ -521,13 +521,13 @@ describe("lib/config/classes", function() { }); describe("Config", function() { - class AlphaGroup extends classes.ConfigGroup { } + class AlphaGroup extends lib.ConfigGroup { } AlphaGroup.defaultAccess = ["local", "remote"]; AlphaGroup.groupName = "alpha"; - class BetaGroup extends classes.ConfigGroup { } + class BetaGroup extends lib.ConfigGroup { } BetaGroup.defaultAccess = ["local", "remote"]; BetaGroup.groupName = "beta"; - class TestConfig extends classes.Config { } + class TestConfig extends lib.Config { } before(function() { AlphaGroup.define({ name: "foo", type: "string", optional: true }); @@ -540,9 +540,9 @@ describe("lib/config/classes", function() { describe(".registerGroup()", function() { it("should throw if the class is finalized", function() { - class FinalizedConfig extends classes.Config { } + class FinalizedConfig extends lib.Config { } FinalizedConfig.finalize(); - class TestGroup extends classes.ConfigGroup { } + class TestGroup extends lib.ConfigGroup { } TestGroup.groupName = "test"; TestGroup.finalize(); @@ -552,7 +552,7 @@ describe("lib/config/classes", function() { ); }); it("should throw if the group is not finalized", function() { - class UnfinishedGroup extends classes.ConfigGroup { } + class UnfinishedGroup extends lib.ConfigGroup { } assert.throws( () => TestConfig.registerGroup(UnfinishedGroup), diff --git a/test/lib/data/ModInfo.js b/test/lib/data/ModInfo.js index 8ff5c170..279f535f 100644 --- a/test/lib/data/ModInfo.js +++ b/test/lib/data/ModInfo.js @@ -3,16 +3,15 @@ const assert = require("assert").strict; const fs = require("fs-extra"); const path = require("path"); -const libSchema = require("@clusterio/lib/schema"); -const libHash = require("@clusterio/lib/hash"); +const lib = require("@clusterio/lib"); const libBuildMod = require("@clusterio/lib/build_mod"); -const ModInfo = require("@clusterio/lib/data/ModInfo"); +const { ModInfo } = lib; describe("lib/data/ModInfo", function() { describe("class ModInfo", function() { it("should round trip serialize", function() { - const validate = libSchema.compile(ModInfo.jsonSchema); + const validate = lib.compile(ModInfo.jsonSchema); function check(pack) { const json = JSON.parse(JSON.stringify(pack)); if (!validate(json)) { @@ -78,7 +77,7 @@ describe("lib/data/ModInfo", function() { outputDir: path.join("temp", "test"), }); const filePath = path.join("temp", "test", "empty_mod_1.0.0.zip"); - const hash = await libHash.hashFile(filePath); + const hash = await lib.hashFile(filePath); const stat = await fs.stat(filePath); const mod = await ModInfo.fromModFile(filePath); assert.deepEqual( diff --git a/test/lib/data/ModPack.js b/test/lib/data/ModPack.js index 49c77a44..10134b68 100644 --- a/test/lib/data/ModPack.js +++ b/test/lib/data/ModPack.js @@ -2,15 +2,14 @@ const assert = require("assert").strict; const zlib = require("zlib"); -const libSchema = require("@clusterio/lib/schema"); -const ExportManifest = require("@clusterio/lib/data/ExportManifest"); -const ModPack = require("@clusterio/lib/data/ModPack"); +const lib = require("@clusterio/lib"); +const { ModPack } = lib; describe("lib/data/ModPack", function() { describe("class ModPack", function() { it("should round trip serialize", function() { - const validate = libSchema.compile(ModPack.jsonSchema); + const validate = lib.compile(ModPack.jsonSchema); function check(pack) { const json = JSON.parse(JSON.stringify(pack)); if (!validate(json)) { diff --git a/test/lib/database.js b/test/lib/database.js index a20627e6..54e0df43 100644 --- a/test/lib/database.js +++ b/test/lib/database.js @@ -3,24 +3,24 @@ const assert = require("assert").strict; const fs = require("fs-extra"); const path = require("path"); -const libDatabase = require("@clusterio/lib/database"); +const lib = require("@clusterio/lib"); describe("lib/database", function() { describe("mapToObject()", function() { it("should throw on non-string key", function() { assert.throws( - () => libDatabase.mapToObject(new Map([[1, 1]])), + () => lib.mapToObject(new Map([[1, 1]])), new Error("Expected all keys to be string but got number") ); assert.throws( - () => libDatabase.mapToObject(new Map([[Symbol("test"), 1]])), + () => lib.mapToObject(new Map([[Symbol("test"), 1]])), new Error("Expected all keys to be string but got symbol") ); }); it("should throw convert a map to an object", function() { assert.deepEqual( - libDatabase.mapToObject(new Map([["a", 1], ["b", true]])), + lib.mapToObject(new Map([["a", 1], ["b", true]])), { "a": 1, "b": true } ); }); @@ -32,7 +32,7 @@ describe("lib/database", function() { for (let type of badTypes) { it(`should reject on ${type} JSON`, async function() { await assert.rejects( - libDatabase.loadJsonAsMap(path.join("test", "file", "json", `${type}.json`)), + lib.loadJsonAsMap(path.join("test", "file", "json", `${type}.json`)), new Error(`Expected object but got ${type}`) ); }); @@ -40,21 +40,21 @@ describe("lib/database", function() { it("should work on empty object JSON", async function() { assert.deepEqual( - await libDatabase.loadJsonAsMap(path.join("test", "file", "json", "object.json")), + await lib.loadJsonAsMap(path.join("test", "file", "json", "object.json")), new Map() ); }); it("should work on object JSON", async function() { assert.deepEqual( - await libDatabase.loadJsonAsMap(path.join("test", "file", "json", "load_map.json")), + await lib.loadJsonAsMap(path.join("test", "file", "json", "load_map.json")), new Map([["a", 1], ["b", true]]) ); }); it("should give an empty Map for non-existant file", async function() { assert.deepEqual( - await libDatabase.loadJsonAsMap(path.join("test", "file", "json", "does-not-exist")), + await lib.loadJsonAsMap(path.join("test", "file", "json", "does-not-exist")), new Map() ); }); @@ -75,7 +75,7 @@ describe("lib/database", function() { } await deleteTestFile(); - await libDatabase.saveMapAsJson( + await lib.saveMapAsJson( testFile, new Map([["c", {}], ["d", "foo"]]) ); @@ -92,7 +92,7 @@ describe("lib/database", function() { for (let type of badTypes) { it(`should reject on ${type} JSON`, async function() { await assert.rejects( - libDatabase.loadJsonArrayAsMap(path.join("test", "file", "json", `${type}.json`)), + lib.loadJsonArrayAsMap(path.join("test", "file", "json", `${type}.json`)), new Error(`Expected array but got ${type}`) ); }); @@ -100,35 +100,35 @@ describe("lib/database", function() { it("should reject on null element", async function() { await assert.rejects( - libDatabase.loadJsonArrayAsMap(path.join("test", "file", "json", "array_null.json")), + lib.loadJsonArrayAsMap(path.join("test", "file", "json", "array_null.json")), new Error("Expected all elements to be objects") ); }); it("should reject on element missing id", async function() { await assert.rejects( - libDatabase.loadJsonArrayAsMap(path.join("test", "file", "json", "array_object.json")), + lib.loadJsonArrayAsMap(path.join("test", "file", "json", "array_object.json")), new Error("Expected all elements to have an id property") ); }); it("should work on empty array JSON", async function() { assert.deepEqual( - await libDatabase.loadJsonArrayAsMap(path.join("test", "file", "json", "array.json")), + await lib.loadJsonArrayAsMap(path.join("test", "file", "json", "array.json")), new Map() ); }); it("should work on array JSON", async function() { assert.deepEqual( - await libDatabase.loadJsonArrayAsMap(path.join("test", "file", "json", "load_array_map.json")), + await lib.loadJsonArrayAsMap(path.join("test", "file", "json", "load_array_map.json")), new Map([["a", { id: "a" }], ["b", { id: "b" }]]) ); }); it("should give an empty Map for non-existant file", async function() { assert.deepEqual( - await libDatabase.loadJsonArrayAsMap(path.join("test", "file", "json", "does-not-exist")), + await lib.loadJsonArrayAsMap(path.join("test", "file", "json", "does-not-exist")), new Map() ); }); @@ -149,7 +149,7 @@ describe("lib/database", function() { } await deleteTestFile(); - await libDatabase.saveMapAsJsonArray( + await lib.saveMapAsJsonArray( testFile, new Map([["c", { id: "c" }], ["d", { id: "d" }]]) ); @@ -163,23 +163,23 @@ describe("lib/database", function() { describe("class ItemDatabase", function() { describe("constructor()", function() { it("should create an empty database with no args", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.deepEqual(items._items, new Map()); }); it("should restore the passed serialized database", function() { - let items = new libDatabase.ItemDatabase({ "a": 1, "b": 2 }); + let items = new lib.ItemDatabase({ "a": 1, "b": 2 }); assert.deepEqual(items._items, new Map([["a", 1], ["b", 2]])); }); it("should throw on invalid serialized database", function() { assert.throws( - () => new libDatabase.ItemDatabase({ "a": NaN }), + () => new lib.ItemDatabase({ "a": NaN }), new Error("count must be a number") ); assert.throws( - () => new libDatabase.ItemDatabase({ "a": "a" }), + () => new lib.ItemDatabase({ "a": "a" }), new Error("count must be a number") ); }); @@ -187,36 +187,36 @@ describe("lib/database", function() { describe(".serialize()", function() { it("should return a serialized database", function() { - let items = new libDatabase.ItemDatabase({ "a": 10 }); + let items = new lib.ItemDatabase({ "a": 10 }); assert.deepEqual(items.serialize(), { "a": 10 }); }); it("should remove zero count entries", function() { - let items = new libDatabase.ItemDatabase({ "a": 0 }); + let items = new lib.ItemDatabase({ "a": 0 }); assert.deepEqual(items.serialize(), {}); }); }); describe(".size", function() { it("should give an approximate size of the database", function() { - let items = new libDatabase.ItemDatabase({ "a": 10 }); + let items = new lib.ItemDatabase({ "a": 10 }); assert.equal(items.size, 1); }); }); describe(".getItemCount()", function() { it("should return the count of the given item", function() { - let items = new libDatabase.ItemDatabase({ "a": 10 }); + let items = new lib.ItemDatabase({ "a": 10 }); assert.equal(items.getItemCount("a"), 10); }); it("should return zero if item does not exist", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.equal(items.getItemCount("b"), 0); }); it("should throw on invalid name", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.throws( () => items.getItemCount(2), new Error("name must be a string") @@ -226,19 +226,19 @@ describe("lib/database", function() { describe(".addItem()", function() { it("should add a new item", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); items.addItem("a", 10); assert.deepEqual(items._items, new Map([["a", 10]])); }); it("should add an existing item", function() { - let items = new libDatabase.ItemDatabase({ "a": 10 }); + let items = new lib.ItemDatabase({ "a": 10 }); items.addItem("a", 10); assert.deepEqual(items._items, new Map([["a", 20]])); }); it("should throw on invalid name", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.throws( () => items.addItem(2, 10), new Error("name must be a string") @@ -246,7 +246,7 @@ describe("lib/database", function() { }); it("should throw on invalid count", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.throws( () => items.addItem("a", NaN), new Error("count must be a number") @@ -260,19 +260,19 @@ describe("lib/database", function() { describe(".removeItem()", function() { it("should remove an existing item", function() { - let items = new libDatabase.ItemDatabase({ "a": 20 }); + let items = new lib.ItemDatabase({ "a": 20 }); items.removeItem("a", 10); assert.deepEqual(items._items, new Map([["a", 10]])); }); it("should turn a non-existing item negative", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); items.removeItem("a", 10); assert.deepEqual(items._items, new Map([["a", -10]])); }); it("should throw on invalid name", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.throws( () => items.removeItem(2, 10), new Error("name must be a string") @@ -280,7 +280,7 @@ describe("lib/database", function() { }); it("should throw on invalid count", function() { - let items = new libDatabase.ItemDatabase(); + let items = new lib.ItemDatabase(); assert.throws( () => items.removeItem("a", "b"), new Error("count must be a number") diff --git a/test/lib/factorio/exchange_string.js b/test/lib/factorio/exchange_string.js index 8164a241..9a660205 100644 --- a/test/lib/factorio/exchange_string.js +++ b/test/lib/factorio/exchange_string.js @@ -2,7 +2,7 @@ const assert = require("assert").strict; const zlib = require("zlib"); -const libFactorio = require("@clusterio/lib/factorio"); +const lib = require("@clusterio/lib"); const testStrings = require("./test_strings"); @@ -23,26 +23,26 @@ class Random { describe("lib/factorio/exchange_string", function() { describe("readMapExchangeString", function() { it("should parse a valid string", function() { - let result = libFactorio.readMapExchangeString(testStrings.default); + let result = lib.readMapExchangeString(testStrings.default); assert.equal(result.map_gen_settings.seed, 1234567890); - result = libFactorio.readMapExchangeString(testStrings.modified); + result = lib.readMapExchangeString(testStrings.modified); assert.equal(result.checksum, 4092204126); }); it("should handle malformed strings", function() { assert.throws( - () => libFactorio.readMapExchangeString("<>"), + () => lib.readMapExchangeString("<>"), new Error("Not a map exchange string") ); assert.throws( - () => libFactorio.readMapExchangeString(testStrings.default.slice(0, 100)), + () => lib.readMapExchangeString(testStrings.default.slice(0, 100)), new Error("Not a map exchange string") ); assert.throws( - () => libFactorio.readMapExchangeString(`>>>${Buffer.from("abk430ia404ah3b4").toString("base64")}<<<`), + () => lib.readMapExchangeString(`>>>${Buffer.from("abk430ia404ah3b4").toString("base64")}<<<`), new Error("Malformed map exchange string: zlib inflate failed") ); @@ -56,7 +56,7 @@ describe("lib/factorio/exchange_string", function() { // eslint-disable-next-line node/no-sync data = zlib.deflateSync(data); assert.throws( - () => libFactorio.readMapExchangeString(`>>>${data.toString("base64")}<<<`), + () => lib.readMapExchangeString(`>>>${data.toString("base64")}<<<`), new Error("Malformed map exchange string: reached end before finishing parsing") ); } @@ -65,7 +65,7 @@ describe("lib/factorio/exchange_string", function() { // eslint-disable-next-line node/no-sync pastEnd = zlib.deflateSync(Buffer.concat([zlib.inflateSync(pastEnd), Buffer.from("junk")])); assert.throws( - () => libFactorio.readMapExchangeString(`>>>${pastEnd.toString("base64")}<<<`), + () => lib.readMapExchangeString(`>>>${pastEnd.toString("base64")}<<<`), new Error("Malformed map exchange string: data after end") ); }); diff --git a/test/lib/factorio/export.js b/test/lib/factorio/export.js index 497a56a9..fbfaddcd 100644 --- a/test/lib/factorio/export.js +++ b/test/lib/factorio/export.js @@ -2,7 +2,7 @@ const assert = require("assert").strict; const path = require("path"); -const libFactorio = require("@clusterio/lib/factorio"); +const lib = require("@clusterio/lib"); describe("lib/factorio/export", function() { @@ -10,12 +10,12 @@ describe("lib/factorio/export", function() { let testServer; before(async function() { let writePath = path.join("temp", "test", "server"); - testServer = new libFactorio.FactorioServer(path.join("test", "file", "factorio"), writePath, {}); + testServer = new lib.FactorioServer(path.join("test", "file", "factorio"), writePath, {}); await testServer.init(); }); it("returns a flattened mapping with locale definitions", async function() { - let locale = await libFactorio._exportLocale(testServer, new Map(), ["base"], "en"); + let locale = await lib._exportLocale(testServer, new Map(), ["base"], "en"); assert.deepEqual(locale, new Map([["test.key-a", "1"], ["test.key-b", "2"]])); }); }); diff --git a/test/lib/factorio/patch.js b/test/lib/factorio/patch.js index e301d583..42ec1792 100644 --- a/test/lib/factorio/patch.js +++ b/test/lib/factorio/patch.js @@ -4,7 +4,7 @@ const fs = require("fs-extra"); const JSZip = require("jszip"); const path = require("path"); -const libFactorio = require("@clusterio/lib/factorio"); +const lib = require("@clusterio/lib"); describe("lib/factorio", function() { @@ -38,7 +38,7 @@ describe("lib/factorio", function() { }; it("should produce output matching the reference", function() { - assert.equal(libFactorio._generateLoader(patchInfo), reference); + assert.equal(lib._generateLoader(patchInfo), reference); }); }); @@ -48,7 +48,7 @@ describe("lib/factorio", function() { { name: "a", version: "1.0.0", dependencies: {"b": "*"} }, { name: "b", version: "1.0.0", dependencies: {} }, ]; - libFactorio._reorderDependencies(modules); + lib._reorderDependencies(modules); assert(modules[0].name === "b", "Dependency was not reorederd"); }); it("should throw on invalid version", function() { @@ -56,7 +56,7 @@ describe("lib/factorio", function() { { name: "a", version: "foo", dependencies: {} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Invalid version 'foo' for module a") ); }); @@ -65,7 +65,7 @@ describe("lib/factorio", function() { { name: "a", version: "1.0.0", dependencies: {"b": "invalid"} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Invalid version range 'invalid' for dependency b on module a") ); }); @@ -74,7 +74,7 @@ describe("lib/factorio", function() { { name: "a", version: "1.0.0", dependencies: {"b": "*"} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Missing dependency b for module a") ); modules = [ @@ -83,7 +83,7 @@ describe("lib/factorio", function() { { name: "c", version: "1.0.0", dependencies: {"d": "*"} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Missing dependency d for module c") ); }); @@ -93,7 +93,7 @@ describe("lib/factorio", function() { { name: "b", version: "1.0.0", dependencies: {"a": ">=2"} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Module b requires a >=2") ); }); @@ -103,7 +103,7 @@ describe("lib/factorio", function() { { name: "b", version: "1.0.0", dependencies: {"a": "*"} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Module dependency loop detected: a -> b -> a") ); modules = [ @@ -113,7 +113,7 @@ describe("lib/factorio", function() { { name: "c", version: "1.0.0", dependencies: {"a": "*"} }, ]; assert.throws( - () => libFactorio._reorderDependencies(modules), + () => lib._reorderDependencies(modules), new Error("Module dependency loop detected: b -> c -> a -> b") ); }); @@ -153,7 +153,7 @@ describe("lib/factorio", function() { } let success = false; try { - libFactorio._reorderDependencies(modules); + lib._reorderDependencies(modules); success = true; } catch (err) { } if (success) { @@ -176,7 +176,7 @@ describe("lib/factorio", function() { await fs.outputFile(zipPath, await zip.generateAsync({ type: "nodebuffer" })); await assert.rejects( - libFactorio.patch(zipPath, []), + lib.patch(zipPath, []), new Error("Unable to patch save, unknown scenario (3acc3be3861144e55604f5ac2f2555071885ebc4)") ); }); diff --git a/test/lib/factorio/server.js b/test/lib/factorio/server.js index c6d05bab..a2508d25 100644 --- a/test/lib/factorio/server.js +++ b/test/lib/factorio/server.js @@ -4,23 +4,23 @@ const events = require("events"); const fs = require("fs-extra"); const path = require("path"); -const libFactorio = require("@clusterio/lib/factorio"); -const { wait } = require("@clusterio/lib/helpers"); +const lib = require("@clusterio/lib"); +const { wait } = lib; const { testLines } = require("./lines"); describe("lib/factorio/server", function() { describe("_getVersion()", function() { it("should get the version from a changelog", async function() { - let version = await libFactorio._getVersion(path.join("test", "file", "changelog-test.txt")); + let version = await lib._getVersion(path.join("test", "file", "changelog-test.txt")); assert.equal(version, "0.1.1"); }); it("should return null if unable to find the version", async function() { - let version = await libFactorio._getVersion(path.join("test", "file", "changelog-bad.txt")); + let version = await lib._getVersion(path.join("test", "file", "changelog-bad.txt")); assert.equal(version, null); }); it("should return null if file does not exist", async function() { - let version = await libFactorio._getVersion(path.join("test", "file", "does-not-exist.txt")); + let version = await lib._getVersion(path.join("test", "file", "does-not-exist.txt")); assert.equal(version, null); }); }); @@ -28,7 +28,7 @@ describe("lib/factorio/server", function() { describe("_versionOrder()", function() { it("should sort an array of versions", function() { let versions = ["1.2.3", "0.1.4", "0.1.2", "1.2.3", "0.1.5", "1.10.2"]; - versions.sort(libFactorio._versionOrder); + versions.sort(lib._versionOrder); assert.deepEqual( versions, ["1.10.2", "1.2.3", "1.2.3", "0.1.5", "0.1.4", "0.1.2"] @@ -39,46 +39,46 @@ describe("lib/factorio/server", function() { describe("_findVersion()", function() { it("should find a given install dir with latest as target", async function() { let installDir = path.join("test", "file", "factorio"); - let [dir, version] = await libFactorio._findVersion(installDir, "latest"); + let [dir, version] = await lib._findVersion(installDir, "latest"); assert.equal(dir, path.join(installDir, "data")); assert.equal(version, "0.1.1"); }); it("should find a given install dir with correct version as target", async function() { let installDir = path.join("test", "file", "factorio"); - let [dir, version] = await libFactorio._findVersion(installDir, "0.1.1"); + let [dir, version] = await lib._findVersion(installDir, "0.1.1"); assert.equal(dir, path.join(installDir, "data")); assert.equal(version, "0.1.1"); }); it("should reject if the install dir version does not match target version", async function() { let installDir = path.join("test", "file", "factorio"); await assert.rejects( - libFactorio._findVersion(installDir, "0.1.2"), + lib._findVersion(installDir, "0.1.2"), new Error("Factorio version 0.1.2 was requested, but install directory contains 0.1.1") ); }); it("should search given directory for latest Factorio install", async function() { let installDir = path.join("test", "file"); - let [dir, version] = await libFactorio._findVersion(installDir, "latest"); + let [dir, version] = await lib._findVersion(installDir, "latest"); assert.equal(dir, path.join(installDir, "factorio", "data")); assert.equal(version, "0.1.1"); }); it("should search given directory for given Factorio install", async function() { let installDir = path.join("test", "file"); - let [dir, version] = await libFactorio._findVersion(installDir, "0.1.1"); + let [dir, version] = await lib._findVersion(installDir, "0.1.1"); assert.equal(dir, path.join(installDir, "factorio", "data")); assert.equal(version, "0.1.1"); }); it("should reject if no factorio install with the given version was found", async function() { let installDir = path.join("test", "file"); await assert.rejects( - libFactorio._findVersion(installDir, "0.1.2"), + lib._findVersion(installDir, "0.1.2"), new Error("Unable to find Factorio version 0.1.2") ); }); it("should reject if no factorio install was found", async function() { let installDir = path.join("test", "file", "instances"); await assert.rejects( - libFactorio._findVersion(installDir, "latest"), + lib._findVersion(installDir, "latest"), new Error(`Unable to find any Factorio install in ${installDir}`) ); }); @@ -86,7 +86,7 @@ describe("lib/factorio/server", function() { describe("randomDynamicPort()", function() { it("should return a port number", function() { - let port = libFactorio._randomDynamicPort(); + let port = lib._randomDynamicPort(); assert.equal(typeof port, "number"); assert(Number.isInteger(port)); assert(0 <= port && port < 2**16); @@ -97,24 +97,24 @@ describe("lib/factorio/server", function() { return (49152 <= port && port <= 65535); } for (let i=0; i < 20; i++) { - assert(validate(libFactorio._randomDynamicPort())); + assert(validate(lib._randomDynamicPort())); } }); }); describe("generatePassword()", function() { it("should return a string", async function() { - let password = await libFactorio._generatePassword(1); + let password = await lib._generatePassword(1); assert.equal(typeof password, "string"); }); it("should return a string of the given length", async function() { - let password = await libFactorio._generatePassword(10); + let password = await lib._generatePassword(10); assert.equal(password.length, 10); }); it("should contain only a-z, A-Z, 0-9", async function() { - let password = await libFactorio._generatePassword(10); + let password = await lib._generatePassword(10); assert(/^[a-zA-Z0-9]+$/.test(password), `${password} failed test`); }); }); @@ -123,7 +123,7 @@ describe("lib/factorio/server", function() { it("should parse the test lines", function() { for (let [line, reference] of testLines) { reference.source = "test"; - let output = libFactorio._parseOutput(line, "test"); + let output = lib._parseOutput(line, "test"); assert.deepEqual(output, reference); } }); @@ -131,12 +131,12 @@ describe("lib/factorio/server", function() { describe("class FactorioServer", function() { let writePath = path.join("temp", "test", "server"); - let server = new libFactorio.FactorioServer(path.join("test", "file", "factorio"), writePath, {}); + let server = new lib.FactorioServer(path.join("test", "file", "factorio"), writePath, {}); describe("constructor()", function() { it("should handle dashes in write path with strapPaths enabled", function() { // eslint-disable-next-line no-new - new libFactorio.FactorioServer( + new lib.FactorioServer( path.join("test", "file", "factorio"), path.join("temp", "test", "server-1"), { stripPaths: true } diff --git a/test/lib/file_ops.js b/test/lib/file_ops.js index 78a53564..ff203138 100644 --- a/test/lib/file_ops.js +++ b/test/lib/file_ops.js @@ -3,7 +3,7 @@ const assert = require("assert").strict; const fs = require("fs-extra"); const path = require("path"); -const libFileOps = require("@clusterio/lib/file_ops"); +const lib = require("@clusterio/lib"); describe("lib/file_ops", function() { let baseDir = path.join("temp", "test", "file_ops"); @@ -28,30 +28,30 @@ describe("lib/file_ops", function() { describe("getNewestFile()", function() { it("returns a string in a directory with files", async function() { - let newest = await libFileOps.getNewestFile(path.join(baseDir, "test")); + let newest = await lib.getNewestFile(path.join(baseDir, "test")); assert.equal(typeof newest, "string"); }); it("returns undefined if all entries were filtered out", async function() { - let newest = await libFileOps.getNewestFile(path.join(baseDir, "test"), (name) => !name.endsWith(".txt")); + let newest = await lib.getNewestFile(path.join(baseDir, "test"), (name) => !name.endsWith(".txt")); assert.equal(newest, undefined); }); it("returns undefined if directory is empty", async function() { - let newest = await libFileOps.getNewestFile(path.join(baseDir, "test", "folder")); + let newest = await lib.getNewestFile(path.join(baseDir, "test", "folder")); assert.equal(newest, undefined); }); }); describe("getNewestFile()", function() { it("returns 0 if directory does not exist", async function() { - let size = await libFileOps.directorySize(path.join(baseDir, "invalid")); + let size = await lib.directorySize(path.join(baseDir, "invalid")); assert.equal(size, 0); }); it("returns 0 if directory is empty", async function() { - let size = await libFileOps.directorySize(path.join(baseDir, "test", "folder")); + let size = await lib.directorySize(path.join(baseDir, "test", "folder")); assert.equal(size, 0); }); it("returns size of files in directory", async function() { - let size = await libFileOps.directorySize(path.join(baseDir, "test")); + let size = await lib.directorySize(path.join(baseDir, "test")); assert.equal(size, 21); }); }); @@ -64,7 +64,7 @@ describe("lib/file_ops", function() { [["file.txt", ".txt"], "file.txt"], ]; for (let [args, expected] of cases) { - let actual = await libFileOps.findUnusedName(path.join(baseDir, "test", "folder"), ...args); + let actual = await lib.findUnusedName(path.join(baseDir, "test", "folder"), ...args); assert.equal(actual, expected); } }); @@ -78,7 +78,7 @@ describe("lib/file_ops", function() { [["bar-1.txt", ".txt"], "bar-3.txt"], ]; for (let [args, expected] of cases) { - let actual = await libFileOps.findUnusedName(path.join(baseDir, "find"), ...args); + let actual = await lib.findUnusedName(path.join(baseDir, "find"), ...args); assert.equal(actual, expected); } }); @@ -87,14 +87,14 @@ describe("lib/file_ops", function() { describe("safeOutputFile()", function() { it("should write new target file", async function() { let target = path.join(baseDir, "safe", "simple.txt"); - await libFileOps.safeOutputFile(target, "a text file", "utf8"); + await lib.safeOutputFile(target, "a text file", "utf8"); assert(!await fs.pathExists(`${target}.tmp`), "temporary was left behind"); assert.equal(await fs.readFile(target, "utf8"), "a text file"); }); it("should overwrite existing target file", async function() { let target = path.join(baseDir, "safe", "exists.txt"); await fs.outputFile(target, "previous", "utf8"); - await libFileOps.safeOutputFile(target, "current", "utf8"); + await lib.safeOutputFile(target, "current", "utf8"); assert(!await fs.pathExists(`${target}.tmp`), "temporary was left behind"); assert.equal(await fs.readFile(target, "utf8"), "current"); }); @@ -102,11 +102,11 @@ describe("lib/file_ops", function() { describe("checkFilename()", function() { it("should allow a basic name", function() { - libFileOps.checkFilename("file"); + lib.checkFilename("file"); }); function check(item, msg) { - assert.throws(() => libFileOps.checkFilename(item), new Error(msg)); + assert.throws(() => lib.checkFilename(item), new Error(msg)); } it("should throw on non-string", function() { @@ -152,7 +152,7 @@ describe("lib/file_ops", function() { describe("cleanFilename()", function() { function clean(item, expected) { - assert.equal(libFileOps.cleanFilename(item), expected); + assert.equal(lib.cleanFilename(item), expected); } it("should allow a basic name", function() { @@ -160,7 +160,7 @@ describe("lib/file_ops", function() { }); function check(item, msg) { - assert.throws(() => libFileOps.cleanFilename(item), new Error(msg)); + assert.throws(() => lib.cleanFilename(item), new Error(msg)); } it("should throw on non-string", function() { diff --git a/test/lib/hash.js b/test/lib/hash.js index 60b0aa7c..adb9f642 100644 --- a/test/lib/hash.js +++ b/test/lib/hash.js @@ -3,21 +3,21 @@ const assert = require("assert").strict; const fs = require("fs"); const path = require("path"); -const libHash = require("@clusterio/lib/hash"); +const lib = require("@clusterio/lib"); describe("lib/hash", function() { describe("hashStream()", function() { it("should hash a stream of bytes", async function() { let stream = fs.createReadStream(path.join("test", "file", "hash.txt")); - let result = await libHash.hashStream(stream); + let result = await lib.hashStream(stream); assert.equal(result, "be417768b5c3c5c1d9bcb2e7c119196dd76b5570"); }); }); describe("hashFile()", function() { it("should hash a file", async function() { - let result = await libHash.hashFile(path.join("test", "file", "hash.txt")); + let result = await lib.hashFile(path.join("test", "file", "hash.txt")); assert.equal(result, "be417768b5c3c5c1d9bcb2e7c119196dd76b5570"); }); }); diff --git a/test/lib/helpers.js b/test/lib/helpers.js index 3d4b89e3..57b23772 100644 --- a/test/lib/helpers.js +++ b/test/lib/helpers.js @@ -2,25 +2,25 @@ const assert = require("assert").strict; const hrtime = process.hrtime.bigint; -const libHelpers = require("@clusterio/lib/helpers"); +const lib = require("@clusterio/lib"); describe("lib/helpers", function() { describe("basicType()", function() { it("should return the expected values", function() { - assert.equal(libHelpers.basicType("s"), "string"); - assert.equal(libHelpers.basicType(null), "null"); - assert.equal(libHelpers.basicType(undefined), "undefined"); - assert.equal(libHelpers.basicType([1, 2]), "array"); - assert.equal(libHelpers.basicType(7), "number"); - assert.equal(libHelpers.basicType({ a: 1 }), "object"); + assert.equal(lib.basicType("s"), "string"); + assert.equal(lib.basicType(null), "null"); + assert.equal(lib.basicType(undefined), "undefined"); + assert.equal(lib.basicType([1, 2]), "array"); + assert.equal(lib.basicType(7), "number"); + assert.equal(lib.basicType({ a: 1 }), "object"); }); }); describe("wait", function() { it("should wait the approximate amount of time given", async function() { let startNs = hrtime(); - await libHelpers.wait(100); + await lib.wait(100); let duration = Number(hrtime() - startNs) / 1e6; // On windows the time waited is normally up to 15 ms late with outliers in the 20ms range. @@ -30,22 +30,22 @@ describe("lib/helpers", function() { describe("timeout", function() { it("should return the result of an already resolved promise", async function() { - assert.equal(await libHelpers.timeout(Promise.resolve("value"), 10, "timeout"), "value"); + assert.equal(await lib.timeout(Promise.resolve("value"), 10, "timeout"), "value"); }); it("should return the result of the promise if received before timeout", async function() { - assert.equal(await libHelpers.timeout( - (async () => { await libHelpers.wait(10); return "value"; })(), 20, "timeout" + assert.equal(await lib.timeout( + (async () => { await lib.wait(10); return "value"; })(), 20, "timeout" ), "value"); }); it("should return the timeoutResult if not received before timeout", async function() { - assert.equal(await libHelpers.timeout( - (async () => { await libHelpers.wait(20); return "value"; })(), 10, "timeout" + assert.equal(await lib.timeout( + (async () => { await lib.wait(20); return "value"; })(), 10, "timeout" ), "timeout"); }); }); function parse(input, attributes) { - const result = libHelpers.parseSearchString(input, attributes); + const result = lib.parseSearchString(input, attributes); if (!result.issues.length) { return result.terms; } @@ -132,7 +132,7 @@ describe("lib/helpers", function() { }); }); describe("wordMatches()", function() { - const match = libHelpers.wordMatches; + const match = lib.wordMatches; it("should match any inputs", function() { assert(match(parse("word")[0], "a word in a string"), "one text"); assert(!match(parse("word")[0], "a string without"), "one text no match"); diff --git a/test/lib/ini.js b/test/lib/ini.js index 846e614c..c7cd39f5 100644 --- a/test/lib/ini.js +++ b/test/lib/ini.js @@ -1,60 +1,60 @@ "use strict"; const assert = require("assert").strict; -const libIni = require("@clusterio/lib/ini"); +const lib = require("@clusterio/lib"); describe("lib/ini", function() { describe("parse()", function() { it("should ignore comments", function() { assert.deepEqual( - libIni.parse("# A comment\n; Another comment\nfoo=bar\n"), + lib.parse("# A comment\n; Another comment\nfoo=bar\n"), { foo: "bar" }, ); }); it("should ignore certain whitespace", function() { assert.deepEqual( - libIni.parse(" # A comment \n\n [spam] \t \n \tfoo=bar\n"), + lib.parse(" # A comment \n\n [spam] \t \n \tfoo=bar\n"), { spam: { foo: "bar" }} ); }); it("should preserve certain whitespace", function() { assert.deepEqual( - libIni.parse("[\t spam\t ]\nfoo =\t bar \n"), + lib.parse("[\t spam\t ]\nfoo =\t bar \n"), { "\t spam\t ": { "foo ": "\t bar " }} ); }); it("should not treat characters specially", function() { assert.deepEqual( - libIni.parse("[#;spam]\nfoo#;=#;bar=#;'\""), + lib.parse("[#;spam]\nfoo#;=#;bar=#;'\""), { "#;spam": { "foo#;": "#;bar=#;'\"" }} ); }); it("should handle windows line endings", function() { assert.deepEqual( - libIni.parse("[spam]\r\nfoo=bar\r\n"), + lib.parse("[spam]\r\nfoo=bar\r\n"), { "spam": { "foo": "bar" }} ); }); it("should throw on incomplete section", function() { assert.throws( - () => libIni.parse("[spam"), + () => lib.parse("[spam"), new Error("Unterminated section header on line 1") ); }); it("should throw on missing value", function() { assert.throws( - () => libIni.parse("key"), + () => lib.parse("key"), new Error("Missing value for key key on line 1") ); }); it("should throw on duplicated section", function() { assert.throws( - () => libIni.parse("[spam]\n[spam]\n"), + () => lib.parse("[spam]\n[spam]\n"), new Error("Duplicated section [spam] on line 2") ); }); it("should throw on duplicated keys", function() { assert.throws( - () => libIni.parse("key=value\nkey=value\n"), + () => lib.parse("key=value\nkey=value\n"), new Error("Duplicated key key on line 2") ); }); @@ -73,7 +73,7 @@ describe("lib/ini", function() { [{ "#;spam": { "foo#;": "#;bar=#;'\"" }}, "[#;spam]\nfoo#;=#;bar=#;'\"\n"], ]; for (let [input, expected] of cases) { - assert.equal(libIni.stringify(input), expected); + assert.equal(lib.stringify(input), expected); } }); }); @@ -86,7 +86,7 @@ describe("lib/ini", function() { { first: { foo: "1", bar: "2" }, second: { spam: "true" }}, { '"#;[] ': ' "#;[] ', ' #;"[ ': { '"#;[] ': ' "#;[ ' }}, ]) { - let actual = libIni.parse(libIni.stringify(expected)); + let actual = lib.parse(lib.stringify(expected)); assert.deepEqual(actual, expected); } }); diff --git a/test/lib/link/connector.js b/test/lib/link/connector.js index ddcfbd49..e589af21 100644 --- a/test/lib/link/connector.js +++ b/test/lib/link/connector.js @@ -3,13 +3,12 @@ const assert = require("assert").strict; const events = require("events"); const mock = require("../../mock"); -const libData = require("@clusterio/lib/data"); -const libLink = require("@clusterio/lib/link"); +const lib = require("@clusterio/lib"); describe("lib/link/connectors", function() { describe("class WebSocketBaseConnector", function() { - let testConnector = new libLink.WebSocketBaseConnector(); + let testConnector = new lib.WebSocketBaseConnector(); describe("._dropSendBufferSeq()", function() { beforeEach(function() { @@ -35,7 +34,7 @@ describe("lib/link/connectors", function() { }); describe("class WebSocketClientConnector", function() { - let testConnector = new libLink.WebSocketClientConnector("url", 1); + let testConnector = new lib.WebSocketClientConnector("url", 1); testConnector._socket = new mock.MockSocket(); describe(".register()", function() { @@ -51,7 +50,7 @@ describe("lib/link/connectors", function() { it("calls send on the socket", function() { testConnector._state = "connecting"; testConnector._socket.sentMessages = []; - testConnector.sendHandshake(new libData.MessageInvalidate()); + testConnector.sendHandshake(new lib.MessageInvalidate()); assert.deepEqual( testConnector._socket.sentMessages.map(JSON.parse), [{ type: "invalidate" }] @@ -63,7 +62,7 @@ describe("lib/link/connectors", function() { it("calls send on the socket", function() { testConnector._state = "connected"; testConnector._socket.sentMessages = []; - testConnector.send(new libData.MessageHeartbeat(1)); + testConnector.send(new lib.MessageHeartbeat(1)); assert.deepEqual( testConnector._socket.sentMessages.map(JSON.parse), [{ seq: 1, type: "heartbeat"}] @@ -96,8 +95,8 @@ describe("lib/link/connectors", function() { let called = false; testConnector.register = () => { called = true; }; testConnector._processHandshake( - new libData.MessageHello( - new libData.HelloData("test", {}) + new lib.MessageHello( + new lib.HelloData("test", {}) ) ); assert(called, "register was not called"); @@ -105,9 +104,9 @@ describe("lib/link/connectors", function() { it("should emit connect on ready", async function() { let result = events.once(testConnector, "connect"); testConnector._processHandshake( - new libData.MessageReady( - new libData.ReadyData( - new libData.Address(libData.Address.control, 1), + new lib.MessageReady( + new lib.ReadyData( + new lib.Address(lib.Address.control, 1), "x", 20, 10, @@ -128,7 +127,7 @@ describe("lib/link/connectors", function() { it("should throw on message received in invalid state", function() { testConnector._state = "closed"; assert.throws( - () => testConnector._socket.events.get("message")(JSON.stringify(new libData.MessageInvalidate())), + () => testConnector._socket.events.get("message")(JSON.stringify(new lib.MessageInvalidate())), new Error("Received message in unexpected state closed") ); }); @@ -136,15 +135,15 @@ describe("lib/link/connectors", function() { testConnector._state = "connecting"; let called = false; testConnector._processHandshake = () => { called = true; }; - testConnector._socket.events.get("message")(JSON.stringify(new libData.MessageInvalidate())); + testConnector._socket.events.get("message")(JSON.stringify(new lib.MessageInvalidate())); assert(called, "_processHandshake was not called"); }); it("should emit message on message in connected state", async function() { testConnector._socket.sentMessages = []; testConnector._state = "connected"; let result = events.once(testConnector, "message"); - let addr = new libData.Address(libData.Address.control, 1); - let event = new libData.MessageEvent(1, addr, addr, "TestEvent"); + let addr = new lib.Address(lib.Address.control, 1); + let event = new lib.MessageEvent(1, addr, addr, "TestEvent"); testConnector._socket.events.get("message")(JSON.stringify(event)); assert.deepEqual((await result)[0], event); }); diff --git a/test/lib/link/link.js b/test/lib/link/link.js index 2b6a2f61..169c8c72 100644 --- a/test/lib/link/link.js +++ b/test/lib/link/link.js @@ -2,12 +2,10 @@ const assert = require("assert").strict; const events = require("events"); -const libData = require("@clusterio/lib/data"); -const libLink = require("@clusterio/lib/link"); -const libErrors = require("@clusterio/lib/errors"); +const lib = require("@clusterio/lib"); const mock = require("../../mock"); -const addr = libData.Address.fromShorthand; +const addr = lib.Address.fromShorthand; describe("lib/link/link", function() { function throwSimple(message) { @@ -28,7 +26,7 @@ describe("lib/link/link", function() { static dst = ["controller", "control"]; static permission = null; } - libLink.Link.register(SimpleRequest); + lib.Link.register(SimpleRequest); class NumberRequest { static type = "request"; static src = ["controller", "control"]; @@ -45,14 +43,14 @@ describe("lib/link/link", function() { toJSON() { return this.value; } static fromJSON(json) { return new this(json); } }; - libLink.Link.register(NumberRequest); + lib.Link.register(NumberRequest); class SimpleEvent { static type = "event"; static src = ["controller", "control"]; static dst = ["controller", "control"]; static permission = null; } - libLink.Link.register(SimpleEvent); + lib.Link.register(SimpleEvent); class NumberEvent { static type = "event"; static src = ["controller", "control"]; @@ -63,11 +61,11 @@ describe("lib/link/link", function() { toJSON() { return this.value; } static fromJSON(json) { return new this(json); } } - libLink.Link.register(NumberEvent); + lib.Link.register(NumberEvent); beforeEach(function() { testConnector = new mock.MockConnector(src, dst); - testLink = new libLink.Link(testConnector); + testLink = new lib.Link(testConnector); }); it("should handle unknown message", async function() { @@ -76,13 +74,13 @@ describe("lib/link/link", function() { describe("Request handling", function() { it("should give an error response back on unrecognized request", function() { - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "UnhandledRequest")); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "UnhandledRequest")); assert.deepEqual(testConnector.sentMessages, [ - new libData.MessageResponseError( + new lib.MessageResponseError( testConnector._seq - 1, src, dst, - new libData.ResponseError("Unrecognized request UnhandledRequest") + new lib.ResponseError("Unrecognized request UnhandledRequest") ), ]); }); @@ -92,14 +90,14 @@ describe("lib/link/link", function() { static src = "controller"; static dst = "control"; } - libLink.Link.register(UnhandledRequest); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "UnhandledRequest")); + lib.Link.register(UnhandledRequest); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "UnhandledRequest")); assert.deepEqual(testConnector.sentMessages, [ - new libData.MessageResponseError( + new lib.MessageResponseError( testConnector._seq - 1, src, dst, - new libData.ResponseError("No handler for UnhandledRequest") + new lib.ResponseError("No handler for UnhandledRequest") ), ]); }); @@ -109,14 +107,14 @@ describe("lib/link/link", function() { static src = "host"; static dst = "control"; } - libLink.Link.register(InvalidSrcRequest); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "InvalidSrcRequest")); + lib.Link.register(InvalidSrcRequest); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "InvalidSrcRequest")); assert.deepEqual(testConnector.sentMessages, [ - new libData.MessageResponseError( + new lib.MessageResponseError( testConnector._seq - 1, src, dst, - new libData.ResponseError("Source [Address controller:0] is not allowed for InvalidSrcRequest") + new lib.ResponseError("Source [Address controller:0] is not allowed for InvalidSrcRequest") ), ]); }); @@ -126,38 +124,38 @@ describe("lib/link/link", function() { static src = "controller"; static dst = "host"; } - libLink.Link.register(InvalidDstRequest); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "InvalidDstRequest")); + lib.Link.register(InvalidDstRequest); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "InvalidDstRequest")); assert.deepEqual(testConnector.sentMessages, [ - new libData.MessageResponseError( + new lib.MessageResponseError( testConnector._seq - 1, src, dst, - new libData.ResponseError( + new lib.ResponseError( "Destination [Address control:1] is not allowed for InvalidDstRequest" ) ), ]); }); it("should give an error response back on broadcast src", function() { - testConnector.emit("message", new libData.MessageRequest(1, addr("allControls"), src, "SimpleRequest")); + testConnector.emit("message", new lib.MessageRequest(1, addr("allControls"), src, "SimpleRequest")); assert.deepEqual(testConnector.sentMessages, [ - new libData.MessageResponseError( + new lib.MessageResponseError( testConnector._seq - 1, src, addr("allControls"), - new libData.ResponseError("Message src may not be broadcast") + new lib.ResponseError("Message src may not be broadcast") ), ]); }); it("should give an error response back on requst with broadcast dst", function() { - testConnector.emit("message", new libData.MessageRequest(1, dst, addr("allControls"), "SimpleRequest")); + testConnector.emit("message", new lib.MessageRequest(1, dst, addr("allControls"), "SimpleRequest")); assert.deepEqual(testConnector.sentMessages, [ - new libData.MessageResponseError( + new lib.MessageResponseError( testConnector._seq - 1, src, dst, - new libData.ResponseError("Destination [Address 4:control] is not allowed for SimpleRequest") + new lib.ResponseError("Destination [Address 4:control] is not allowed for SimpleRequest") ), ]); }); @@ -165,7 +163,7 @@ describe("lib/link/link", function() { describe("Event handling", function() { it("should ignore unrecognized event", function() { - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "UnhandledEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "UnhandledEvent")); assert.deepEqual(testConnector.sentMessages, []); }); it("should ignore unhandled event", function() { @@ -174,8 +172,8 @@ describe("lib/link/link", function() { static src = "controller"; static dst = "control"; } - libLink.Link.register(UnhandledEvent); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "UnhandledEvent")); + lib.Link.register(UnhandledEvent); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "UnhandledEvent")); assert.deepEqual(testConnector.sentMessages, []); }); it("should ignore invalid src", function() { @@ -185,9 +183,9 @@ describe("lib/link/link", function() { static dst = "control"; } let handled = false; - libLink.Link.register(InvalidSrcEvent); + lib.Link.register(InvalidSrcEvent); testLink.snoopEvent(InvalidSrcEvent, async () => { handled = true; }); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "InvalidSrcEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "InvalidSrcEvent")); assert(!handled, "event was not ignored"); assert.deepEqual(testConnector.sentMessages, []); }); @@ -197,25 +195,25 @@ describe("lib/link/link", function() { static src = "controller"; static dst = "host"; } - libLink.Link.register(InvalidDstEvent); + lib.Link.register(InvalidDstEvent); let handled = false; testLink.snoopEvent(InvalidDstEvent, async () => { handled = true; }); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "InvalidDstEvent")); - testConnector.emit("message", new libData.MessageEvent(1, dst, addr("allControls"), "InvalidDstEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "InvalidDstEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, addr("allControls"), "InvalidDstEvent")); assert(!handled, "event was not ignored"); assert.deepEqual(testConnector.sentMessages, []); }); it("should ignore broadcast src", function() { let handled = false; testLink.snoopEvent(SimpleEvent, async () => { handled = true; }); - testConnector.emit("message", new libData.MessageEvent(1, addr("allControls"), src, "SimpleEvent")); + testConnector.emit("message", new lib.MessageEvent(1, addr("allControls"), src, "SimpleEvent")); assert(!handled, "event was not ignored"); assert.deepEqual(testConnector.sentMessages, []); }); it("should handle event with broadcast dst", function() { let handled = false; testLink.snoopEvent(SimpleEvent, async () => { handled = true; }); - testConnector.emit("message", new libData.MessageEvent(1, dst, addr("allControls"), "SimpleEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, addr("allControls"), "SimpleEvent")); assert(handled, "event was ignored"); assert.deepEqual(testConnector.sentMessages, []); }); @@ -225,14 +223,14 @@ describe("lib/link/link", function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testConnector.emit("disconnectPrepare"); - assert.deepEqual(await message, [new libData.MessageDisconnect("ready")]); + assert.deepEqual(await message, [new lib.MessageDisconnect("ready")]); }); it("should send ready on connector prepareDisconnect if an error occurs", async function() { testLink.prepareDisconnect = async () => { throwSimple("Error occured"); }; let message = events.once(testConnector, "send"); message.catch(() => {}); testConnector.emit("disconnectPrepare"); - assert.deepEqual(await message, [new libData.MessageDisconnect("ready")]); + assert.deepEqual(await message, [new lib.MessageDisconnect("ready")]); }); it("should reject pending requests on close", async function() { @@ -253,39 +251,39 @@ describe("lib/link/link", function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testLink.send(new SimpleRequest()); - let srcReq = new libData.Address(libData.Address.control, 1, 1); + let srcReq = new lib.Address(lib.Address.control, 1, 1); assert.deepEqual( await message, - [new libData.MessageRequest(1, srcReq, dst, "SimpleRequest", undefined)] + [new lib.MessageRequest(1, srcReq, dst, "SimpleRequest", undefined)] ); }); it("should send request with data to the other side of the link", async function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testLink.send(new NumberRequest(22)); - let srcReq = new libData.Address(libData.Address.control, 1, 1); + let srcReq = new lib.Address(lib.Address.control, 1, 1); assert.deepEqual( await message, - [new libData.MessageRequest(1, srcReq, dst, "NumberRequest", new NumberRequest(22))] + [new lib.MessageRequest(1, srcReq, dst, "NumberRequest", new NumberRequest(22))] ); }); it("should send request and resolve when response is received", async function() { let message = events.once(testConnector, "send"); message.catch(() => {}); let request = testLink.send(new SimpleRequest()); - let srcReq = new libData.Address(libData.Address.control, 1, 1); - testConnector.emit("message", new libData.MessageResponse(1, dst, srcReq)); + let srcReq = new lib.Address(lib.Address.control, 1, 1); + testConnector.emit("message", new lib.MessageResponse(1, dst, srcReq)); await request; }); it("should send request and reject with error when error response is received", async function() { let message = events.once(testConnector, "send"); message.catch(() => {}); let request = testLink.send(new SimpleRequest()); - let srcReq = new libData.Address(libData.Address.control, 1, 1); + let srcReq = new lib.Address(lib.Address.control, 1, 1); testConnector.emit( "message", - new libData.MessageResponseError( - 1, dst, srcReq, new libData.ResponseError("Error") + new lib.MessageResponseError( + 1, dst, srcReq, new lib.ResponseError("Error") ) ); await assert.rejects( @@ -297,8 +295,8 @@ describe("lib/link/link", function() { let message = events.once(testConnector, "send"); message.catch(() => {}); let request = testLink.send(new NumberRequest(22)); - let srcReq = new libData.Address(libData.Address.control, 1, 1); - testConnector.emit("message", new libData.MessageResponse(1, dst, srcReq, 44)); + let srcReq = new lib.Address(lib.Address.control, 1, 1); + testConnector.emit("message", new lib.MessageResponse(1, dst, srcReq, 44)); assert.deepEqual(await request, new NumberRequest.Response(44)); }); it("should send event to the other side of the link", async function() { @@ -307,7 +305,7 @@ describe("lib/link/link", function() { testLink.send(new SimpleEvent()); assert.deepEqual( await message, - [new libData.MessageEvent(1, src, dst, "SimpleEvent", undefined)] + [new lib.MessageEvent(1, src, dst, "SimpleEvent", undefined)] ); }); it("should send event with data to the other side of the link", async function() { @@ -316,7 +314,7 @@ describe("lib/link/link", function() { testLink.send(new NumberEvent(22)); assert.deepEqual( await message, - [new libData.MessageEvent(1, src, dst, "NumberEvent", new NumberEvent(22))] + [new lib.MessageEvent(1, src, dst, "NumberEvent", new NumberEvent(22))] ); }); }); @@ -325,18 +323,18 @@ describe("lib/link/link", function() { let handled = false; testLink.handle(SimpleRequest, async () => { handled = true; }); assert(testLink._requestHandlers.has(SimpleRequest), "request handler was not registered"); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "SimpleRequest")); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "SimpleRequest")); assert(handled, "request was not handled"); }); it("should send response error from request handler throwing", async function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testLink.handle(SimpleRequest, async () => { throwSimple("Error"); }); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "SimpleRequest")); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "SimpleRequest")); assert.deepEqual( await message, - [new libData.MessageResponseError( - 1, src, dst, new libData.ResponseError("Error", undefined, "Error") + [new lib.MessageResponseError( + 1, src, dst, new lib.ResponseError("Error", undefined, "Error") )] ); }); @@ -344,13 +342,13 @@ describe("lib/link/link", function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testLink.handle(NumberRequest, async () => 1); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "NumberRequest", "not a number")); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "NumberRequest", "not a number")); let response = (await message)[0]; assert.deepEqual( response, - new libData.MessageResponseError( + new lib.MessageResponseError( 1, src, dst, - new libData.ResponseError( + new lib.ResponseError( "Request NumberRequest failed validation", response.data.code, response.data.stack, @@ -362,13 +360,13 @@ describe("lib/link/link", function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testLink.handle(NumberRequest, async () => "not a number"); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "NumberRequest", 1)); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "NumberRequest", 1)); let response = (await message)[0]; assert.deepEqual( response, - new libData.MessageResponseError( + new lib.MessageResponseError( 1, src, dst, - new libData.ResponseError( + new lib.ResponseError( "Response for request NumberRequest failed validation", response.data.code, response.data.stack, @@ -380,29 +378,29 @@ describe("lib/link/link", function() { let message = events.once(testConnector, "send"); message.catch(() => {}); testLink.handle(NumberRequest, async (request) => request.value + 4); - testConnector.emit("message", new libData.MessageRequest(1, dst, src, "NumberRequest", 1)); + testConnector.emit("message", new lib.MessageRequest(1, dst, src, "NumberRequest", 1)); let response = (await message)[0]; assert.deepEqual( response, - new libData.MessageResponse(1, src, dst, 5) + new lib.MessageResponse(1, src, dst, 5) ); }); it("should register an event handler", function() { let handled = false; testLink.handle(SimpleEvent, async () => { handled = true; }); assert(testLink._eventHandlers.has(SimpleEvent), "event handler was not registered"); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "SimpleEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "SimpleEvent")); assert(handled, "event was not handled"); }); it("should pass value to event handler", async function() { let value; testLink.handle(NumberEvent, async (event) => { value = event.value; }); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "NumberEvent", 9)); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "NumberEvent", 9)); assert.deepEqual(value, 9); }); it("should log errors from event handler", function() { testLink.handle(SimpleEvent, async () => { throwSimple("Error"); }); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "SimpleEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "SimpleEvent")); }); it("should throw on unknown type", function() { assert.throws( @@ -432,7 +430,7 @@ describe("lib/link/link", function() { static jsonSchema = {}; } assert.throws( - () => libLink.Link.register(BadRequest1), + () => lib.Link.register(BadRequest1), new Error("Request BadRequest1 has static jsonSchema but is missing static fromJSON") ); class BadRequest2 { @@ -442,7 +440,7 @@ describe("lib/link/link", function() { static fromJSON() {}; } assert.throws( - () => libLink.Link.register(BadRequest2), + () => lib.Link.register(BadRequest2), new Error("Request BadRequest2 has static fromJSON but is missing static jsonSchema") ); }); @@ -454,7 +452,7 @@ describe("lib/link/link", function() { static jsonSchema = {}; } assert.throws( - () => libLink.Link.register(BadEvent1), + () => lib.Link.register(BadEvent1), new Error("Event BadEvent1 has static jsonSchema but is missing static fromJSON") ); class BadEvent2 { @@ -464,7 +462,7 @@ describe("lib/link/link", function() { static fromJSON() {}; } assert.throws( - () => libLink.Link.register(BadEvent2), + () => lib.Link.register(BadEvent2), new Error("Event BadEvent2 has static fromJSON but is missing static jsonSchema") ); }); @@ -486,10 +484,10 @@ describe("lib/link/link", function() { static jsonSchema = { type: "string" }; static fromJSON(json) { return new this(json); }; } - libLink.Link.register(StringEvent); + lib.Link.register(StringEvent); testLink.handle(StringEvent, () => {}); assert.throws( - () => testLink._processMessage(new libData.MessageEvent(1, dst, src, "StringEvent", 99)), + () => testLink._processMessage(new lib.MessageEvent(1, dst, src, "StringEvent", 99)), { message: "Event StringEvent failed validation" } ); }); @@ -500,12 +498,12 @@ describe("lib/link/link", function() { let handled = false; testLink.snoopEvent(SimpleEvent, async () => { handled = true; }); assert(testLink._eventSnoopers.has(SimpleEvent), "event was not snooped"); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "SimpleEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "SimpleEvent")); assert(handled, "event was not handled"); }); it("should log errors from snoop handler", function() { testLink.snoopEvent(SimpleEvent, async () => { throwSimple("Error"); }); - testConnector.emit("message", new libData.MessageEvent(1, dst, src, "SimpleEvent")); + testConnector.emit("message", new lib.MessageEvent(1, dst, src, "SimpleEvent")); }); it("should throw on double registration", function() { testLink.snoopEvent(SimpleEvent); diff --git a/test/lib/logging_utils.js b/test/lib/logging_utils.js index 0dc36566..630691d0 100644 --- a/test/lib/logging_utils.js +++ b/test/lib/logging_utils.js @@ -2,19 +2,16 @@ const assert = require("assert").strict; const fs = require("fs-extra"); const path = require("path"); -const util = require("util"); - const { testLines } = require("./factorio/lines"); -const libLoggingUtils = require("@clusterio/lib/logging_utils"); -const libStream = require("@clusterio/lib/stream"); +const lib = require("@clusterio/lib"); describe("lib/logging_utils.js", function() { describe("formatServerOutput", function() { it("should pass the test lines", function() { for (let [reference, output] of testLines) { - let line = libLoggingUtils._formatServerOutput(output); + let line = lib._formatServerOutput(output); // Strip colours line = line.replace(/\x1B\[\d+m/g, ""); assert.deepEqual(line, reference); @@ -25,11 +22,11 @@ describe("lib/logging_utils.js", function() { let logDir = path.join("test", "file", "log"); describe("class LogIndex", function() { it("should create a new empty index if index.json does not exist", async function() { - let logIndex = await libLoggingUtils.LogIndex.load(logDir); + let logIndex = await lib.LogIndex.load(logDir); assert.deepEqual(logIndex.index, new Map()); }); it("should build index of only past log files", async function() { - let logIndex = await libLoggingUtils.LogIndex.load(logDir); + let logIndex = await lib.LogIndex.load(logDir); await logIndex.buildIndex(); assert.deepEqual( new Set(logIndex.index.keys()), @@ -37,12 +34,12 @@ describe("lib/logging_utils.js", function() { ); }); it("should roundtrip index on save load cycle", async function() { - let logIndex = await libLoggingUtils.LogIndex.load(logDir); + let logIndex = await lib.LogIndex.load(logDir); await logIndex.buildIndex(); let tempDir = path.join("temp", "test", "log"); logIndex.logDirectory = tempDir; await logIndex.save(); - let loadedIndex = await libLoggingUtils.LogIndex.load(tempDir); + let loadedIndex = await lib.LogIndex.load(tempDir); assert.deepEqual( loadedIndex, logIndex @@ -51,7 +48,7 @@ describe("lib/logging_utils.js", function() { it("should handle loading broken index", async function() { let tempDir = path.join("temp", "test", "log"); await fs.outputFile(path.join(tempDir, "index.json"), "Broken JSON"); - let logIndex = await libLoggingUtils.LogIndex.load(tempDir); + let logIndex = await lib.LogIndex.load(tempDir); assert.deepEqual(logIndex.index, new Map()); }); }); @@ -64,7 +61,7 @@ describe("lib/logging_utils.js", function() { continue; } let fileStream = fs.createReadStream(path.join(logDir, file)); - let lineStream = new libStream.LineSplitter({ readableObjectMode: true }); + let lineStream = new lib.LineSplitter({ readableObjectMode: true }); fileStream.pipe(lineStream); for await (let line of lineStream) { try { @@ -75,7 +72,7 @@ describe("lib/logging_utils.js", function() { } } - logIndex = await libLoggingUtils.LogIndex.load(logDir); + logIndex = await lib.LogIndex.load(logDir); await logIndex.buildIndex(); }); @@ -83,45 +80,45 @@ describe("lib/logging_utils.js", function() { for (let index of [() => undefined, () => logIndex]) { describe(index() === undefined ? "without index" : "with index", function() { it("returns nothing with an empty filter", async function() { - let log = await libLoggingUtils.queryLog(logDir, {}, index()); + let log = await lib.queryLog(logDir, {}, index()); assert.deepEqual(log, []); }); it("should return the whole log when querying all", async function() { - let log = await libLoggingUtils.queryLog(logDir, { all: true }, index()); + let log = await lib.queryLog(logDir, { all: true }, index()); assert.deepEqual(log, allLines); }); it("should return the whole log in reverse when querying all desc", async function() { - let log = await libLoggingUtils.queryLog(logDir, { all: true, order: "desc" }, index()); + let log = await lib.queryLog(logDir, { all: true, order: "desc" }, index()); assert.deepEqual(log, [...allLines].reverse()); }); it("should limit by limit", async function() { - let log = await libLoggingUtils.queryLog(logDir, { limit: 2, all: true }, index()); + let log = await lib.queryLog(logDir, { limit: 2, all: true }, index()); assert.deepEqual(log, allLines.slice(0, 2)); }); it("should filter by maxLevel", async function() { - let log = await libLoggingUtils.queryLog(logDir, { maxLevel: "info", all: true }, index()); + let log = await lib.queryLog(logDir, { maxLevel: "info", all: true }, index()); assert.deepEqual(log, allLines.filter( info => ["fatal", "error", "warn", "audit", "info"].includes(info.level) )); - log = await libLoggingUtils.queryLog(logDir, { maxLevel: "fatal", all: true }, index()); + log = await lib.queryLog(logDir, { maxLevel: "fatal", all: true }, index()); assert.deepEqual(log, allLines.filter( info => ["fatal"].includes(info.level) )); }); it("should filter by controller", async function() { - let log = await libLoggingUtils.queryLog(logDir, { controller: true }, index()); + let log = await lib.queryLog(logDir, { controller: true }, index()); assert.deepEqual(log, allLines.filter( info => info.host_id === undefined && info.instance_id === undefined )); }); it("should filter by hostIds", async function() { - let log = await libLoggingUtils.queryLog(logDir, { hostIds: [1, 2] }, index()); + let log = await lib.queryLog(logDir, { hostIds: [1, 2] }, index()); assert.deepEqual(log, allLines.filter( info => [1, 2].includes(info.host_id) && info.instance_id === undefined )); }); it("should filter by instanceIds", async function() { - let log = await libLoggingUtils.queryLog(logDir, { instanceIds: [10, 11] }, index()); + let log = await lib.queryLog(logDir, { instanceIds: [10, 11] }, index()); assert.deepEqual(log, allLines.filter(info => [10, 11].includes(info.instance_id))); }); }); diff --git a/test/lib/lua_tools.js b/test/lib/lua_tools.js index 3558542b..8fcbac74 100644 --- a/test/lib/lua_tools.js +++ b/test/lib/lua_tools.js @@ -1,31 +1,31 @@ "use strict"; const assert = require("assert").strict; -const libLuaTools = require("@clusterio/lib/lua_tools"); +const lib = require("@clusterio/lib"); describe("lib/lua_tools", function() { describe("escapeString()", function() { it("should escape backslashes", function() { - assert.equal(libLuaTools.escapeString("\\a"), "\\\\a"); + assert.equal(lib.escapeString("\\a"), "\\\\a"); }); it("should escape double quotes", function() { - assert.equal(libLuaTools.escapeString('"a"'), '\\"a\\"'); + assert.equal(lib.escapeString('"a"'), '\\"a\\"'); }); it("should escape single quotes", function() { - assert.equal(libLuaTools.escapeString("'a'"), "\\'a\\'"); + assert.equal(lib.escapeString("'a'"), "\\'a\\'"); }); it("should escape nul bytes", function() { - assert.equal(libLuaTools.escapeString("a\0b"), "a\\0b"); + assert.equal(lib.escapeString("a\0b"), "a\\0b"); }); it("should escape newlines", function() { - assert.equal(libLuaTools.escapeString("a\nb"), "a\\nb"); + assert.equal(lib.escapeString("a\nb"), "a\\nb"); }); it("should escape carriage return", function() { - assert.equal(libLuaTools.escapeString("a\rb"), "a\\rb"); + assert.equal(lib.escapeString("a\rb"), "a\\rb"); }); it("should escape all combined", function() { - assert.equal(libLuaTools.escapeString("a\\b\"c'd\0e\nf\rg"), "a\\\\b\\\"c\\'d\\0e\\nf\\rg"); + assert.equal(lib.escapeString("a\\b\"c'd\0e\nf\rg"), "a\\\\b\\\"c\\'d\\0e\\nf\\rg"); }); }); }); diff --git a/test/lib/plugin.js b/test/lib/plugin.js index f825cd30..a23b80d0 100644 --- a/test/lib/plugin.js +++ b/test/lib/plugin.js @@ -2,14 +2,14 @@ const assert = require("assert").strict; const mock = require("../mock"); -const libPlugin = require("@clusterio/lib/plugin"); +const lib = require("@clusterio/lib"); describe("lib/plugin", function() { describe("class BaseInstancePlugin", function() { let instancePlugin; it("should be constructible", async function() { - instancePlugin = new libPlugin.BaseInstancePlugin({}, new mock.MockInstance(), {}); + instancePlugin = new lib.BaseInstancePlugin({}, new mock.MockInstance(), {}); await instancePlugin.init(); }); it("should define defaults for hooks", async function() { @@ -56,7 +56,7 @@ describe("lib/plugin", function() { describe("class BaseControllerPlugin", function() { let controllerPlugin; it("should be constructible", async function() { - controllerPlugin = new libPlugin.BaseControllerPlugin({}, {}, {}, new mock.MockLogger()); + controllerPlugin = new lib.BaseControllerPlugin({}, {}, {}, new mock.MockLogger()); await controllerPlugin.init(); }); it("should define defaults for hooks", async function() { @@ -87,15 +87,15 @@ describe("lib/plugin", function() { }], ]); it("should invoke the hook on the plugin", async function() { - await libPlugin.invokeHook(plugins, "test"); + await lib.invokeHook(plugins, "test"); assert(betaTestCalled, "Hook was not called"); }); it("should pass and return args", async function() { - let result = await libPlugin.invokeHook(plugins, "pass", 1234); + let result = await lib.invokeHook(plugins, "pass", 1234); assert.deepEqual(result, [1234]); }); it("should ignore errors", async function() { - await libPlugin.invokeHook(plugins, "error"); + await lib.invokeHook(plugins, "error"); }); }); }); diff --git a/test/lib/plugin_loader.js b/test/lib/plugin_loader.js index 84502bfd..6e2e1348 100644 --- a/test/lib/plugin_loader.js +++ b/test/lib/plugin_loader.js @@ -3,8 +3,8 @@ const assert = require("assert").strict; const fs = require("fs-extra"); const path = require("path"); -const libPluginLoader = require("@clusterio/lib/plugin_loader"); -const { escapeRegExp } = require("@clusterio/lib/helpers"); +const lib = require("@clusterio/lib"); +const { escapeRegExp } = lib; describe("lib/plugin_loader", function() { @@ -34,13 +34,13 @@ describe("lib/plugin_loader", function() { it("should throw on missing plugin", async function() { await assert.rejects( - libPluginLoader.loadPluginInfos(new Map([["missing", missingPlugin]]), []), + lib.loadPluginInfos(new Map([["missing", missingPlugin]]), []), new RegExp(`^Error: PluginError: Cannot find module '${escapeRegExp(missingPlugin)}/info'`) ); }); it("should load test plugin", async function() { assert.deepEqual( - await libPluginLoader.loadPluginInfos(new Map([["test", path.resolve(testPlugin)]])), + await lib.loadPluginInfos(new Map([["test", path.resolve(testPlugin)]])), [{ name: "test", version: "0.0.1", requirePath: path.resolve(testPlugin) }] ); }); @@ -53,13 +53,13 @@ describe("lib/plugin_loader", function() { brokenMessage = err.message; } await assert.rejects( - libPluginLoader.loadPluginInfos(new Map([["broken", path.resolve(brokenPlugin)]])), + lib.loadPluginInfos(new Map([["broken", path.resolve(brokenPlugin)]])), { message: `PluginError: ${brokenMessage}` } ); }); it("should reject on invalid plugin", async function() { await assert.rejects( - libPluginLoader.loadPluginInfos(new Map([["invalid", path.resolve(invalidPlugin)]])), + lib.loadPluginInfos(new Map([["invalid", path.resolve(invalidPlugin)]])), { message: `Expected plugin at ${path.resolve(invalidPlugin)} to be named invalid but got wrong` } ); }); @@ -80,7 +80,7 @@ describe("lib/plugin_loader", function() { }); it("should throw if class is missing from entrypoint", async function() { await assert.rejects( - libPluginLoader.loadControllerPluginClass({ + lib.loadControllerPluginClass({ name: "test", controllerEntrypoint: "controller", requirePath: path.resolve(missingClass), @@ -94,7 +94,7 @@ describe("lib/plugin_loader", function() { }); it("should throw if class is not a subclass of BaseControllerPlugin", async function() { await assert.rejects( - libPluginLoader.loadControllerPluginClass({ + lib.loadControllerPluginClass({ name: "test", controllerEntrypoint: "controller", requirePath: path.resolve(wrongParentClass), diff --git a/test/lib/prometheus.js b/test/lib/prometheus.js index 311a893c..b0f24ca3 100644 --- a/test/lib/prometheus.js +++ b/test/lib/prometheus.js @@ -1,7 +1,7 @@ "use strict"; const assert = require("assert").strict; -const prometheus = require("@clusterio/lib/prometheus"); +const prometheus = require("@clusterio/lib"); describe("lib/prometheus", function() { diff --git a/test/lib/stream.js b/test/lib/stream.js index f85af99f..f1ec849b 100644 --- a/test/lib/stream.js +++ b/test/lib/stream.js @@ -1,12 +1,11 @@ "use strict"; const assert = require("assert").strict; -const events = require("events"); const fs = require("fs-extra"); const path = require("path"); const stream = require("stream"); const util = require("util"); -const libStream = require("@clusterio/lib/stream"); +const lib = require("@clusterio/lib"); const finished = util.promisify(stream.finished); @@ -14,7 +13,7 @@ const finished = util.promisify(stream.finished); describe("lib/stream", function() { describe("class LineSplitter", function() { function createSplitter(lines) { - let lineStream = new libStream.LineSplitter({ readableObjectMode: true }); + let lineStream = new lib.LineSplitter({ readableObjectMode: true }); lineStream.on("data", line => lines.push(line.toString("utf-8"))); return lineStream; } @@ -61,7 +60,7 @@ describe("lib/stream", function() { describe("class ReverseLineSplitter", function() { function createReverseSplitter(lines) { - let lineStream = new libStream.ReverseLineSplitter({ readableObjectMode: true }); + let lineStream = new lib.ReverseLineSplitter({ readableObjectMode: true }); lineStream.on("data", line => lines.push(line.toString("utf-8"))); return lineStream; } @@ -111,7 +110,7 @@ describe("lib/stream", function() { let content = ""; for (let i = 0; i < 10; i++) { content += String(i).repeat(10); } await fs.outputFile(path.join("temp", "test", "reverse.txt"), content); - let reverseStream = await libStream.createReverseReadStream( + let reverseStream = await lib.createReverseReadStream( path.join("temp", "test", "reverse.txt"), { encoding: "utf8", highWaterMark: 10 } ); @@ -131,9 +130,9 @@ describe("lib/stream", function() { ws.end(); await finished(ws); - let lineStream = new libStream.ReverseLineSplitter({ readableObjectMode: true }); + let lineStream = new lib.ReverseLineSplitter({ readableObjectMode: true }); let index = 99999; - let rs = await libStream.createReverseReadStream(path.join("temp", "test", "reverse.txt")); + let rs = await lib.createReverseReadStream(path.join("temp", "test", "reverse.txt")); lineStream.on("data", line => { let n = Number(line.toString()); if (index !== n) { diff --git a/test/lib/users.js b/test/lib/users.js index 6dd95a1f..457a01a0 100644 --- a/test/lib/users.js +++ b/test/lib/users.js @@ -1,25 +1,25 @@ "use strict"; const assert = require("assert").strict; -const libUsers = require("@clusterio/lib/users"); +const lib = require("@clusterio/lib"); describe("lib/users", function() { describe("definePermission()", function() { it("should validate the types of its arguments", function() { assert.throws( - () => libUsers.definePermission({ name: 123, title: "Test", description: "A test" }), + () => lib.definePermission({ name: 123, title: "Test", description: "A test" }), new Error("Expected name to be a non-empty string") ); assert.throws( - () => libUsers.definePermission({ name: "test", title: 123, description: "A test" }), + () => lib.definePermission({ name: "test", title: 123, description: "A test" }), new Error("Expected title to be a non-empty string") ); assert.throws( - () => libUsers.definePermission({ name: "test", title: "Test", description: 123 }), + () => lib.definePermission({ name: "test", title: "Test", description: 123 }), new Error("Expected description to be a non-empty string") ); assert.throws( - () => libUsers.definePermission({ + () => lib.definePermission({ name: "test", title: "Test", description: "A test", grantByDefault: 1, }), new Error("Expected grantByDefault to be a boolean") @@ -27,10 +27,10 @@ describe("lib/users", function() { }); it("should define a permission", function() { - libUsers.definePermission({ name: "test", title: "Test", description: "A test" }); - assert(libUsers.permissions.has("test"), "Permission was not defined"); + lib.definePermission({ name: "test", title: "Test", description: "A test" }); + assert(lib.permissions.has("test"), "Permission was not defined"); - let test = libUsers.permissions.get("test"); + let test = lib.permissions.get("test"); assert.equal(test.name, "test"); assert.equal(test.title, "Test"); assert.equal(test.description, "A test"); @@ -39,7 +39,7 @@ describe("lib/users", function() { it("should throw on already defined permission", function() { assert.throws( - () => libUsers.definePermission({ name: "test", title: "Test", description: "A test" }), + () => lib.definePermission({ name: "test", title: "Test", description: "A test" }), new Error("Permission 'test' is already defined") ); }); @@ -47,19 +47,19 @@ describe("lib/users", function() { describe("class Role", function() { it("should round trip serialize", function() { - let orig = new libUsers.Role({ id: 11, name: "Role", description: "My Role", permissions: ["test"] }); - let copy = new libUsers.Role(orig.serialize()); + let orig = new lib.Role({ id: 11, name: "Role", description: "My Role", permissions: ["test"] }); + let copy = new lib.Role(orig.serialize()); assert.deepEqual(copy, orig); }); describe(".grantDefaultRoles()", function() { it("should only grant permissions with grantByDefault", function() { - let role = new libUsers.Role({ id: 11, name: "Role", description: "My Role" }); + let role = new lib.Role({ id: 11, name: "Role", description: "My Role" }); role.grantDefaultPermissions(); assert(role.permissions.size > 0, "No permissions were granted"); for (let permission of role.permissions) { assert( - libUsers.permissions.get(permission).grantByDefault === true, + lib.permissions.get(permission).grantByDefault === true, "Non-default permission granted" ); } @@ -69,15 +69,15 @@ describe("lib/users", function() { describe("class User", function() { let roles = new Map([ - [1, new libUsers.Role({ id: 1, name: "a", description: "a role", permissions: ["core.admin"] })], - [2, new libUsers.Role({ id: 2, name: "b", description: "b role", permissions: ["test"] })], + [1, new lib.Role({ id: 1, name: "a", description: "a role", permissions: ["core.admin"] })], + [2, new lib.Role({ id: 2, name: "b", description: "b role", permissions: ["test"] })], ]); it("should round trip serialize", function() { function test_roundtrip(serialized) { - let user = new libUsers.User(serialized, roles); + let user = new lib.User(serialized, roles); let user_serialized = user.serialize(); assert.deepEqual(user_serialized, serialized); - let user_deserialized = new libUsers.User(user_serialized, roles); + let user_deserialized = new lib.User(user_serialized, roles); assert.deepEqual(user_deserialized, user); } @@ -88,36 +88,36 @@ describe("lib/users", function() { test_roundtrip({ name: "user", instance_stats: [[1, { join_count: 1 }]]}); }); it("should ignore invalid roles", function() { - let user = new libUsers.User({ name: "test", roles: [1, 4, 55] }, roles); + let user = new lib.User({ name: "test", roles: [1, 4, 55] }, roles); assert.equal(user.roles.size, 1, "Unexpected count of roles"); }); it("should track online users", function() { - let user = new libUsers.User({ name: "admin", roles: [1] }, roles); - assert(!libUsers.User.onlineUsers.has(user)); + let user = new lib.User({ name: "admin", roles: [1] }, roles); + assert(!lib.User.onlineUsers.has(user)); assert.deepEqual(user.instances, new Set()); user.notifyJoin(12); - assert(libUsers.User.onlineUsers.has(user)); + assert(lib.User.onlineUsers.has(user)); assert.deepEqual(user.instances, new Set([12])); user.notifyJoin(8); - assert(libUsers.User.onlineUsers.has(user)); + assert(lib.User.onlineUsers.has(user)); assert.deepEqual(user.instances, new Set([12, 8])); user.notifyLeave(11); - assert(libUsers.User.onlineUsers.has(user)); + assert(lib.User.onlineUsers.has(user)); assert.deepEqual(user.instances, new Set([12, 8])); user.notifyLeave(12); - assert(libUsers.User.onlineUsers.has(user)); + assert(lib.User.onlineUsers.has(user)); assert.deepEqual(user.instances, new Set([8])); user.notifyLeave(8); - assert(!libUsers.User.onlineUsers.has(user)); + assert(!lib.User.onlineUsers.has(user)); assert.deepEqual(user.instances, new Set()); }); it("should calculate playerStats", function() { - let user = new libUsers.User({ name: "test", roles: [1], instance_stats: [ + let user = new lib.User({ name: "test", roles: [1], instance_stats: [ [1, { join_count: 1, online_time_ms: 60e3, @@ -148,9 +148,9 @@ describe("lib/users", function() { describe(".checkPermission()", function() { it("should correctly resolve permissions", function() { - let a = new libUsers.User({ name: "admin", roles: [1] }, roles); - let b = new libUsers.User({ name: "user", roles: [2] }, roles); - let c = new libUsers.User({ name: "null", roles: [] }, roles); + let a = new lib.User({ name: "admin", roles: [1] }, roles); + let b = new lib.User({ name: "user", roles: [2] }, roles); + let c = new lib.User({ name: "null", roles: [] }, roles); a.checkPermission("core.control.connect"); assert.throws(() => b.checkPermission("core.control.connect"), new Error("Permission denied")); diff --git a/test/lib/zip_ops.js b/test/lib/zip_ops.js index 622c65ae..76b28dd1 100644 --- a/test/lib/zip_ops.js +++ b/test/lib/zip_ops.js @@ -2,7 +2,7 @@ const assert = require("assert").strict; const JSZip = require("jszip"); -const { findRoot } = require("@clusterio/lib/zip_ops"); +const { findRoot } = require("@clusterio/lib"); describe("lib/factorio", function() { diff --git a/test/mock.js b/test/mock.js index 2006e360..eb73ae66 100644 --- a/test/mock.js +++ b/test/mock.js @@ -3,16 +3,11 @@ const events = require("events"); const http = require("http"); const express = require("express"); -const libData = require("@clusterio/lib/data"); -const libHelpers = require("@clusterio/lib/helpers"); -const libLink = require("@clusterio/lib/link"); -const libPlugin = require("@clusterio/lib/plugin"); -const libUsers = require("@clusterio/lib/users"); -const libPrometheus = require("@clusterio/lib/prometheus"); +const lib = require("@clusterio/lib"); const UserManager = require("@clusterio/controller/src/UserManager"); -const addr = libData.Address.fromShorthand; +const addr = lib.Address.fromShorthand; class MockLogger { child() { return this; } @@ -72,7 +67,7 @@ class MockSocket { } } -class MockConnector extends libLink.BaseConnector { +class MockConnector extends lib.BaseConnector { constructor(src, dst) { super(src, dst); @@ -107,7 +102,7 @@ class MockServer extends events.EventEmitter { result = { response: result }; } if (result.time) { - await libHelpers.wait(result.time); + await lib.wait(result.time); } if (result.response instanceof Error) { throw result.response; @@ -116,7 +111,7 @@ class MockServer extends events.EventEmitter { } } -class MockInstance extends libLink.Link { +class MockInstance extends lib.Link { constructor() { super(new MockConnector(addr({ instanceId: 7357 }), addr({ hostId: 1 }))); this.logger = new MockLogger(); @@ -143,13 +138,13 @@ class MockInstance extends libLink.Link { } } -class MockHost extends libLink.Link { +class MockHost extends lib.Link { constructor() { super(new MockConnector(addr({ hostId: 1 }), addr("controller"))); } } -class MockControl extends libLink.Link { } +class MockControl extends lib.Link { } class MockController { constructor() { @@ -172,14 +167,14 @@ class MockController { this.userManager = new UserManager(); this.userManager.roles = new Map([ - [0, new libUsers.Role({ id: 0, name: "Admin", description: "admin", permissions: ["core.admin"] })], - [1, new libUsers.Role({ id: 1, name: "Player", description: "player", permissions: [] })], + [0, new lib.Role({ id: 0, name: "Admin", description: "admin", permissions: ["core.admin"] })], + [1, new lib.Role({ id: 1, name: "Player", description: "player", permissions: [] })], ]); this.userManager.roles.get(1).grantDefaultPermissions(); this.userManager.users = new Map([ - ["test", new libUsers.User({ name: "test", roles: [0, 1] }, this.userManager.roles)], - ["player", new libUsers.User({ name: "player", roles: [1] }, this.userManager.roles)], + ["test", new lib.User({ name: "test", roles: [0, 1] }, this.userManager.roles)], + ["player", new lib.User({ name: "player", roles: [1] }, this.userManager.roles)], ]); this.instances = new Map(); this.hosts = new Map(); @@ -210,7 +205,7 @@ class MockController { } async function createControllerPlugin(ControllerPluginClass, info) { - libLink.registerPluginMessages([info]); + lib.registerPluginMessages([info]); let controller = new MockController(); let metrics = {}; let logger = new MockLogger();