From f41377bb81d10b83eb634e825468ff3fb47c5bae Mon Sep 17 00:00:00 2001
From: Sainan <63328889+Sainan@users.noreply.github.com>
Date: Fri, 20 Jun 2025 09:40:53 -0700
Subject: [PATCH 1/4] chore: npm audit fix (#2220)
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2220
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
---
package-lock.json | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 5d1f4a36..ca339e31 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -121,9 +121,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -171,9 +171,9 @@
}
},
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -998,9 +998,9 @@
}
},
"node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1552,9 +1552,9 @@
}
},
"node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1983,9 +1983,9 @@
}
},
"node_modules/glob/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
From eadc9c4ecb2eeb429c7a4caad03b47ed64a06722 Mon Sep 17 00:00:00 2001
From: Sainan <63328889+Sainan@users.noreply.github.com>
Date: Fri, 20 Jun 2025 14:00:39 -0700
Subject: [PATCH 2/4] feat(webui): max rank plexus (#2219)
Closes #1740
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2219
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
---
static/webui/index.html | 3 ++
static/webui/script.js | 82 ++++++++++++++++++++++-----------
static/webui/translations/de.js | 3 +-
static/webui/translations/en.js | 3 +-
static/webui/translations/es.js | 3 +-
static/webui/translations/fr.js | 3 +-
static/webui/translations/ru.js | 3 +-
static/webui/translations/zh.js | 3 +-
8 files changed, 70 insertions(+), 33 deletions(-)
diff --git a/static/webui/index.html b/static/webui/index.html
index e80d9fe7..5b92f727 100644
--- a/static/webui/index.html
+++ b/static/webui/index.html
@@ -452,6 +452,9 @@
+
+
+
diff --git a/static/webui/script.js b/static/webui/script.js
index bd32266f..f4c43175 100644
--- a/static/webui/script.js
+++ b/static/webui/script.js
@@ -594,8 +594,9 @@ function updateInventory() {
a.onclick = function (event) {
event.preventDefault();
revalidateAuthz(() => {
+ const promises = [];
if (item.XP < maxXP) {
- addGearExp(category, item.ItemId.$oid, maxXP - item.XP);
+ promises.push(addGearExp(category, item.ItemId.$oid, maxXP - item.XP));
}
if ("exalted" in itemMap[item.ItemType]) {
for (const exaltedType of itemMap[item.ItemType].exalted) {
@@ -604,15 +605,20 @@ function updateInventory() {
const exaltedCap =
itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
if (exaltedItem.XP < exaltedCap) {
- addGearExp(
- "SpecialItems",
- exaltedItem.ItemId.$oid,
- exaltedCap - exaltedItem.XP
+ promises.push(
+ addGearExp(
+ "SpecialItems",
+ exaltedItem.ItemId.$oid,
+ exaltedCap - exaltedItem.XP
+ )
);
}
}
}
}
+ Promise.all(promises).then(() => {
+ updateInventory();
+ });
});
};
a.title = loc("code_maxRank");
@@ -761,6 +767,13 @@ function updateInventory() {
giveAllQEvolutionProgress.disabled = true;
}
+ if (data.CrewShipHarnesses?.length) {
+ window.plexus = {
+ id: data.CrewShipHarnesses[0].ItemId.$oid,
+ xp: data.CrewShipHarnesses[0].XP
+ };
+ }
+
// Populate quests route
document.getElementById("QuestKeys-list").innerHTML = "";
data.QuestKeys.forEach(item => {
@@ -1443,20 +1456,17 @@ function maxRankAllEquipment(categories) {
XP: maxXP
});
}
- if (category === "Suits") {
- if ("exalted" in itemMap[item.ItemType]) {
- for (const exaltedType of itemMap[item.ItemType].exalted) {
- const exaltedItem = data["SpecialItems"].find(x => x.ItemType == exaltedType);
- if (exaltedItem) {
- const exaltedCap =
- itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
- if (exaltedItem.XP < exaltedCap) {
- batchData["SpecialItems"] ??= [];
- batchData["SpecialItems"].push({
- ItemId: { $oid: exaltedItem.ItemId.$oid },
- XP: exaltedCap
- });
- }
+ if (item.ItemType in itemMap && "exalted" in itemMap[item.ItemType]) {
+ for (const exaltedType of itemMap[item.ItemType].exalted) {
+ const exaltedItem = data["SpecialItems"].find(x => x.ItemType == exaltedType);
+ if (exaltedItem) {
+ const exaltedCap = itemMap[exaltedType]?.type == "weapons" ? 800_000 : 1_600_000;
+ if (exaltedItem.XP < exaltedCap) {
+ batchData["SpecialItems"] ??= [];
+ batchData["SpecialItems"].push({
+ ItemId: { $oid: exaltedItem.ItemId.$oid },
+ XP: exaltedCap
+ });
}
}
}
@@ -1483,14 +1493,14 @@ function addGearExp(category, oid, xp) {
XP: xp
}
];
- $.post({
- url: "/custom/addXp?" + window.authz,
- contentType: "application/json",
- data: JSON.stringify(data)
- }).done(function () {
- if (category != "SpecialItems") {
- updateInventory();
- }
+ return new Promise((resolve, reject) => {
+ $.post({
+ url: "/custom/addXp?" + window.authz,
+ contentType: "application/json",
+ data: JSON.stringify(data)
+ })
+ .done(resolve)
+ .fail(reject);
});
}
@@ -2249,3 +2259,21 @@ function formatDatetime(fmt, date) {
}
});
}
+
+const calls_in_flight = new Set();
+
+async function debounce(func, ...args) {
+ calls_in_flight.add(func);
+ await func(...args);
+ calls_in_flight.delete(func);
+}
+
+async function doMaxPlexus() {
+ if ((window.plexus?.xp ?? 0) < 900_000) {
+ await addGearExp("CrewShipHarnesses", window.plexus.id, 900_000 - window.plexus.xp);
+ window.plexus.xp = 900_000;
+ toast(loc("code_succRankUp"));
+ } else {
+ toast(loc("code_noEquipmentToRankUp"));
+ }
+}
diff --git a/static/webui/translations/de.js b/static/webui/translations/de.js
index b84df0f2..0401beb9 100644
--- a/static/webui/translations/de.js
+++ b/static/webui/translations/de.js
@@ -86,6 +86,7 @@ dict = {
inventory_moaPets: `Moas`,
inventory_kubrowPets: `Bestien`,
inventory_evolutionProgress: `Incarnon-Entwicklungsfortschritte`,
+ inventory_Boosters: `[UNTRANSLATED] Boosters`,
inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
@@ -100,7 +101,7 @@ dict = {
inventory_bulkRankUpSentinels: `Alle Wächter auf Max. Rang`,
inventory_bulkRankUpSentinelWeapons: `Alle Wächter-Waffen auf Max. Rang`,
inventory_bulkRankUpEvolutionProgress: `Alle Incarnon-Entwicklungsfortschritte auf Max. Rang`,
- inventory_Boosters: `[UNTRANSLATED] Boosters`,
+ inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`,
quests_list: `Quests`,
quests_completeAll: `Alle Quests abschließen`,
diff --git a/static/webui/translations/en.js b/static/webui/translations/en.js
index 7f5b5aca..28bd1e48 100644
--- a/static/webui/translations/en.js
+++ b/static/webui/translations/en.js
@@ -85,6 +85,7 @@ dict = {
inventory_moaPets: `Moas`,
inventory_kubrowPets: `Beasts`,
inventory_evolutionProgress: `Incarnon Evolution Progress`,
+ inventory_Boosters: `Boosters`,
inventory_bulkAddSuits: `Add Missing Warframes`,
inventory_bulkAddWeapons: `Add Missing Weapons`,
inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
@@ -99,7 +100,7 @@ dict = {
inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
inventory_bulkRankUpEvolutionProgress: `Max Rank All Incarnon Evolution Progress`,
- inventory_Boosters: `Boosters`,
+ inventory_maxPlexus: `Max Rank Plexus`,
quests_list: `Quests`,
quests_completeAll: `Complete All Quests`,
diff --git a/static/webui/translations/es.js b/static/webui/translations/es.js
index da50fe7e..e46bcedd 100644
--- a/static/webui/translations/es.js
+++ b/static/webui/translations/es.js
@@ -86,6 +86,7 @@ dict = {
inventory_moaPets: `Moas`,
inventory_kubrowPets: `Bestias`,
inventory_evolutionProgress: `Progreso de evolución Incarnon`,
+ inventory_Boosters: `Potenciadores`,
inventory_bulkAddSuits: `Agregar Warframes faltantes`,
inventory_bulkAddWeapons: `Agregar armas faltantes`,
inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`,
@@ -100,7 +101,7 @@ dict = {
inventory_bulkRankUpSentinels: `Maximizar rango de todos los centinelas`,
inventory_bulkRankUpSentinelWeapons: `Maximizar rango de todas las armas de centinela`,
inventory_bulkRankUpEvolutionProgress: `Maximizar todo el progreso de evolución Incarnon`,
- inventory_Boosters: `Potenciadores`,
+ inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`,
quests_list: `Misiones`,
quests_completeAll: `Completar todas las misiones`,
diff --git a/static/webui/translations/fr.js b/static/webui/translations/fr.js
index 4a8fae03..4958dd8e 100644
--- a/static/webui/translations/fr.js
+++ b/static/webui/translations/fr.js
@@ -86,6 +86,7 @@ dict = {
inventory_moaPets: `Moas`,
inventory_kubrowPets: `Bêtes`,
inventory_evolutionProgress: `Progrès de l'évolution Incarnon`,
+ inventory_Boosters: `[UNTRANSLATED] Boosters`,
inventory_bulkAddSuits: `Ajouter les Warframes manquantes`,
inventory_bulkAddWeapons: `Ajouter les armes manquantes`,
inventory_bulkAddSpaceSuits: `Ajouter les Archwings manquants`,
@@ -100,7 +101,7 @@ dict = {
inventory_bulkRankUpSentinels: `Toutes les Sentinelles au rang max`,
inventory_bulkRankUpSentinelWeapons: `Toutes les armes de Sentinelles au rang max`,
inventory_bulkRankUpEvolutionProgress: `Toutes les évolutions Incarnon au rang max`,
- inventory_Boosters: `[UNTRANSLATED] Boosters`,
+ inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`,
quests_list: `Quêtes`,
quests_completeAll: `Compléter toutes les quêtes`,
diff --git a/static/webui/translations/ru.js b/static/webui/translations/ru.js
index 612555b3..d7369199 100644
--- a/static/webui/translations/ru.js
+++ b/static/webui/translations/ru.js
@@ -86,6 +86,7 @@ dict = {
inventory_moaPets: `МОА`,
inventory_kubrowPets: `Звери`,
inventory_evolutionProgress: `Прогресс эволюции Инкарнонов`,
+ inventory_Boosters: `[UNTRANSLATED] Boosters`,
inventory_bulkAddSuits: `Добавить отсутствующие варфреймы`,
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
inventory_bulkAddSpaceSuits: `Добавить отсутствующие арчвинги`,
@@ -100,7 +101,7 @@ dict = {
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
inventory_bulkRankUpEvolutionProgress: `Максимальный ранг всех эволюций Инкарнонов`,
- inventory_Boosters: `[UNTRANSLATED] Boosters`,
+ inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`,
quests_list: `Квесты`,
quests_completeAll: `Завершить все квесты`,
diff --git a/static/webui/translations/zh.js b/static/webui/translations/zh.js
index 6b1d4b7f..1bd23d49 100644
--- a/static/webui/translations/zh.js
+++ b/static/webui/translations/zh.js
@@ -86,6 +86,7 @@ dict = {
inventory_moaPets: `恐鸟`,
inventory_kubrowPets: `动物同伴`,
inventory_evolutionProgress: `灵化之源进度`,
+ inventory_Boosters: `加成器`,
inventory_bulkAddSuits: `添加缺失战甲`,
inventory_bulkAddWeapons: `添加缺失武器`,
inventory_bulkAddSpaceSuits: `添加缺失Archwing`,
@@ -100,7 +101,7 @@ dict = {
inventory_bulkRankUpSentinels: `所有守护升满级`,
inventory_bulkRankUpSentinelWeapons: `所有守护武器升满级`,
inventory_bulkRankUpEvolutionProgress: `所有灵化之源最大等级`,
- inventory_Boosters: `加成器`,
+ inventory_maxPlexus: `[UNTRANSLATED] Max Rank Plexus`,
quests_list: `任务`,
quests_completeAll: `完成所有任务`,
From 4cb0f8b167a6e10404ac4ef9eed26a4d9b78dfbf Mon Sep 17 00:00:00 2001
From: Sainan <63328889+Sainan@users.noreply.github.com>
Date: Fri, 20 Jun 2025 14:00:55 -0700
Subject: [PATCH 3/4] feat(webui): initial websocket integration to be more
responsive (#2221)
For now just handles changes to config.json but in the future might keep the inventory tabs up-to-date with in-game actions.
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2221
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
---
package-lock.json | 34 +++++++++++++++++++-
package.json | 4 ++-
src/services/configWatcherService.ts | 8 ++++-
src/services/webService.ts | 46 ++++++++++++++++++++++++++++
static/webui/script.js | 26 ++++++++++++++--
5 files changed, 112 insertions(+), 6 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index ca339e31..1708e273 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"dependencies": {
"@types/express": "^5",
"@types/morgan": "^1.9.9",
+ "@types/ws": "^8.18.1",
"crc-32": "^1.2.2",
"express": "^5",
"json-with-bigint": "^3.4.4",
@@ -21,7 +22,8 @@
"warframe-public-export-plus": "^0.5.68",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
- "winston-daily-rotate-file": "^5.0.0"
+ "winston-daily-rotate-file": "^5.0.0",
+ "ws": "^8.18.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.28.0",
@@ -472,6 +474,15 @@
"@types/webidl-conversions": "*"
}
},
+ "node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.32.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz",
@@ -3931,6 +3942,27 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
+ "node_modules/ws": {
+ "version": "8.18.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
+ "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index b8d00e39..c5a98e44 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"dependencies": {
"@types/express": "^5",
"@types/morgan": "^1.9.9",
+ "@types/ws": "^8.18.1",
"crc-32": "^1.2.2",
"express": "^5",
"json-with-bigint": "^3.4.4",
@@ -28,7 +29,8 @@
"warframe-public-export-plus": "^0.5.68",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
- "winston-daily-rotate-file": "^5.0.0"
+ "winston-daily-rotate-file": "^5.0.0",
+ "ws": "^8.18.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.28.0",
diff --git a/src/services/configWatcherService.ts b/src/services/configWatcherService.ts
index 197a9567..b6f8e83c 100644
--- a/src/services/configWatcherService.ts
+++ b/src/services/configWatcherService.ts
@@ -2,7 +2,7 @@ import fs from "fs";
import fsPromises from "fs/promises";
import { logger } from "../utils/logger";
import { config, configPath, loadConfig } from "./configService";
-import { getWebPorts, startWebServer, stopWebServer } from "./webService";
+import { getWebPorts, sendWsBroadcast, startWebServer, stopWebServer } from "./webService";
let amnesia = false;
fs.watchFile(configPath, () => {
@@ -21,7 +21,13 @@ fs.watchFile(configPath, () => {
const webPorts = getWebPorts();
if (config.httpPort != webPorts.http || config.httpsPort != webPorts.https) {
logger.info(`Restarting web server to apply port changes.`);
+
+ // Tell webui clients to reload with new port
+ sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } });
+
void stopWebServer().then(startWebServer);
+ } else {
+ sendWsBroadcast({ config_reloaded: true });
}
}
});
diff --git a/src/services/webService.ts b/src/services/webService.ts
index 77fe01fe..d4d1227c 100644
--- a/src/services/webService.ts
+++ b/src/services/webService.ts
@@ -5,9 +5,12 @@ import { config } from "./configService";
import { logger } from "../utils/logger";
import { app } from "../app";
import { AddressInfo } from "node:net";
+import ws from "ws";
let httpServer: http.Server | undefined;
let httpsServer: https.Server | undefined;
+let wsServer: ws.Server | undefined;
+let wssServer: ws.Server | undefined;
const tlsOptions = {
key: fs.readFileSync("static/certs/key.pem"),
@@ -21,10 +24,17 @@ export const startWebServer = (): void => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
httpServer = http.createServer(app);
httpServer.listen(httpPort, () => {
+ wsServer = new ws.Server({ server: httpServer });
+ //wsServer.on("connection", wsOnConnect);
+
logger.info("HTTP server started on port " + httpPort);
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
httpsServer = https.createServer(tlsOptions, app);
httpsServer.listen(httpsPort, () => {
+ wssServer = new ws.Server({ server: httpsServer });
+ //wssServer.on("connection", wsOnConnect);
+
logger.info("HTTPS server started on port " + httpsPort);
logger.info(
@@ -61,5 +71,41 @@ export const stopWebServer = async (): Promise => {
})
);
}
+ if (wsServer) {
+ promises.push(
+ new Promise(resolve => {
+ wsServer!.close(() => {
+ resolve();
+ });
+ })
+ );
+ }
+ if (wssServer) {
+ promises.push(
+ new Promise(resolve => {
+ wssServer!.close(() => {
+ resolve();
+ });
+ })
+ );
+ }
await Promise.all(promises);
};
+
+/*const wsOnConnect = (ws: ws, _req: http.IncomingMessage): void => {
+ ws.on("message", console.log);
+};*/
+
+export const sendWsBroadcast = (data: T): void => {
+ const msg = JSON.stringify(data);
+ if (wsServer) {
+ for (const client of wsServer.clients) {
+ client.send(msg);
+ }
+ }
+ if (wssServer) {
+ for (const client of wssServer.clients) {
+ client.send(msg);
+ }
+ }
+};
diff --git a/static/webui/script.js b/static/webui/script.js
index f4c43175..dfe4e096 100644
--- a/static/webui/script.js
+++ b/static/webui/script.js
@@ -1,3 +1,23 @@
+function openWebSocket() {
+ window.ws = new WebSocket("/custom/ws");
+ window.ws.onmessage = e => {
+ const msg = JSON.parse(e.data);
+ if ("ports" in msg) {
+ location.port = location.protocol == "https:" ? msg.ports.https : msg.ports.http;
+ }
+ if ("config_reloaded" in msg) {
+ //window.is_admin = undefined;
+ if (single.getCurrentPath() == "/webui/cheats") {
+ single.loadRoute("/webui/cheats");
+ }
+ }
+ };
+ window.ws.onclose = function () {
+ setTimeout(openWebSocket, 3000);
+ };
+}
+openWebSocket();
+
let loginOrRegisterPending = false;
window.registerSubmit = false;
@@ -1822,6 +1842,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
clearInterval(interval);
fetch("/custom/config?" + window.authz).then(async res => {
if (res.status == 200) {
+ //window.is_admin = true;
$("#server-settings-no-perms").addClass("d-none");
$("#server-settings").removeClass("d-none");
res.json().then(json =>
@@ -1830,9 +1851,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
var x = document.getElementById(`${key}`);
if (x != null) {
if (x.type == "checkbox") {
- if (value === true) {
- x.setAttribute("checked", "checked");
- }
+ x.checked = value;
} else if (x.type == "number") {
x.setAttribute("value", `${value}`);
}
@@ -1847,6 +1866,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
}
});
} else {
+ //window.is_admin = false;
$("#server-settings-no-perms").removeClass("d-none");
$("#server-settings").addClass("d-none");
}
From f84cc54c97d7040d11c94e8bf84318d7473e2e77 Mon Sep 17 00:00:00 2001
From: Sainan <63328889+Sainan@users.noreply.github.com>
Date: Fri, 20 Jun 2025 18:30:52 -0700
Subject: [PATCH 4/4] chore: use build & start process for development as well
(#2222)
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2222
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
---
docker-entrypoint.sh | 2 +-
package-lock.json | 538 +-----------------
package.json | 8 +-
scripts/dev.js | 49 ++
scripts/update-translations.js | 1 +
.../webuiFileChangeDetectedController.ts | 11 +
src/helpers/commandLineArguments.ts | 23 +
src/helpers/pathHelper.ts | 3 +-
src/routes/custom.ts | 4 +-
src/routes/webui.ts | 21 +-
src/services/configService.ts | 3 +-
src/services/serversideVendorsService.ts | 4 +-
static/webui/script.js | 17 +-
13 files changed, 138 insertions(+), 546 deletions(-)
create mode 100644 scripts/dev.js
create mode 100644 src/controllers/custom/webuiFileChangeDetectedController.ts
create mode 100644 src/helpers/commandLineArguments.ts
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
index 457173d9..703b7eaf 100755
--- a/docker-entrypoint.sh
+++ b/docker-entrypoint.sh
@@ -5,4 +5,4 @@ if [ ! -f conf/config.json ]; then
jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config.json.example > /app/conf/config.json
fi
-exec npm run start conf/config.json
+exec npm run start -- --configPath conf/config.json
diff --git a/package-lock.json b/package-lock.json
index 1708e273..dc6eb284 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -29,11 +29,11 @@
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"@typescript/native-preview": "^7.0.0-dev.20250523.1",
+ "chokidar": "^4.0.3",
"eslint": "^8",
"eslint-plugin-prettier": "^5.2.5",
"prettier": "^3.5.3",
- "ts-node-dev": "^2.0.0",
- "tsconfig-paths": "^4.2.0"
+ "tree-kill": "^1.2.2"
}
},
"node_modules/@colors/colors": {
@@ -45,19 +45,6 @@
"node": ">=0.1.90"
}
},
- "node_modules/@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/trace-mapping": "0.3.9"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/@dabh/diagnostics": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
@@ -218,34 +205,6 @@
"dev": true,
"license": "BSD-3-Clause"
},
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
"node_modules/@mongodb-js/saslprep": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.2.tgz",
@@ -306,34 +265,6 @@
"url": "https://opencollective.com/pkgr"
}
},
- "node_modules/@tsconfig/node10": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
- "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node16": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
- "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -439,20 +370,6 @@
"@types/send": "*"
}
},
- "node_modules/@types/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/strip-json-comments": {
- "version": "0.0.30",
- "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
- "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/triple-beam": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
@@ -860,19 +777,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/acorn-walk": {
- "version": "8.3.4",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
- "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "acorn": "^8.11.0"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -916,27 +820,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -975,19 +858,6 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
@@ -1040,13 +910,6 @@
"node": ">=16.20.1"
}
},
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -1113,41 +976,19 @@
}
},
"node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
+ "readdirp": "^4.0.1"
},
"engines": {
- "node": ">= 8.10.0"
+ "node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/chokidar/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
}
},
"node_modules/color": {
@@ -1272,13 +1113,6 @@
"node": ">=0.8"
}
},
- "node_modules/create-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -1327,16 +1161,6 @@
"node": ">= 0.8"
}
},
- "node_modules/diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
- }
- },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -1364,16 +1188,6 @@
"node": ">= 0.4"
}
},
- "node_modules/dynamic-dedupe": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
- "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "xtend": "^4.0.0"
- }
- },
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1897,21 +1711,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -2184,35 +1983,6 @@
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"license": "MIT"
},
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2321,19 +2091,6 @@
"integrity": "sha512-AhpYAAaZsPjU7smaBomDt1SOQshi9rEm6BlTbfVwsG1vNmeHKtEedJi62sHZzJTyKNtwzmNnrsd55kjwJ7054A==",
"license": "MIT"
},
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/kareem": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
@@ -2413,13 +2170,6 @@
"node": ">= 12.0.0"
}
},
- "node_modules/make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -2517,29 +2267,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
@@ -2722,16 +2449,6 @@
"node": ">= 0.6"
}
},
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/object-hash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
@@ -2894,13 +2611,6 @@
"node": ">=8"
}
},
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/path-to-regexp": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
@@ -3059,37 +2769,17 @@
}
},
"node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
"engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.10",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
- "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-core-module": "^2.16.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
+ "node": ">= 14.18.0"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
}
},
"node_modules/resolve-from": {
@@ -3371,27 +3061,6 @@
"is-arrayish": "^0.3.1"
}
},
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
@@ -3441,16 +3110,6 @@
"node": ">=8"
}
},
- "node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -3477,19 +3136,6 @@
"node": ">=8"
}
},
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/synckit": {
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz",
@@ -3586,137 +3232,6 @@
"typescript": ">=4.8.4"
}
},
- "node_modules/ts-node": {
- "version": "10.9.2",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
- "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- },
- "bin": {
- "ts-node": "dist/bin.js",
- "ts-node-cwd": "dist/bin-cwd.js",
- "ts-node-esm": "dist/bin-esm.js",
- "ts-node-script": "dist/bin-script.js",
- "ts-node-transpile-only": "dist/bin-transpile.js",
- "ts-script": "dist/bin-script-deprecated.js"
- },
- "peerDependencies": {
- "@swc/core": ">=1.2.50",
- "@swc/wasm": ">=1.2.50",
- "@types/node": "*",
- "typescript": ">=2.7"
- },
- "peerDependenciesMeta": {
- "@swc/core": {
- "optional": true
- },
- "@swc/wasm": {
- "optional": true
- }
- }
- },
- "node_modules/ts-node-dev": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
- "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chokidar": "^3.5.1",
- "dynamic-dedupe": "^0.3.0",
- "minimist": "^1.2.6",
- "mkdirp": "^1.0.4",
- "resolve": "^1.0.0",
- "rimraf": "^2.6.1",
- "source-map-support": "^0.5.12",
- "tree-kill": "^1.2.2",
- "ts-node": "^10.4.0",
- "tsconfig": "^7.0.0"
- },
- "bin": {
- "ts-node-dev": "lib/bin.js",
- "tsnd": "lib/bin.js"
- },
- "engines": {
- "node": ">=0.8.0"
- },
- "peerDependencies": {
- "node-notifier": "*",
- "typescript": "*"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/ts-node-dev/node_modules/rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- }
- },
- "node_modules/tsconfig": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
- "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/strip-bom": "^3.0.0",
- "@types/strip-json-comments": "0.0.30",
- "strip-bom": "^3.0.0",
- "strip-json-comments": "^2.0.0"
- }
- },
- "node_modules/tsconfig-paths": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
- "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "json5": "^2.2.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tsconfig/node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -3808,13 +3323,6 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
- "node_modules/v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -3963,26 +3471,6 @@
}
}
},
- "node_modules/xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.4"
- }
- },
- "node_modules/yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index c5a98e44..b5ca4fbd 100644
--- a/package.json
+++ b/package.json
@@ -5,8 +5,10 @@
"main": "index.ts",
"scripts": {
"start": "node --enable-source-maps --import ./build/src/pathman.js build/src/index.js",
- "dev": "ts-node-dev --openssl-legacy-provider -r tsconfig-paths/register src/index.ts ",
"build": "tsc --incremental --sourceMap && ncp static/webui build/static/webui",
+ "build:dev": "tsc --incremental --sourceMap",
+ "build-and-start": "npm run build && npm run start",
+ "dev": "node scripts/dev.js",
"verify": "tsgo --noEmit",
"lint": "eslint --ext .ts .",
"lint:ci": "eslint --ext .ts --rule \"prettier/prettier: off\" .",
@@ -36,10 +38,10 @@
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"@typescript/native-preview": "^7.0.0-dev.20250523.1",
+ "chokidar": "^4.0.3",
"eslint": "^8",
"eslint-plugin-prettier": "^5.2.5",
"prettier": "^3.5.3",
- "ts-node-dev": "^2.0.0",
- "tsconfig-paths": "^4.2.0"
+ "tree-kill": "^1.2.2"
}
}
diff --git a/scripts/dev.js b/scripts/dev.js
new file mode 100644
index 00000000..1852a131
--- /dev/null
+++ b/scripts/dev.js
@@ -0,0 +1,49 @@
+/* eslint-disable */
+const { spawn } = require("child_process");
+const chokidar = require("chokidar");
+const kill = require("tree-kill");
+
+let secret = "";
+for (let i = 0; i != 10; ++i) {
+ secret += String.fromCharCode(Math.floor(Math.random() * 26) + 0x41);
+}
+
+const args = [...process.argv].splice(2);
+args.push("--dev");
+args.push("--secret");
+args.push(secret);
+
+let buildproc, runproc;
+function run(changedFile) {
+ if (changedFile) {
+ console.log(`Change to ${changedFile} detected`);
+ }
+
+ if (buildproc) {
+ kill(buildproc.pid);
+ buildproc = undefined;
+ }
+ if (runproc) {
+ kill(runproc.pid);
+ runproc = undefined;
+ }
+
+ buildproc = spawn("npm", ["run", "build:dev"], { stdio: "inherit", shell: true });
+ buildproc.on("exit", code => {
+ buildproc = undefined;
+ if (code === 0) {
+ runproc = spawn("npm", ["run", "start", "--", ...args], { stdio: "inherit", shell: true });
+ runproc.on("exit", () => {
+ runproc = undefined;
+ });
+ }
+ });
+}
+
+run();
+chokidar.watch("src").on("change", run);
+chokidar.watch("static/fixed_responses").on("change", run);
+
+chokidar.watch("static/webui").on("change", () => {
+ fetch("http://localhost/custom/webuiFileChangeDetected?secret=" + secret);
+});
diff --git a/scripts/update-translations.js b/scripts/update-translations.js
index 5351afaa..0f1f56ec 100644
--- a/scripts/update-translations.js
+++ b/scripts/update-translations.js
@@ -1,6 +1,7 @@
// Based on https://onlyg.it/OpenWF/Translations/src/branch/main/update.php
// Converted via ChatGPT-4o
+/* eslint-disable */
const fs = require("fs");
function extractStrings(content) {
diff --git a/src/controllers/custom/webuiFileChangeDetectedController.ts b/src/controllers/custom/webuiFileChangeDetectedController.ts
new file mode 100644
index 00000000..3ec52a48
--- /dev/null
+++ b/src/controllers/custom/webuiFileChangeDetectedController.ts
@@ -0,0 +1,11 @@
+import { args } from "@/src/helpers/commandLineArguments";
+import { config } from "@/src/services/configService";
+import { sendWsBroadcast } from "@/src/services/webService";
+import { RequestHandler } from "express";
+
+export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {
+ if (args.dev && args.secret && req.query.secret == args.secret) {
+ sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } });
+ }
+ res.end();
+};
diff --git a/src/helpers/commandLineArguments.ts b/src/helpers/commandLineArguments.ts
new file mode 100644
index 00000000..09af105d
--- /dev/null
+++ b/src/helpers/commandLineArguments.ts
@@ -0,0 +1,23 @@
+interface IArguments {
+ configPath?: string;
+ dev?: boolean;
+ secret?: string;
+}
+
+export const args: IArguments = {};
+
+for (let i = 2; i < process.argv.length; ) {
+ switch (process.argv[i++]) {
+ case "--configPath":
+ args.configPath = process.argv[i++];
+ break;
+
+ case "--dev":
+ args.dev = true;
+ break;
+
+ case "--secret":
+ args.secret = process.argv[i++];
+ break;
+ }
+}
diff --git a/src/helpers/pathHelper.ts b/src/helpers/pathHelper.ts
index 94a0f242..37e87dff 100644
--- a/src/helpers/pathHelper.ts
+++ b/src/helpers/pathHelper.ts
@@ -1,5 +1,4 @@
import path from "path";
export const rootDir = path.join(__dirname, "../..");
-export const isDev = path.basename(rootDir) != "build";
-export const repoDir = isDev ? rootDir : path.join(rootDir, "..");
+export const repoDir = path.basename(rootDir) != "build" ? rootDir : path.join(rootDir, "..");
diff --git a/src/routes/custom.ts b/src/routes/custom.ts
index 7d8c7c82..75eb80a4 100644
--- a/src/routes/custom.ts
+++ b/src/routes/custom.ts
@@ -11,6 +11,7 @@ import { renameAccountController } from "@/src/controllers/custom/renameAccountC
import { ircDroppedController } from "@/src/controllers/custom/ircDroppedController";
import { unlockAllIntrinsicsController } from "@/src/controllers/custom/unlockAllIntrinsicsController";
import { addMissingMaxRankModsController } from "@/src/controllers/custom/addMissingMaxRankModsController";
+import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webuiFileChangeDetectedController";
import { createAccountController } from "@/src/controllers/custom/createAccountController";
import { createMessageController } from "@/src/controllers/custom/createMessageController";
@@ -20,10 +21,10 @@ import { addXpController } from "@/src/controllers/custom/addXpController";
import { importController } from "@/src/controllers/custom/importController";
import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController";
import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
+import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
-import { setBoosterController } from "../controllers/custom/setBoosterController";
const customRouter = express.Router();
@@ -38,6 +39,7 @@ customRouter.get("/renameAccount", renameAccountController);
customRouter.get("/ircDropped", ircDroppedController);
customRouter.get("/unlockAllIntrinsics", unlockAllIntrinsicsController);
customRouter.get("/addMissingMaxRankMods", addMissingMaxRankModsController);
+customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
customRouter.post("/createAccount", createAccountController);
customRouter.post("/createMessage", createMessageController);
diff --git a/src/routes/webui.ts b/src/routes/webui.ts
index 02224903..535d68b1 100644
--- a/src/routes/webui.ts
+++ b/src/routes/webui.ts
@@ -1,6 +1,9 @@
import express from "express";
import path from "path";
import { repoDir, rootDir } from "@/src/helpers/pathHelper";
+import { args } from "@/src/helpers/commandLineArguments";
+
+const baseDir = args.dev ? repoDir : rootDir;
const webuiRouter = express.Router();
@@ -19,29 +22,29 @@ webuiRouter.use("/webui", (req, res, next) => {
// Serve virtual routes
webuiRouter.get("/webui/inventory", (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
webuiRouter.get(/webui\/powersuit\/(.+)/, (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
webuiRouter.get("/webui/mods", (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
webuiRouter.get("/webui/settings", (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
webuiRouter.get("/webui/quests", (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
webuiRouter.get("/webui/cheats", (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
webuiRouter.get("/webui/import", (_req, res) => {
- res.sendFile(path.join(rootDir, "static/webui/index.html"));
+ res.sendFile(path.join(baseDir, "static/webui/index.html"));
});
// Serve static files
-webuiRouter.use("/webui", express.static(path.join(rootDir, "static/webui")));
+webuiRouter.use("/webui", express.static(path.join(baseDir, "static/webui")));
// Serve favicon
webuiRouter.get("/favicon.ico", (_req, res) => {
@@ -58,7 +61,7 @@ webuiRouter.get("/webui/riven-tool/RivenParser.js", (_req, res) => {
// Serve translations
webuiRouter.get("/translations/:file", (req, res) => {
- res.sendFile(path.join(rootDir, `static/webui/translations/${req.params.file}`));
+ res.sendFile(path.join(baseDir, `static/webui/translations/${req.params.file}`));
});
export { webuiRouter };
diff --git a/src/services/configService.ts b/src/services/configService.ts
index b4566096..6ef2e96f 100644
--- a/src/services/configService.ts
+++ b/src/services/configService.ts
@@ -1,6 +1,7 @@
import fs from "fs";
import path from "path";
import { repoDir } from "@/src/helpers/pathHelper";
+import { args } from "@/src/helpers/commandLineArguments";
export interface IConfig {
mongodbUrl: string;
@@ -79,7 +80,7 @@ export interface IConfig {
};
}
-export const configPath = path.join(repoDir, process.argv[2] ?? "config.json");
+export const configPath = path.join(repoDir, args.configPath ?? "config.json");
export const config: IConfig = {
mongodbUrl: "mongodb://127.0.0.1:27017/openWF",
diff --git a/src/services/serversideVendorsService.ts b/src/services/serversideVendorsService.ts
index 774180d6..0e4b3856 100644
--- a/src/services/serversideVendorsService.ts
+++ b/src/services/serversideVendorsService.ts
@@ -1,5 +1,5 @@
import { unixTimesInMs } from "@/src/constants/timeConstants";
-import { isDev } from "@/src/helpers/pathHelper";
+import { args } from "@/src/helpers/commandLineArguments";
import { catBreadHash } from "@/src/helpers/stringHelpers";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { mixSeeds, SRng } from "@/src/services/rngService";
@@ -421,7 +421,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
return cacheEntry;
};
-if (isDev) {
+if (args.dev) {
if (
getCycleDuration(ExportVendors["/Lotus/Types/Game/VendorManifests/Hubs/TeshinHardModeVendorManifest"]) !=
unixTimesInMs.week
diff --git a/static/webui/script.js b/static/webui/script.js
index dfe4e096..6f2731c3 100644
--- a/static/webui/script.js
+++ b/static/webui/script.js
@@ -1,3 +1,13 @@
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-floating-promises */
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable no-undef */
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/explicit-function-return-type */
+
function openWebSocket() {
window.ws = new WebSocket("/custom/ws");
window.ws.onmessage = e => {
@@ -64,6 +74,7 @@ function doLoginRequest(succ_cb, fail_cb) {
time: parseInt(new Date() / 1000),
s: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==", // signature of some kind
lang: "en",
+ // eslint-disable-next-line no-loss-of-precision
date: 1501230947855458660, // ???
ClientType: registerSubmit ? "webui-register" : "webui",
PS: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==" // anti-cheat data
@@ -1697,7 +1708,9 @@ function doAcquireRiven() {
if (typeof fingerprint !== "object") {
fingerprint = JSON.parse(fingerprint);
}
- } catch (e) {}
+ } catch (e) {
+ /* empty */
+ }
if (
typeof fingerprint !== "object" ||
!("compat" in fingerprint) ||
@@ -1950,7 +1963,7 @@ function doAddAllMods() {
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
req.done(data => {
for (const modOwned of data.RawUpgrades) {
- if (modOwned.ItemCount ?? 1 > 0) {
+ if ((modOwned.ItemCount ?? 1) > 0) {
modsAll.delete(modOwned.ItemType);
}
}