@hediet/linkrpc-cli 0.0.3-next.20261023.3 → 0.0.3-next.20261024.1
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/README.md +22 -0
- package/dist/chunks/{cli-B93twHKF.js → cli-CXAAnZDA.js} +81 -11
- package/dist/chunks/cli-CXAAnZDA.js.map +1 -0
- package/dist/chunks/{runApprovalUi-CNp2DhKG.js → runApprovalUi-BdPp7WNP.js} +3 -3
- package/dist/chunks/{runApprovalUi-CNp2DhKG.js.map → runApprovalUi-BdPp7WNP.js.map} +1 -1
- package/dist/chunks/{runComplete-C9LMCMk7.js → runComplete-M-eKaNkI.js} +21 -7
- package/dist/chunks/runComplete-M-eKaNkI.js.map +1 -0
- package/dist/chunks/{runUi-B4rV3ZfF.js → runUi-Deeox_Ef.js} +4 -4
- package/dist/chunks/{runUi-B4rV3ZfF.js.map → runUi-Deeox_Ef.js.map} +1 -1
- package/dist/chunks/{scroll-DGHNxpYN.js → scroll-CYhlBDSN.js} +2 -2
- package/dist/chunks/{scroll-DGHNxpYN.js.map → scroll-CYhlBDSN.js.map} +1 -1
- package/dist/chunks/{src-CCyOTeN5.js → src-yrqRWXzG.js} +2 -2
- package/dist/chunks/{src-CCyOTeN5.js.map → src-yrqRWXzG.js.map} +1 -1
- package/dist/hub.js +1 -1
- package/dist/index.js +1 -1
- package/dist/linkrpc.js +1 -1
- package/dist/rpc.js +1 -1
- package/package.json +5 -5
- package/dist/chunks/cli-B93twHKF.js.map +0 -1
- package/dist/chunks/runComplete-C9LMCMk7.js.map +0 -1
package/README.md
CHANGED
|
@@ -793,6 +793,7 @@ initial document:
|
|
|
793
793
|
| `connection notifications [--after n] [--wait 25s] [--follow]` | Read incoming remote notifications from the broker's bounded buffer. `--follow` emits one JSON object per line and can run alongside calls. |
|
|
794
794
|
| `connection destroy` | Stop the configured connection broker through its local overlay. |
|
|
795
795
|
| `json-rpc-stdio <serviceId> [--params <json>]` | In the Hub profile, expose `<serviceId>::jsonRpcConnection::connectRaw` as newline-delimited JSON-RPC on stdin/stdout. Diagnostics remain on stderr. |
|
|
796
|
+
| `json-rpc-export --target-endpoint <uri> --serviceId <id> --path <path> ...` | In the Hub profile, export multiple JSON-RPC factories through one authenticated raw WebSocket listener. |
|
|
796
797
|
|
|
797
798
|
The inherited `--schema <path-or-url>` option also overlays static
|
|
798
799
|
`hubrpc.defaults`, `hubrpc.directory`, and `hubrpc.schemas` reflection for
|
|
@@ -812,6 +813,27 @@ frame, and each remote frame is written as one JSON line:
|
|
|
812
813
|
hub --endpoint unix:/run/hub.sock json-rpc-stdio language-server
|
|
813
814
|
```
|
|
814
815
|
|
|
816
|
+
`json-rpc-export` maps multiple Hub JSON-RPC services to distinct paths on one listener:
|
|
817
|
+
|
|
818
|
+
```sh
|
|
819
|
+
linkrpc hub json-rpc-export \
|
|
820
|
+
--target-endpoint "listen:ws://127.0.0.1:8123" \
|
|
821
|
+
--target-token "$EXPORT_TOKEN" \
|
|
822
|
+
--target-token-query-param tkn \
|
|
823
|
+
--serviceId foo --path /foo \
|
|
824
|
+
--serviceId bar --path /bar
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
Each `--serviceId` must be followed by its `--path`; a leading slash is optional. Missing pairs, duplicate paths, and unsupported endpoints fail before connecting to the Hub. Each WebSocket client opens an independent `<serviceId>::jsonRpcConnection::connectRaw` session, including clients on the same route. Requests, responses, notifications, and server-initiated requests pass unchanged, without a `hubrpc::initialize` handshake.
|
|
828
|
+
|
|
829
|
+
The nonempty export token is separate from the source Hub credentials. Clients authenticate during the WebSocket upgrade with `Authorization: Bearer <token>` or a configured query parameter. Without `--target-token-query-param`, the accepted query names are `tkn` (VS Code sends its `connectionToken` under this name) and `token`. Supplying the repeatable option replaces those defaults: for example `--target-token-query-param connectionToken --target-token-query-param api_key` accepts either custom name. Bearer headers remain accepted. Exactly one credential is required: duplicate query parameters, multiple Authorization headers, or a header combined with a recognized query parameter are rejected, even if their values match. Unrecognized parameters are not credentials.
|
|
830
|
+
|
|
831
|
+
Alternatively, configure the listener token in the target URI as `listen:ws://127.0.0.1:8123?token=...`; this configuration syntax is independent of the accepted client query names. Readiness output never includes the token. Unknown routes return 404 and missing/invalid/ambiguous credentials return 401 without opening an upstream session. Anyone holding this token can access all configured routes using the export process's Hub identity; use a narrowly scoped identity and protect the token. Client credentials are consumed by the listener and never forwarded to the upstream factory.
|
|
832
|
+
|
|
833
|
+
Only `listen:ws://` TCP listeners are currently supported, not named pipes or TLS listeners. Bind loopback for local use. For remote access, terminate TLS in a trusted reverse proxy rather than sending tokens over unencrypted networks. The gateway limits connections to 100, frames to 16 MiB, and pending input per client to 32 MiB / 1024 frames; slow consumers and failed upstreams close only their own connection. Factories must open within 30 seconds.
|
|
834
|
+
|
|
835
|
+
The command stays in the foreground until SIGINT/SIGTERM, then closes clients and the listener. Use the existing Hub daemon/service lifecycle to supervise it; this command neither installs a service nor starts remote AHP hosts. Diagnostics and the bound address (including an assigned port when using port 0) go to stderr.
|
|
836
|
+
|
|
815
837
|
### Participant proxy
|
|
816
838
|
|
|
817
839
|
`proxy` stands in for a participant on the hub: the participant is either this
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as requestTopologyAccess, B as proxyCommand, F as disconnectBroker, G as parseDuration, H as withStaticHubReflection, I as getBrokerStatus, L as readBrokerNotifications, M as readEndpointDiscovery, N as ContextStore, P as formatContextReference, Q as requestReflectionAccess, R as stopConnectionBroker, St as mcpForwardInterface, U as parseConnectionLimit, V as tunnelCommand, W as parseConnectionLimitMilliseconds, _t as validateValueAgainstSchema, a as resolveInvocationEndpoint, bt as parseParamOverride, c as resolveLocalEndpoint, ct as parsePrincipalSpec, dt as connectViaTransport, et as setupSigning, ft as resolveTargetEndpoint, gt as explainValidation, ht as describeSchema, i as resolveInvocationContext, it as walkHub, lt as connect, m as managedEndpointsInterface, mt as describeObjectParams, n as loadStaticHubSchema, nt as fetchSchema$1, o as resolveSigning, ot as logoutCliIdentity, pt as resolvedEndpointToConfig, q as resolveCliInvocation, r as resolveStaticHubSchemaSource, rt as findMethodInSchema, s as validationDefault, st as formatPrincipalSource, t as completeForLine, tt as fetchDefaults, ut as connectViaRootOverlay, xt as MethodRefWithOptHash, y as HubHome, yt as mergeParams, z as ConnectionBroker } from "./runComplete-
|
|
1
|
+
import { $ as requestTopologyAccess, B as proxyCommand, F as disconnectBroker, G as parseDuration, H as withStaticHubReflection, I as getBrokerStatus, L as readBrokerNotifications, M as readEndpointDiscovery, N as ContextStore, P as formatContextReference, Q as requestReflectionAccess, R as stopConnectionBroker, St as mcpForwardInterface, U as parseConnectionLimit, V as tunnelCommand, W as parseConnectionLimitMilliseconds, _t as validateValueAgainstSchema, a as resolveInvocationEndpoint, bt as parseParamOverride, c as resolveLocalEndpoint, ct as parsePrincipalSpec, dt as connectViaTransport, et as setupSigning, ft as resolveTargetEndpoint, gt as explainValidation, ht as describeSchema, i as resolveInvocationContext, it as walkHub, lt as connect, m as managedEndpointsInterface, mt as describeObjectParams, n as loadStaticHubSchema, nt as fetchSchema$1, o as resolveSigning, ot as logoutCliIdentity, pt as resolvedEndpointToConfig, q as resolveCliInvocation, r as resolveStaticHubSchemaSource, rt as findMethodInSchema, s as validationDefault, st as formatPrincipalSource, t as completeForLine, tt as fetchDefaults, ut as connectViaRootOverlay, xt as MethodRefWithOptHash, y as HubHome, yt as mergeParams, z as ConnectionBroker } from "./runComplete-M-eKaNkI.js";
|
|
2
2
|
import { ErrorCode, INTERFACE_TEMPLATES_EXTENSION, LinkRpcConnection, RpcError, computeInterfaceHash, connectTransports, createSchemaToZod, directoryInterface, exportStaticHubSchema, generateTsContract, generateTsInterface, interfaceTemplateArgumentsEquivalent, interfaceTemplateMemberName, interfaceTemplatesEqual, isAssignable, jcsCanonicalize, matchParams, schemaToZod, validateInterfaceTemplates } from "@hediet/linkrpc";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { WebSocketTransport, connectNdjson, connectToHub, formatEndpointUri, isHubEndpoint, openWebSocket, parseEndpointUri, runInitializeHandshake, traceMessageTransport as traceMessageTransport$1 } from "@hediet/linkrpc/node";
|
|
@@ -26,6 +26,7 @@ import { stdin, stdout } from "node:process";
|
|
|
26
26
|
import { TrafficFlowAggregator, createTerminalConsentPrompt, formatFlowSummary } from "@hediet/linkrpc-hub";
|
|
27
27
|
import { loadHubConfig, printHubConfigSchema } from "@hediet/linkrpc-hub/config-file";
|
|
28
28
|
import { connectJsonRpcTransports, connectRawJsonRpcTransport, createNdjsonJsonRpcTransport, jsonRpcConnectionInterface } from "@hediet/linkrpc-infra/json-rpc";
|
|
29
|
+
import { startJsonRpcWebSocketExport, validateJsonRpcExport } from "@hediet/linkrpc-infra/json-rpc/node";
|
|
29
30
|
import { GRAPH_INTERFACE_TAG, IMMUTABLE_GRAPH_INTERFACE_ID, ROOT_WATCH_INTERFACE_ID, evaluateGraphPresentation, graphPresentationInterface, graphPresentationSchema, isGraphRef, standardGraphRuntimeOptions, validateGraphInterfaceSchema } from "@hediet/linkrpc-infra/graph";
|
|
30
31
|
import React from "react";
|
|
31
32
|
import { Box, Text, measureElement, render } from "ink";
|
|
@@ -406,7 +407,7 @@ function contextNamespace(reference) {
|
|
|
406
407
|
async function useLocalManagement(start, action) {
|
|
407
408
|
const home = HubHome.resolve();
|
|
408
409
|
if (start) {
|
|
409
|
-
const { startDaemon, nodeDaemonLaunch } = await import("./src-
|
|
410
|
+
const { startDaemon, nodeDaemonLaunch } = await import("./src-yrqRWXzG.js");
|
|
410
411
|
if (await startDaemon({
|
|
411
412
|
home,
|
|
412
413
|
launch: nodeDaemonLaunch(home)
|
|
@@ -426,7 +427,7 @@ async function useLocalManagement(start, action) {
|
|
|
426
427
|
}
|
|
427
428
|
}
|
|
428
429
|
async function restartLocalDaemon() {
|
|
429
|
-
const { startDaemon, stopDaemon, nodeDaemonLaunch } = await import("./src-
|
|
430
|
+
const { startDaemon, stopDaemon, nodeDaemonLaunch } = await import("./src-yrqRWXzG.js");
|
|
430
431
|
const home = HubHome.resolve();
|
|
431
432
|
process.stderr.write("Restarting the local Hub daemon: clients will disconnect and managed workloads will stop. OS autostart settings are unchanged.\n");
|
|
432
433
|
await stopDaemon(home);
|
|
@@ -3510,6 +3511,36 @@ async function jsonRpcStdioCommand(options) {
|
|
|
3510
3511
|
stdio.close("closed");
|
|
3511
3512
|
}
|
|
3512
3513
|
//#endregion
|
|
3514
|
+
//#region src/commands/jsonRpcExport.ts
|
|
3515
|
+
/** Preserve option order so a missing path cannot shift subsequent service mappings. */
|
|
3516
|
+
var JsonRpcExportRoutes = class {
|
|
3517
|
+
_routes = [];
|
|
3518
|
+
_pendingService;
|
|
3519
|
+
serviceId(value) {
|
|
3520
|
+
if (this._pendingService !== void 0) throw new Error("Each --serviceId must be followed by --path.");
|
|
3521
|
+
this._pendingService = value;
|
|
3522
|
+
}
|
|
3523
|
+
path(value) {
|
|
3524
|
+
if (this._pendingService === void 0) throw new Error("--path must follow --serviceId.");
|
|
3525
|
+
this._routes.push({
|
|
3526
|
+
serviceId: this._pendingService,
|
|
3527
|
+
path: value.startsWith("/") ? value : `/${value}`
|
|
3528
|
+
});
|
|
3529
|
+
this._pendingService = void 0;
|
|
3530
|
+
}
|
|
3531
|
+
getRoutes() {
|
|
3532
|
+
if (this._pendingService !== void 0) throw new Error("Each --serviceId must be followed by --path.");
|
|
3533
|
+
return this._routes;
|
|
3534
|
+
}
|
|
3535
|
+
};
|
|
3536
|
+
async function jsonRpcExportCommand(options) {
|
|
3537
|
+
const connection = new LinkRpcConnection(options.local.rpcChannel);
|
|
3538
|
+
return startJsonRpcWebSocketExport({
|
|
3539
|
+
...options,
|
|
3540
|
+
openTransport: (serviceId, signal) => connectRawJsonRpcTransport(connection.service(serviceId).get(jsonRpcConnectionInterface), void 0, signal)
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
//#endregion
|
|
3513
3544
|
//#region ../../node_modules/.pnpm/@vscode+observables@0.1.1-0/node_modules/@vscode/observables/dist/observableInternal/logging/logging.js
|
|
3514
3545
|
let globalObservableLogger;
|
|
3515
3546
|
function addLogger(logger) {
|
|
@@ -8953,6 +8984,40 @@ Batch options:
|
|
|
8953
8984
|
});
|
|
8954
8985
|
});
|
|
8955
8986
|
if (profile === "hub") {
|
|
8987
|
+
const exportRoutes = new JsonRpcExportRoutes();
|
|
8988
|
+
program.command("json-rpc-export").description("Export Hub JSON-RPC services through one authenticated raw WebSocket listener.").requiredOption("--target-endpoint <uri>", "Listener URI, e.g. listen:ws://127.0.0.1:8123").option("--target-token <token>", "Local client authentication token (or put token in target URI)").option("--target-token-query-param <name>", "Accepted token query parameter (repeatable; replaces defaults tkn and token)", collectOption).option("--serviceId <id>", "Begin a route; follow each occurrence with --path", (value) => {
|
|
8989
|
+
exportRoutes.serviceId(value);
|
|
8990
|
+
return value;
|
|
8991
|
+
}).option("--path <path>", "Path for the preceding service ID; repeat pairs for multiple routes", (value) => {
|
|
8992
|
+
exportRoutes.path(value);
|
|
8993
|
+
return value;
|
|
8994
|
+
}).action(async (opts) => {
|
|
8995
|
+
const options = {
|
|
8996
|
+
targetEndpoint: opts.targetEndpoint,
|
|
8997
|
+
token: opts.targetToken,
|
|
8998
|
+
tokenQueryParameters: opts.targetTokenQueryParam,
|
|
8999
|
+
routes: exportRoutes.getRoutes()
|
|
9000
|
+
};
|
|
9001
|
+
validateJsonRpcExport(options);
|
|
9002
|
+
const localEp = needEndpoint(endpoint);
|
|
9003
|
+
const local = await connect(localEp, wireLog("hub"));
|
|
9004
|
+
try {
|
|
9005
|
+
reportIdentity(await setupSigning(local.channel, local.signing, getPrincipalSpec(), { negotiateHubCaps: isHubEndpoint(localEp) }));
|
|
9006
|
+
const server = await jsonRpcExportCommand({
|
|
9007
|
+
...options,
|
|
9008
|
+
local,
|
|
9009
|
+
onError: (error) => process.stderr.write(`linkrpc: ${error.message}\n`)
|
|
9010
|
+
});
|
|
9011
|
+
try {
|
|
9012
|
+
process.stderr.write(`linkrpc: JSON-RPC export listening at ${server.endpoint}\n`);
|
|
9013
|
+
await _untilSignalled();
|
|
9014
|
+
} finally {
|
|
9015
|
+
await server.close();
|
|
9016
|
+
}
|
|
9017
|
+
} finally {
|
|
9018
|
+
local.close();
|
|
9019
|
+
}
|
|
9020
|
+
});
|
|
8956
9021
|
program.command("json-rpc-stdio <serviceId>").description("Expose <serviceId>::jsonRpcConnection::connectRaw as a newline-delimited JSON-RPC endpoint on this process's stdin/stdout.").option("--params <json>", "JSON value passed to the remote transport factory").action(async (serviceId, opts) => {
|
|
8957
9022
|
const localEp = needEndpoint(endpoint);
|
|
8958
9023
|
let params;
|
|
@@ -9017,11 +9082,16 @@ Batch options:
|
|
|
9017
9082
|
const remote = await connectTargetEndpoint(targetEp, serviceId);
|
|
9018
9083
|
try {
|
|
9019
9084
|
reportIdentity(await setupSigning(local.channel, local.signing, getPrincipalSpec(), { negotiateHubCaps: isHubEndpoint(localEp) }));
|
|
9085
|
+
const lost = Promise.race([local.closed.then(() => "source"), remote.closed.then(() => "target")]).then((side) => {
|
|
9086
|
+
process.stderr.write(`linkrpc: tunnel: the ${side} connection closed\n`);
|
|
9087
|
+
process.exitCode = 1;
|
|
9088
|
+
});
|
|
9020
9089
|
await tunnelCommand({
|
|
9021
9090
|
serviceId,
|
|
9022
9091
|
local,
|
|
9023
9092
|
remote,
|
|
9024
|
-
bidi: cmdOpts.bidi
|
|
9093
|
+
bidi: cmdOpts.bidi,
|
|
9094
|
+
stop: Promise.race([lost, _untilSignalled()])
|
|
9025
9095
|
});
|
|
9026
9096
|
} finally {
|
|
9027
9097
|
remote.close();
|
|
@@ -9048,10 +9118,10 @@ Batch options:
|
|
|
9048
9118
|
const principal = typeof cmdOpts.signAs === "string" ? parsePrincipalSpec(cmdOpts.signAs) : getPrincipalSpec();
|
|
9049
9119
|
reportIdentity(await setupSigning(hub.channel, hub.signing, principal, { negotiateHubCaps: isHubEndpoint(localEp) }));
|
|
9050
9120
|
}
|
|
9051
|
-
const participant = targetEp === void 0 ? await connectStdioParticipant() : {
|
|
9052
|
-
connection
|
|
9053
|
-
closed:
|
|
9054
|
-
};
|
|
9121
|
+
const participant = targetEp === void 0 ? await connectStdioParticipant() : await connectTargetEndpoint(targetEp, cmdOpts.claim ?? "").then((connection) => ({
|
|
9122
|
+
connection,
|
|
9123
|
+
closed: connection.closed
|
|
9124
|
+
}));
|
|
9055
9125
|
try {
|
|
9056
9126
|
await proxyCommand({
|
|
9057
9127
|
hub,
|
|
@@ -9186,7 +9256,7 @@ Batch options:
|
|
|
9186
9256
|
process.once("SIGINT", onSignal);
|
|
9187
9257
|
process.once("SIGTERM", onSignal);
|
|
9188
9258
|
try {
|
|
9189
|
-
const { runApprovalUi } = await import("./runApprovalUi-
|
|
9259
|
+
const { runApprovalUi } = await import("./runApprovalUi-BdPp7WNP.js");
|
|
9190
9260
|
await runApprovalUi({
|
|
9191
9261
|
client,
|
|
9192
9262
|
signal: stop.signal
|
|
@@ -9201,7 +9271,7 @@ Batch options:
|
|
|
9201
9271
|
registerViewCommands(program, (action) => withChannel(endpoint, getPrincipalSpec(), action));
|
|
9202
9272
|
program.command("ui").description("Launch the terminal UI (form-based browser of services + methods).").action(async () => {
|
|
9203
9273
|
const acquired = await acquireConnection(endpoint);
|
|
9204
|
-
const { runUi } = await import("./runUi-
|
|
9274
|
+
const { runUi } = await import("./runUi-Deeox_Ef.js");
|
|
9205
9275
|
try {
|
|
9206
9276
|
await runUi({
|
|
9207
9277
|
endpoint: acquired.ep,
|
|
@@ -9737,4 +9807,4 @@ function safeJson(value) {
|
|
|
9737
9807
|
//#endregion
|
|
9738
9808
|
export { formatCondition as _, formatCommandLegend as a, targetId as b, safeTerminalText as c, ObservablePromise as d, observableValue as f, resolveViewTarget as g, Disposable as h, dispatchHostKey as i, approvalDetailLines as l, derived as m, views as n, hostCommands as o, autorun as p, ViewFrame as r, matchesKey as s, runCli as t, ObservableLazyPromise as u, interfaceTarget as v, matchesTarget as y };
|
|
9739
9809
|
|
|
9740
|
-
//# sourceMappingURL=cli-
|
|
9810
|
+
//# sourceMappingURL=cli-CXAAnZDA.js.map
|