Commit Graph
123 Commits
Author SHA1 Message Date
ILLISISandClaude Opus 5.5 b2a426bb30 Throw on a missing file when loadJsonObject is asked to
Controller.loadJsonObject(path, true) returned {} for a missing file, so
loadPlugins' catch never ran and a plugin whose web build was expected but
missing was not reported (the second half of #1046; #1047 fixed the path).
With throwOnMissing set, every error now throws; without it only a missing
file is ignored, so a malformed JSON file throws again as before #1047.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BGUULoiHNbAegwMK4PSjHJ
2026-10-07 01:21:11 +11:00
Cooldude2606 7b2f7064b9 Fix lint error 2026-10-05 00:46:06 +01:00
Cooldude2606 4c0c89c5ff Fix broken manifest url resolution 2026-10-05 00:30:47 +01:00
Cooldude2606 d1b1f58f00 Fix broken manifest path resolution (#1047) 2026-10-04 20:42:57 +01:00
bbassie db84455c34 Merge remote-tracking branch 'upstream/master' into refactor/plugin-hooks-v2
# Conflicts:
#	packages/lib/src/data/messages_plugin.ts
#	packages/web_ui/src/components/PluginViewPage.tsx
#	test/lib/plugin.js
2026-09-12 18:07:12 +00:00
BastiaanandClaude Fable 5.1 1a10b38743 Only report a missing plugin web build when one is expected (#1013)
Plugins with only host, instance or ctl code have no reason to ship a
webpack build, yet the plugin list showed "Missing dist/web/manifest.json"
as an error for them and the controller logged a warning on every start.

Decide whether a build is expected from the plugin declaration, using the
same rule the create tool uses to decide when to generate one: a web or
controller entrypoint, or any config fields. Plugins outside that rule get
no bundle path and no error, the web UI skips loading them, and the plugin
pages show them as having no web module instead of an error or a prompt to
reload.

Fixes #1004

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 01:59:16 +01:00
7122cbccf8 Add typed hook system for plugins
Replace invokeHook and the per plugin on* methods with AsyncHook
collections on the controller, host, instance, clusterioctl and web
control objects. Plugin entrypoints export a default function that
receives a load context and attaches handlers to the hooks it needs.
Class exports still load through fromContext with a deprecation
warning. The create templates and docs use the entrypoint function.

This is clusterio/clusterio#921 recreated on top of master after the
ESM migration and the PluginDeclaration permissions change.

Closes #730

Co-Authored-By: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 22:49:09 +00:00
Hornwitser 5dcaca4d0b Migrate to ECMAScript Modules
Migrate the usage of CommonJS specific code and imports to ESM.  Roughly
summarised this:
- Changes all require() calls to import statement or expressions.
- Changes usage of module.exports to export statements.
- Replaces require.resolve with import.meta.resolve.
- Replaces conditional imports with conditional subpath imports.
- Replaces module === require.main with import.meta.main.
- Adds the full filename with extention to all relative imports.
- Changes all usage of __dirname and __filename to their import.meta
  equivalents.
- Sets "type": "module" in package.json files.
- Removes usage of "use strict".
- Adds .ts an an alias of .js for the webpack build.

Due to differences in how require and import resolves files the plugin
entrypoints will have to include the filename and extension after this
migration in order to work.
2026-09-11 22:43:57 +02:00
Hornwitser a025d01294 Fix mainBundle being passed as array in dev mode
Values in the assetsByChunkName object are arrays not strings.  This
caused the dev mode to fail after 2f4e0c4418 added an additional step
filtering out the static/ prefix from what it expected to be a string.
2026-09-11 19:59:41 +02:00
Hornwitser 30083b96c1 Add packagePath to plugin info
Provide the absolute path to the package.json file in the resolved
plugin info to simplify the logic around loading files from it.
2026-09-11 19:51:15 +02:00
Hornwitser 7c0d7faa24 Add config to set URL for static assets
Add option in the controller config to set where static assets are
loaded from in order to support deployments where the static assets are
server via a CDN while the API is directly accessed.

This is useful because some CDNs put low limits on how large requests
bodies can be, which causes issues with uploading large mods and saves.
2026-08-31 19:17:31 +02:00
bbassieandClaude Fable 5 2f4e0c4418 Make staticRoot include the static/ prefix and use it for plugin bundles
staticRoot was set to the same value as webRoot, so the static/ prefix
ended up scattered across consumers: index.html relied on the manifest
path containing it, the export stores hardcoded `${staticRoot}static/`,
and bootstrap loaded plugin bundles from webRoot instead. Now staticRoot
is `${webRoot}static/` and the controller strips the static/ prefix from
bundle paths before handing them to the page and to /api/plugins.

Plugins that fetch assets with `${staticRoot}static/...` need to drop the
static/ part.

Fixes #980

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 09:50:08 +00:00
Loi NguyenandLoi Nguyen 08651b5917 fix: prevent restart downgrades (#951)
Co-authored-by: Loi Nguyen <1948922+lntutor@users.noreply.github.com>
2026-07-26 12:20:22 +01:00
Cooldude2606 573274875c Rename to SourceVersion 2026-07-02 00:27:05 +01:00
Cooldude2606 2e27c4f499 Maintain strict tagging of GameVersion 2026-07-02 00:08:09 +01:00
bbassieandClaude Opus 4.8 8029ad3b2d Resolve GameVersion type as a plain-string supertype
Cooldude's GameVersion brand was disjoint from the clean version types in
both directions, forcing safeVersion/safeFactorioVersion companions and
breaking widening from FullVersion at file-name call sites.

Make GameVersion a plain string alias: the raw, un-normalised version as the
game reads it. The stricter template-literal types (FullVersion,
MajorMinorVersion, PartialVersion) now widen into it for free, while a
GameVersion still can't be used where a normalised version is required
without going through normaliseGameVersion/integerGameVersion. Runtime
validation stays in GameVersionSchema.

- Drop safeVersion/safeFactorioVersion; ModInfo.version stays raw (verbatim so
  it matches the mod's file name), integerVersion normalises via the new
  integerGameVersion. factorioVersion reverts to a normalised MajorMinorVersion
  since it is never part of a file name.
- ModRecord.version becomes a GameVersion so mod packs round-trip the exact
  file-name version.
- ModVersionEquality.testVersion / ModVersionRange.testVersion accept a raw
  GameVersion and normalise it; the equality bound stays strictly validated.
- Migration only pads clean partial versions; raw versions are kept verbatim.
- Cover the leading-zeros case: version kept verbatim in the file name while
  comparing equal to its normalised form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:54:06 +00:00
bbassieandClaude Opus 4.8 9da48d5387 Add release channels as instance version targets
An instance's factorio.version can now target a release channel such as
"stable" or "experimental" (any key from factorio.com/api/latest-releases)
in addition to "latest" and specific X.Y / X.Y.Z versions.

The controller proxies the latest-releases API through a ValueCache and
persists the last successful response to latest-releases.json, serving that
copy when the API is unreachable. On instance start the host resolves a
channel to the concrete version it points to and feeds it into the existing
checkForUpdates/findVersion path, so a channel auto-installs and runs like a
pinned version. The version selector in the web UI lists the available
channels alongside "latest".

Also clarifies the host log/error when a newer version cannot be downloaded
automatically because the host uses a direct (single-version) Factorio
install rather than a versioned directory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 14:19:34 +00:00
Cooldude2606 21b050b220 Call subscriptionUpdate for all update cases 2026-05-28 00:38:15 +01:00
Hornwitser 2e48b728dd Remove fs-extra and klaw (#882)
These packages are obsoleted by the promises API to the built-in Node fs
module.  The fs-extra package is also causing problems with broken APIs
that don't behave the same as Node's fs module, and throwing errors
without code properties on them.
2026-04-09 22:53:13 +02:00
Cooldude2606 4868ed2d63 Merge branch 'master' into feature/config-validation 2026-03-16 23:22:54 +00:00
Hornwitser 2f70db4b7e Ignore errors fetching Factorio versions
If an error occurs trying to fetch the list of Factorio versions log a
warning and then return an empty list instead of preventing the system
from operating.
2026-03-09 15:16:46 +01:00
Hornwitser 276c36b6e9 Throw error if lib is imported twice (#863)
The lib library was written with the assumption that there's only one
copy of it in the whole application and everything imports that one
copy.  Unfortunately there are quite a few circumstances were package
managers end up installing multiple copies of lib and then different
parts use different versions of the library.

This causes Clusterio to break with strange and hard to track down
errors.  Most notably permissions and link messages for a plugin may get
registered to one copy of lib while the controller uses a different copy
and thus does not see or register that what the plugin added exists.

Detect this condition when importing @clusterio/lib and throw an error
when it has been imported twice in order to prevent the broken
installation from causing future hard to debug issues.
2026-03-06 18:50:18 +01:00
Cooldude2606 014b18caf8 Fix type of controller.auth_secret 2026-03-04 21:02:39 +00:00
Cooldude2606andHornwitser 2235294c59 Refactor user and instance manager (#837)
* Refactor UserManager to use Datastore

* Rename lib.User to UserDetails also adds to/fromUserDetails

* Fix existing tests

* Add user class tests

* Add tests for finaliseUsers

* Move HostDetails to own file with tests

* Move InstanceDetails to its own file with tests

* Rename HostInfo and add tests

* Rename InstanceInfo and add tests

- Also changes the names of the host properties related to instances
- Also removes the need to specify the location of InstanceInfo

* Make json round trip test validate schema

* Add InstanceManager

* Fix lint errors

* Extra tests

* Add final test coverage

* Add one last test to InstanceManager

* Response to comments

* Use generator rather than return anonumous generator

Co-authored-by: Hornwitser <github@hornwitser.no>

* Fix lint issue with generator

---------

Co-authored-by: Hornwitser <github@hornwitser.no>
2026-03-01 23:04:37 +00:00
Cooldude2606 1228baa9a3 Move ensure default roles onto Role class 2026-02-07 01:27:59 +00:00
Cooldude2606 ccd5232e70 Fix system info migration logic 2026-02-01 22:35:32 +00:00
Cooldude2606 9729743a29 Add startedAtMs to all processes 2026-02-01 21:30:00 +00:00
Cooldude2606 6f68cf74a7 Add network events and switch to tree select 2026-01-24 16:27:28 +00:00
Cooldude2606 43def44136 Fix package path for restart required 2025-11-07 21:47:48 +00:00
Cooldude2606 d52931a326 Better handling of mod dependencies (#801)
* Add ModDependency and version types

* Add warnings for mod dependencies

* Add warning for wrong factorio version

* Add fix issues button

* Add automatic dependency resolution and download

* Add abilty to check for updates

* Add extra test coverage

* One extra test

* Fix copy paste error
2025-11-07 19:22:17 +00:00
Cooldude2606 73cc019d2f Sets restart required when a plugin is updated (#794)
* Template type for load plugin config

* Add plugin update checking

* Add restart icon to instance list

* Add tests

* Log package name when failing to read package json
2025-11-01 16:11:11 +00:00
Cooldude2606 681e78967f Webpack Build Improvements (#791)
* Bump @swc/core to 1.13.3

* Switch to using --mode production rather than --env

Closes #792

* Add cache
2025-08-17 15:54:37 +01:00
Danielv123 7e2f10e842 Fix linting issues with new rules 2025-08-01 22:26:25 +00:00
Cooldude2606 df1edec623 Add role subscriptions and data model 2025-06-14 00:28:03 +01:00
Cooldude2606 a5bf8d92d9 Separate roles to their own file 2025-06-13 22:24:56 +01:00
Cooldude2606 331fc7d947 Add types to event emitters and clean up connections (#772)
* Event types for controller

* Clean up ctl event emitters

* Event types for server

* Event types for lib

* Remove TypedEventEmitter

* Event types for webui

* Fix compile issues

* Small cleanup of connectors
2025-06-13 22:20:50 +01:00
Cooldude2606 63e30dd0ee Add missing migrations for system info and tests (#766)
* Add missing migration for SystemInfo

* Add missing migration tests
2025-05-21 17:07:24 +01:00
Cooldude2606 726a3538c2 Move save and load into config class 2025-05-12 21:32:44 +01:00
Cooldude2606 17db53403a Move filepath into config class 2025-05-12 21:30:48 +01:00
Daniel 0adb45bba4 Merge pull request #758 from Cooldude2606/feature/pending-restart
Add indicators for host version mismatch and required restart
2025-05-11 14:14:39 +02:00
Cooldude2606 be071be8f2 Add recovery startup mode (#757)
* Add recovery startup mode

* Change error code to RecoveryMode
2025-05-10 21:33:45 +01:00
Cooldude2606 c120443657 Add checks for updated version on disk 2025-04-27 23:57:58 +01:00
Cooldude2606 cf9f087cba Add icons for mis-matched version and restart required 2025-04-27 22:35:00 +01:00
Danielv123 25099c03ba Use config instead of constants, other review commetns 2025-04-13 18:00:52 +02:00
Danielv123 d50230becc Cache mods on controller 2025-04-08 22:42:03 +02:00
Cooldude2606 8996671bea Add default mod packs (#735) 2025-02-14 14:47:26 +00:00
Cooldude2606andDanielv123 4248e57dcb Add config migrations (#693)
Co-authored-by: Danielv123 <danielv@danielv.no>
2024-11-26 23:14:56 +00:00
Hornwitser 34da073800 Fix setting instance config fields not being saved
If only the config of an instance is updated the dirty flag of the
instance is not set, which results in changes being discarded when the
controller shuts down afterwards.

Fix by always triggering the update logic when an instance field is
changed.
2024-10-28 19:30:03 +01:00
Hornwitser 44e5847a1d Implement shared Factorio credentials
Add config entries to controller and host for the Factorio username and
token to use when talking to the Factorio APIs.  If set an username and
token is not set in factorio.settings then these settings are used,
making it easy to configure one set of credentials for a cluster/host.

For running more public provide your own hardware clusters, there's an
option to disable controller sharing the credential with the hosts so
that each host have to set their own credentials.
2024-09-16 23:23:21 +02:00
Hornwitser 7547a48fd6 Fix controller not accepting old hosts.json format
Migrate the content of the hosts.json file before attempting to loading
it into the new datastore format.
2024-09-04 13:40:15 +02:00