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.
Files changed (59) hide show
  1. package/dist/{InterventionLog-PZT2CCN3.es.js → InterventionLog-OPQ6VOBV.es.js} +3 -3
  2. package/dist/InterventionLog-WNVDQFAH.cjs +30 -0
  3. package/dist/{InterventionLog-CRP6YJVM.cjs.map → InterventionLog-WNVDQFAH.cjs.map} +1 -1
  4. package/dist/LogStore-AP4T2CFD.cjs +54 -0
  5. package/dist/{LogStore-7MTUQA4G.cjs.map → LogStore-AP4T2CFD.cjs.map} +1 -1
  6. package/dist/{LogStore-Q35YFNAY.es.js → LogStore-DWIPPRCA.es.js} +2 -2
  7. package/dist/asaihost-nodejs.cjs +580 -567
  8. package/dist/asaihost-nodejs.cjs.map +1 -1
  9. package/dist/asaihost-nodejs.d.cts +18 -2
  10. package/dist/asaihost-nodejs.d.ts +18 -2
  11. package/dist/asaihost-nodejs.es.js +273 -260
  12. package/dist/asaihost-nodejs.es.js.map +1 -1
  13. package/dist/{chunk-A6VJPLDD.es.js → chunk-5WJQD4RZ.es.js} +3 -3
  14. package/dist/{chunk-RIRKIYET.cjs → chunk-ARHPHWT5.cjs} +12 -12
  15. package/dist/{chunk-RIRKIYET.cjs.map → chunk-ARHPHWT5.cjs.map} +1 -1
  16. package/dist/{chunk-A5CDJGJI.es.js → chunk-BOIRAQXE.es.js} +1 -1
  17. package/dist/chunk-BOIRAQXE.es.js.map +1 -0
  18. package/dist/{chunk-LTEP4XB2.es.js → chunk-EC67M7RR.es.js} +115 -21
  19. package/dist/chunk-EC67M7RR.es.js.map +1 -0
  20. package/dist/{chunk-SB23ESX2.es.js → chunk-GCR56QH7.es.js} +2 -2
  21. package/dist/{chunk-H3K33HBA.cjs → chunk-GXOFLFFW.cjs} +1 -1
  22. package/dist/{chunk-H3K33HBA.cjs.map → chunk-GXOFLFFW.cjs.map} +1 -1
  23. package/dist/{chunk-TKJAHTPO.cjs → chunk-HR5JKN7Y.cjs} +161 -67
  24. package/dist/chunk-HR5JKN7Y.cjs.map +1 -0
  25. package/dist/{chunk-VUZO7DCA.es.js → chunk-N6LBKGML.es.js} +2 -2
  26. package/dist/{chunk-57UQJKSL.es.js → chunk-OTL2B4WS.es.js} +2 -2
  27. package/dist/{chunk-4E7Z5K5U.cjs → chunk-U2YJH2RW.cjs} +4 -4
  28. package/dist/{chunk-4E7Z5K5U.cjs.map → chunk-U2YJH2RW.cjs.map} +1 -1
  29. package/dist/{chunk-K2QPSQEV.cjs → chunk-WXW5DYNU.cjs} +9 -9
  30. package/dist/{chunk-K2QPSQEV.cjs.map → chunk-WXW5DYNU.cjs.map} +1 -1
  31. package/dist/{chunk-LXJMGLKW.cjs → chunk-ZK4O4Z2O.cjs} +20 -20
  32. package/dist/{chunk-LXJMGLKW.cjs.map → chunk-ZK4O4Z2O.cjs.map} +1 -1
  33. package/dist/intervention-hooks-4NAAAZK3.cjs +21 -0
  34. package/dist/{intervention-hooks-KF3SNB5Q.cjs.map → intervention-hooks-4NAAAZK3.cjs.map} +1 -1
  35. package/dist/{intervention-hooks-TCGIC4IV.es.js → intervention-hooks-QNA4IZT7.es.js} +4 -4
  36. package/dist/{password-4BABWAG4.es.js → password-4P7IZUDQ.es.js} +3 -3
  37. package/dist/password-MDYRL6ZD.cjs +20 -0
  38. package/dist/{password-PJHJRGPE.cjs.map → password-MDYRL6ZD.cjs.map} +1 -1
  39. package/dist/user-store-55HOLHEM.cjs +12 -0
  40. package/dist/{user-store-6J2PSEIN.cjs.map → user-store-55HOLHEM.cjs.map} +1 -1
  41. package/dist/{user-store-UC5URX3C.es.js → user-store-FXD2N55G.es.js} +3 -3
  42. package/package.json +1 -1
  43. package/dist/InterventionLog-CRP6YJVM.cjs +0 -30
  44. package/dist/LogStore-7MTUQA4G.cjs +0 -54
  45. package/dist/chunk-A5CDJGJI.es.js.map +0 -1
  46. package/dist/chunk-LTEP4XB2.es.js.map +0 -1
  47. package/dist/chunk-TKJAHTPO.cjs.map +0 -1
  48. package/dist/intervention-hooks-KF3SNB5Q.cjs +0 -21
  49. package/dist/password-PJHJRGPE.cjs +0 -20
  50. package/dist/user-store-6J2PSEIN.cjs +0 -12
  51. /package/dist/{InterventionLog-PZT2CCN3.es.js.map → InterventionLog-OPQ6VOBV.es.js.map} +0 -0
  52. /package/dist/{LogStore-Q35YFNAY.es.js.map → LogStore-DWIPPRCA.es.js.map} +0 -0
  53. /package/dist/{chunk-A6VJPLDD.es.js.map → chunk-5WJQD4RZ.es.js.map} +0 -0
  54. /package/dist/{chunk-SB23ESX2.es.js.map → chunk-GCR56QH7.es.js.map} +0 -0
  55. /package/dist/{chunk-VUZO7DCA.es.js.map → chunk-N6LBKGML.es.js.map} +0 -0
  56. /package/dist/{chunk-57UQJKSL.es.js.map → chunk-OTL2B4WS.es.js.map} +0 -0
  57. /package/dist/{intervention-hooks-TCGIC4IV.es.js.map → intervention-hooks-QNA4IZT7.es.js.map} +0 -0
  58. /package/dist/{password-4BABWAG4.es.js.map → password-4P7IZUDQ.es.js.map} +0 -0
  59. /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-SB23ESX2.es.js";
7
+ } from "./chunk-GCR56QH7.es.js";
8
8
  import {
9
9
  InterventionLog_exports
10
- } from "./chunk-VUZO7DCA.es.js";
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-LTEP4XB2.es.js";
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-57UQJKSL.es.js";
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-A6VJPLDD.es.js";
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-A5CDJGJI.es.js";
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-TCGIC4IV.es.js").then(
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-TCGIC4IV.es.js").then(
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-TCGIC4IV.es.js").then(
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-Q35YFNAY.es.js").then(
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 path7 = normalizeRequestPath(url);
1462
- if (!path7) return false;
1463
- if (exact.has(path7)) return true;
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 (path7.startsWith(prefixes[i])) return true;
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
- if (req.headers["if-none-match"] === etag) {
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-UC5URX3C.es.js");
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(path7, pattern) {
2385
+ function pathMatchesPattern(path8, pattern) {
2377
2386
  if (pattern.endsWith("*")) {
2378
- return path7.startsWith(pattern.slice(0, -1));
2387
+ return path8.startsWith(pattern.slice(0, -1));
2379
2388
  }
2380
- return path7 === pattern;
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
- [authResult, rawBody] = await Promise.all([
2667
- validateHttpAuthAsync(req, $asai, pathname),
2668
- bodyPromise ?? Promise.resolve("")
2669
- ]);
2670
- } catch (err) {
2671
- releaseSlot();
2672
- if (err?.message === "PAYLOAD_TOO_LARGE") {
2673
- return sendError(res, 413, "Payload Too Large");
2674
- }
2675
- return sendError(res, 400, err?.message || "Bad Request");
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
- } else {
2721
- if (Object.keys(query)?.length) {
2722
- qrdata = query;
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
- if (req.method === "POST") {
2725
- $asai.$lib.AsNodeTool.upBinary(req).then((postdata2) => {
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
- apiFn.post(req, res, hostdir, {
2728
- qrdata,
2729
- data: postdata2
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(postdata2);
2721
+ res.end(typeof postdata === "string" ? postdata : JSON.stringify(postdata ?? ""));
2733
2722
  }
2734
- }).catch((err) => {
2735
- return sendError(res, 400, "Invalid content type");
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
- const authResult = await validateHttpAuthAsync(req, $asai, urlPath);
2874
- if (!authResult.ok) {
2875
- return sendAuthError(res, authResult);
2876
- }
2877
- const handler = $asai.hostserversys[handlerKey]?.($asai);
2878
- if (!handler) {
2879
- return sendError(res, 500, "Handler Initialization Failed");
2880
- }
2881
- if (handler?.show && typeof handler?.show === "function") {
2882
- handler.show(req, res, hostdir);
2883
- } else {
2884
- res.end("postdata");
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
- if (!handler) {
2887
- res.writeHead(404, {
2888
- "Content-Type": "application/json; charset=utf-8"
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: "AUTH_FAIL", path: url, method: "POST", user: us, ip, detail: "password_changed" });
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: "AUTH_FAIL", path: url, method: "POST", user: us, ip, detail: "register_ok" });
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: "AUTH_FAIL", path: url, method: "POST", user: us, ip, detail: "login_ok" });
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 (us) logSecurityEvent($asai, { type: "AUTH_FAIL", path: url, method: "POST", user: String(us), ip, detail: "logout" });
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(fs12, relativePath) {
4537
+ ensureDir(fs11, relativePath) {
4503
4538
  const absPathDir = this.toDirPath(relativePath);
4504
4539
  const absPath = this.toAbsolutePath(relativePath);
4505
- if (!fs12.existsSync(absPath)) {
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 (!fs12.existsSync(pathTmp)) {
4514
- if (!fs12.mkdirSync(pathTmp, { recursive: true })) {
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(fs12, filePaths) {
4558
+ makeDir(fs11, filePaths) {
4524
4559
  return new Promise((resolve6, reject) => {
4525
4560
  try {
4526
- const newPath = this.ensureDir(fs12, filePaths);
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
- return decodeURIComponent(rawPath);
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 path4 from "path";
5244
+ import path5 from "path";
5156
5245
  async function ensureFile(filePath) {
5157
- const normalized = path4.normalize(filePath);
5158
- await fs9.mkdir(path4.dirname(normalized), { recursive: true });
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(path4.normalize(filePath));
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(path4.normalize(filePath), "utf8");
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 = path4.resolve(baseDir);
5185
- const target = path4.resolve(base, relPath.replace(/\\/g, "/"));
5186
- const rel = path4.relative(base, target);
5187
- if (rel.startsWith("..") || path4.isAbsolute(rel)) {
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 = path4.resolve(dir);
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 = path4.basename(resolved);
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 = path4.join(resolved, entry.name);
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: path4.normalize(fullPath),
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: path4.normalize(resolved),
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(path4.normalize(filePath));
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 = path4.normalize(filePath);
5241
- await fs9.mkdir(path4.dirname(normalized), { recursive: true });
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(path4.normalize(filePath), "utf8");
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 path5 from "path";
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 = path5.resolve(baseDir);
5425
- const target = path5.resolve(targetPath);
5426
- const relative4 = path5.relative(base, target);
5427
- if (!relative4) return true;
5428
- return !relative4.startsWith("..") && !path5.isAbsolute(relative4);
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 fs11 from "fs";
5610
- import * as path6 from "path";
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
- this.baseDirAbs = path6.resolve(process.cwd(), config.dir);
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 fs11.existsSync(this.getAbsPath(file, false));
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 = path6.isAbsolute(relPath) ? path6.normalize(relPath) : path6.resolve(this.baseDirAbs, relPath);
5649
+ const abs = path7.isAbsolute(relPath) ? path7.normalize(relPath) : path7.resolve(this.baseDirAbs, relPath);
5637
5650
  if (!isPathInside2(this.baseDirAbs, abs)) {
5638
- return this.baseDirAbs;
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 path6.isAbsolute(relPath) ? path6.relative(this.baseDirAbs, relPath) : relPath;
5663
+ return path7.isAbsolute(relPath) ? path7.relative(this.baseDirAbs, relPath) : relPath;
5651
5664
  }
5652
5665
  ensureDir(relPath) {
5653
- const relative4 = this.normalizeRelPath(relPath);
5654
- const dirPath = path6.dirname(relative4);
5666
+ const relative5 = this.normalizeRelPath(relPath);
5667
+ const dirPath = path7.dirname(relative5);
5655
5668
  const absDir = this.resolvePath(dirPath === "." ? "" : dirPath);
5656
- if (this.createDir && !fs11.existsSync(absDir)) {
5669
+ if (this.createDir && !fs10.existsSync(absDir)) {
5657
5670
  this.dbLog("mkdir", "[MKDIR]", absDir);
5658
- fs11.mkdirSync(absDir, { recursive: true });
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 (!fs11.existsSync(absPath)) {
5687
+ if (!fs10.existsSync(absPath)) {
5675
5688
  return;
5676
5689
  }
5677
5690
  this.dbLog("delete", "[RMDIR]", absPath);
5678
- const entries = fs11.readdirSync(absPath, { withFileTypes: true });
5691
+ const entries = fs10.readdirSync(absPath, { withFileTypes: true });
5679
5692
  for (const entry of entries) {
5680
- const current = path6.join(absPath, entry.name);
5693
+ const current = path7.join(absPath, entry.name);
5681
5694
  if (entry.isDirectory()) {
5682
- this.deldir(path6.join(relativePath, entry.name));
5695
+ this.deldir(path7.join(relativePath, entry.name));
5683
5696
  } else {
5684
5697
  this.dbLog("delete", "[UNLINK]", current);
5685
- fs11.unlinkSync(current);
5698
+ fs10.unlinkSync(current);
5686
5699
  }
5687
5700
  }
5688
- fs11.rmdirSync(absPath);
5701
+ fs10.rmdirSync(absPath);
5689
5702
  }
5690
5703
  getReadPath(file, sql) {
5691
5704
  const candidates = [];
5692
5705
  if (sql?.filename) {
5693
- candidates.push({ dir: path6.join(file, sql.filename) });
5694
- candidates.push({ dir: path6.join(file + ".delete" + this.fileExt, sql.filename) });
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 (fs11.existsSync(abs)) {
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: path6.dirname(read2.path), dir: path6.dirname(read2.dir) };
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(path6.join(file, sql.filename), true);
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
- fs11.writeFileSync(filePath, data, "utf8");
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 = fs11.readFileSync(read2.path, { encoding }) || "";
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
- fs11.renameSync(del.path, target);
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
- fs11.unlinkSync(del.path);
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
- fs11.renameSync(del.path, original);
5795
+ fs10.renameSync(del.path, original);
5783
5796
  }
5784
5797
  } else {
5785
5798
  this.dbLog("force delete", "[FORCE DELETE]", del.path);
5786
- fs11.unlinkSync(del.path);
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 = fs11.readdirSync(absDir, { withFileTypes: true });
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 = path6.join(absDir, fileName);
5825
+ const fullPath = path7.join(absDir, fileName);
5813
5826
  try {
5814
- const data = fs11.readFileSync(fullPath, "utf8");
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.5" : "0.0.1";
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,