asaihost-nodejs 0.0.5 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{InterventionLog-PZT2CCN3.es.js → InterventionLog-OPQ6VOBV.es.js} +3 -3
- package/dist/InterventionLog-WNVDQFAH.cjs +30 -0
- package/dist/{InterventionLog-CRP6YJVM.cjs.map → InterventionLog-WNVDQFAH.cjs.map} +1 -1
- package/dist/LogStore-AP4T2CFD.cjs +54 -0
- package/dist/{LogStore-7MTUQA4G.cjs.map → LogStore-AP4T2CFD.cjs.map} +1 -1
- package/dist/{LogStore-Q35YFNAY.es.js → LogStore-DWIPPRCA.es.js} +2 -2
- package/dist/asaihost-nodejs.cjs +580 -567
- package/dist/asaihost-nodejs.cjs.map +1 -1
- package/dist/asaihost-nodejs.d.cts +18 -2
- package/dist/asaihost-nodejs.d.ts +18 -2
- package/dist/asaihost-nodejs.es.js +273 -260
- package/dist/asaihost-nodejs.es.js.map +1 -1
- package/dist/{chunk-A6VJPLDD.es.js → chunk-5WJQD4RZ.es.js} +3 -3
- package/dist/{chunk-RIRKIYET.cjs → chunk-ARHPHWT5.cjs} +12 -12
- package/dist/{chunk-RIRKIYET.cjs.map → chunk-ARHPHWT5.cjs.map} +1 -1
- package/dist/{chunk-A5CDJGJI.es.js → chunk-BOIRAQXE.es.js} +1 -1
- package/dist/chunk-BOIRAQXE.es.js.map +1 -0
- package/dist/{chunk-LTEP4XB2.es.js → chunk-EC67M7RR.es.js} +115 -21
- package/dist/chunk-EC67M7RR.es.js.map +1 -0
- package/dist/{chunk-SB23ESX2.es.js → chunk-GCR56QH7.es.js} +2 -2
- package/dist/{chunk-H3K33HBA.cjs → chunk-GXOFLFFW.cjs} +1 -1
- package/dist/{chunk-H3K33HBA.cjs.map → chunk-GXOFLFFW.cjs.map} +1 -1
- package/dist/{chunk-TKJAHTPO.cjs → chunk-HR5JKN7Y.cjs} +161 -67
- package/dist/chunk-HR5JKN7Y.cjs.map +1 -0
- package/dist/{chunk-VUZO7DCA.es.js → chunk-N6LBKGML.es.js} +2 -2
- package/dist/{chunk-57UQJKSL.es.js → chunk-OTL2B4WS.es.js} +2 -2
- package/dist/{chunk-4E7Z5K5U.cjs → chunk-U2YJH2RW.cjs} +4 -4
- package/dist/{chunk-4E7Z5K5U.cjs.map → chunk-U2YJH2RW.cjs.map} +1 -1
- package/dist/{chunk-K2QPSQEV.cjs → chunk-WXW5DYNU.cjs} +9 -9
- package/dist/{chunk-K2QPSQEV.cjs.map → chunk-WXW5DYNU.cjs.map} +1 -1
- package/dist/{chunk-LXJMGLKW.cjs → chunk-ZK4O4Z2O.cjs} +20 -20
- package/dist/{chunk-LXJMGLKW.cjs.map → chunk-ZK4O4Z2O.cjs.map} +1 -1
- package/dist/intervention-hooks-4NAAAZK3.cjs +21 -0
- package/dist/{intervention-hooks-KF3SNB5Q.cjs.map → intervention-hooks-4NAAAZK3.cjs.map} +1 -1
- package/dist/{intervention-hooks-TCGIC4IV.es.js → intervention-hooks-QNA4IZT7.es.js} +4 -4
- package/dist/{password-4BABWAG4.es.js → password-4P7IZUDQ.es.js} +3 -3
- package/dist/password-MDYRL6ZD.cjs +20 -0
- package/dist/{password-PJHJRGPE.cjs.map → password-MDYRL6ZD.cjs.map} +1 -1
- package/dist/user-store-55HOLHEM.cjs +12 -0
- package/dist/{user-store-6J2PSEIN.cjs.map → user-store-55HOLHEM.cjs.map} +1 -1
- package/dist/{user-store-UC5URX3C.es.js → user-store-FXD2N55G.es.js} +3 -3
- package/package.json +1 -1
- package/dist/InterventionLog-CRP6YJVM.cjs +0 -30
- package/dist/LogStore-7MTUQA4G.cjs +0 -54
- package/dist/chunk-A5CDJGJI.es.js.map +0 -1
- package/dist/chunk-LTEP4XB2.es.js.map +0 -1
- package/dist/chunk-TKJAHTPO.cjs.map +0 -1
- package/dist/intervention-hooks-KF3SNB5Q.cjs +0 -21
- package/dist/password-PJHJRGPE.cjs +0 -20
- package/dist/user-store-6J2PSEIN.cjs +0 -12
- /package/dist/{InterventionLog-PZT2CCN3.es.js.map → InterventionLog-OPQ6VOBV.es.js.map} +0 -0
- /package/dist/{LogStore-Q35YFNAY.es.js.map → LogStore-DWIPPRCA.es.js.map} +0 -0
- /package/dist/{chunk-A6VJPLDD.es.js.map → chunk-5WJQD4RZ.es.js.map} +0 -0
- /package/dist/{chunk-SB23ESX2.es.js.map → chunk-GCR56QH7.es.js.map} +0 -0
- /package/dist/{chunk-VUZO7DCA.es.js.map → chunk-N6LBKGML.es.js.map} +0 -0
- /package/dist/{chunk-57UQJKSL.es.js.map → chunk-OTL2B4WS.es.js.map} +0 -0
- /package/dist/{intervention-hooks-TCGIC4IV.es.js.map → intervention-hooks-QNA4IZT7.es.js.map} +0 -0
- /package/dist/{password-4BABWAG4.es.js.map → password-4P7IZUDQ.es.js.map} +0 -0
- /package/dist/{user-store-UC5URX3C.es.js.map → user-store-FXD2N55G.es.js.map} +0 -0
|
@@ -4,17 +4,19 @@ import {
|
|
|
4
4
|
logSecurityConfigIntervention,
|
|
5
5
|
logSessionTerminate,
|
|
6
6
|
logUserRbacChange
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GCR56QH7.es.js";
|
|
8
8
|
import {
|
|
9
9
|
InterventionLog_exports
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-N6LBKGML.es.js";
|
|
11
11
|
import {
|
|
12
|
+
AsPath_exports,
|
|
12
13
|
LogStore_exports,
|
|
13
14
|
archiveInterventionYear,
|
|
14
15
|
exportLogContent,
|
|
15
16
|
getComplianceReport,
|
|
16
17
|
getEffectiveStoreType,
|
|
17
18
|
getLogStoreMeta,
|
|
19
|
+
getPrimaryServerRoot,
|
|
18
20
|
getUnifiedEntry,
|
|
19
21
|
getUnifiedStats,
|
|
20
22
|
groupsToInterventionFiles,
|
|
@@ -28,7 +30,7 @@ import {
|
|
|
28
30
|
queryUnifiedLogs,
|
|
29
31
|
readWebLogFromStore,
|
|
30
32
|
searchUnifiedLogs
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-EC67M7RR.es.js";
|
|
32
34
|
import {
|
|
33
35
|
W3C_ACCESS_FIELDS,
|
|
34
36
|
W3C_SERVER_FIELDS,
|
|
@@ -48,7 +50,7 @@ import {
|
|
|
48
50
|
secureCompare,
|
|
49
51
|
validatePasswordChange,
|
|
50
52
|
verifyPassword
|
|
51
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-OTL2B4WS.es.js";
|
|
52
54
|
import {
|
|
53
55
|
USER_LV,
|
|
54
56
|
applySecretsToHostConfig,
|
|
@@ -60,7 +62,7 @@ import {
|
|
|
60
62
|
resolveHttpsCertFromPaths,
|
|
61
63
|
stripForbiddenSecretsFromHostConfig,
|
|
62
64
|
validateAsaiSecrets
|
|
63
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-5WJQD4RZ.es.js";
|
|
64
66
|
import {
|
|
65
67
|
getDefaultResetPassword,
|
|
66
68
|
getPasswordPolicy,
|
|
@@ -73,7 +75,7 @@ import {
|
|
|
73
75
|
resolveRoleForLevel,
|
|
74
76
|
saveUserLevelConfig,
|
|
75
77
|
validatePasswordWithPolicy
|
|
76
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-BOIRAQXE.es.js";
|
|
77
79
|
import {
|
|
78
80
|
getDataServerForAsDb
|
|
79
81
|
} from "./chunk-ZQBHJRAO.es.js";
|
|
@@ -212,7 +214,7 @@ ${reason.name}: ${reason.message}`;
|
|
|
212
214
|
if (restartTimes.length > MAX_RESTARTS) {
|
|
213
215
|
try {
|
|
214
216
|
$asai.$log("NO_RESTART", "Process crashed too frequently, gracefully shutdown and wait for daemon restart.");
|
|
215
|
-
void import("./intervention-hooks-
|
|
217
|
+
void import("./intervention-hooks-QNA4IZT7.es.js").then(
|
|
216
218
|
({ logProcessGuardEvent }) => logProcessGuardEvent($asai, {
|
|
217
219
|
action: "crash_loop_shutdown",
|
|
218
220
|
detail: `${restartTimes.length} crashes in ${RESTART_WINDOW}ms window`,
|
|
@@ -254,7 +256,7 @@ ${reason.name}: ${reason.message}`;
|
|
|
254
256
|
}
|
|
255
257
|
__name(initProcess, "initProcess");
|
|
256
258
|
function gracefulShutdown($asai) {
|
|
257
|
-
void import("./intervention-hooks-
|
|
259
|
+
void import("./intervention-hooks-QNA4IZT7.es.js").then(
|
|
258
260
|
({ logProcessGuardEvent }) => logProcessGuardEvent($asai, {
|
|
259
261
|
action: "graceful_shutdown",
|
|
260
262
|
detail: "SIGTERM/SIGINT or crash guard triggered",
|
|
@@ -872,7 +874,7 @@ function initAsaiHostNodejs($asai, _opt) {
|
|
|
872
874
|
type: "CONFIG_WARN",
|
|
873
875
|
detail: "Using dev-only password; set ASAI_HOST_PASSWORD for production (IEC 62443-4-2 CR 1.7)"
|
|
874
876
|
});
|
|
875
|
-
void import("./intervention-hooks-
|
|
877
|
+
void import("./intervention-hooks-QNA4IZT7.es.js").then(
|
|
876
878
|
({ logSecurityConfigIntervention: logSecurityConfigIntervention2 }) => logSecurityConfigIntervention2($asai, {
|
|
877
879
|
section: "password",
|
|
878
880
|
detail: "dev-default-password detected at startup"
|
|
@@ -898,7 +900,7 @@ function scheduleLogComplianceCheck($asai) {
|
|
|
898
900
|
if (hours <= 0) return;
|
|
899
901
|
const ms = hours * 3600 * 1e3;
|
|
900
902
|
setInterval(() => {
|
|
901
|
-
void import("./LogStore-
|
|
903
|
+
void import("./LogStore-DWIPPRCA.es.js").then(
|
|
902
904
|
({ getComplianceReport: getComplianceReport2 }) => getComplianceReport2($asai, "prod")
|
|
903
905
|
).catch(() => void 0);
|
|
904
906
|
}, ms);
|
|
@@ -1458,11 +1460,11 @@ function createSkipChecker($asai) {
|
|
|
1458
1460
|
}
|
|
1459
1461
|
if (exact.size === 0 && prefixes.length === 0) return () => false;
|
|
1460
1462
|
return (url) => {
|
|
1461
|
-
const
|
|
1462
|
-
if (!
|
|
1463
|
-
if (exact.has(
|
|
1463
|
+
const path8 = normalizeRequestPath(url);
|
|
1464
|
+
if (!path8) return false;
|
|
1465
|
+
if (exact.has(path8)) return true;
|
|
1464
1466
|
for (let i = 0; i < prefixes.length; i++) {
|
|
1465
|
-
if (
|
|
1467
|
+
if (path8.startsWith(prefixes[i])) return true;
|
|
1466
1468
|
}
|
|
1467
1469
|
return false;
|
|
1468
1470
|
};
|
|
@@ -1582,10 +1584,10 @@ function getStaticBaseDirs($asai) {
|
|
|
1582
1584
|
bases.push(abs);
|
|
1583
1585
|
}
|
|
1584
1586
|
}, "add");
|
|
1587
|
+
if ($asai.serverRoot) add($asai.serverRoot);
|
|
1585
1588
|
if (Array.isArray($asai.runtimeBaseDirs)) {
|
|
1586
1589
|
for (const b of $asai.runtimeBaseDirs) add(b);
|
|
1587
1590
|
}
|
|
1588
|
-
if ($asai.serverRoot) add($asai.serverRoot);
|
|
1589
1591
|
if ($asai.pkgSnapshotDir) add($asai.pkgSnapshotDir);
|
|
1590
1592
|
return bases;
|
|
1591
1593
|
}
|
|
@@ -1652,6 +1654,11 @@ function parseUrlPath(requrl) {
|
|
|
1652
1654
|
}
|
|
1653
1655
|
__name(parseUrlPath, "parseUrlPath");
|
|
1654
1656
|
var STATIC_ASSET_PREFIXES = ["/assets/", "/webmodel/", "/assets/entry/", "/assets/chunk/"];
|
|
1657
|
+
function isMutableWebmodelConfig(urlPath) {
|
|
1658
|
+
const p = parseUrlPath(urlPath);
|
|
1659
|
+
return /^\/webmodel\/sys\/setting\/[^/]+\.json$/i.test(p);
|
|
1660
|
+
}
|
|
1661
|
+
__name(isMutableWebmodelConfig, "isMutableWebmodelConfig");
|
|
1655
1662
|
function isStaticAssetPath(urlPath, indexFile) {
|
|
1656
1663
|
const p = parseUrlPath(urlPath);
|
|
1657
1664
|
const base = p.split("/").pop() || "";
|
|
@@ -1660,9 +1667,10 @@ function isStaticAssetPath(urlPath, indexFile) {
|
|
|
1660
1667
|
return /\.(css|js|mjs|cjs|json|png|jpe?g|gif|svg|ico|woff2?|ttf|map|wasm|zip)(\?|$)/i.test(p);
|
|
1661
1668
|
}
|
|
1662
1669
|
__name(isStaticAssetPath, "isStaticAssetPath");
|
|
1663
|
-
function sendStaticBuffer(req, res, data, mimeType, mtimeMs, $asai) {
|
|
1670
|
+
function sendStaticBuffer(req, res, data, mimeType, mtimeMs, $asai, urlPath = "") {
|
|
1664
1671
|
const etag = `"${data.length}-${mtimeMs}"`;
|
|
1665
|
-
|
|
1672
|
+
const noCache = isMutableWebmodelConfig(urlPath);
|
|
1673
|
+
if (!noCache && req.headers["if-none-match"] === etag) {
|
|
1666
1674
|
res.writeHead(304);
|
|
1667
1675
|
res.end();
|
|
1668
1676
|
return;
|
|
@@ -1671,7 +1679,7 @@ function sendStaticBuffer(req, res, data, mimeType, mtimeMs, $asai) {
|
|
|
1671
1679
|
res.writeHead(200, {
|
|
1672
1680
|
"Content-Type": mimeType,
|
|
1673
1681
|
"Content-Length": data.length,
|
|
1674
|
-
"Cache-Control": "public, max-age=3600",
|
|
1682
|
+
"Cache-Control": noCache ? "no-cache, must-revalidate" : "public, max-age=3600",
|
|
1675
1683
|
ETag: etag,
|
|
1676
1684
|
"Last-Modified": new Date(mtimeMs).toUTCString()
|
|
1677
1685
|
});
|
|
@@ -1685,7 +1693,8 @@ function sendStaticBuffer(req, res, data, mimeType, mtimeMs, $asai) {
|
|
|
1685
1693
|
}
|
|
1686
1694
|
}
|
|
1687
1695
|
__name(sendStaticBuffer, "sendStaticBuffer");
|
|
1688
|
-
function serveStaticFile(req, res, foundPath, mimeType, stat, $asai) {
|
|
1696
|
+
function serveStaticFile(req, res, foundPath, mimeType, stat, $asai, urlPath = "") {
|
|
1697
|
+
const noCache = isMutableWebmodelConfig(urlPath);
|
|
1689
1698
|
if (stat.size <= STATIC_READ_MAX) {
|
|
1690
1699
|
fs6.readFile(foundPath, (err, data) => {
|
|
1691
1700
|
if (err) {
|
|
@@ -1696,13 +1705,13 @@ function serveStaticFile(req, res, foundPath, mimeType, stat, $asai) {
|
|
|
1696
1705
|
}
|
|
1697
1706
|
return;
|
|
1698
1707
|
}
|
|
1699
|
-
sendStaticBuffer(req, res, data, mimeType, stat.mtimeMs, $asai);
|
|
1708
|
+
sendStaticBuffer(req, res, data, mimeType, stat.mtimeMs, $asai, urlPath);
|
|
1700
1709
|
});
|
|
1701
1710
|
return;
|
|
1702
1711
|
}
|
|
1703
1712
|
const readStream = fs6.createReadStream(foundPath);
|
|
1704
1713
|
const etag = `"${stat.size}-${stat.mtimeMs}"`;
|
|
1705
|
-
if (req.headers["if-none-match"] === etag) {
|
|
1714
|
+
if (!noCache && req.headers["if-none-match"] === etag) {
|
|
1706
1715
|
readStream.destroy();
|
|
1707
1716
|
res.writeHead(304);
|
|
1708
1717
|
res.end();
|
|
@@ -1721,7 +1730,7 @@ function serveStaticFile(req, res, foundPath, mimeType, stat, $asai) {
|
|
|
1721
1730
|
try {
|
|
1722
1731
|
res.writeHead(200, {
|
|
1723
1732
|
"Content-Type": mimeType,
|
|
1724
|
-
"Cache-Control": "public, max-age=3600",
|
|
1733
|
+
"Cache-Control": noCache ? "no-cache, must-revalidate" : "public, max-age=3600",
|
|
1725
1734
|
ETag: etag,
|
|
1726
1735
|
"Last-Modified": stat.mtime.toUTCString()
|
|
1727
1736
|
});
|
|
@@ -1779,7 +1788,7 @@ function createStaticHandler(ctx) {
|
|
|
1779
1788
|
return;
|
|
1780
1789
|
}
|
|
1781
1790
|
const mimeType = hostcfg.mimetypes?.[nodePath2.extname(found.filePath)] || "application/octet-stream";
|
|
1782
|
-
serveStaticFile(req, res, found.filePath, mimeType, found.stat, $asai);
|
|
1791
|
+
serveStaticFile(req, res, found.filePath, mimeType, found.stat, $asai, processedUrl);
|
|
1783
1792
|
}, "showHostDirs");
|
|
1784
1793
|
return (req, res, url) => {
|
|
1785
1794
|
res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
|
|
@@ -2342,7 +2351,7 @@ async function attachServerUserLevel(req, $asai) {
|
|
|
2342
2351
|
if (!Array.isArray(userinfo) || !userinfo[0]) return;
|
|
2343
2352
|
const us = String(userinfo[0]);
|
|
2344
2353
|
try {
|
|
2345
|
-
const { createUserStore: createUserStore2 } = await import("./user-store-
|
|
2354
|
+
const { createUserStore: createUserStore2 } = await import("./user-store-FXD2N55G.es.js");
|
|
2346
2355
|
const user = await createUserStore2($asai).findByUsername(us);
|
|
2347
2356
|
if (user && user.status === "active") {
|
|
2348
2357
|
req._serverUser = { us: user.us, lv: user.lv, status: user.status };
|
|
@@ -2373,11 +2382,11 @@ function getSecurityConfig($asai) {
|
|
|
2373
2382
|
return $asai?.hostconfig?.security || {};
|
|
2374
2383
|
}
|
|
2375
2384
|
__name(getSecurityConfig, "getSecurityConfig");
|
|
2376
|
-
function pathMatchesPattern(
|
|
2385
|
+
function pathMatchesPattern(path8, pattern) {
|
|
2377
2386
|
if (pattern.endsWith("*")) {
|
|
2378
|
-
return
|
|
2387
|
+
return path8.startsWith(pattern.slice(0, -1));
|
|
2379
2388
|
}
|
|
2380
|
-
return
|
|
2389
|
+
return path8 === pattern;
|
|
2381
2390
|
}
|
|
2382
2391
|
__name(pathMatchesPattern, "pathMatchesPattern");
|
|
2383
2392
|
function isAuthSkipped($asai, pathname) {
|
|
@@ -2555,6 +2564,10 @@ function isRawUploadPost(url = "") {
|
|
|
2555
2564
|
return /\/api\/asaifile\/manage\/up(?:base64|binary)(?:batch)?\//.test(url);
|
|
2556
2565
|
}
|
|
2557
2566
|
__name(isRawUploadPost, "isRawUploadPost");
|
|
2567
|
+
function isPlainSourcePost(url = "") {
|
|
2568
|
+
return /\/api\/robotcode\//.test(url);
|
|
2569
|
+
}
|
|
2570
|
+
__name(isPlainSourcePost, "isPlainSourcePost");
|
|
2558
2571
|
function processPostPayload($asai, req, postdata, pm) {
|
|
2559
2572
|
let isAes = false;
|
|
2560
2573
|
let out = postdata;
|
|
@@ -2570,7 +2583,7 @@ function processPostPayload($asai, req, postdata, pm) {
|
|
|
2570
2583
|
}
|
|
2571
2584
|
}
|
|
2572
2585
|
const plainJson = typeof out === "string" && out.trimStart().startsWith("{");
|
|
2573
|
-
if (req?.Userinfo?.[2] && !plainJson && !isRawUploadPost(req?.url)) {
|
|
2586
|
+
if (req?.Userinfo?.[2] && !plainJson && !isRawUploadPost(req?.url) && !isPlainSourcePost(req?.url)) {
|
|
2574
2587
|
pm = req.Userinfo[2];
|
|
2575
2588
|
out = $asai.$lib.AsCode.asdecode(out, pm);
|
|
2576
2589
|
}
|
|
@@ -2660,83 +2673,95 @@ var Api_default = /* @__PURE__ */ __name(($asai, opt = {}) => {
|
|
|
2660
2673
|
const isTextPost = req.method === "POST" && req.url.indexOf("binary") === -1;
|
|
2661
2674
|
const bodyPromise = isTextPost ? readRequestBody(req, maxBody) : null;
|
|
2662
2675
|
void (async () => {
|
|
2663
|
-
let authResult;
|
|
2664
|
-
let rawBody = "";
|
|
2665
2676
|
try {
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
if (!authResult.ok) {
|
|
2678
|
-
releaseSlot();
|
|
2679
|
-
return sendAuthError(res, authResult);
|
|
2680
|
-
}
|
|
2681
|
-
let apiFn = $asai.hostserverapi[apiHandlerKey]?.($asai, query);
|
|
2682
|
-
if (!apiFn) {
|
|
2683
|
-
return sendError(res, 501, "Not Implemented");
|
|
2684
|
-
}
|
|
2685
|
-
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
2686
|
-
$asai.$log("API", req.method, urlParse.pathname, query);
|
|
2687
|
-
let qrdata;
|
|
2688
|
-
let postdata;
|
|
2689
|
-
if (req.url.indexOf("binary") === -1) {
|
|
2690
|
-
qrdata = query;
|
|
2691
|
-
if (req.method === "POST") {
|
|
2692
|
-
try {
|
|
2693
|
-
const processed = processPostPayload($asai, req, rawBody, pm);
|
|
2694
|
-
postdata = processed.postdata;
|
|
2695
|
-
pm = processed.pm;
|
|
2696
|
-
isAes = processed.isAes;
|
|
2697
|
-
} catch {
|
|
2698
|
-
return sendError(res, 400, "AES decrypt failed");
|
|
2699
|
-
}
|
|
2700
|
-
if (apiFn?.post && typeof apiFn?.post === "function") {
|
|
2701
|
-
const optTmp = { qrdata, data: postdata, pm };
|
|
2702
|
-
if (isAes || $asai.$lib.aesfns?.allaes) {
|
|
2703
|
-
optTmp.resAES = $asai.$lib.aesfns?.resAES;
|
|
2704
|
-
}
|
|
2705
|
-
apiFn.post(req, res, hostdir, optTmp);
|
|
2706
|
-
} else {
|
|
2707
|
-
res.end(typeof postdata === "string" ? postdata : JSON.stringify(postdata ?? ""));
|
|
2708
|
-
}
|
|
2709
|
-
} else if (req.method === "GET") {
|
|
2710
|
-
if (apiFn?.get && typeof apiFn?.get === "function") {
|
|
2711
|
-
const optTmp = { qrdata, data: qrdata, pm };
|
|
2712
|
-
if (isAes || $asai.$lib.aesfns?.allaes) {
|
|
2713
|
-
optTmp.resAES = $asai.$lib.aesfns?.resAES;
|
|
2714
|
-
}
|
|
2715
|
-
apiFn.get(req, res, hostdir, optTmp);
|
|
2716
|
-
} else {
|
|
2717
|
-
res.end(JSON.stringify(qrdata));
|
|
2677
|
+
let authResult;
|
|
2678
|
+
let rawBody = "";
|
|
2679
|
+
try {
|
|
2680
|
+
[authResult, rawBody] = await Promise.all([
|
|
2681
|
+
validateHttpAuthAsync(req, $asai, pathname),
|
|
2682
|
+
bodyPromise ?? Promise.resolve("")
|
|
2683
|
+
]);
|
|
2684
|
+
} catch (err) {
|
|
2685
|
+
releaseSlot();
|
|
2686
|
+
if (err?.message === "PAYLOAD_TOO_LARGE") {
|
|
2687
|
+
return sendError(res, 413, "Payload Too Large");
|
|
2718
2688
|
}
|
|
2689
|
+
return sendError(res, 400, err?.message || "Bad Request");
|
|
2719
2690
|
}
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2691
|
+
if (!authResult.ok) {
|
|
2692
|
+
releaseSlot();
|
|
2693
|
+
return sendAuthError(res, authResult);
|
|
2694
|
+
}
|
|
2695
|
+
let apiFn = $asai.hostserverapi[apiHandlerKey]?.($asai, query);
|
|
2696
|
+
if (!apiFn) {
|
|
2697
|
+
return sendError(res, 501, "Not Implemented");
|
|
2723
2698
|
}
|
|
2724
|
-
|
|
2725
|
-
|
|
2699
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
2700
|
+
$asai.$log("API", req.method, urlParse.pathname, query);
|
|
2701
|
+
let qrdata;
|
|
2702
|
+
let postdata;
|
|
2703
|
+
if (req.url.indexOf("binary") === -1) {
|
|
2704
|
+
qrdata = query;
|
|
2705
|
+
if (req.method === "POST") {
|
|
2706
|
+
try {
|
|
2707
|
+
const processed = processPostPayload($asai, req, rawBody, pm);
|
|
2708
|
+
postdata = processed.postdata;
|
|
2709
|
+
pm = processed.pm;
|
|
2710
|
+
isAes = processed.isAes;
|
|
2711
|
+
} catch {
|
|
2712
|
+
return sendError(res, 400, "AES decrypt failed");
|
|
2713
|
+
}
|
|
2726
2714
|
if (apiFn?.post && typeof apiFn?.post === "function") {
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
}
|
|
2715
|
+
const optTmp = { qrdata, data: postdata, pm };
|
|
2716
|
+
if (isAes || $asai.$lib.aesfns?.allaes) {
|
|
2717
|
+
optTmp.resAES = $asai.$lib.aesfns?.resAES;
|
|
2718
|
+
}
|
|
2719
|
+
apiFn.post(req, res, hostdir, optTmp);
|
|
2731
2720
|
} else {
|
|
2732
|
-
res.end(
|
|
2721
|
+
res.end(typeof postdata === "string" ? postdata : JSON.stringify(postdata ?? ""));
|
|
2733
2722
|
}
|
|
2734
|
-
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2723
|
+
} else if (req.method === "GET") {
|
|
2724
|
+
if (apiFn?.get && typeof apiFn?.get === "function") {
|
|
2725
|
+
const optTmp = { qrdata, data: qrdata, pm };
|
|
2726
|
+
if (isAes || $asai.$lib.aesfns?.allaes) {
|
|
2727
|
+
optTmp.resAES = $asai.$lib.aesfns?.resAES;
|
|
2728
|
+
}
|
|
2729
|
+
apiFn.get(req, res, hostdir, optTmp);
|
|
2730
|
+
} else {
|
|
2731
|
+
res.end(JSON.stringify(qrdata));
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
} else {
|
|
2735
|
+
if (Object.keys(query)?.length) {
|
|
2736
|
+
qrdata = query;
|
|
2737
|
+
}
|
|
2738
|
+
if (req.method === "POST") {
|
|
2739
|
+
$asai.$lib.AsNodeTool.upBinary(req).then((postdata2) => {
|
|
2740
|
+
if (apiFn?.post && typeof apiFn?.post === "function") {
|
|
2741
|
+
apiFn.post(req, res, hostdir, {
|
|
2742
|
+
qrdata,
|
|
2743
|
+
data: postdata2
|
|
2744
|
+
});
|
|
2745
|
+
} else {
|
|
2746
|
+
res.end(postdata2);
|
|
2747
|
+
}
|
|
2748
|
+
}).catch((err) => {
|
|
2749
|
+
return sendError(res, 400, "Invalid content type");
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2737
2752
|
}
|
|
2753
|
+
} catch (err) {
|
|
2754
|
+
releaseSlot();
|
|
2755
|
+
if (!res.headersSent) {
|
|
2756
|
+
return sendError(res, 500, err?.message || "Internal Server Error");
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
})().catch((err) => {
|
|
2760
|
+
releaseSlot();
|
|
2761
|
+
if (!res.headersSent) {
|
|
2762
|
+
sendError(res, 500, err?.message || "Internal Server Error");
|
|
2738
2763
|
}
|
|
2739
|
-
})
|
|
2764
|
+
});
|
|
2740
2765
|
} else {
|
|
2741
2766
|
$asai.$log("API", req.method, req.url);
|
|
2742
2767
|
}
|
|
@@ -2870,27 +2895,28 @@ var Sys_default = /* @__PURE__ */ __name(($asai, opt = {}) => {
|
|
|
2870
2895
|
}
|
|
2871
2896
|
const urlPath = (req.url || "").split("?")[0];
|
|
2872
2897
|
void (async () => {
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
handler
|
|
2883
|
-
|
|
2884
|
-
|
|
2898
|
+
try {
|
|
2899
|
+
const authResult = await validateHttpAuthAsync(req, $asai, urlPath);
|
|
2900
|
+
if (!authResult.ok) {
|
|
2901
|
+
return sendAuthError(res, authResult);
|
|
2902
|
+
}
|
|
2903
|
+
const handler = $asai.hostserversys[handlerKey]?.($asai);
|
|
2904
|
+
if (!handler) {
|
|
2905
|
+
return sendError(res, 500, "Handler Initialization Failed");
|
|
2906
|
+
}
|
|
2907
|
+
if (handler?.show && typeof handler?.show === "function") {
|
|
2908
|
+
handler.show(req, res, hostdir);
|
|
2909
|
+
} else {
|
|
2910
|
+
res.end("postdata");
|
|
2911
|
+
}
|
|
2912
|
+
} catch (err) {
|
|
2913
|
+
return sendError(res, 500, err?.message || "Internal Server Error");
|
|
2885
2914
|
}
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
});
|
|
2890
|
-
res.end(req.url);
|
|
2891
|
-
} else {
|
|
2915
|
+
})().catch((err) => {
|
|
2916
|
+
if (!res.headersSent) {
|
|
2917
|
+
sendError(res, 500, err?.message || "Internal Server Error");
|
|
2892
2918
|
}
|
|
2893
|
-
})
|
|
2919
|
+
});
|
|
2894
2920
|
}
|
|
2895
2921
|
__name(sysWork, "sysWork");
|
|
2896
2922
|
return { sysWork };
|
|
@@ -4052,7 +4078,7 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4052
4078
|
passwordChangedAt: Date.now(),
|
|
4053
4079
|
passHistory
|
|
4054
4080
|
});
|
|
4055
|
-
logSecurityEvent($asai, { type: "
|
|
4081
|
+
logSecurityEvent($asai, { type: "AUTH_SUCCESS", path: url, method: "POST", user: us, ip, detail: "password_changed" });
|
|
4056
4082
|
return sendSuccess(res, { ok: true }, opt);
|
|
4057
4083
|
} catch (err) {
|
|
4058
4084
|
return sendFail(res, err?.message || err, opt);
|
|
@@ -4085,7 +4111,7 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4085
4111
|
passwordChangedAt: Date.now(),
|
|
4086
4112
|
passHistory: "[]"
|
|
4087
4113
|
});
|
|
4088
|
-
logSecurityEvent($asai, { type: "
|
|
4114
|
+
logSecurityEvent($asai, { type: "AUTH_SUCCESS", path: url, method: "POST", user: us, ip, detail: "register_ok" });
|
|
4089
4115
|
return sendSuccess(res, { user: publicUser($asai, user) }, opt);
|
|
4090
4116
|
} catch (err) {
|
|
4091
4117
|
const msg = err?.message || String(err);
|
|
@@ -4139,7 +4165,7 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4139
4165
|
const session = buildSessionRecord($asai, us, ip);
|
|
4140
4166
|
session.lastActivityAt = Date.now();
|
|
4141
4167
|
await store.addSession(session);
|
|
4142
|
-
logSecurityEvent($asai, { type: "
|
|
4168
|
+
logSecurityEvent($asai, { type: "AUTH_SUCCESS", path: url, method: "POST", user: us, ip, detail: "login_ok" });
|
|
4143
4169
|
return sendSuccess(
|
|
4144
4170
|
res,
|
|
4145
4171
|
{
|
|
@@ -4157,9 +4183,18 @@ var login_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
4157
4183
|
if (url.startsWith("/api/user/login/logout/")) {
|
|
4158
4184
|
try {
|
|
4159
4185
|
const bodySid = body.sessionId ? sanitizeString(body.sessionId, 64) : "";
|
|
4160
|
-
if (bodySid) await store.removeSession(bodySid);
|
|
4161
4186
|
const us = req?.Userinfo?.[0];
|
|
4162
|
-
if (
|
|
4187
|
+
if (bodySid) {
|
|
4188
|
+
if (!us) {
|
|
4189
|
+
return sendErr(res, "AUTH_MISSING", void 0, opt);
|
|
4190
|
+
}
|
|
4191
|
+
const sessions = await store.getSessions();
|
|
4192
|
+
const target = sessions.find((s) => s.id === bodySid);
|
|
4193
|
+
if (target && target.us === us) {
|
|
4194
|
+
await store.removeSession(bodySid);
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
if (us) logSecurityEvent($asai, { type: "AUTH_SUCCESS", path: url, method: "POST", user: String(us), ip, detail: "logout" });
|
|
4163
4198
|
return sendSuccess(res, "ok", opt);
|
|
4164
4199
|
} catch (err) {
|
|
4165
4200
|
return sendFail(res, err?.message || err, opt);
|
|
@@ -4499,10 +4534,10 @@ var As_default = {
|
|
|
4499
4534
|
return relativePath;
|
|
4500
4535
|
},
|
|
4501
4536
|
//创建多层文件夹 同步
|
|
4502
|
-
ensureDir(
|
|
4537
|
+
ensureDir(fs11, relativePath) {
|
|
4503
4538
|
const absPathDir = this.toDirPath(relativePath);
|
|
4504
4539
|
const absPath = this.toAbsolutePath(relativePath);
|
|
4505
|
-
if (!
|
|
4540
|
+
if (!fs11.existsSync(absPath)) {
|
|
4506
4541
|
let pathTmp = "";
|
|
4507
4542
|
absPathDir.split("/").forEach((el) => {
|
|
4508
4543
|
if (el) {
|
|
@@ -4510,8 +4545,8 @@ var As_default = {
|
|
|
4510
4545
|
pathTmp += "/";
|
|
4511
4546
|
}
|
|
4512
4547
|
pathTmp += el;
|
|
4513
|
-
if (!
|
|
4514
|
-
if (!
|
|
4548
|
+
if (!fs11.existsSync(pathTmp)) {
|
|
4549
|
+
if (!fs11.mkdirSync(pathTmp, { recursive: true })) {
|
|
4515
4550
|
return absPath;
|
|
4516
4551
|
}
|
|
4517
4552
|
}
|
|
@@ -4520,10 +4555,10 @@ var As_default = {
|
|
|
4520
4555
|
}
|
|
4521
4556
|
return absPath;
|
|
4522
4557
|
},
|
|
4523
|
-
makeDir(
|
|
4558
|
+
makeDir(fs11, filePaths) {
|
|
4524
4559
|
return new Promise((resolve6, reject) => {
|
|
4525
4560
|
try {
|
|
4526
|
-
const newPath = this.ensureDir(
|
|
4561
|
+
const newPath = this.ensureDir(fs11, filePaths);
|
|
4527
4562
|
resolve6(newPath);
|
|
4528
4563
|
} catch (err) {
|
|
4529
4564
|
reject(err);
|
|
@@ -4976,8 +5011,36 @@ var AsDb_default = /* @__PURE__ */ __name(($asai, cfg) => {
|
|
|
4976
5011
|
return resdb;
|
|
4977
5012
|
}
|
|
4978
5013
|
__name(dbFresh, "dbFresh");
|
|
5014
|
+
function normalizeFileSelectRow(row) {
|
|
5015
|
+
const nameKey = cfg.field?.data?.[0] || "name";
|
|
5016
|
+
const contentKey = cfg.field?.data?.[1] || "content";
|
|
5017
|
+
if (!row || typeof row !== "object") return row;
|
|
5018
|
+
const out = { ...row };
|
|
5019
|
+
if (out[nameKey] != null) {
|
|
5020
|
+
out[nameKey] = bareFileName(String(out[nameKey]));
|
|
5021
|
+
}
|
|
5022
|
+
const raw = out[contentKey];
|
|
5023
|
+
if (raw != null && typeof raw !== "string") {
|
|
5024
|
+
out[contentKey] = JSON.stringify(raw);
|
|
5025
|
+
}
|
|
5026
|
+
return out;
|
|
5027
|
+
}
|
|
5028
|
+
__name(normalizeFileSelectRow, "normalizeFileSelectRow");
|
|
5029
|
+
function isFileSingleNameSelect(params) {
|
|
5030
|
+
return cfg?.type === "file" && params?.type === "select" && !!params?.where?.length;
|
|
5031
|
+
}
|
|
5032
|
+
__name(isFileSingleNameSelect, "isFileSingleNameSelect");
|
|
4979
5033
|
function normalizeSelectResult(params, resdb) {
|
|
4980
5034
|
let data = resdb;
|
|
5035
|
+
if (isFileSingleNameSelect(params)) {
|
|
5036
|
+
if (Array.isArray(data)) {
|
|
5037
|
+
return data.map(normalizeFileSelectRow);
|
|
5038
|
+
}
|
|
5039
|
+
if (data && typeof data === "object") {
|
|
5040
|
+
return [normalizeFileSelectRow(data)];
|
|
5041
|
+
}
|
|
5042
|
+
return data;
|
|
5043
|
+
}
|
|
4981
5044
|
if (params?.where?.length && Array.isArray(data) && data.length === 1) {
|
|
4982
5045
|
data = data[0];
|
|
4983
5046
|
}
|
|
@@ -5092,6 +5155,7 @@ var AsDb_default = /* @__PURE__ */ __name(($asai, cfg) => {
|
|
|
5092
5155
|
}, "default");
|
|
5093
5156
|
|
|
5094
5157
|
// src/sysserver/lib/common/reqWork.ts
|
|
5158
|
+
import * as path4 from "path";
|
|
5095
5159
|
var reqWork_default = /* @__PURE__ */ __name(($asai) => {
|
|
5096
5160
|
function hostDefault2(mod) {
|
|
5097
5161
|
if (mod && typeof mod === "object" && "default" in mod) {
|
|
@@ -5103,7 +5167,32 @@ var reqWork_default = /* @__PURE__ */ __name(($asai) => {
|
|
|
5103
5167
|
__name(hostDefault2, "hostDefault");
|
|
5104
5168
|
function getPathFromOpt(opt) {
|
|
5105
5169
|
const rawPath = opt.qrdata?.path || opt.data?.path;
|
|
5106
|
-
|
|
5170
|
+
if (!rawPath) {
|
|
5171
|
+
throw new Error("Missing path");
|
|
5172
|
+
}
|
|
5173
|
+
const decoded = decodeURIComponent(String(rawPath));
|
|
5174
|
+
if (path4.isAbsolute(decoded)) {
|
|
5175
|
+
return path4.normalize(decoded);
|
|
5176
|
+
}
|
|
5177
|
+
const rel = decoded.replace(/^\.(\/)?/, "");
|
|
5178
|
+
const serverRoot = $asai?.serverRoot;
|
|
5179
|
+
if (serverRoot && rel) {
|
|
5180
|
+
const absRoot = path4.resolve(serverRoot);
|
|
5181
|
+
const abs = path4.resolve(absRoot, rel);
|
|
5182
|
+
const relCheck = path4.relative(absRoot, abs);
|
|
5183
|
+
if (relCheck === "" || !relCheck.startsWith("..") && !path4.isAbsolute(relCheck)) {
|
|
5184
|
+
return abs;
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
const roots = $asai?.asaihost?.getHostAllowedRoots?.($asai?.hostconfig) || [];
|
|
5188
|
+
if (!roots.length) {
|
|
5189
|
+
const fallback = $asai?.serverRoot || process.cwd();
|
|
5190
|
+
if (fallback) roots.push(fallback);
|
|
5191
|
+
}
|
|
5192
|
+
if (!$asai?.asaihost?.resolvePathUnderRoots) {
|
|
5193
|
+
throw new Error("Path resolver unavailable");
|
|
5194
|
+
}
|
|
5195
|
+
return $asai.asaihost.resolvePathUnderRoots(decoded, roots);
|
|
5107
5196
|
}
|
|
5108
5197
|
__name(getPathFromOpt, "getPathFromOpt");
|
|
5109
5198
|
function sendSuccess(res, data, opt) {
|
|
@@ -5152,17 +5241,17 @@ __export(AsFs_exports, {
|
|
|
5152
5241
|
writeJson: () => writeJson
|
|
5153
5242
|
});
|
|
5154
5243
|
import fs9 from "fs/promises";
|
|
5155
|
-
import
|
|
5244
|
+
import path5 from "path";
|
|
5156
5245
|
async function ensureFile(filePath) {
|
|
5157
|
-
const normalized =
|
|
5158
|
-
await fs9.mkdir(
|
|
5246
|
+
const normalized = path5.normalize(filePath);
|
|
5247
|
+
await fs9.mkdir(path5.dirname(normalized), { recursive: true });
|
|
5159
5248
|
const fh = await fs9.open(normalized, "a");
|
|
5160
5249
|
await fh.close();
|
|
5161
5250
|
}
|
|
5162
5251
|
__name(ensureFile, "ensureFile");
|
|
5163
5252
|
async function pathExists(filePath) {
|
|
5164
5253
|
try {
|
|
5165
|
-
await fs9.access(
|
|
5254
|
+
await fs9.access(path5.normalize(filePath));
|
|
5166
5255
|
return true;
|
|
5167
5256
|
} catch {
|
|
5168
5257
|
return false;
|
|
@@ -5170,7 +5259,7 @@ async function pathExists(filePath) {
|
|
|
5170
5259
|
}
|
|
5171
5260
|
__name(pathExists, "pathExists");
|
|
5172
5261
|
async function readJson(filePath) {
|
|
5173
|
-
const raw = await fs9.readFile(
|
|
5262
|
+
const raw = await fs9.readFile(path5.normalize(filePath), "utf8");
|
|
5174
5263
|
return JSON.parse(raw);
|
|
5175
5264
|
}
|
|
5176
5265
|
__name(readJson, "readJson");
|
|
@@ -5181,26 +5270,26 @@ function resolvePathUnderBase(baseDir, relPath) {
|
|
|
5181
5270
|
if (relPath.includes("\0")) {
|
|
5182
5271
|
throw new Error("Invalid path");
|
|
5183
5272
|
}
|
|
5184
|
-
const base =
|
|
5185
|
-
const target =
|
|
5186
|
-
const rel =
|
|
5187
|
-
if (rel.startsWith("..") ||
|
|
5273
|
+
const base = path5.resolve(baseDir);
|
|
5274
|
+
const target = path5.resolve(base, relPath.replace(/\\/g, "/"));
|
|
5275
|
+
const rel = path5.relative(base, target);
|
|
5276
|
+
if (rel.startsWith("..") || path5.isAbsolute(rel)) {
|
|
5188
5277
|
throw new Error("Path not allowed");
|
|
5189
5278
|
}
|
|
5190
5279
|
return target;
|
|
5191
5280
|
}
|
|
5192
5281
|
__name(resolvePathUnderBase, "resolvePathUnderBase");
|
|
5193
5282
|
async function readLogDir(dir) {
|
|
5194
|
-
const resolved =
|
|
5283
|
+
const resolved = path5.resolve(dir);
|
|
5195
5284
|
const stats = await fs9.stat(resolved);
|
|
5196
5285
|
if (!stats.isDirectory()) {
|
|
5197
5286
|
throw new Error("Not a directory");
|
|
5198
5287
|
}
|
|
5199
|
-
const dirName =
|
|
5288
|
+
const dirName = path5.basename(resolved);
|
|
5200
5289
|
const entries = await fs9.readdir(resolved, { withFileTypes: true });
|
|
5201
5290
|
const children = await Promise.all(
|
|
5202
5291
|
entries.map(async (entry) => {
|
|
5203
|
-
const fullPath =
|
|
5292
|
+
const fullPath = path5.join(resolved, entry.name);
|
|
5204
5293
|
const st = await fs9.stat(fullPath);
|
|
5205
5294
|
const dot = entry.name.lastIndexOf(".");
|
|
5206
5295
|
const type = entry.isDirectory() ? "dir" : dot > -1 ? entry.name.substring(dot) : "file";
|
|
@@ -5208,7 +5297,7 @@ async function readLogDir(dir) {
|
|
|
5208
5297
|
name: entry.name,
|
|
5209
5298
|
size: st.size,
|
|
5210
5299
|
time: st.mtime.toISOString(),
|
|
5211
|
-
path:
|
|
5300
|
+
path: path5.normalize(fullPath),
|
|
5212
5301
|
type,
|
|
5213
5302
|
created: st.birthtime.toISOString(),
|
|
5214
5303
|
permissions: st.mode.toString(8).slice(-3)
|
|
@@ -5219,7 +5308,7 @@ async function readLogDir(dir) {
|
|
|
5219
5308
|
name: dirName,
|
|
5220
5309
|
size: stats.size,
|
|
5221
5310
|
time: stats.mtime.toISOString(),
|
|
5222
|
-
path:
|
|
5311
|
+
path: path5.normalize(resolved),
|
|
5223
5312
|
type: "dir",
|
|
5224
5313
|
created: stats.birthtime.toISOString(),
|
|
5225
5314
|
permissions: stats.mode.toString(8).slice(-3),
|
|
@@ -5229,7 +5318,7 @@ async function readLogDir(dir) {
|
|
|
5229
5318
|
__name(readLogDir, "readLogDir");
|
|
5230
5319
|
async function removeFile(filePath) {
|
|
5231
5320
|
try {
|
|
5232
|
-
await fs9.unlink(
|
|
5321
|
+
await fs9.unlink(path5.normalize(filePath));
|
|
5233
5322
|
} catch (err) {
|
|
5234
5323
|
if (err?.code !== "ENOENT") throw err;
|
|
5235
5324
|
}
|
|
@@ -5237,13 +5326,13 @@ async function removeFile(filePath) {
|
|
|
5237
5326
|
__name(removeFile, "removeFile");
|
|
5238
5327
|
var remove = removeFile;
|
|
5239
5328
|
async function write(filePath, content) {
|
|
5240
|
-
const normalized =
|
|
5241
|
-
await fs9.mkdir(
|
|
5329
|
+
const normalized = path5.normalize(filePath);
|
|
5330
|
+
await fs9.mkdir(path5.dirname(normalized), { recursive: true });
|
|
5242
5331
|
await fs9.writeFile(normalized, content, "utf8");
|
|
5243
5332
|
}
|
|
5244
5333
|
__name(write, "write");
|
|
5245
5334
|
async function read(filePath) {
|
|
5246
|
-
return fs9.readFile(
|
|
5335
|
+
return fs9.readFile(path5.normalize(filePath), "utf8");
|
|
5247
5336
|
}
|
|
5248
5337
|
__name(read, "read");
|
|
5249
5338
|
async function writeJson(filePath, data) {
|
|
@@ -5251,83 +5340,6 @@ async function writeJson(filePath, data) {
|
|
|
5251
5340
|
}
|
|
5252
5341
|
__name(writeJson, "writeJson");
|
|
5253
5342
|
|
|
5254
|
-
// src/sysserver/lib/common/AsPath.ts
|
|
5255
|
-
var AsPath_exports = {};
|
|
5256
|
-
__export(AsPath_exports, {
|
|
5257
|
-
getEntryDir: () => getEntryDir,
|
|
5258
|
-
getExecDir: () => getExecDir,
|
|
5259
|
-
getPkgSnapshotDir: () => getPkgSnapshotDir,
|
|
5260
|
-
getPrimaryServerRoot: () => getPrimaryServerRoot,
|
|
5261
|
-
getRuntimeBaseDirs: () => getRuntimeBaseDirs,
|
|
5262
|
-
isPkgRuntime: () => isPkgRuntime
|
|
5263
|
-
});
|
|
5264
|
-
import * as fs10 from "fs";
|
|
5265
|
-
import * as nodePath4 from "path";
|
|
5266
|
-
function isPkgRuntime() {
|
|
5267
|
-
return typeof process.pkg !== "undefined";
|
|
5268
|
-
}
|
|
5269
|
-
__name(isPkgRuntime, "isPkgRuntime");
|
|
5270
|
-
function getPkgSnapshotDir() {
|
|
5271
|
-
if (!isPkgRuntime()) return void 0;
|
|
5272
|
-
const entry = process.pkg?.entrypoint ?? process.pkg?.defaultEntrypoint;
|
|
5273
|
-
if (!entry) return void 0;
|
|
5274
|
-
return nodePath4.resolve(nodePath4.dirname(entry));
|
|
5275
|
-
}
|
|
5276
|
-
__name(getPkgSnapshotDir, "getPkgSnapshotDir");
|
|
5277
|
-
function getEntryDir() {
|
|
5278
|
-
const snapshot = getPkgSnapshotDir();
|
|
5279
|
-
if (snapshot) return snapshot;
|
|
5280
|
-
const entry = process.argv[1];
|
|
5281
|
-
if (!entry) {
|
|
5282
|
-
return nodePath4.dirname(process.execPath);
|
|
5283
|
-
}
|
|
5284
|
-
return nodePath4.resolve(nodePath4.dirname(entry));
|
|
5285
|
-
}
|
|
5286
|
-
__name(getEntryDir, "getEntryDir");
|
|
5287
|
-
function getExecDir() {
|
|
5288
|
-
return nodePath4.dirname(process.execPath);
|
|
5289
|
-
}
|
|
5290
|
-
__name(getExecDir, "getExecDir");
|
|
5291
|
-
function getRuntimeBaseDirs() {
|
|
5292
|
-
const bases = [];
|
|
5293
|
-
const seen = /* @__PURE__ */ new Set();
|
|
5294
|
-
const add = /* @__PURE__ */ __name((p) => {
|
|
5295
|
-
if (!p) return;
|
|
5296
|
-
const abs = nodePath4.resolve(p);
|
|
5297
|
-
if (!seen.has(abs)) {
|
|
5298
|
-
seen.add(abs);
|
|
5299
|
-
bases.push(abs);
|
|
5300
|
-
}
|
|
5301
|
-
}, "add");
|
|
5302
|
-
add(process.cwd());
|
|
5303
|
-
add(getExecDir());
|
|
5304
|
-
if (isPkgRuntime()) {
|
|
5305
|
-
add(getPkgSnapshotDir());
|
|
5306
|
-
} else {
|
|
5307
|
-
const entryDir = getEntryDir();
|
|
5308
|
-
if (entryDir !== getExecDir()) {
|
|
5309
|
-
add(entryDir);
|
|
5310
|
-
}
|
|
5311
|
-
}
|
|
5312
|
-
return bases;
|
|
5313
|
-
}
|
|
5314
|
-
__name(getRuntimeBaseDirs, "getRuntimeBaseDirs");
|
|
5315
|
-
function getPrimaryServerRoot() {
|
|
5316
|
-
for (const base of getRuntimeBaseDirs()) {
|
|
5317
|
-
try {
|
|
5318
|
-
if (fs10.statSync(nodePath4.join(base, "websys")).isDirectory()) {
|
|
5319
|
-
return base;
|
|
5320
|
-
}
|
|
5321
|
-
} catch {
|
|
5322
|
-
}
|
|
5323
|
-
}
|
|
5324
|
-
if (isPkgRuntime()) {
|
|
5325
|
-
return getExecDir();
|
|
5326
|
-
}
|
|
5327
|
-
return getEntryDir();
|
|
5328
|
-
}
|
|
5329
|
-
__name(getPrimaryServerRoot, "getPrimaryServerRoot");
|
|
5330
|
-
|
|
5331
5343
|
// src/sysserver/lib/index.ts
|
|
5332
5344
|
var lib_default = {
|
|
5333
5345
|
As: As_default,
|
|
@@ -5356,7 +5368,7 @@ __export(common_exports, {
|
|
|
5356
5368
|
toSetObject: () => toSetObject,
|
|
5357
5369
|
toWherePairs: () => toWherePairs
|
|
5358
5370
|
});
|
|
5359
|
-
import * as
|
|
5371
|
+
import * as path6 from "path";
|
|
5360
5372
|
function promisifySqlDb(query, sql) {
|
|
5361
5373
|
return new Promise((resolve6, reject) => {
|
|
5362
5374
|
query(sql, (err, result) => {
|
|
@@ -5421,11 +5433,11 @@ function toInsertRows(sql) {
|
|
|
5421
5433
|
}
|
|
5422
5434
|
__name(toInsertRows, "toInsertRows");
|
|
5423
5435
|
function isPathInside(baseDir, targetPath) {
|
|
5424
|
-
const base =
|
|
5425
|
-
const target =
|
|
5426
|
-
const
|
|
5427
|
-
if (!
|
|
5428
|
-
return !
|
|
5436
|
+
const base = path6.resolve(baseDir);
|
|
5437
|
+
const target = path6.resolve(targetPath);
|
|
5438
|
+
const relative5 = path6.relative(base, target);
|
|
5439
|
+
if (!relative5) return true;
|
|
5440
|
+
return !relative5.startsWith("..") && !path6.isAbsolute(relative5);
|
|
5429
5441
|
}
|
|
5430
5442
|
__name(isPathInside, "isPathInside");
|
|
5431
5443
|
function joinTablePath(table, ...segments) {
|
|
@@ -5606,8 +5618,8 @@ var Sql_default = {
|
|
|
5606
5618
|
};
|
|
5607
5619
|
|
|
5608
5620
|
// src/sysserver/db/src/file/Index.ts
|
|
5609
|
-
import * as
|
|
5610
|
-
import * as
|
|
5621
|
+
import * as fs10 from "fs";
|
|
5622
|
+
import * as path7 from "path";
|
|
5611
5623
|
function dbDriver(opt = {}) {
|
|
5612
5624
|
const { Sql, DbCommon } = opt;
|
|
5613
5625
|
const { isPathInside: isPathInside2, joinTablePath: joinTablePath2 } = DbCommon;
|
|
@@ -5620,22 +5632,23 @@ function dbDriver(opt = {}) {
|
|
|
5620
5632
|
this.fileExt = config.ext === ".*" ? "" : config.ext || "";
|
|
5621
5633
|
this.fileDel = (config.del || 0) !== 0;
|
|
5622
5634
|
this.createDir = config.create || false;
|
|
5623
|
-
|
|
5635
|
+
const root = config.$asai?.serverRoot || getPrimaryServerRoot();
|
|
5636
|
+
this.baseDirAbs = path7.resolve(root, config.dir);
|
|
5624
5637
|
}
|
|
5625
5638
|
dbLog(...args) {
|
|
5626
5639
|
(this.config?.$asai?.$log || console.log)("FILE", ...args);
|
|
5627
5640
|
}
|
|
5628
5641
|
checkFile(file) {
|
|
5629
|
-
return
|
|
5642
|
+
return fs10.existsSync(this.getAbsPath(file, false));
|
|
5630
5643
|
}
|
|
5631
5644
|
/** 解析相对路径并限制在数据根目录内,防止路径穿越(跨平台) */
|
|
5632
5645
|
resolvePath(relPath) {
|
|
5633
5646
|
if (!relPath) {
|
|
5634
5647
|
return this.baseDirAbs;
|
|
5635
5648
|
}
|
|
5636
|
-
const abs =
|
|
5649
|
+
const abs = path7.isAbsolute(relPath) ? path7.normalize(relPath) : path7.resolve(this.baseDirAbs, relPath);
|
|
5637
5650
|
if (!isPathInside2(this.baseDirAbs, abs)) {
|
|
5638
|
-
|
|
5651
|
+
throw new Error("Path not allowed");
|
|
5639
5652
|
}
|
|
5640
5653
|
return abs;
|
|
5641
5654
|
}
|
|
@@ -5647,15 +5660,15 @@ function dbDriver(opt = {}) {
|
|
|
5647
5660
|
if (!relPath) {
|
|
5648
5661
|
return "";
|
|
5649
5662
|
}
|
|
5650
|
-
return
|
|
5663
|
+
return path7.isAbsolute(relPath) ? path7.relative(this.baseDirAbs, relPath) : relPath;
|
|
5651
5664
|
}
|
|
5652
5665
|
ensureDir(relPath) {
|
|
5653
|
-
const
|
|
5654
|
-
const dirPath =
|
|
5666
|
+
const relative5 = this.normalizeRelPath(relPath);
|
|
5667
|
+
const dirPath = path7.dirname(relative5);
|
|
5655
5668
|
const absDir = this.resolvePath(dirPath === "." ? "" : dirPath);
|
|
5656
|
-
if (this.createDir && !
|
|
5669
|
+
if (this.createDir && !fs10.existsSync(absDir)) {
|
|
5657
5670
|
this.dbLog("mkdir", "[MKDIR]", absDir);
|
|
5658
|
-
|
|
5671
|
+
fs10.mkdirSync(absDir, { recursive: true });
|
|
5659
5672
|
}
|
|
5660
5673
|
return absDir;
|
|
5661
5674
|
}
|
|
@@ -5671,34 +5684,34 @@ function dbDriver(opt = {}) {
|
|
|
5671
5684
|
}
|
|
5672
5685
|
deldir(relativePath) {
|
|
5673
5686
|
const absPath = this.resolvePath(relativePath);
|
|
5674
|
-
if (!
|
|
5687
|
+
if (!fs10.existsSync(absPath)) {
|
|
5675
5688
|
return;
|
|
5676
5689
|
}
|
|
5677
5690
|
this.dbLog("delete", "[RMDIR]", absPath);
|
|
5678
|
-
const entries =
|
|
5691
|
+
const entries = fs10.readdirSync(absPath, { withFileTypes: true });
|
|
5679
5692
|
for (const entry of entries) {
|
|
5680
|
-
const current =
|
|
5693
|
+
const current = path7.join(absPath, entry.name);
|
|
5681
5694
|
if (entry.isDirectory()) {
|
|
5682
|
-
this.deldir(
|
|
5695
|
+
this.deldir(path7.join(relativePath, entry.name));
|
|
5683
5696
|
} else {
|
|
5684
5697
|
this.dbLog("delete", "[UNLINK]", current);
|
|
5685
|
-
|
|
5698
|
+
fs10.unlinkSync(current);
|
|
5686
5699
|
}
|
|
5687
5700
|
}
|
|
5688
|
-
|
|
5701
|
+
fs10.rmdirSync(absPath);
|
|
5689
5702
|
}
|
|
5690
5703
|
getReadPath(file, sql) {
|
|
5691
5704
|
const candidates = [];
|
|
5692
5705
|
if (sql?.filename) {
|
|
5693
|
-
candidates.push({ dir:
|
|
5694
|
-
candidates.push({ dir:
|
|
5706
|
+
candidates.push({ dir: path7.join(file, sql.filename) });
|
|
5707
|
+
candidates.push({ dir: path7.join(file + ".delete" + this.fileExt, sql.filename) });
|
|
5695
5708
|
} else {
|
|
5696
5709
|
candidates.push({ dir: file });
|
|
5697
5710
|
candidates.push({ dir: file + this.fileExt + ".delete" });
|
|
5698
5711
|
}
|
|
5699
5712
|
for (const candidate of candidates) {
|
|
5700
5713
|
const abs = this.getAbsPath(candidate.dir, false);
|
|
5701
|
-
if (
|
|
5714
|
+
if (fs10.existsSync(abs)) {
|
|
5702
5715
|
return { path: abs, dir: candidate.dir };
|
|
5703
5716
|
}
|
|
5704
5717
|
}
|
|
@@ -5710,13 +5723,13 @@ function dbDriver(opt = {}) {
|
|
|
5710
5723
|
return { path: "", dir: read2.dir };
|
|
5711
5724
|
}
|
|
5712
5725
|
if (sql?.filename) {
|
|
5713
|
-
return { path:
|
|
5726
|
+
return { path: path7.dirname(read2.path), dir: path7.dirname(read2.dir) };
|
|
5714
5727
|
}
|
|
5715
5728
|
return { path: read2.path, dir: read2.dir };
|
|
5716
5729
|
}
|
|
5717
5730
|
getNewPath(file, sql) {
|
|
5718
5731
|
if (sql?.filename) {
|
|
5719
|
-
return this.getAbsPath(
|
|
5732
|
+
return this.getAbsPath(path7.join(file, sql.filename), true);
|
|
5720
5733
|
}
|
|
5721
5734
|
return this.getAbsPath(file, true);
|
|
5722
5735
|
}
|
|
@@ -5724,7 +5737,7 @@ function dbDriver(opt = {}) {
|
|
|
5724
5737
|
try {
|
|
5725
5738
|
const filePath = sql?.type === "insert" ? this.getNewPath(file, sql) : this.getReadPath(file, sql).path || this.getNewPath(file, sql);
|
|
5726
5739
|
this.dbLog("write", "[WRITE]", filePath);
|
|
5727
|
-
|
|
5740
|
+
fs10.writeFileSync(filePath, data, "utf8");
|
|
5728
5741
|
return "ok";
|
|
5729
5742
|
} catch (e) {
|
|
5730
5743
|
this.dbLog("write failed", "[WRITE ERROR]", e);
|
|
@@ -5738,7 +5751,7 @@ function dbDriver(opt = {}) {
|
|
|
5738
5751
|
return { error: "empty" };
|
|
5739
5752
|
}
|
|
5740
5753
|
this.dbLog("read", "[READ]", read2.path);
|
|
5741
|
-
const data =
|
|
5754
|
+
const data = fs10.readFileSync(read2.path, { encoding }) || "";
|
|
5742
5755
|
const fileName = this.fileExt && read2.dir.endsWith(this.fileExt) ? read2.dir : read2.dir + this.fileExt;
|
|
5743
5756
|
return [{ data, file: fileName }];
|
|
5744
5757
|
} catch (e) {
|
|
@@ -5755,12 +5768,12 @@ function dbDriver(opt = {}) {
|
|
|
5755
5768
|
if (this.fileDel && sql?.deltrue) {
|
|
5756
5769
|
const target = del.path + ".delete" + this.fileExt;
|
|
5757
5770
|
this.dbLog("soft delete", "[SOFT DELETE]", `${del.path} -> ${target}`);
|
|
5758
|
-
|
|
5771
|
+
fs10.renameSync(del.path, target);
|
|
5759
5772
|
} else if (sql?.filename) {
|
|
5760
5773
|
this.deldir(del.dir);
|
|
5761
5774
|
} else {
|
|
5762
5775
|
this.dbLog("delete", "[DELETE]", del.path);
|
|
5763
|
-
|
|
5776
|
+
fs10.unlinkSync(del.path);
|
|
5764
5777
|
}
|
|
5765
5778
|
return "ok";
|
|
5766
5779
|
} catch (e) {
|
|
@@ -5779,11 +5792,11 @@ function dbDriver(opt = {}) {
|
|
|
5779
5792
|
const original = del.path.replace(new RegExp(`.delete${extPattern}$`), "");
|
|
5780
5793
|
if (original !== del.path) {
|
|
5781
5794
|
this.dbLog("restore", "[RESTORE]", `${del.path} -> ${original}`);
|
|
5782
|
-
|
|
5795
|
+
fs10.renameSync(del.path, original);
|
|
5783
5796
|
}
|
|
5784
5797
|
} else {
|
|
5785
5798
|
this.dbLog("force delete", "[FORCE DELETE]", del.path);
|
|
5786
|
-
|
|
5799
|
+
fs10.unlinkSync(del.path);
|
|
5787
5800
|
}
|
|
5788
5801
|
return "ok";
|
|
5789
5802
|
} catch (e) {
|
|
@@ -5797,7 +5810,7 @@ function dbDriver(opt = {}) {
|
|
|
5797
5810
|
this.dbLog("list", "[LIST]", absDir);
|
|
5798
5811
|
let entries;
|
|
5799
5812
|
try {
|
|
5800
|
-
entries =
|
|
5813
|
+
entries = fs10.readdirSync(absDir, { withFileTypes: true });
|
|
5801
5814
|
} catch {
|
|
5802
5815
|
return sql?.list ? { open: [], delete: [] } : [];
|
|
5803
5816
|
}
|
|
@@ -5809,9 +5822,9 @@ function dbDriver(opt = {}) {
|
|
|
5809
5822
|
const isDelete = fileName.endsWith(deleteSuffix);
|
|
5810
5823
|
const baseName = isDelete ? fileName.slice(0, -deleteSuffix.length) : fileName;
|
|
5811
5824
|
if (this.fileExt && !baseName.endsWith(this.fileExt)) continue;
|
|
5812
|
-
const fullPath =
|
|
5825
|
+
const fullPath = path7.join(absDir, fileName);
|
|
5813
5826
|
try {
|
|
5814
|
-
const data =
|
|
5827
|
+
const data = fs10.readFileSync(fullPath, "utf8");
|
|
5815
5828
|
const entryData = { data, file: baseName };
|
|
5816
5829
|
if (isDelete) {
|
|
5817
5830
|
if (sql?.list) result.delete.push(entryData);
|
|
@@ -6577,7 +6590,7 @@ var initAsaiHostNodejs2 = {
|
|
|
6577
6590
|
createTransportDataHandler,
|
|
6578
6591
|
wireTransportConnectionLogs
|
|
6579
6592
|
};
|
|
6580
|
-
var PLUGIN_VERSION = true ? "0.0.
|
|
6593
|
+
var PLUGIN_VERSION = true ? "0.0.8" : "0.0.1";
|
|
6581
6594
|
var index_default = initAsaiHostNodejs2;
|
|
6582
6595
|
export {
|
|
6583
6596
|
Index_default as AsaiCommon,
|