@bulolo/hermes-link 0.2.3 → 0.2.7
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.
|
@@ -1529,33 +1529,51 @@ function discoverLanIpsFromInterfaces(interfaces) {
|
|
|
1529
1529
|
}
|
|
1530
1530
|
async function observePublicRoute(options) {
|
|
1531
1531
|
const fetcher = options.fetchImpl ?? fetch;
|
|
1532
|
-
const
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1532
|
+
const simpleIp = await fetchPublicIpSimple(fetcher).catch(() => null);
|
|
1533
|
+
try {
|
|
1534
|
+
const response = await fetcher(
|
|
1535
|
+
`${options.relayBaseUrl.replace(/\/+$/u, "")}/api/v1/relay/public-route/observe`,
|
|
1536
|
+
{
|
|
1537
|
+
method: "POST",
|
|
1538
|
+
headers: {
|
|
1539
|
+
"content-type": "application/json",
|
|
1540
|
+
...options.relayBootstrapToken ? { authorization: `Bearer ${options.relayBootstrapToken}` } : {}
|
|
1541
|
+
},
|
|
1542
|
+
body: JSON.stringify({
|
|
1543
|
+
install_id: options.installId,
|
|
1544
|
+
link_id: options.linkId,
|
|
1545
|
+
public_key_pem: options.publicKeyPem
|
|
1546
|
+
}),
|
|
1547
|
+
signal: AbortSignal.timeout(5e3)
|
|
1548
|
+
}
|
|
1549
|
+
);
|
|
1550
|
+
const payload = await response.json().catch(() => null);
|
|
1551
|
+
const record = typeof payload?.record === "object" && payload.record !== null ? payload.record : null;
|
|
1552
|
+
const observed = typeof payload?.observed === "object" && payload.observed !== null ? payload.observed : null;
|
|
1553
|
+
const values = [
|
|
1554
|
+
simpleIp,
|
|
1555
|
+
readIpRecord(record?.ipv4),
|
|
1556
|
+
readIpRecord(record?.ipv6),
|
|
1557
|
+
typeof observed?.ip === "string" ? observed.ip : null
|
|
1558
|
+
].filter((v) => Boolean(v));
|
|
1559
|
+
return {
|
|
1560
|
+
publicIpv4s: unique(values.filter(isUsablePublicIpv4)),
|
|
1561
|
+
publicIpv6s: unique(values.filter(isUsablePublicIpv6))
|
|
1562
|
+
};
|
|
1563
|
+
} catch {
|
|
1564
|
+
const values = [simpleIp].filter((v) => Boolean(v));
|
|
1565
|
+
return {
|
|
1566
|
+
publicIpv4s: unique(values.filter(isUsablePublicIpv4)),
|
|
1567
|
+
publicIpv6s: []
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
async function fetchPublicIpSimple(fetcher) {
|
|
1572
|
+
const res = await fetcher("https://api.ipify.org?format=json", {
|
|
1573
|
+
signal: AbortSignal.timeout(4e3)
|
|
1574
|
+
});
|
|
1575
|
+
const data = await res.json();
|
|
1576
|
+
return typeof data.ip === "string" && data.ip.trim() ? data.ip.trim() : null;
|
|
1559
1577
|
}
|
|
1560
1578
|
function readIpRecord(value) {
|
|
1561
1579
|
if (typeof value !== "object" || value === null) return null;
|
|
@@ -3506,8 +3524,9 @@ async function startLinkService(options) {
|
|
|
3506
3524
|
const statsRouter = createStatisticsRouter({ db, paths });
|
|
3507
3525
|
app.use(statsRouter.routes());
|
|
3508
3526
|
app.use(statsRouter.allowedMethods());
|
|
3527
|
+
const listenHost = process.env.HERMESLINK_LISTEN_HOST ?? "0.0.0.0";
|
|
3509
3528
|
const server = await new Promise((resolve, reject) => {
|
|
3510
|
-
const s = app.listen(config.port,
|
|
3529
|
+
const s = app.listen(config.port, listenHost, () => resolve(s));
|
|
3511
3530
|
s.once("error", reject);
|
|
3512
3531
|
});
|
|
3513
3532
|
const relayClient = new RelayClient({
|
package/dist/cli/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
saveConfig,
|
|
24
24
|
startLinkService,
|
|
25
25
|
writeJsonFile
|
|
26
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-ZN3XW7FI.js";
|
|
27
27
|
|
|
28
28
|
// src/cli/index.ts
|
|
29
29
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
@@ -262,28 +262,30 @@ async function runPairingPreflight(options) {
|
|
|
262
262
|
};
|
|
263
263
|
await mkdir2(options.paths.pairingDir, { recursive: true, mode: 448 }).catch(() => void 0);
|
|
264
264
|
await writeJsonFile(pairingSessionPath(sessionId, options.paths), session);
|
|
265
|
+
const lanUrls = (routes?.lanIps ?? []).map((ip) => `http://${ip}:${options.config.port}`);
|
|
266
|
+
const publicUrls = (routes?.publicIpv4s ?? []).map((ip) => `http://${ip}:${options.config.port}`);
|
|
265
267
|
const pairingUrl = buildPairingUrl({
|
|
266
268
|
linkId: options.identity.link_id ?? "",
|
|
267
269
|
installId: options.identity.install_id,
|
|
268
270
|
connectToken: token.token,
|
|
269
271
|
port: options.config.port,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
+
lanUrls,
|
|
273
|
+
publicUrls
|
|
272
274
|
});
|
|
273
275
|
if (options.openBrowser !== false) {
|
|
274
276
|
await openSystemBrowser(pairingUrl).catch(() => void 0);
|
|
275
277
|
}
|
|
276
|
-
return { pairingUrl, connectToken: token.token };
|
|
278
|
+
return { pairingUrl, connectToken: token.token, bestUrl };
|
|
277
279
|
}
|
|
278
280
|
function buildPairingUrl(params) {
|
|
279
281
|
const qs = new URLSearchParams({
|
|
280
282
|
link_id: params.linkId,
|
|
281
283
|
install_id: params.installId,
|
|
282
284
|
connect_token: params.connectToken,
|
|
283
|
-
port: String(params.port)
|
|
284
|
-
local_url: params.localApiUrl,
|
|
285
|
-
preferred_urls: params.preferredUrls.join(",")
|
|
285
|
+
port: String(params.port)
|
|
286
286
|
});
|
|
287
|
+
if (params.lanUrls.length > 0) qs.set("lan_urls", params.lanUrls.join(","));
|
|
288
|
+
if (params.publicUrls.length > 0) qs.set("public_urls", params.publicUrls.join(","));
|
|
287
289
|
return `hermesapp://pair?${qs.toString()}`;
|
|
288
290
|
}
|
|
289
291
|
|
|
@@ -441,10 +443,14 @@ async function cmdPair(paths) {
|
|
|
441
443
|
return;
|
|
442
444
|
}
|
|
443
445
|
const result = await runPairingPreflight({ identity, config, paths });
|
|
446
|
+
const pageBase = result.bestUrl.replace(/\/+$/u, "");
|
|
447
|
+
const pageUrl = `${pageBase}/pair?connect_token=${encodeURIComponent(result.connectToken)}`;
|
|
444
448
|
process.stdout.write("\n");
|
|
445
449
|
qrcode.generate(result.pairingUrl, { small: true });
|
|
446
450
|
process.stdout.write(`
|
|
447
451
|
Pairing URL: ${result.pairingUrl}
|
|
452
|
+
`);
|
|
453
|
+
process.stdout.write(`Pairing page: ${pageUrl}
|
|
448
454
|
`);
|
|
449
455
|
process.stdout.write(`Connect token: ${result.connectToken}
|
|
450
456
|
`);
|
package/dist/http/app.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bulolo/hermes-link",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Hermes Link companion service and CLI for connecting hermes-agent through zhiji",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"prepack": "npm run build",
|
|
37
37
|
"start": "node ./dist/cli/index.js",
|
|
38
38
|
"test": "vitest",
|
|
39
|
-
"publish:npm": "npm publish --access public"
|
|
39
|
+
"publish:npm": "npm publish --access public --registry https://registry.npmjs.org"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@koa/cors": "^5.0.0",
|