alink-cli 0.8.6 → 0.8.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.
- package/dist/bin.mjs +123 -6
- package/dist/bin.mjs.map +1 -1
- package/dist/daemon.js +30 -0
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -52350,6 +52350,7 @@ function isEnvelope(value) {
|
|
|
52350
52350
|
//#endregion
|
|
52351
52351
|
//#region src/tunnel/bridge.ts
|
|
52352
52352
|
const TUNNEL_SCOPES = [AuthOrchestrationReadScope, AuthOrchestrationOperateScope];
|
|
52353
|
+
const hubFrameDecoder = new TextDecoder();
|
|
52353
52354
|
const ResponseDefectEncoded = (cause) => ({
|
|
52354
52355
|
_tag: "Defect",
|
|
52355
52356
|
defect: cause instanceof Error ? {
|
|
@@ -52433,6 +52434,12 @@ const splitHubFrame = (text) => {
|
|
|
52433
52434
|
rest: text.slice(spaceAt + 1)
|
|
52434
52435
|
};
|
|
52435
52436
|
};
|
|
52437
|
+
function isHttpTunnelRequestFrame(value) {
|
|
52438
|
+
return typeof value === "object" && value !== null && value._tag === "HttpRequest" && typeof value.id === "string" && typeof value.method === "string" && typeof value.path === "string" && Array.isArray(value.headers) && (value.body === null || typeof value.body === "string");
|
|
52439
|
+
}
|
|
52440
|
+
function encodeHttpTunnelResponseFrame(frame) {
|
|
52441
|
+
return JSON.stringify(frame);
|
|
52442
|
+
}
|
|
52436
52443
|
const makeTunnelSocket = (input) => {
|
|
52437
52444
|
const runRaw = (handler, options) => scopedWith((scope) => gen(function* () {
|
|
52438
52445
|
const fiberSet = yield* make$62().pipe(provide$2(scope));
|
|
@@ -52478,7 +52485,7 @@ const runHubTunnel = (config) => gen(function* () {
|
|
|
52478
52485
|
const writeRaw = yield* socket.writer;
|
|
52479
52486
|
yield* forever(take$1(outbox).pipe(flatMap$1(writeRaw)));
|
|
52480
52487
|
}));
|
|
52481
|
-
const
|
|
52488
|
+
const attachRpcTunnel = (tunnelId, live) => gen(function* () {
|
|
52482
52489
|
yield* addFinalizer(() => sync(() => {
|
|
52483
52490
|
if (tunnels.get(tunnelId) !== live) return;
|
|
52484
52491
|
tunnels.delete(tunnelId);
|
|
@@ -52515,14 +52522,121 @@ const runHubTunnel = (config) => gen(function* () {
|
|
|
52515
52522
|
type: "tunnel_open",
|
|
52516
52523
|
tunnelId
|
|
52517
52524
|
}))) dropTunnel(tunnelId);
|
|
52518
|
-
yield* logInfo("hub tunnel: attached", {
|
|
52525
|
+
yield* logInfo("hub tunnel: attached", {
|
|
52526
|
+
tunnelId,
|
|
52527
|
+
purpose: live.purpose
|
|
52528
|
+
});
|
|
52519
52529
|
yield* _await(live.closed);
|
|
52520
52530
|
}).pipe(catch_((error) => logWarning$1("hub tunnel: attach failed", {
|
|
52521
52531
|
tunnelId,
|
|
52522
52532
|
error
|
|
52523
52533
|
})));
|
|
52524
|
-
|
|
52525
|
-
|
|
52534
|
+
const attachHttpTunnel = (tunnelId, live) => gen(function* () {
|
|
52535
|
+
yield* addFinalizer(() => sync(() => {
|
|
52536
|
+
if (tunnels.get(tunnelId) !== live) return;
|
|
52537
|
+
tunnels.delete(tunnelId);
|
|
52538
|
+
writeHub(JSON.stringify({
|
|
52539
|
+
type: "tunnel_close",
|
|
52540
|
+
tunnelId,
|
|
52541
|
+
code: 1011,
|
|
52542
|
+
reason: "daemon http tunnel ended"
|
|
52543
|
+
}));
|
|
52544
|
+
}));
|
|
52545
|
+
const issued = yield* serverAuth.issueSession({
|
|
52546
|
+
subject: "hub-tunnel-http",
|
|
52547
|
+
label: "AgentLink hub tunnel HTTP proxy",
|
|
52548
|
+
scopes: [...TUNNEL_SCOPES]
|
|
52549
|
+
});
|
|
52550
|
+
yield* addFinalizer(() => sessionsStore.markDisconnected(issued.sessionId).pipe(andThen(serverAuth.revokeSession(issued.sessionId)), ignore$1));
|
|
52551
|
+
yield* sessionsStore.markConnected(issued.sessionId);
|
|
52552
|
+
const serverConfig = yield* ServerConfig;
|
|
52553
|
+
const httpClient = yield* HttpClient;
|
|
52554
|
+
const localBaseUrl = `http://127.0.0.1:${serverConfig.port}`;
|
|
52555
|
+
const sendEncrypted = (frame) => {
|
|
52556
|
+
try {
|
|
52557
|
+
const envelope = utf8ToEnvelope(config.enckey, encodeHttpTunnelResponseFrame(frame));
|
|
52558
|
+
if (!writeHub(`${tunnelId} ${JSON.stringify(envelope)}`)) dropTunnel(tunnelId);
|
|
52559
|
+
} catch {
|
|
52560
|
+
dropTunnel(tunnelId);
|
|
52561
|
+
}
|
|
52562
|
+
};
|
|
52563
|
+
live.onDecryptedFrame = (frame) => {
|
|
52564
|
+
let requestFrame;
|
|
52565
|
+
try {
|
|
52566
|
+
const parsed = JSON.parse(frame);
|
|
52567
|
+
if (!isHttpTunnelRequestFrame(parsed)) {
|
|
52568
|
+
sendEncrypted({
|
|
52569
|
+
_tag: "HttpResponse",
|
|
52570
|
+
id: typeof parsed?.id === "string" ? parsed.id : "unknown",
|
|
52571
|
+
status: 400,
|
|
52572
|
+
statusText: "Bad Request",
|
|
52573
|
+
headers: [["content-type", "text/plain"]],
|
|
52574
|
+
body: Buffer.from("Invalid HTTP tunnel request frame").toString("base64")
|
|
52575
|
+
});
|
|
52576
|
+
return;
|
|
52577
|
+
}
|
|
52578
|
+
requestFrame = parsed;
|
|
52579
|
+
} catch {
|
|
52580
|
+
sendEncrypted({
|
|
52581
|
+
_tag: "HttpResponse",
|
|
52582
|
+
id: "unknown",
|
|
52583
|
+
status: 400,
|
|
52584
|
+
statusText: "Bad Request",
|
|
52585
|
+
headers: [["content-type", "text/plain"]],
|
|
52586
|
+
body: Buffer.from("Malformed HTTP tunnel request frame").toString("base64")
|
|
52587
|
+
});
|
|
52588
|
+
return;
|
|
52589
|
+
}
|
|
52590
|
+
runFork(gen(function* () {
|
|
52591
|
+
const targetUrl = `${localBaseUrl}${requestFrame.path}`;
|
|
52592
|
+
const headers = { authorization: `Bearer ${issued.token}` };
|
|
52593
|
+
for (const [key, value] of requestFrame.headers) {
|
|
52594
|
+
const lower = key.toLowerCase();
|
|
52595
|
+
if (lower === "authorization" || lower === "cookie") continue;
|
|
52596
|
+
headers[lower] = value;
|
|
52597
|
+
}
|
|
52598
|
+
let request = make$61(requestFrame.method)(targetUrl).pipe(setHeaders(headers));
|
|
52599
|
+
if (requestFrame.body !== null) request = setBody(uint8Array(Buffer.from(requestFrame.body, "base64")))(request);
|
|
52600
|
+
const response = yield* httpClient.execute(request);
|
|
52601
|
+
const responseBody = yield* response.arrayBuffer;
|
|
52602
|
+
const responseHeaders = [];
|
|
52603
|
+
for (const [key, value] of Object.entries(response.headers)) if (typeof value === "string") responseHeaders.push([key, value]);
|
|
52604
|
+
return {
|
|
52605
|
+
_tag: "HttpResponse",
|
|
52606
|
+
id: requestFrame.id,
|
|
52607
|
+
status: response.status,
|
|
52608
|
+
statusText: "",
|
|
52609
|
+
headers: responseHeaders,
|
|
52610
|
+
body: Buffer.from(responseBody).toString("base64")
|
|
52611
|
+
};
|
|
52612
|
+
}).pipe(match$2({
|
|
52613
|
+
onFailure: (cause) => ({
|
|
52614
|
+
_tag: "HttpResponse",
|
|
52615
|
+
id: requestFrame.id,
|
|
52616
|
+
status: 502,
|
|
52617
|
+
statusText: "Bad Gateway",
|
|
52618
|
+
headers: [["content-type", "text/plain"]],
|
|
52619
|
+
body: Buffer.from(cause instanceof Error ? cause.message : String(cause)).toString("base64")
|
|
52620
|
+
}),
|
|
52621
|
+
onSuccess: (response) => response
|
|
52622
|
+
}), tap((frame) => sync(() => sendEncrypted(frame)))));
|
|
52623
|
+
};
|
|
52624
|
+
if (!writeHub(JSON.stringify({
|
|
52625
|
+
type: "tunnel_open",
|
|
52626
|
+
tunnelId
|
|
52627
|
+
}))) dropTunnel(tunnelId);
|
|
52628
|
+
yield* logInfo("hub tunnel: attached", {
|
|
52629
|
+
tunnelId,
|
|
52630
|
+
purpose: live.purpose
|
|
52631
|
+
});
|
|
52632
|
+
yield* _await(live.closed);
|
|
52633
|
+
}).pipe(catch_((error) => logWarning$1("hub tunnel: attach failed", {
|
|
52634
|
+
tunnelId,
|
|
52635
|
+
error
|
|
52636
|
+
})));
|
|
52637
|
+
yield* socket.runRaw((rawData) => {
|
|
52638
|
+
const data = typeof rawData === "string" ? rawData : rawData instanceof Uint8Array ? hubFrameDecoder.decode(rawData) : null;
|
|
52639
|
+
if (data === null) return;
|
|
52526
52640
|
if (data.startsWith("{")) {
|
|
52527
52641
|
let control;
|
|
52528
52642
|
try {
|
|
@@ -52534,13 +52648,16 @@ const runHubTunnel = (config) => gen(function* () {
|
|
|
52534
52648
|
const tunnelId = control.tunnelId;
|
|
52535
52649
|
if (tunnels.has(tunnelId)) return;
|
|
52536
52650
|
return gen(function* () {
|
|
52651
|
+
const closed = yield* make$70();
|
|
52652
|
+
const purpose = control.purpose === "http" ? "http" : "rpc";
|
|
52537
52653
|
const live = {
|
|
52538
|
-
closed
|
|
52654
|
+
closed,
|
|
52539
52655
|
pendingFrames: [],
|
|
52656
|
+
purpose,
|
|
52540
52657
|
onDecryptedFrame: null
|
|
52541
52658
|
};
|
|
52542
52659
|
tunnels.set(tunnelId, live);
|
|
52543
|
-
yield* forkScoped(scoped(
|
|
52660
|
+
yield* forkScoped(scoped((purpose === "http" ? attachHttpTunnel : attachRpcTunnel)(tunnelId, live)));
|
|
52544
52661
|
});
|
|
52545
52662
|
}
|
|
52546
52663
|
if (control.type === "tunnel_close" && typeof control.tunnelId === "string") dropTunnel(control.tunnelId);
|