diff --git a/.npmignore b/.npmignore index ad8bdb41..e8289707 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,3 @@ -webpack.config.js +vite.config.js dist/web/build dist/browser diff --git a/exp_auto_restart/controller.ts b/exp_auto_restart/controller.ts index 5695c293..7d060bd4 100644 --- a/exp_auto_restart/controller.ts +++ b/exp_auto_restart/controller.ts @@ -197,7 +197,7 @@ export class AutoRestart { } catch (err: any) { this.pending.delete(host.id); // The host refusing is final for this process, anything else is retried - if (!(err instanceof lib.RequestError)) { + if (!(err instanceof lib.ClientError)) { this.requested.delete(host.id); } this.logger.error(`Failed to restart host ${host.name}: ${err.message}`); diff --git a/exp_auto_restart/index.ts b/exp_auto_restart/index.ts index 8ad37769..27420411 100644 --- a/exp_auto_restart/index.ts +++ b/exp_auto_restart/index.ts @@ -13,7 +13,6 @@ export const plugin: lib.PluginDeclaration = { name: "exp_auto_restart", title: "ExpGaming - Auto Restart", description: "Clusterio plugin restarting hosts and the controller once no players are online", - webEntrypoint: "./web", controllerEntrypoint: "./dist/node/controller.js", controllerConfigFields: { diff --git a/exp_auto_restart/package.json b/exp_auto_restart/package.json index e1e47930..aeae5453 100644 --- a/exp_auto_restart/package.json +++ b/exp_auto_restart/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -27,12 +27,11 @@ "devDependencies": { "@clusterio/controller": "workspace:^", "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", "tap": "^21.1.0", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "publishConfig": { "access": "public" diff --git a/exp_auto_restart/test/controller.test.js b/exp_auto_restart/test/controller.test.js index 05ec45e9..c2eb13da 100644 --- a/exp_auto_restart/test/controller.test.js +++ b/exp_auto_restart/test/controller.test.js @@ -219,7 +219,7 @@ t.test("class AutoRestart", t2 => { addInstance(controller, 10, 1); addSystem(controller, 1); - controller.sendTo = async () => { throw new lib.RequestError("Cannot restart"); }; + controller.sendTo = async () => { throw new lib.ConflictError("Cannot restart"); }; await plugin.check(now); await plugin.check(now + 10_000); t3.strictSame(logs.filter(([level]) => level === "error").length, 1, "a refusal is logged once"); diff --git a/exp_auto_restart/tsconfig.browser.json b/exp_auto_restart/tsconfig.browser.json index 1ab2704e..1d2c5bb9 100644 --- a/exp_auto_restart/tsconfig.browser.json +++ b/exp_auto_restart/tsconfig.browser.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.browser.json", - "include": [ "web/**/*.tsx", "web/**/*.ts", "package.json" ], + "include": [ "index.ts", "package.json" ], } diff --git a/exp_auto_restart/vite.config.js b/exp_auto_restart/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_auto_restart/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_auto_restart/web/index.tsx b/exp_auto_restart/web/index.tsx deleted file mode 100644 index a5e4ff33..00000000 --- a/exp_auto_restart/web/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export default function() {}; \ No newline at end of file diff --git a/exp_auto_restart/webpack.config.cjs b/exp_auto_restart/webpack.config.cjs deleted file mode 100644 index f4b83f6c..00000000 --- a/exp_auto_restart/webpack.config.cjs +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_auto_restart", - library: { type: "window", name: "plugin_exp_auto_restart" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - }, - }), - ], -}); diff --git a/exp_commands/index.ts b/exp_commands/index.ts index fb5bb201..b29c88eb 100644 --- a/exp_commands/index.ts +++ b/exp_commands/index.ts @@ -5,5 +5,4 @@ export const plugin: lib.PluginDeclaration = { title: "ExpGaming - Commands", description: "Clusterio plugin providing a Lua command processing library.", instanceEntrypoint: "./dist/node/instance.js", - webEntrypoint: "./web", }; diff --git a/exp_commands/package.json b/exp_commands/package.json index 993b109b..c72624b3 100644 --- a/exp_commands/package.json +++ b/exp_commands/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production" + "prepare": "tsc --build && vite build" }, "engines": { "node": ">=22" @@ -25,11 +25,10 @@ "devDependencies": { "@clusterio/host": "workspace:^", "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@expcluster/lib_util": "workspace:^", diff --git a/exp_commands/tsconfig.browser.json b/exp_commands/tsconfig.browser.json index 1ab2704e..1d2c5bb9 100644 --- a/exp_commands/tsconfig.browser.json +++ b/exp_commands/tsconfig.browser.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.browser.json", - "include": [ "web/**/*.tsx", "web/**/*.ts", "package.json" ], + "include": [ "index.ts", "package.json" ], } diff --git a/exp_commands/vite.config.js b/exp_commands/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_commands/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_commands/web/index.tsx b/exp_commands/web/index.tsx deleted file mode 100644 index a5e4ff33..00000000 --- a/exp_commands/web/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export default function() {}; \ No newline at end of file diff --git a/exp_commands/webpack.config.cjs b/exp_commands/webpack.config.cjs deleted file mode 100644 index 88d7cdf9..00000000 --- a/exp_commands/webpack.config.cjs +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_commands", - library: { type: "window", name: "plugin_exp_commands" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - }, - }), - ], -}); diff --git a/exp_discord_auth/controller.ts b/exp_discord_auth/controller.ts index 0d575cb5..b66ee2be 100644 --- a/exp_discord_auth/controller.ts +++ b/exp_discord_auth/controller.ts @@ -95,12 +95,10 @@ export class ControllerPlugin { const controller = context.controller; const databaseDirectory = controller.config.get("controller.database_directory"); - const accounts = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_discord_auth", "accounts.json"), - messages.DiscordAccountRecord.fromJSON.bind(messages.DiscordAccountRecord), - ).bootstrap() - ); + const accounts = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_discord_auth", "accounts.json"), + messages.DiscordAccountRecord.fromJSON.bind(messages.DiscordAccountRecord), + )); return new ControllerPlugin(controller, context.logger, context.plugin.name, accounts); } @@ -387,7 +385,7 @@ export class ControllerPlugin { const entry = this.codes.get(code); const session = entry ? this.sessions.get(entry.sessionId) : undefined; if (!entry || !session || entry.expiresMs < Date.now()) { - throw new lib.RequestError( + throw new lib.ValidationError( `This code is invalid or has expired, get a new one from ${this.controller.getControllerUrl()}` ); } @@ -405,7 +403,7 @@ export class ControllerPlugin { const alreadyLinked = existing?.factorioNames.some(linked => linked.toLowerCase() === name); const maxAccounts = this.controller.config.get("exp_discord_auth.max_accounts"); if (!alreadyLinked && (existing?.factorioNames.length ?? 0) >= maxAccounts) { - throw new lib.RequestError( + throw new lib.ConflictError( `${discordUser.name} already has ${maxAccounts} Factorio accounts linked, unlink one first` ); } diff --git a/exp_discord_auth/package.json b/exp_discord_auth/package.json index f37e07b0..9f01e393 100644 --- a/exp_discord_auth/package.json +++ b/exp_discord_auth/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -40,11 +40,9 @@ "react": "catalog:", "react-dom": "catalog:", "react-router-dom": "catalog:", - "typescript": "catalog:", - "webpack": "catalog:", "tap": "^21.1.0", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "typescript": "catalog:", + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:", diff --git a/exp_discord_auth/vite.config.js b/exp_discord_auth/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_discord_auth/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_discord_auth/webpack.config.cjs b/exp_discord_auth/webpack.config.cjs deleted file mode 100644 index 0b445740..00000000 --- a/exp_discord_auth/webpack.config.cjs +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_discord_auth", - library: { type: "window", name: "plugin_exp_discord_auth" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - "antd": { import: false }, - "react": { import: false }, - "react-dom": { import: false }, - "react-router": { import: false }, - "react-router-dom": { import: false }, - }, - }), - ], -}); diff --git a/exp_groups/controller.ts b/exp_groups/controller.ts index 8e143dbd..8d31f9a4 100644 --- a/exp_groups/controller.ts +++ b/exp_groups/controller.ts @@ -26,26 +26,20 @@ export class ControllerPlugin { const controller = context.controller; const databaseDirectory = controller.config.get("controller.database_directory"); - const groups = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_groups", "groups.json"), - messages.GroupRecord.fromJSON.bind(messages.GroupRecord), - ).bootstrap() - ); + const groups = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_groups", "groups.json"), + messages.GroupRecord.fromJSON.bind(messages.GroupRecord), + )); - const roleMappings = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_groups", "role_mappings.json"), - messages.RoleMappingRecord.fromJSON.bind(messages.RoleMappingRecord), - ).bootstrap() - ); + const roleMappings = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_groups", "role_mappings.json"), + messages.RoleMappingRecord.fromJSON.bind(messages.RoleMappingRecord), + )); - const manualAssignments = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_groups", "assignments.json"), - messages.AssignmentRecord.fromJSON.bind(messages.AssignmentRecord), - ).bootstrap() - ); + const manualAssignments = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_groups", "assignments.json"), + messages.AssignmentRecord.fromJSON.bind(messages.AssignmentRecord), + )); const plugin = new ControllerPlugin( controller, context.logger, context.plugin.name, groups, roleMappings, manualAssignments, @@ -239,7 +233,7 @@ export class ControllerPlugin { async handleGroupCreateRequest(request: messages.GroupCreateRequest) { if ([...this.groups.values()].some(g => g.name === request.name)) { - throw new lib.RequestError(`Group with name '${request.name}' already exists`); + throw new lib.ConflictError(`Group with name '${request.name}' already exists`); } let id = Math.random() * 2**31 | 0; @@ -255,7 +249,7 @@ export class ControllerPlugin { async handleGroupUpdateRequest(request: messages.GroupUpdateRequest) { const group = request.group; if (group.id === undefined || !this.groups.has(group.id)) { - throw new lib.RequestError(`Group with ID ${group.id} does not exist`); + throw new lib.NotFoundError(`Group with ID ${group.id} does not exist`); } this.groups.set(group); @@ -266,7 +260,7 @@ export class ControllerPlugin { const group = this.groups.getMutable(groupId); if (!group) { - throw new lib.RequestError(`Group with ID ${groupId} does not exist`); + throw new lib.NotFoundError(`Group with ID ${groupId} does not exist`); } this.groups.delete(group); @@ -275,7 +269,7 @@ export class ControllerPlugin { async handleGroupGetRequest(request: messages.GroupGetRequest) { const group = this.groups.get(request.groupId); if (!group) { - throw new lib.RequestError(`Group with ID ${request.groupId} does not exist`); + throw new lib.NotFoundError(`Group with ID ${request.groupId} does not exist`); } return group; @@ -292,7 +286,7 @@ export class ControllerPlugin { async handleAssignmentCreateRequest(request: messages.AssignmentCreateRequest) { const { name, groupId } = request; if (this.manualAssignments.has(name)) { - throw new lib.RequestError(`Assignment for '${name}' already exists`); + throw new lib.ConflictError(`Assignment for '${name}' already exists`); } const assignment = new messages.AssignmentRecord(name, groupId); @@ -303,7 +297,7 @@ export class ControllerPlugin { async handleAssignmentUpdateRequest(request: messages.AssignmentUpdateRequest) { const assignment = request.assignment; if (!this.manualAssignments.has(assignment.name)) { - throw new lib.RequestError(`Assignment for '${assignment.name}' does not exist`); + throw new lib.NotFoundError(`Assignment for '${assignment.name}' does not exist`); } this.manualAssignments.set(assignment); @@ -314,7 +308,7 @@ export class ControllerPlugin { const assignment = this.manualAssignments.getMutable(name); if (!assignment) { - throw new lib.RequestError(`Assignment for '${name}' does not exist`); + throw new lib.NotFoundError(`Assignment for '${name}' does not exist`); } this.manualAssignments.delete(assignment); @@ -333,7 +327,7 @@ export class ControllerPlugin { const assignment = this.manualAssignments.get(request.name); if (!assignment) { - throw new lib.RequestError(`Assignment for '${request.name}' does not exist`); + throw new lib.NotFoundError(`Assignment for '${request.name}' does not exist`); } return assignment; @@ -370,7 +364,7 @@ export class ControllerPlugin { async handleRoleMappingUpdateRequest(request: messages.RoleMappingUpdateRequest) { const roleMapping = request.roleMapping; if (roleMapping.id === undefined || !this.roleMappings.has(roleMapping.id)) { - throw new lib.RequestError(`Role mapping with ID ${roleMapping.id} does not exist`); + throw new lib.NotFoundError(`Role mapping with ID ${roleMapping.id} does not exist`); } const existing = new Set( @@ -392,7 +386,7 @@ export class ControllerPlugin { const mapping = this.roleMappings.getMutable(id); if (!mapping) { - throw new lib.RequestError(`Role mapping with ID ${id} does not exist`); + throw new lib.NotFoundError(`Role mapping with ID ${id} does not exist`); } this.roleMappings.delete(mapping); @@ -401,7 +395,7 @@ export class ControllerPlugin { async handleRoleMappingGetRequest(request: messages.RoleMappingGetRequest) { const mapping = this.roleMappings.get(request.id); if (!mapping) { - throw new lib.RequestError(`Role mapping with ID ${request.id} does not exist`); + throw new lib.NotFoundError(`Role mapping with ID ${request.id} does not exist`); } return mapping; diff --git a/exp_groups/package.json b/exp_groups/package.json index 4346ec28..e50b3eb9 100644 --- a/exp_groups/package.json +++ b/exp_groups/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production" + "prepare": "tsc --build && vite build" }, "engines": { "node": ">=22" @@ -39,9 +39,7 @@ "react-dom": "catalog:", "react-router-dom": "catalog:", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:" @@ -54,4 +52,4 @@ "clusterio-plugin", "factorio" ] -} \ No newline at end of file +} diff --git a/exp_groups/vite.config.js b/exp_groups/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_groups/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_groups/webpack.config.cjs b/exp_groups/webpack.config.cjs deleted file mode 100644 index b1f01165..00000000 --- a/exp_groups/webpack.config.cjs +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_groups", - library: { type: "window", name: "plugin_exp_groups" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - "antd": { import: false }, - "react": { import: false }, - "react-dom": { import: false }, - "react-router": { import: false }, - "react-router-dom": { import: false }, - }, - }), - ], -}); diff --git a/exp_gui/index.ts b/exp_gui/index.ts index 56e8e4e1..93a8b400 100644 --- a/exp_gui/index.ts +++ b/exp_gui/index.ts @@ -5,5 +5,4 @@ export const plugin: lib.PluginDeclaration = { title: "ExpGaming - GUI", description: "Clusterio plugin providing a Lua GUI definition library.", instanceEntrypoint: "./dist/node/instance.js", - webEntrypoint: "./web", }; diff --git a/exp_gui/package.json b/exp_gui/package.json index a9ba7998..57273995 100644 --- a/exp_gui/package.json +++ b/exp_gui/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production" + "prepare": "tsc --build && vite build" }, "engines": { "node": ">=22" @@ -25,11 +25,10 @@ "devDependencies": { "@clusterio/host": "workspace:^", "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@expcluster/lib_util": "workspace:^", diff --git a/exp_gui/tsconfig.browser.json b/exp_gui/tsconfig.browser.json index 1ab2704e..1d2c5bb9 100644 --- a/exp_gui/tsconfig.browser.json +++ b/exp_gui/tsconfig.browser.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.browser.json", - "include": [ "web/**/*.tsx", "web/**/*.ts", "package.json" ], + "include": [ "index.ts", "package.json" ], } diff --git a/exp_gui/vite.config.js b/exp_gui/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_gui/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_gui/web/index.tsx b/exp_gui/web/index.tsx deleted file mode 100644 index a5e4ff33..00000000 --- a/exp_gui/web/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export default function() {}; \ No newline at end of file diff --git a/exp_gui/webpack.config.cjs b/exp_gui/webpack.config.cjs deleted file mode 100644 index 640e5770..00000000 --- a/exp_gui/webpack.config.cjs +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_gui", - library: { type: "window", name: "plugin_exp_gui" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - }, - }), - ], -}); diff --git a/exp_player_statistics/controller.ts b/exp_player_statistics/controller.ts index 815eb124..5460897e 100644 --- a/exp_player_statistics/controller.ts +++ b/exp_player_statistics/controller.ts @@ -7,12 +7,10 @@ import * as path from "node:path"; export default async function (context: ControllerPluginContext) { const { controller, plugin } = context; const databaseDirectory = controller.config.get("controller.database_directory"); - const players = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_player_statistics", "players.json"), - messages.PlayerStatistics.fromJSON.bind(messages.PlayerStatistics), - ).bootstrap() - ); + const players = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_player_statistics", "players.json"), + messages.PlayerStatistics.fromJSON.bind(messages.PlayerStatistics), + )); function addDeltas(deltas: messages.StatisticsDelta[]) { const changed = new Map(); diff --git a/exp_player_statistics/package.json b/exp_player_statistics/package.json index 0f3cb47a..17ac2d00 100644 --- a/exp_player_statistics/package.json +++ b/exp_player_statistics/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -42,9 +42,7 @@ "react-router-dom": "catalog:", "tap": "^21.1.0", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:", diff --git a/exp_player_statistics/test/instance.test.js b/exp_player_statistics/test/instance.test.js index e7742994..fd6894f1 100644 --- a/exp_player_statistics/test/instance.test.js +++ b/exp_player_statistics/test/instance.test.js @@ -29,15 +29,16 @@ async function startPlugin(t2, { status = "running", stats = { Kills: 3 } } = {} instanceConfig.set("instance.id", 1); instanceConfig.set("instance.name", "test"); - const instance = new Instance( - { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), "factorioDir", instanceConfig - ); const state = { sent: [], rcons: [], warnings: [] }; const ipc = new Map(); - instance.server = { + const server = { + on: () => {}, handle: (name, handler) => ipc.set(name, handler), }; + const instance = new Instance( + { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), instanceConfig, server + ); instance.sendRcon = async command => { state.rcons.push(command); return ""; diff --git a/exp_player_statistics/vite.config.js b/exp_player_statistics/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_player_statistics/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_player_statistics/web/components/StatisticsPage.tsx b/exp_player_statistics/web/components/StatisticsPage.tsx index 9bcb2532..8862a034 100644 --- a/exp_player_statistics/web/components/StatisticsPage.tsx +++ b/exp_player_statistics/web/components/StatisticsPage.tsx @@ -47,7 +47,7 @@ export default function StatisticsPage() { const rows = useMemo(() => [...players.values()].map(player => new PlayerStatistics( player.id, - { ...player.stats, ...userStatistics(users.get(player.id.toLowerCase())) }, + { ...player.stats, ...userStatistics(users.get(player.id.toLowerCase()), player.stats) }, player.updatedAtMs, )), [players, users]); diff --git a/exp_player_statistics/webpack.config.cjs b/exp_player_statistics/webpack.config.cjs deleted file mode 100644 index 7834f626..00000000 --- a/exp_player_statistics/webpack.config.cjs +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_player_statistics", - library: { type: "window", name: "plugin_exp_player_statistics" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - "antd": { import: false }, - "react": { import: false }, - "react-dom": { import: false }, - "react-router": { import: false }, - "react-router-dom": { import: false }, - }, - }), - ], -}); diff --git a/exp_reports/controller.ts b/exp_reports/controller.ts index 8d7e2a47..542828d2 100644 --- a/exp_reports/controller.ts +++ b/exp_reports/controller.ts @@ -11,19 +11,15 @@ function migrateReports(rawJson: unknown[]) { export default async function (context: ControllerPluginContext) { const { controller, logger, plugin } = context; const databaseDirectory = controller.config.get("controller.database_directory"); - const reports = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_reports", "reports.json"), - messages.ReportRecord.fromJSON.bind(messages.ReportRecord), - migrateReports, - ).bootstrap() - ); - const watchList = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_reports", "watch_list.json"), - messages.WatchListRecord.fromJSON.bind(messages.WatchListRecord), - ).bootstrap() - ); + const reports = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_reports", "reports.json"), + messages.ReportRecord.fromJSON.bind(messages.ReportRecord), + migrateReports, + )); + const watchList = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_reports", "watch_list.json"), + messages.WatchListRecord.fromJSON.bind(messages.WatchListRecord), + )); /** Every report, or only those against one player. */ function listReports(playerName?: string) { @@ -162,7 +158,7 @@ export default async function (context: ControllerPluginContext) { controller.handle(messages.ReportGetRequest, async (request: messages.ReportGetRequest) => { const report = reports.get(request.id); if (!report) { - throw new lib.RequestError(`Report with ID ${request.id} does not exist`); + throw new lib.NotFoundError(`Report with ID ${request.id} does not exist`); } return report; }); @@ -178,13 +174,13 @@ export default async function (context: ControllerPluginContext) { } if (!byPlayerName) { - throw new lib.RequestError("A report needs the name of the player making it"); + throw new lib.ValidationError("A report needs the name of the player making it"); } if (!request.reason.trim()) { - throw new lib.RequestError("A report needs a reason"); + throw new lib.ValidationError("A report needs a reason"); } if (listReports(request.playerName).some(report => report.byPlayerName === byPlayerName)) { - throw new lib.RequestError(`${byPlayerName} has already reported ${request.playerName}`); + throw new lib.ConflictError(`${byPlayerName} has already reported ${request.playerName}`); } let id = Math.random() * 2 ** 31 | 0; @@ -203,7 +199,7 @@ export default async function (context: ControllerPluginContext) { controller.handle(messages.ReportDeleteRequest, async (request: messages.ReportDeleteRequest) => { const report = reports.getMutable(request.id); if (!report) { - throw new lib.RequestError(`Report with ID ${request.id} does not exist`); + throw new lib.NotFoundError(`Report with ID ${request.id} does not exist`); } reports.delete(report); }); @@ -211,7 +207,7 @@ export default async function (context: ControllerPluginContext) { controller.handle(messages.ReportSetReadRequest, async (request: messages.ReportSetReadRequest) => { const report = reports.getMutable(request.id); if (!report) { - throw new lib.RequestError(`Report with ID ${request.id} does not exist`); + throw new lib.NotFoundError(`Report with ID ${request.id} does not exist`); } report.isRead = request.isRead; reports.set(report); @@ -220,14 +216,14 @@ export default async function (context: ControllerPluginContext) { controller.handle(messages.WatchListAddRequest, async (request: messages.WatchListAddRequest, src: lib.Address) => { const playerName = request.playerName.trim(); if (!playerName) { - throw new lib.RequestError("A player name is required"); + throw new lib.ValidationError("A player name is required"); } if (!request.reason.trim()) { - throw new lib.RequestError("A reason is required"); + throw new lib.ValidationError("A reason is required"); } const existing = watchList.get(playerName.toLowerCase()); if (existing) { - throw new lib.RequestError(`${existing.playerName} is already on the watch list`); + throw new lib.ConflictError(`${existing.playerName} is already on the watch list`); } const entry = new messages.WatchListRecord(playerName, request.reason.trim(), controlUserName(src), Date.now()); @@ -238,7 +234,7 @@ export default async function (context: ControllerPluginContext) { controller.handle(messages.WatchListRemoveRequest, async (request: messages.WatchListRemoveRequest) => { const entry = watchList.getMutable(request.playerName.toLowerCase()); if (!entry) { - throw new lib.RequestError(`${request.playerName} is not on the watch list`); + throw new lib.NotFoundError(`${request.playerName} is not on the watch list`); } watchList.delete(entry); }); diff --git a/exp_reports/package.json b/exp_reports/package.json index 52c98fbc..741efab9 100644 --- a/exp_reports/package.json +++ b/exp_reports/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -37,15 +37,13 @@ "@types/node": "catalog:", "@types/react": "catalog:", "antd": "catalog:", + "fengari": "^0.1.5", "react": "catalog:", "react-dom": "catalog:", "react-router-dom": "catalog:", - "typescript": "catalog:", - "webpack": "catalog:", - "fengari": "^0.1.5", "tap": "^21.1.0", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "typescript": "catalog:", + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:", diff --git a/exp_reports/test/instance.test.js b/exp_reports/test/instance.test.js index 92ce2733..b23742f0 100644 --- a/exp_reports/test/instance.test.js +++ b/exp_reports/test/instance.test.js @@ -31,20 +31,20 @@ async function startPlugin(t2, { reports = [report(1, "bob", "alice"), report(2, instanceConfig.set("instance.id", 1); instanceConfig.set("instance.name", "test"); - const instance = new Instance( - { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), "factorioDir", instanceConfig - ); - // Spies which record the messages and commands leaving the instance const state = { sent: [], rcons: [], failNext: null }; const ipc = new Map(); - instance.server = { + const server = { + on: () => {}, handle: (name, handler) => ipc.set(name, handler), sendRcon: async command => { state.rcons.push(command); return ""; }, }; + const instance = new Instance( + { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), instanceConfig, server + ); instance.sendTo = async (dst, request) => { state.sent.push(request); if (state.failNext) { @@ -102,7 +102,7 @@ t.test("instance plugin", t2 => { t2.test("exp_reports:create prints a refusal to the reporter", async t3 => { const { state, createIPC } = await startPlugin(t3); - state.failNext = new lib.RequestError("dave has already reported bob"); + state.failNext = new lib.ConflictError("dave has already reported bob"); await createIPC({ player_name: "bob", by_player_name: "dave", reason: "griefing" }); const { receiver, payload } = decodeRcon(state.rcons[0]); @@ -113,7 +113,7 @@ t.test("instance plugin", t2 => { t2.test("text that closes a long bracket stays inside the json", async t3 => { const { state, createIPC } = await startPlugin(t3); const message = "]=]) game.print(1) --[==[ ]==] ]===]"; - state.failNext = new lib.RequestError(message); + state.failNext = new lib.ConflictError(message); await createIPC({ player_name: "bob", by_player_name: "dave", reason: message }); const { payload } = decodeRcon(state.rcons[0]); diff --git a/exp_reports/vite.config.js b/exp_reports/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_reports/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_reports/webpack.config.cjs b/exp_reports/webpack.config.cjs deleted file mode 100644 index 4f147284..00000000 --- a/exp_reports/webpack.config.cjs +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_reports", - library: { type: "window", name: "plugin_exp_reports" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - "antd": { import: false }, - "react": { import: false }, - "react-dom": { import: false }, - "react-router": { import: false }, - "react-router-dom": { import: false }, - }, - }), - ], -}); diff --git a/exp_roles/controller.ts b/exp_roles/controller.ts index fb317696..e1fc3817 100644 --- a/exp_roles/controller.ts +++ b/exp_roles/controller.ts @@ -22,12 +22,10 @@ export class ControllerPlugin { const controller = context.controller; const databaseDirectory = controller.config.get("controller.database_directory"); - const roleMeta = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_roles", "role_meta.json"), - messages.RoleMetaRecord.fromJSON.bind(messages.RoleMetaRecord), - ).bootstrap() - ); + const roleMeta = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_roles", "role_meta.json"), + messages.RoleMetaRecord.fromJSON.bind(messages.RoleMetaRecord), + )); const plugin = new ControllerPlugin(controller, context.logger, context.plugin.name, roleMeta); loaded.set(controller, plugin); @@ -149,7 +147,7 @@ export class ControllerPlugin { async handleRoleMetaUpdateRequest(request: messages.RoleMetaUpdateRequest) { const meta = request.meta; if (!this.controller.roles.has(meta.id)) { - throw new lib.RequestError(`Role with ID ${meta.id} does not exist`); + throw new lib.NotFoundError(`Role with ID ${meta.id} does not exist`); } this.roleMeta.set(meta); @@ -250,12 +248,12 @@ export class ControllerPlugin { async handleAssignmentUpdateRequest(request: messages.AssignmentUpdateRequest) { const user = this.controller.users.getByNameMutable(request.name); if (!user) { - throw new lib.RequestError(`User '${request.name}' does not exist`); + throw new lib.NotFoundError(`User '${request.name}' does not exist`); } for (const roleId of [...request.assign, ...request.unassign]) { if (!this.controller.roles.has(roleId)) { - throw new lib.RequestError(`Role with ID ${roleId} does not exist`); + throw new lib.NotFoundError(`Role with ID ${roleId} does not exist`); } } diff --git a/exp_roles/package.json b/exp_roles/package.json index 0acaa89c..9636bee0 100644 --- a/exp_roles/package.json +++ b/exp_roles/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -37,15 +37,13 @@ "@types/node": "catalog:", "@types/react": "catalog:", "antd": "catalog:", + "fengari": "^0.1.5", "react": "catalog:", "react-dom": "catalog:", "react-router-dom": "catalog:", - "typescript": "catalog:", - "webpack": "catalog:", - "fengari": "^0.1.5", "tap": "^21.1.0", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "typescript": "catalog:", + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:" diff --git a/exp_roles/test/instance.test.js b/exp_roles/test/instance.test.js index 6ed398b7..81fdf520 100644 --- a/exp_roles/test/instance.test.js +++ b/exp_roles/test/instance.test.js @@ -40,21 +40,21 @@ async function startPlugin(t2, { syncMode = "bidirectional", roles = sampleRoles instanceConfig.set("instance.name", "test"); instanceConfig.set("exp_roles.sync_mode", syncMode); - const instance = new Instance( - { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), "factorioDir", instanceConfig - ); - // Spies which record the messages and commands leaving the instance const state = { sent: [], rcons: [], warnings: [], failNext: null }; const handlers = new Map(); - instance.handle = (Event, handler) => handlers.set(Event, handler); - instance.server = { + const server = { + on: () => {}, handle: (name, handler) => handlers.set(name, handler), sendRcon: async command => { state.rcons.push(command); return ""; }, }; + const instance = new Instance( + { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), instanceConfig, server + ); + instance.handle = (Event, handler) => handlers.set(Event, handler); instance.sendTo = async (dst, request) => { state.sent.push(request); if (state.failNext) { @@ -96,10 +96,10 @@ t.test("entrypoint", async t2 => { const instanceConfig = new lib.InstanceConfig("host"); instanceConfig.set("instance.id", 1); instanceConfig.set("instance.name", "test"); + const server = { on: () => {}, handle: () => {} }; const instance = new Instance( - { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), "factorioDir", instanceConfig + { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), instanceConfig, server ); - instance.server = { handle: () => {} }; await entrypoint({ instance, host: {}, logger, plugin: { name: "exp_roles" } }); for (const hook of ["instanceConfigFieldChanged", "start"]) { t2.ok([...instance.hooks[hook].attached].includes("exp_roles"), `attached to ${hook}`); diff --git a/exp_roles/vite.config.js b/exp_roles/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_roles/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_roles/webpack.config.cjs b/exp_roles/webpack.config.cjs deleted file mode 100644 index 20f6cfb5..00000000 --- a/exp_roles/webpack.config.cjs +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_roles", - library: { type: "window", name: "plugin_exp_roles" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - "antd": { import: false }, - "react": { import: false }, - "react-dom": { import: false }, - "react-router": { import: false }, - "react-router-dom": { import: false }, - }, - }), - ], -}); diff --git a/exp_scenario/controller.ts b/exp_scenario/controller.ts index 6c391805..618629a9 100644 --- a/exp_scenario/controller.ts +++ b/exp_scenario/controller.ts @@ -12,18 +12,14 @@ import { SeedRole, SeedGroup, seedRoles, seedGroups, flattenSeedPermissions } fr export default async function (context: ControllerPluginContext) { const { controller, logger, plugin } = context; const databaseDirectory = controller.config.get("controller.database_directory"); - const featureStore = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_scenario", "features.json"), - messages.FeatureRecord.fromJSON.bind(messages.FeatureRecord), - ).bootstrap() - ); - const playerStore = new lib.SubscribableDatastore( - ...await new lib.JsonIdDatastoreProvider( - path.join(databaseDirectory, "exp_scenario", "players.json"), - messages.PlayerRecord.fromJSON.bind(messages.PlayerRecord), - ).bootstrap() - ); + const featureStore = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_scenario", "features.json"), + messages.FeatureRecord.fromJSON.bind(messages.FeatureRecord), + )); + const playerStore = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider( + path.join(databaseDirectory, "exp_scenario", "players.json"), + messages.PlayerRecord.fromJSON.bind(messages.PlayerRecord), + )); type PlayerSettings = Pick; @@ -179,7 +175,7 @@ export default async function (context: ControllerPluginContext) { const rolesPlugin = RolesPlugin.get(controller); const groupsPlugin = GroupsPlugin.get(controller); if (!rolesPlugin || !groupsPlugin) { - throw new lib.RequestError("Seeding requires the exp_roles and exp_groups plugins"); + throw new lib.UnavailableError("Seeding requires the exp_roles and exp_groups plugins"); } const roleIds = new Map(); @@ -218,7 +214,7 @@ export default async function (context: ControllerPluginContext) { try { values = validateFeatureValues(request.id, request.values); } catch (err: any) { - throw new lib.RequestError(err.message); + throw new lib.ValidationError(err.message); } const feature = new messages.FeatureRecord(request.id, request.enabled, values); diff --git a/exp_scenario/package.json b/exp_scenario/package.json index c7ba8c29..800eb7bb 100644 --- a/exp_scenario/package.json +++ b/exp_scenario/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -41,9 +41,7 @@ "react-dom": "catalog:", "tap": "^21.1.0", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@expcluster/lib_commands": "workspace:^", diff --git a/exp_scenario/test/instance.test.js b/exp_scenario/test/instance.test.js index 1b201bcb..692eff91 100644 --- a/exp_scenario/test/instance.test.js +++ b/exp_scenario/test/instance.test.js @@ -32,19 +32,19 @@ async function startPlugin( instanceConfig.set("instance.id", 1); instanceConfig.set("instance.name", "test"); - const instance = new Instance( - { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), "factorioDir", instanceConfig - ); - const state = { sent: [], rcons: [] }; const ipcHandlers = new Map(); - instance.server = { + const server = { + on: () => {}, handle: (channel, handler) => ipcHandlers.set(channel, handler), sendRcon: async command => { state.rcons.push(command); return ""; }, }; + const instance = new Instance( + { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), instanceConfig, server + ); instance.sendTo = async (dst, request) => { state.sent.push(request); if (request instanceof messages.PlayerGetRequest) { diff --git a/exp_scenario/vite.config.js b/exp_scenario/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_scenario/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_scenario/webpack.config.cjs b/exp_scenario/webpack.config.cjs deleted file mode 100644 index b507169f..00000000 --- a/exp_scenario/webpack.config.cjs +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_scenario", - library: { type: "window", name: "plugin_exp_scenario" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - "antd": { import: false }, - "react": { import: false }, - "react-dom": { import: false }, - }, - }), - ], -}); diff --git a/exp_server_list/index.ts b/exp_server_list/index.ts index 8b9ce6c4..2bbcc7b7 100644 --- a/exp_server_list/index.ts +++ b/exp_server_list/index.ts @@ -24,7 +24,6 @@ export const plugin: lib.PluginDeclaration = { name: "exp_server_list", title: "ExpGaming - Server List", description: "Clusterio plugin sharing the details of every instance with the others", - webEntrypoint: "./web", controllerEntrypoint: "./dist/node/controller.js", instanceEntrypoint: "./dist/node/instance.js", diff --git a/exp_server_list/package.json b/exp_server_list/package.json index a500aa6e..a1b48792 100644 --- a/exp_server_list/package.json +++ b/exp_server_list/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production", + "prepare": "tsc --build && vite build", "test": "tap --type-strip-only --disable-coverage --allow-empty-coverage test/*.test.js", "coverage": "tap --coverage-report=text test/*.test.js" }, @@ -37,9 +37,7 @@ "fengari": "^0.1.5", "tap": "^21.1.0", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:", diff --git a/exp_server_list/test/instance.test.js b/exp_server_list/test/instance.test.js index 758ede46..58ffbf52 100644 --- a/exp_server_list/test/instance.test.js +++ b/exp_server_list/test/instance.test.js @@ -35,18 +35,19 @@ async function startPlugin(t2, servers = [server(1), server(2)]) { instanceConfig.set("instance.id", 1); instanceConfig.set("instance.name", "test"); - const instance = new Instance( - { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), "factorioDir", instanceConfig - ); const state = { sent: [], rcons: [] }; - instance.server = { + const server = { + on: () => {}, handle: () => {}, sendRcon: async command => { state.rcons.push(command); return ""; }, }; + const instance = new Instance( + { assignGamePort: () => 1 }, new TestConnector(), t2.testdir(), instanceConfig, server + ); instance.sendTo = async (dst, request) => { if (request instanceof lib.InstanceStatusChangedEvent) { return undefined; diff --git a/exp_server_list/tsconfig.browser.json b/exp_server_list/tsconfig.browser.json index a621b69f..05225306 100644 --- a/exp_server_list/tsconfig.browser.json +++ b/exp_server_list/tsconfig.browser.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.browser.json", - "include": [ "web/**/*.tsx", "web/**/*.ts", "index.ts", "messages.ts", "package.json" ], + "include": [ "index.ts", "messages.ts", "package.json" ], } diff --git a/exp_server_list/vite.config.js b/exp_server_list/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_server_list/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_server_list/web/index.tsx b/exp_server_list/web/index.tsx deleted file mode 100644 index a5e4ff33..00000000 --- a/exp_server_list/web/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export default function() {}; \ No newline at end of file diff --git a/exp_server_list/webpack.config.cjs b/exp_server_list/webpack.config.cjs deleted file mode 100644 index 124ef5d0..00000000 --- a/exp_server_list/webpack.config.cjs +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_server_list", - library: { type: "window", name: "plugin_exp_server_list" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - }, - }), - ], -}); diff --git a/exp_server_ups/index.ts b/exp_server_ups/index.ts index 85516393..404259e9 100644 --- a/exp_server_ups/index.ts +++ b/exp_server_ups/index.ts @@ -11,7 +11,6 @@ export const plugin: lib.PluginDeclaration = { name: "exp_server_ups", title: "ExpGaming - Server UPS", description: "Clusterio plugin providing in game server ups counter", - webEntrypoint: "./web", instanceEntrypoint: "./dist/node/instance.js", instanceConfigFields: { diff --git a/exp_server_ups/package.json b/exp_server_ups/package.json index 07401a1b..98431728 100644 --- a/exp_server_ups/package.json +++ b/exp_server_ups/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production" + "prepare": "tsc --build && vite build" }, "engines": { "node": ">=22" @@ -25,11 +25,10 @@ "devDependencies": { "@clusterio/host": "workspace:^", "@clusterio/lib": "workspace:^", - "typescript": "catalog:", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "typescript": "catalog:", + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:", @@ -45,4 +44,4 @@ "clusterio-plugin", "factorio" ] -} \ No newline at end of file +} diff --git a/exp_server_ups/tsconfig.browser.json b/exp_server_ups/tsconfig.browser.json index 1ab2704e..1d2c5bb9 100644 --- a/exp_server_ups/tsconfig.browser.json +++ b/exp_server_ups/tsconfig.browser.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.browser.json", - "include": [ "web/**/*.tsx", "web/**/*.ts", "package.json" ], + "include": [ "index.ts", "package.json" ], } diff --git a/exp_server_ups/vite.config.js b/exp_server_ups/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_server_ups/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_server_ups/web/index.tsx b/exp_server_ups/web/index.tsx deleted file mode 100644 index a5e4ff33..00000000 --- a/exp_server_ups/web/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export default function() {}; \ No newline at end of file diff --git a/exp_server_ups/webpack.config.cjs b/exp_server_ups/webpack.config.cjs deleted file mode 100644 index d0eaa345..00000000 --- a/exp_server_ups/webpack.config.cjs +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_server_ups", - library: { type: "window", name: "plugin_exp_server_ups" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - }, - }), - ], -}); diff --git a/exp_util/index.ts b/exp_util/index.ts index 863a60c3..e851a478 100644 --- a/exp_util/index.ts +++ b/exp_util/index.ts @@ -5,5 +5,4 @@ export const plugin: lib.PluginDeclaration = { title: "ExpGaming - Module Utilities", description: "Provides extensions and overrides of base Lua library functions, and provides utility modules for improved module compatibly", instanceEntrypoint: "./dist/node/instance.js", - webEntrypoint: "./web", }; diff --git a/exp_util/package.json b/exp_util/package.json index 5c6c2073..1d1fd3dc 100644 --- a/exp_util/package.json +++ b/exp_util/package.json @@ -8,7 +8,7 @@ "type": "module", "main": "dist/node/index.js", "scripts": { - "prepare": "tsc --build && webpack-cli --env production" + "prepare": "tsc --build && vite build" }, "engines": { "node": ">=22" @@ -25,11 +25,10 @@ "devDependencies": { "@clusterio/host": "workspace:^", "@clusterio/lib": "workspace:^", + "@clusterio/web_ui": "workspace:^", "@types/node": "catalog:", "typescript": "catalog:", - "webpack": "catalog:", - "webpack-cli": "catalog:", - "webpack-merge": "catalog:" + "vite": "catalog:" }, "dependencies": { "@sinclair/typebox": "catalog:" diff --git a/exp_util/tsconfig.browser.json b/exp_util/tsconfig.browser.json index 1ab2704e..1d2c5bb9 100644 --- a/exp_util/tsconfig.browser.json +++ b/exp_util/tsconfig.browser.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.browser.json", - "include": [ "web/**/*.tsx", "web/**/*.ts", "package.json" ], + "include": [ "index.ts", "package.json" ], } diff --git a/exp_util/vite.config.js b/exp_util/vite.config.js new file mode 100644 index 00000000..5db067d0 --- /dev/null +++ b/exp_util/vite.config.js @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { clusterioPlugin } from "@clusterio/web_ui/vite.mjs"; + +export default defineConfig({ + plugins: [clusterioPlugin()], +}); diff --git a/exp_util/web/index.tsx b/exp_util/web/index.tsx deleted file mode 100644 index a5e4ff33..00000000 --- a/exp_util/web/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export default function() {}; \ No newline at end of file diff --git a/exp_util/webpack.config.cjs b/exp_util/webpack.config.cjs deleted file mode 100644 index fc72ab41..00000000 --- a/exp_util/webpack.config.cjs +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -const path = require("path"); -const webpack = require("webpack"); -const { merge } = require("webpack-merge"); - -const common = require("@clusterio/web_ui/webpack.common"); - -module.exports = (env = {}) => merge(common(env), { - context: __dirname, - entry: "./web/index.tsx", - output: { - path: path.resolve(__dirname, "dist", "web"), - }, - plugins: [ - new webpack.container.ModuleFederationPlugin({ - name: "exp_util", - library: { type: "window", name: "plugin_exp_util" }, - exposes: { - "./": "./index.ts", - "./package.json": "./package.json", - "./web": "./web/index.tsx", - }, - shared: { - "@clusterio/lib": { import: false }, - "@clusterio/web_ui": { import: false }, - }, - }), - ], -});