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();