@decentnetwork/lan 0.1.235 → 0.1.240

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.
@@ -1,4 +1,4 @@
1
- window.__DK_UI_VERSION="0.1.235";
1
+ window.__DK_UI_VERSION="0.1.240";
2
2
  const ICON_PATHS = {
3
3
  // ---- tab bar (the four must feel like one set) ----
4
4
  users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
@@ -3002,6 +3002,7 @@ function DkApp() {
3002
3002
  sessionStorage.setItem(key, "1");
3003
3003
  window.location.reload();
3004
3004
  }, [me && me.lanVer]);
3005
+ const peers = data.peers;
3005
3006
  const [pendingAddr, setPendingAddr] = React.useState(() => dkParseDeepLinkAddress());
3006
3007
  React.useEffect(() => {
3007
3008
  const onHash = () => {
@@ -3030,7 +3031,6 @@ function DkApp() {
3030
3031
  }
3031
3032
  }
3032
3033
  }, [pendingAddr, peers]);
3033
- const peers = data.peers;
3034
3034
  const requests = data.requests;
3035
3035
  const exits = data.exits;
3036
3036
  const activeExit = data.activeExit;
package/dist/ui/server.js CHANGED
@@ -242,7 +242,9 @@ export function startFriendUi(opts) {
242
242
  }
243
243
  });
244
244
  });
245
- const server = http.createServer(async (req, res) => {
245
+ // Named so the IPv6 loopback listener below can share it (Node binds one
246
+ // listener to one address, and `localhost` is two addresses).
247
+ const handler = async (req, res) => {
246
248
  try {
247
249
  const url = (req.url || "/").split("?")[0];
248
250
  // Desktop UI bundle (the design). Falls back to the classic page when
@@ -922,12 +924,39 @@ export function startFriendUi(opts) {
922
924
  catch (err) {
923
925
  sendJson(res, 500, { ok: false, error: err instanceof Error ? err.message : String(err) });
924
926
  }
925
- });
926
- server.listen(port, host, () => {
927
- log(`Friend UI on http://${host}:${port}`);
927
+ };
928
+ const server = http.createServer(handler);
929
+ // `localhost` resolves to BOTH ::1 and 127.0.0.1. Binding only 127.0.0.1
930
+ // left the UI unreachable in a browser: Chrome/Safari try ::1 first and
931
+ // don't fall back the way curl does, so http://localhost:8765 refused the
932
+ // connection while 127.0.0.1:8765 served fine — and the daemon log claimed
933
+ // the UI was up. When the caller asked for loopback (the default), listen on
934
+ // BOTH families. An explicit non-loopback host is honoured as given.
935
+ const isLoopback = host === "127.0.0.1" || host === "localhost" || host === "::1";
936
+ let v6 = null;
937
+ server.listen(port, host === "localhost" ? "127.0.0.1" : host, () => {
938
+ log(`Friend UI on http://${isLoopback ? "localhost" : host}:${port}`);
928
939
  log(`(serves the running daemon's friends + pending requests over IPC)`);
929
940
  });
930
- return { stop: () => server.close() };
941
+ if (isLoopback) {
942
+ // Second server object on ::1: Node can't bind one listener to two
943
+ // specific addresses, and binding :: instead would expose the UI on every
944
+ // interface — the opposite of what a loopback default promises.
945
+ v6 = http.createServer(handler);
946
+ v6.on("error", (err) => {
947
+ // A host with IPv6 disabled gives EADDRNOTAVAIL/EAFNOSUPPORT; the IPv4
948
+ // listener above is already serving, so this is not fatal.
949
+ if (err.code !== "EADDRINUSE")
950
+ log(`(IPv6 loopback unavailable: ${err.code ?? err.message} — IPv4 still serving)`);
951
+ });
952
+ v6.listen(port, "::1");
953
+ }
954
+ return {
955
+ stop: () => {
956
+ server.close();
957
+ v6?.close();
958
+ },
959
+ };
931
960
  }
932
961
  const PAGE = `<!doctype html>
933
962
  <html lang="en"><head><meta charset="utf-8"/>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.235",
3
+ "version": "0.1.240",
4
4
  "description": "Private virtual LAN for self-hosted services and AI agents, built on Elastos Carrier. NAT-traversal, name service, ACL, all over a peer-to-peer mesh — no public IP required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -84,7 +84,7 @@
84
84
  },
85
85
  "dependencies": {
86
86
  "@decentnetwork/dora": "^0.1.14",
87
- "@decentnetwork/peer": "^0.1.111",
87
+ "@decentnetwork/peer": "^0.1.116",
88
88
  "@decentnetwork/peer-webrtc": "^0.2.10",
89
89
  "ink": "^5.2.1",
90
90
  "js-yaml": "^4.1.0",