@decentnetwork/lan 0.1.91 → 0.1.92
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.
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/ui/server.js
CHANGED
|
@@ -17,6 +17,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
import { dirname, join } from "node:path";
|
|
19
19
|
import yaml from "js-yaml";
|
|
20
|
+
import { DEFAULT_EXITS } from "../config/loader.js";
|
|
20
21
|
// Directory holding the built desktop UI bundle (index.html, app.js, vendor/).
|
|
21
22
|
// scripts/build-ui.mjs emits it next to this compiled module at dist/ui/desktop/.
|
|
22
23
|
const DESKTOP_DIR = join(dirname(fileURLToPath(import.meta.url)), "desktop");
|
|
@@ -194,27 +195,65 @@ export function startFriendUi(opts) {
|
|
|
194
195
|
via: "lan",
|
|
195
196
|
time: "",
|
|
196
197
|
}));
|
|
197
|
-
// Exit nodes
|
|
198
|
+
// Exit nodes = the AVAILABLE exits this node knows about, grouped by
|
|
199
|
+
// region. The authoritative list is the shipped DEFAULT_EXITS
|
|
200
|
+
// (config/default-exits.yaml) — every install has it, so the panel is
|
|
201
|
+
// populated out-of-the-box even on a node with no routes.yaml. Any
|
|
202
|
+
// extra exit IPs an operator added to routes.yaml are folded in too.
|
|
203
|
+
// online status: is that exit a currently-connected friend (by userid,
|
|
204
|
+
// else by its virtual ip showing up as a live peer).
|
|
198
205
|
let routes = { regions: [], default: "direct" };
|
|
199
206
|
if (existsSync(opts.routesPath)) {
|
|
200
207
|
routes = yaml.load(readFileSync(opts.routesPath, "utf-8")) ?? routes;
|
|
201
208
|
}
|
|
209
|
+
const onlineUserids = new Set();
|
|
202
210
|
const onlineIps = new Set();
|
|
203
|
-
for (const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
211
|
+
for (const f of diagFriends) {
|
|
212
|
+
const uid = f.carrierId || f.pubkey || "";
|
|
213
|
+
const s = f.session;
|
|
214
|
+
if (uid && s && s.transport && s.transport !== "none") {
|
|
215
|
+
onlineUserids.add(uid);
|
|
216
|
+
const ip = ipByUserid.get(uid);
|
|
217
|
+
if (ip)
|
|
218
|
+
onlineIps.add(ip);
|
|
219
|
+
}
|
|
207
220
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
label:
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
const regionMeta = {
|
|
222
|
+
china: { flag: "CN", label: "China" },
|
|
223
|
+
japan: { flag: "JP", label: "Japan" },
|
|
224
|
+
us: { flag: "US", label: "United States" },
|
|
225
|
+
};
|
|
226
|
+
const byRegion = new Map();
|
|
227
|
+
for (const e of DEFAULT_EXITS) {
|
|
228
|
+
if (!e.virtual_ip)
|
|
229
|
+
continue;
|
|
230
|
+
const region = e.region || "other";
|
|
231
|
+
if (!byRegion.has(region))
|
|
232
|
+
byRegion.set(region, []);
|
|
233
|
+
byRegion.get(region).push({
|
|
234
|
+
ip: e.virtual_ip,
|
|
235
|
+
host: e.name,
|
|
236
|
+
online: onlineUserids.has(e.userid) || onlineIps.has(e.virtual_ip),
|
|
215
237
|
ping: null,
|
|
216
|
-
|
|
217
|
-
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// Fold in any extra exit IPs from routes.yaml not already covered.
|
|
241
|
+
const knownIps = new Set(DEFAULT_EXITS.flatMap((e) => (e.virtual_ip ? [e.virtual_ip] : [])));
|
|
242
|
+
for (const r of routes.regions ?? []) {
|
|
243
|
+
for (const ip of r.exits ?? []) {
|
|
244
|
+
if (knownIps.has(ip))
|
|
245
|
+
continue;
|
|
246
|
+
knownIps.add(ip);
|
|
247
|
+
if (!byRegion.has(r.name))
|
|
248
|
+
byRegion.set(r.name, []);
|
|
249
|
+
byRegion.get(r.name).push({ ip, host: ip, online: onlineIps.has(ip), ping: null });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const exits = [...byRegion.entries()].map(([region, nodes]) => ({
|
|
253
|
+
region,
|
|
254
|
+
flag: regionMeta[region]?.flag ?? region.slice(0, 2).toUpperCase(),
|
|
255
|
+
label: regionMeta[region]?.label ?? region,
|
|
256
|
+
nodes,
|
|
218
257
|
}));
|
|
219
258
|
const activeExit = routes.default && routes.default !== "direct" ? routes.default : null;
|
|
220
259
|
sendJson(res, 200, { me, peers, requests, exits, activeExit });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/lan",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.92",
|
|
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",
|