Commit Graph
208 Commits
Author SHA1 Message Date
Hornwitser 001db4befe Refactor config to JSON data class pattern
Refactor the Config and ConfigGroup classes to match the JSON data class
pattern with toJSON, toRemote and fromJSON methods replacing the load,
init, and serialize methods.  Since fromJSON requires extra information
the messages structures passes around the plain JSON representation of
the configs instead of serialising instances of the config classes
automatically.
2024-01-06 19:53:32 +01:00
Hornwitser 27af142a87 Remove silly support for async initial_value
This complicates the handling of configs for no good reason.
2024-01-06 19:49:35 +01:00
Hornwitser 8c17adf15b Refactor EventSubscriber to track its resource
Process updates of the resource EventSubscriber are subscribed to and
have it keep a mapping of id to value syncronised with event provider as
long as there are subscription callbacks registered with it.  The
mapping is kept around after the last callback is unsubscribed so that
it can be efficiently resynced with the resource based on the updatedAt
timestaps of individual elements.

This allows the EventSubscriber to provide the right building blocks to
provide its values to React components via the the useSyncExternalStore
hook.  This in turn greatly simplifies the web_ui models for the
subscribed resources.
2023-12-12 23:40:29 +01:00
Hornwitser 867bb0c646 Add ModInfo.id getter
Provide a simple unique identifier for mods consisting of the name
followed by an underscore and then the version.
2023-12-12 00:08:25 +01:00
Hornwitser ddba58ca99 Require control in EventSubscriber.constructor
Reduce complexity in the implementation of EventSubscriber by requiring
a control link be passed to its constructor.  This is possible after the
change in 8c724e3 made the web interface control instance available to
plugins at init time.
2023-12-11 23:14:37 +01:00
Hornwitser a2914bda33 Cache save details on the controller
Keep a copy of the instance saves details on the controller so that
saves can be queried even when the host is disconnected and the
controller can properly track and provide updates on the saves to
its clients.
2023-12-11 20:21:43 +01:00
Hornwitser 20330bc2c3 Push multiple updates in each update event
Refactor HostUpdatesEvent, InstanceDetailsUpdatesEvent, ModUpdatesEvent,
ModPackUpdatesEvent and UserUpdatesEvent to have multiple updates of the
entities they support in each event. This is intended to make the events
capable of syncing the entire list that they represent.
2023-12-08 22:01:46 +01:00
Hornwitser 58914042cc Remove channels to simplify subscription
Make subscriptions either on or off to greatly simplify the logic of
subscribing to events.
2023-12-03 20:32:48 +01:00
Hornwitser 853866492b Refactor controller mod storage into ModStore
Structure the storage of mods on the controller into into a reusable
component in preparation for the host using the same kind of mod storage
to retrieve and cache the mods it needs to run mod packs on instances.
2023-12-03 19:59:14 +01:00
Hornwitser ec734c92bc Fix bad typings detected by linting
Fix badly typed expressions that were detected by turning on
`@typescript-eslint/no-unnecessary-condition` in eslint.
2023-12-02 01:47:02 +01:00
Hornwitser 90a88f7e01 Fix /api/plugins leaking filesystem paths
Replace PluginWebApi's requirePath member with npmPackage which is only
populated if the package is not marked as private and the requirePath
matches the name. This prevents the public /api/plugins endpoint from
leaking filesystem paths into the controller.
2023-12-02 01:43:28 +01:00
Hornwitser 11ffee646e Add the other packages to typedoc output
Add controller, host, ctl, and web_ui packages to the typedoc output.
2023-12-02 01:43:28 +01:00
Hornwitser e453a80155 Refactor User and Role into data classes (#531)
Use the JSON data class pattern for User, Role, and PlayerStats and move
them into lib/src/data.  This means that User is purely data now and
can't reference role objects directly.  To make it possible easily check
permissions attached to roles and store data only visible on the
controller on user objects a ControllerUser type is introduced which is
linked with the UserManager and can therefore reference role objects
directly.

Resolves #525.
2023-12-02 01:41:43 +01:00
Hornwitser 0a4368d1c0 Rename index.css to style.css
Make the tab completion on web/in<Tab> give the TypeScript code instead
of annoyingly stopping at the extension.
2023-11-28 15:52:54 +01:00
Hornwitser 6a404d9fb3 Refactor and port plugin web code to TypeScript
Clean up the configuration for compiling TypeScript for the Web
interface to us its own tsconfig.web.json config files and reference the
TypeScript source files directly in the configuration and imports
instead of files compiled to dist.

To properly support recompliation with TypeScript's projects feature
each package's tsconfig.web.json file is set to output the build to
dist/web_build which is then ignored in .npmignore.  Webpack is still
used to create the proper build in dist/web, so this is mainly to make
TypeScipt's compiler happy but it also allows the root tsconfig.json
file to include the web interface code, meaning running the build script
now also checks the typing of the web interface.

Final part of #491.
2023-11-28 15:52:54 +01:00
Hornwitser 8c724e3bc5 Provide control at init time for web plugins
The control interface is required for adding handlers for message types
a plugin defines, but the plugins were loaded before the Control
instance was created. This meant there was no sensible way for web
plugins to register handlers for their own message types.

Move the creating of the Control instance to before plugins are loaded
and set this.control for web plugins before init is called.
2023-11-28 15:35:40 +01:00
Hornwitser 70d2b319b3 Fix types related to plugins and the web interface 2023-11-28 15:35:40 +01:00
Hornwitser ceb7e48c99 Fix global declaration of staticRoot and webRoot
These variables were intended to be globals declare in the global
namespace. That this ends up on the window object is an implementation
detail of JavaScript. Remove the window. prefix put in front of
staticRoot and webRoot and include the global declaration in the
TypeScript module.
2023-11-28 15:35:40 +01:00
Hornwitser 9df6717364 Move PluginWebApi to lib
Resolve circular dependency of controller depending on web_ui and web_ui
depending on controller by moving the type from controller that was used
in web_ui to lib.
2023-11-28 14:48:06 +01:00
Hornwitser 808eda0513 Move base plugins to their respective packages
Move BaseControllerPlugin to controller/src/BaseControllerPlugin.ts
Move BaseInstancePlugin to host/src/BaseInstancePlugin.ts
Move BaseControlPlugin to ctl/src/BaseCtlPlugin.ts
Move BaseWebPlugin to web_ui/src/BaseWebPlugin.ts

This solves the circular package dependency problem of the base plugins
needing types that are available only in the dependencies to lib.
2023-11-25 18:41:43 +01:00
Hornwitser 87e52b804e Convert JSON file indents to tabs
Be consistent with the usage of tabs as indents in all JSON files in the
project.  This makes it easier to configure editors to emit the right
indents when manually editing these files.
2023-11-25 18:19:15 +01:00
Hornwitser 52d3bba6f6 Move instance buttons out of InstanceViewPage
Break out the button row at the top of the instance page into its own
component to reduce the complexity of InstanceViewPage.
2023-11-20 13:49:23 +01:00
Hornwitser 80e1904175 Fix bad typings left over from the migration 2023-11-19 04:50:07 +01:00
Hornwitser 7314dc99c8 Fix code style errors
Remove extra whitespace, use more consistent spacing, add missing
semicolons, using dangling commas, break up long lines, consistent
multiline operator placement, add missing JSDoc strings and so on.
2023-11-19 04:48:38 +01:00
Hornwitser 60f09b11f9 Merge pull request #510 from Cooldude2606/refactor/subscriptions
Refactor/subscriptions - Create a generalized event subscription class
2023-10-13 14:45:44 +02:00
Cooldude2606 b15b1a6007 Fixed bugs found during pre-review 2023-10-06 18:30:15 +01:00
Luciole e2dea35e02 allow to revoke host tokens from web ui (#511)
* allow to revoke / restore host access from web ui

* refector to what is expected

* remove core.admin check on HostViewPage.tsx

* update core.host.revoke_token description
2023-09-29 19:50:14 +02:00
Cooldude2606 da25196830 Refactor to use subsribers 2023-09-05 01:46:45 +01:00
Luciole 838170a9ff Port packages/web_ui to TypeScript (#508)
* .jsx to .tsx

* controller: tsc --build before webpack-cli

* Type Annotation

* disabled move into the <Input/> and <Checkbox/>

* cleanup debug left over

* documentation

* default ModPack

* modPackUpdateHandlers no undefined

* PluginInfo changes proposition

* PluginInfo changes proposition miss

* ModRecord & ModInfo feedback loop at const mods = [ ?

* ["connect", "drop", "resume", "close"] as const

* .tsx to .ts when possible
2023-09-02 14:51:35 +02:00
Hornwitser 6d1ff4c178 Fix web interface broken by TypeScript porting 2023-08-25 15:25:43 +02:00
Hornwitser 2a52a82fb7 Port message types to TypeScript 2023-08-11 00:24:00 +02:00
Hornwitser a5c7eb3a27 Move user token signing to UserManager
Only the controller has access to the secret needed to sign user tokens
so it makes sense for the user signing code to live in the controller.
This saves about 20ms on the time ctl takes to start up due to lib no
longer needing to import jsonwebtoken.
2023-07-28 16:03:29 +02:00
Hornwitser bfe119eaa3 Flatten lib namespace
Move all functions and classes currently available through lib/name and
libName to be under a single flat namespace in lib.  This make
reorganising the lib namespace much simpler as the location of symbols
can move without breaking the consumers of lib.

The multi-entrypoint design was already problematic for the web plugin
system which couldn't effectively use it due to how webpack's shared
module system is awkward to set up with multiple entrypoints per package.
2023-07-28 16:03:29 +02:00
Hornwitser fd709fd98c Update web dependencies
- react: Update to new root rendering method
- react-router: Replace useHistory with useNavigate
- react-router: Replace <Switch> with <Routes>
- reimplement sticky notice from scratch in ModPackViewPage
- remove isomorphic-ws as it's latest version doesn't work and only
  saves one line of code.
- remove import of antd.dark.css
- fix misc css breakages.
2023-07-27 17:50:14 +02:00
Hornwitser 8d98eaf3a5 Reimplement PageHeader
Implement our own version ofwhe PageHeader component, due to it being
removed from ant design v5.
2023-07-27 17:37:27 +02:00
Hornwitser 789c02b5c7 Fix missing return in applyModPackChanges 2023-07-27 13:43:32 +02:00
Hornwitser a1c9bc5f9b Migrate deprecated ant design APIs
Rename visible to open and use menu instead of overlay in Dropdown as
both of these have been removed in the next major version of Antd.
2023-07-27 13:42:35 +02:00
Hornwitser 1a9cbd26b3 Update non-web dependencies
Update non-web related dependencies to their latest version were
possible. It appears yargs has changed its parsing of command line
options to no longer remove a layer of quotes.
2023-07-27 00:35:26 +02:00
Hornwitser 295cc7543a Reverse argument order for sendTo
It makes more sense to put the address first then have the large
structure to send as the second argument to sendTo.  The opposite order
was originally chosen to be similar to that of sendto in BSD sockets.
2023-07-27 00:24:24 +02:00
Hornwitser 156d517976 Prefer putting nested structures on new lines
Format arguments to have nested structures start on a new line instead
of inline to make it easier to see where the structures starts and what
structure it is.
2023-07-26 14:27:49 +02:00
Hornwitser 7a9aec74b5 Optimize ModPackViewPage performance
Avoid re-rendering everything by using useCallback and memo to skip
rendering of form elements that haven't changed.
2023-06-11 17:30:29 +02:00
Hornwitser 04b46540fb Fix minimized web_ui build stripping class names
The data class pattern used for request and event payloads require the
class names to be preserved as they are used for identifying the type of
the requests and events.
2023-06-11 17:30:11 +02:00
Hornwitser 7f8a700716 Refactor message registration and validation
Split up the action of registring an event or request data class to be
decoded by the Link class and the action of registring a handler for
those requests and events.  This moves the validation work from Link
instantiation time to startup initialisation which makes logic errors
fail on startup instead of failing instantiation of the link when a
connection attempt is made.

Additionally implement a partial validation logic for messages received
using the newly refactored message registration.  This unfortunately
ended up merged with the registration refactor.
2023-06-03 16:47:47 +02:00
Hornwitser bcd94709d2 Refactor link system to JSON serialisable class pattern
Reverse the direction of the API for sending messages from

    messageDefinition.send(link, { content });

to

    link.send(new MessageClass(content));

and convert all message definitions to use the JSON serialisable class
pattern and explicit registration of message handlers, along with a
end-to-end based routing of messages instead of link to link.

The experience I gained from the existing way messages were defined and
sent over links was that it was difficult to understand for people
unfamiliar with the system.  The automatic registration of message
handlers ment that code was being called as if by magic from nowhere
with no easy way to discover it.  The manual forwarding and rules for
what can be sent where and how obscured its working.

The use of pure JSON as both input and output from message handlers made
it tedious to work with.  Data had to be manually converted between the
program representation and the over the wire format, which made handler
code unplesant to write.  Particularly because the over the wire format
used snake_case while the program code uses camelCase for variables.
The idea behind the decision to do it this way was to make it more clear
which data came from the wire and which from the program, and while this
worked it didn't make message handlers any nicer to write.

The direction of the API and magic registration of message handlers also
meant that a future migration to TypeScript would be troublesome.  While
it may be possible to implement, the degree of TypeScript magic required
would go starkly against the principle of keep it simple stupid.

By refactoring to using the JSON serialisable class pattern most of
these issues go away.  There is no longer a need to distinguish the on
wire format of messages with the program representation because the only
place that deals with the wire format of messages are the toJSON and
fromJSON methods on the classes themselves.  Message handlers will work
with proper instances of classes instead of raw data, something that
makes them easier to write, and trivial to type with TypeScript.

End-to-end routing also simplifies sending messages that need to do
mulitple hops to reach the destination.  And removes the need for having
all messages be specified in plugin's info module, as they can be routed
without having to be parsed completely.

The explicit registration of message handlers is something that I
thought would be tedious boilerplate code that could be automated away.
But experience now shows it to be the opposite.  Allthough dull
repetition, the purpose it serves is to link together the code in a way
that humans can easily find.  With explicit registration searching the
name of the message handler in the editor will show the registration that
ties it together with the type of message it handles and the kind of
registration.  With implicit registration searching the name of the
message handler turns up only the handler with no clue as to what calls
it.
2023-04-23 13:19:46 +02:00
Hornwitser 9a967a5779 Refactor JSON serialiable class pattern
Change the JSON seriasiable data classes to use an explicit static
fromJSON method and an optional toJSON method for turning them to and
from JSON.

This improves over the previous pattern of passing the JSON to the
constructor as it frees up the constructor to be able to take whichever
argument types suits the code instead of being beholden to the JSON
serialised form.
2023-02-25 00:02:12 +01:00
Hornwitser 6fc3abafd5 Rename Slave to Host
The role of a slave as a host for Factorio servers is not well reflected
in its name and has caused confusion among users.  Rename slave to host
to better reflect its role as a host of Factorio servers.
2023-02-22 15:30:51 +01:00
Hornwitser 70ad295a89 Rename Master to Controller
The role of the master server as the party controlling every part of the
cluster is not well reflected in its name and has caused confusion among
users on several occasions.  Rename master to controller to better
reflects its role.
2023-02-22 15:30:51 +01:00
Hornwitser 8662243ed1 Show which config entries requires a restart
Add a label in the web UI to config entries that require a restart to
take effect as this is not obvious to end users.
2023-02-21 22:39:23 +01:00
Hornwitser 2960db2cca Add revoke user token action
Implement revoking of user tokens to allow lost credentials to be
invalidated.
2023-02-21 22:39:23 +01:00
Hornwitser 27633d51b6 Fix log filtering in Web UI
Remove broken alternative logFilter implementation in
web_ui/src/websocket in favour of having one proper
function in lib/logging
2023-02-16 01:22:30 +01:00