返回提交历史
Modified
docker-entrypoint.sh
+1
-1
Modified
package-lock.json
+13
-525
Modified
package.json
+5
-3
Added
scripts/dev.js
+49
-0
Modified
scripts/update-translations.js
+1
-0
Added
src/controllers/custom/webuiFileChangeDetectedController.ts
+11
-0
Added
src/helpers/commandLineArguments.ts
+23
-0
Modified
src/helpers/pathHelper.ts
+1
-2
Modified
src/routes/custom.ts
+3
-1
Modified
src/routes/webui.ts
+12
-9
Modified
src/services/configService.ts
+2
-1
Modified
src/services/serversideVendorsService.ts
+2
-2
Modified
static/webui/script.js
+15
-2
XFEstudio/SpaceNinjaServer
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>
f84cc54c
代码差异
13 个文件
+138
-546
@@ -5,4 +5,4 @@ if [ ! -f conf/config.json ]; then
5
5
jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config.json.example > /app/conf/config.json
6
6
fi
7
7
8
exec npm run start conf/config.json
8
exec npm run start -- --configPath conf/config.json
@@ -5,8 +5,10 @@
5
5
"main": "index.ts",
6
6
"scripts": {
7
7
"start": "node --enable-source-maps --import ./build/src/pathman.js build/src/index.js",
8
"dev": "ts-node-dev --openssl-legacy-provider -r tsconfig-paths/register src/index.ts ",
9
8
"build": "tsc --incremental --sourceMap && ncp static/webui build/static/webui",
9
"build:dev": "tsc --incremental --sourceMap",
10
"build-and-start": "npm run build && npm run start",
11
"dev": "node scripts/dev.js",
10
12
"verify": "tsgo --noEmit",
11
13
"lint": "eslint --ext .ts .",
12
14
"lint:ci": "eslint --ext .ts --rule \"prettier/prettier: off\" .",
@@ -36,10 +38,10 @@
36
38
"@typescript-eslint/eslint-plugin": "^8.28.0",
37
39
"@typescript-eslint/parser": "^8.28.0",
38
40
"@typescript/native-preview": "^7.0.0-dev.20250523.1",
41
"chokidar": "^4.0.3",
39
42
"eslint": "^8",
40
43
"eslint-plugin-prettier": "^5.2.5",
41
44
"prettier": "^3.5.3",
42
"ts-node-dev": "^2.0.0",
43
"tsconfig-paths": "^4.2.0"
45
"tree-kill": "^1.2.2"
44
46
}
45
47
}
@@ -0,0 +1,49 @@
1
/* eslint-disable */
2
const { spawn } = require("child_process");
3
const chokidar = require("chokidar");
4
const kill = require("tree-kill");
5
6
let secret = "";
7
for (let i = 0; i != 10; ++i) {
8
secret += String.fromCharCode(Math.floor(Math.random() * 26) + 0x41);
9
}
10
11
const args = [...process.argv].splice(2);
12
args.push("--dev");
13
args.push("--secret");
14
args.push(secret);
15
16
let buildproc, runproc;
17
function run(changedFile) {
18
if (changedFile) {
19
console.log(`Change to ${changedFile} detected`);
20
}
21
22
if (buildproc) {
23
kill(buildproc.pid);
24
buildproc = undefined;
25
}
26
if (runproc) {
27
kill(runproc.pid);
28
runproc = undefined;
29
}
30
31
buildproc = spawn("npm", ["run", "build:dev"], { stdio: "inherit", shell: true });
32
buildproc.on("exit", code => {
33
buildproc = undefined;
34
if (code === 0) {
35
runproc = spawn("npm", ["run", "start", "--", ...args], { stdio: "inherit", shell: true });
36
runproc.on("exit", () => {
37
runproc = undefined;
38
});
39
}
40
});
41
}
42
43
run();
44
chokidar.watch("src").on("change", run);
45
chokidar.watch("static/fixed_responses").on("change", run);
46
47
chokidar.watch("static/webui").on("change", () => {
48
fetch("http://localhost/custom/webuiFileChangeDetected?secret=" + secret);
49
});
@@ -1,6 +1,7 @@
1
1
// Based on https://onlyg.it/OpenWF/Translations/src/branch/main/update.php
2
2
// Converted via ChatGPT-4o
3
3
4
/* eslint-disable */
4
5
const fs = require("fs");
5
6
6
7
function extractStrings(content) {
@@ -0,0 +1,11 @@
1
import { args } from "@/src/helpers/commandLineArguments";
2
import { config } from "@/src/services/configService";
3
import { sendWsBroadcast } from "@/src/services/webService";
4
import { RequestHandler } from "express";
5
6
export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {
7
if (args.dev && args.secret && req.query.secret == args.secret) {
8
sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } });
9
}
10
res.end();
11
};
@@ -0,0 +1,23 @@
1
interface IArguments {
2
configPath?: string;
3
dev?: boolean;
4
secret?: string;
5
}
6
7
export const args: IArguments = {};
8
9
for (let i = 2; i < process.argv.length; ) {
10
switch (process.argv[i++]) {
11
case "--configPath":
12
args.configPath = process.argv[i++];
13
break;
14
15
case "--dev":
16
args.dev = true;
17
break;
18
19
case "--secret":
20
args.secret = process.argv[i++];
21
break;
22
}
23
}
@@ -1,5 +1,4 @@
1
1
import path from "path";
2
2
3
3
export const rootDir = path.join(__dirname, "../..");
4
export const isDev = path.basename(rootDir) != "build";
5
export const repoDir = isDev ? rootDir : path.join(rootDir, "..");
4
export const repoDir = path.basename(rootDir) != "build" ? rootDir : path.join(rootDir, "..");
@@ -11,6 +11,7 @@ import { renameAccountController } from "@/src/controllers/custom/renameAccountC
11
11
import { ircDroppedController } from "@/src/controllers/custom/ircDroppedController";
12
12
import { unlockAllIntrinsicsController } from "@/src/controllers/custom/unlockAllIntrinsicsController";
13
13
import { addMissingMaxRankModsController } from "@/src/controllers/custom/addMissingMaxRankModsController";
14
import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webuiFileChangeDetectedController";
14
15
15
16
import { createAccountController } from "@/src/controllers/custom/createAccountController";
16
17
import { createMessageController } from "@/src/controllers/custom/createMessageController";
@@ -20,10 +21,10 @@ import { addXpController } from "@/src/controllers/custom/addXpController";
20
21
import { importController } from "@/src/controllers/custom/importController";
21
22
import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController";
22
23
import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
24
import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
23
25
24
26
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
25
27
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
26
import { setBoosterController } from "../controllers/custom/setBoosterController";
27
28
28
29
const customRouter = express.Router();
29
30
@@ -38,6 +39,7 @@ customRouter.get("/renameAccount", renameAccountController);
38
39
customRouter.get("/ircDropped", ircDroppedController);
39
40
customRouter.get("/unlockAllIntrinsics", unlockAllIntrinsicsController);
40
41
customRouter.get("/addMissingMaxRankMods", addMissingMaxRankModsController);
42
customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
41
43
42
44
customRouter.post("/createAccount", createAccountController);
43
45
customRouter.post("/createMessage", createMessageController);
@@ -1,6 +1,9 @@
1
1
import express from "express";
2
2
import path from "path";
3
3
import { repoDir, rootDir } from "@/src/helpers/pathHelper";
4
import { args } from "@/src/helpers/commandLineArguments";
5
6
const baseDir = args.dev ? repoDir : rootDir;
4
7
5
8
const webuiRouter = express.Router();
6
9
@@ -19,29 +22,29 @@ webuiRouter.use("/webui", (req, res, next) => {
19
22
20
23
// Serve virtual routes
21
24
webuiRouter.get("/webui/inventory", (_req, res) => {
22
res.sendFile(path.join(rootDir, "static/webui/index.html"));
25
res.sendFile(path.join(baseDir, "static/webui/index.html"));
23
26
});
24
27
webuiRouter.get(/webui\/powersuit\/(.+)/, (_req, res) => {
25
res.sendFile(path.join(rootDir, "static/webui/index.html"));
28
res.sendFile(path.join(baseDir, "static/webui/index.html"));
26
29
});
27
30
webuiRouter.get("/webui/mods", (_req, res) => {
28
res.sendFile(path.join(rootDir, "static/webui/index.html"));
31
res.sendFile(path.join(baseDir, "static/webui/index.html"));
29
32
});
30
33
webuiRouter.get("/webui/settings", (_req, res) => {
31
res.sendFile(path.join(rootDir, "static/webui/index.html"));
34
res.sendFile(path.join(baseDir, "static/webui/index.html"));
32
35
});
33
36
webuiRouter.get("/webui/quests", (_req, res) => {
34
res.sendFile(path.join(rootDir, "static/webui/index.html"));
37
res.sendFile(path.join(baseDir, "static/webui/index.html"));
35
38
});
36
39
webuiRouter.get("/webui/cheats", (_req, res) => {
37
res.sendFile(path.join(rootDir, "static/webui/index.html"));
40
res.sendFile(path.join(baseDir, "static/webui/index.html"));
38
41
});
39
42
webuiRouter.get("/webui/import", (_req, res) => {
40
res.sendFile(path.join(rootDir, "static/webui/index.html"));
43
res.sendFile(path.join(baseDir, "static/webui/index.html"));
41
44
});
42
45
43
46
// Serve static files
44
webuiRouter.use("/webui", express.static(path.join(rootDir, "static/webui")));
47
webuiRouter.use("/webui", express.static(path.join(baseDir, "static/webui")));
45
48
46
49
// Serve favicon
47
50
webuiRouter.get("/favicon.ico", (_req, res) => {
@@ -58,7 +61,7 @@ webuiRouter.get("/webui/riven-tool/RivenParser.js", (_req, res) => {
58
61
59
62
// Serve translations
60
63
webuiRouter.get("/translations/:file", (req, res) => {
61
res.sendFile(path.join(rootDir, `static/webui/translations/${req.params.file}`));
64
res.sendFile(path.join(baseDir, `static/webui/translations/${req.params.file}`));
62
65
});
63
66
64
67
export { webuiRouter };
@@ -1,6 +1,7 @@
1
1
import fs from "fs";
2
2
import path from "path";
3
3
import { repoDir } from "@/src/helpers/pathHelper";
4
import { args } from "@/src/helpers/commandLineArguments";
4
5
5
6
export interface IConfig {
6
7
mongodbUrl: string;
@@ -79,7 +80,7 @@ export interface IConfig {
79
80
};
80
81
}
81
82
82
export const configPath = path.join(repoDir, process.argv[2] ?? "config.json");
83
export const configPath = path.join(repoDir, args.configPath ?? "config.json");
83
84
84
85
export const config: IConfig = {
85
86
mongodbUrl: "mongodb://127.0.0.1:27017/openWF",
@@ -1,5 +1,5 @@
1
1
import { unixTimesInMs } from "@/src/constants/timeConstants";
2
import { isDev } from "@/src/helpers/pathHelper";
2
import { args } from "@/src/helpers/commandLineArguments";
3
3
import { catBreadHash } from "@/src/helpers/stringHelpers";
4
4
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
5
5
import { mixSeeds, SRng } from "@/src/services/rngService";
@@ -421,7 +421,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
421
421
return cacheEntry;
422
422
};
423
423
424
if (isDev) {
424
if (args.dev) {
425
425
if (
426
426
getCycleDuration(ExportVendors["/Lotus/Types/Game/VendorManifests/Hubs/TeshinHardModeVendorManifest"]) !=
427
427
unixTimesInMs.week
@@ -1,3 +1,13 @@
1
/* eslint-disable @typescript-eslint/no-unsafe-return */
2
/* eslint-disable @typescript-eslint/no-floating-promises */
3
/* eslint-disable @typescript-eslint/no-unused-vars */
4
/* eslint-disable @typescript-eslint/no-unsafe-argument */
5
/* eslint-disable no-undef */
6
/* eslint-disable @typescript-eslint/no-unsafe-call */
7
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
8
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
9
/* eslint-disable @typescript-eslint/explicit-function-return-type */
10
1
11
function openWebSocket() {
2
12
window.ws = new WebSocket("/custom/ws");
3
13
window.ws.onmessage = e => {
@@ -64,6 +74,7 @@ function doLoginRequest(succ_cb, fail_cb) {
64
74
time: parseInt(new Date() / 1000),
65
75
s: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==", // signature of some kind
66
76
lang: "en",
77
// eslint-disable-next-line no-loss-of-precision
67
78
date: 1501230947855458660, // ???
68
79
ClientType: registerSubmit ? "webui-register" : "webui",
69
80
PS: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==" // anti-cheat data
@@ -1697,7 +1708,9 @@ function doAcquireRiven() {
1697
1708
if (typeof fingerprint !== "object") {
1698
1709
fingerprint = JSON.parse(fingerprint);
1699
1710
}
1700
} catch (e) {}
1711
} catch (e) {
1712
/* empty */
1713
}
1701
1714
if (
1702
1715
typeof fingerprint !== "object" ||
1703
1716
!("compat" in fingerprint) ||
@@ -1950,7 +1963,7 @@ function doAddAllMods() {
1950
1963
const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
1951
1964
req.done(data => {
1952
1965
for (const modOwned of data.RawUpgrades) {
1953
if (modOwned.ItemCount ?? 1 > 0) {
1966
if ((modOwned.ItemCount ?? 1) > 0) {
1954
1967
modsAll.delete(modOwned.ItemType);
1955
1968
}
1956
1969
}