@hediet/linkrpc-cli 0.0.2 → 0.0.3-next.20260921.2
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 +33 -1
- package/dist/chunks/{cli-D_-vlAa2.js → cli-FDKN1ydZ.js} +55 -15
- package/dist/chunks/cli-FDKN1ydZ.js.map +1 -0
- package/dist/chunks/{runApprovalUi-BvJZdjKm.js → runApprovalUi-CTyhiDpa.js} +3 -3
- package/dist/chunks/{runApprovalUi-BvJZdjKm.js.map → runApprovalUi-CTyhiDpa.js.map} +1 -1
- package/dist/chunks/{runComplete-BkQwzPbF.js → runComplete-Du5wmOdB.js} +12 -72
- package/dist/chunks/runComplete-Du5wmOdB.js.map +1 -0
- package/dist/chunks/{runUi-D-8LMU4F.js → runUi-CuJr8_tY.js} +4 -4
- package/dist/chunks/{runUi-D-8LMU4F.js.map → runUi-CuJr8_tY.js.map} +1 -1
- package/dist/chunks/{scroll-BTzAYh4N.js → scroll--AVfTs5W.js} +2 -2
- package/dist/chunks/{scroll-BTzAYh4N.js.map → scroll--AVfTs5W.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 +10 -5
- package/dist/chunks/cli-D_-vlAa2.js.map +0 -1
- package/dist/chunks/runComplete-BkQwzPbF.js.map +0 -1
package/README.md
CHANGED
|
@@ -133,16 +133,48 @@ LINKRPC_ENDPOINT=unix:/run/hub/hub.sock?token=abc linkrpc ls
|
|
|
133
133
|
| ----------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
134
134
|
| `ls` | Explore the directory referral graph and its services/interfaces. Supports exact and prefix filters, regexp `--search`, `--format pretty\|json\|jsonl`, `--watch`, `--dump <file>`, and `--dump-patches <file\|->`. |
|
|
135
135
|
| `defaults` | Print the preset service/interface (wraps `hubrpc.defaults::get`). |
|
|
136
|
+
| `contract export --output <file\|-> [--service <id>] [--max-depth <n>]` | Export a complete reusable static contract from live reflection. |
|
|
136
137
|
| `schema show <interfaceId>[@hash]` | Print an interface schema (wraps `hubrpc.schemas::get`). `--method <name>`, `--json`. |
|
|
137
138
|
| `schema hash <schema.json>` | Compute `computeInterfaceHash` for a local schema without connecting. |
|
|
138
139
|
| `schema check-compat <interfaceId> <local.json>` | Compare a live interface schema with a local schema. |
|
|
139
140
|
| `codegen --input <bundle> --interface <id> --name <name> --output <file> [--preserve-wire-schema] [--check]` | Generate a TypeScript interface definition from a validated offline static bundle. |
|
|
141
|
+
| `codegen --input <contract> --output <file> [--names <json>] [--check]` | Generate all reusable interface definitions and typed root/service/default/bare bindings. |
|
|
140
142
|
|
|
141
|
-
`codegen` uses the same `{ interfaceSchemas, services
|
|
143
|
+
`codegen` uses the same `{ interfaceSchemas, services?, defaultInterface?, bareInterfaces? }`
|
|
142
144
|
bundle parser and interface-hash verification as static reflection. `--check`
|
|
143
145
|
compares the generated source with the output file and exits unsuccessfully if
|
|
144
146
|
the file is missing or stale; it never overwrites in check mode.
|
|
145
147
|
|
|
148
|
+
```sh
|
|
149
|
+
linkrpc --endpoint-cmd-stdio "node server.js" contract export --output contract.json
|
|
150
|
+
linkrpc codegen --input contract.json --output generated.ts
|
|
151
|
+
linkrpc codegen --input contract.json --output generated.ts --check
|
|
152
|
+
# Existing per-interface generation remains available:
|
|
153
|
+
linkrpc codegen --input contract.json --interface demo.echo --name echoInterface \
|
|
154
|
+
--output echo.ts --preserve-wire-schema
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Omit both `--interface` and `--name` for whole-contract generation. Every interface
|
|
158
|
+
is emitted once, with canonical wire schemas preserved, and each binding refers
|
|
159
|
+
to that definition. For `demo.echo`, default names include `demoEchoInterface`,
|
|
160
|
+
`demoEchoRoot`, `demoEchoDefault`, and (for bare prefix `Runtime.`) `runtimeBare`.
|
|
161
|
+
A service `worker` produces `workerDemoEchoService`. If names collide, supply a
|
|
162
|
+
local `--names` JSON file containing `interfaceNames` (`"id@hash": "exportName"`)
|
|
163
|
+
and/or `bindingNames` (`"root:id@hash"`, `"service:serviceId:id@hash"`,
|
|
164
|
+
`"default"`, or `"bare:prefix"` keys). Unknown keys and colliding overrides fail.
|
|
165
|
+
|
|
166
|
+
Contract export queries directory interfaces, `defaults.get`, and
|
|
167
|
+
`defaults.listBindings`; it fails explicitly if discovery is inaccessible,
|
|
168
|
+
truncated or depth-limited, default metadata is incomplete, or schemas cannot be
|
|
169
|
+
retrieved and hash-verified. It writes the output only after successful completion.
|
|
170
|
+
`--service` selects a reflection scope; default/bare bindings describe that scope's
|
|
171
|
+
preset routes, not additional service-qualified foreign methods. No default or
|
|
172
|
+
bare bindings are guessed from directory listings.
|
|
173
|
+
|
|
174
|
+
`ls --dump` remains the diagnostic graph format, including directory provenance.
|
|
175
|
+
It is not a static contract and is not an input to `contract export`. Export a
|
|
176
|
+
contract directly from the endpoint for offline generation instead.
|
|
177
|
+
|
|
146
178
|
`hub ls --format json` waits for finite exploration and prints the final state.
|
|
147
179
|
`--format jsonl` emits progressive state while requests fan out: the first line
|
|
148
180
|
is `{ "type": "snapshot", "revision": n, "value": ... }` and each later line
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as connectViaRootOverlay, C as findMethodInSchema, D as formatPrincipalSource, E as logoutCliIdentity, F as describeSchema, H as mcpForwardInterface, I as explainValidation, L as validateValueAgainstSchema, M as resolveTargetEndpoint, N as resolvedEndpointToConfig, O as parsePrincipalSpec, P as describeObjectParams, S as fetchSchema$1, V as MethodRefWithOptHash, a as resolveStaticHubSchemaSource, b as setupSigning, c as resolveInvocationEndpoint, d as formatContextReference, i as loadStaticHubSchema, j as connectViaTransport, k as connect, l as validationDefault, n as StaticHubReflection, o as mutationReference, p as resolveCliInvocation, r as withStaticHubReflection, s as resolveInvocationContext, t as completeForLine, u as ContextStore, v as requestReflectionAccess, w as walkHub, x as fetchDefaults, y as requestTopologyAccess, z as mergeParams } from "./runComplete-
|
|
2
|
-
import { ErrorCode, LinkRpcConnection, RpcError, TransportPair, computeInterfaceHash, connectTransports, generateTsInterface, isAssignable, jcsCanonicalize } from "@hediet/linkrpc";
|
|
1
|
+
import { A as connectViaRootOverlay, C as findMethodInSchema, D as formatPrincipalSource, E as logoutCliIdentity, F as describeSchema, H as mcpForwardInterface, I as explainValidation, L as validateValueAgainstSchema, M as resolveTargetEndpoint, N as resolvedEndpointToConfig, O as parsePrincipalSpec, P as describeObjectParams, S as fetchSchema$1, V as MethodRefWithOptHash, a as resolveStaticHubSchemaSource, b as setupSigning, c as resolveInvocationEndpoint, d as formatContextReference, i as loadStaticHubSchema, j as connectViaTransport, k as connect, l as validationDefault, n as StaticHubReflection, o as mutationReference, p as resolveCliInvocation, r as withStaticHubReflection, s as resolveInvocationContext, t as completeForLine, u as ContextStore, v as requestReflectionAccess, w as walkHub, x as fetchDefaults, y as requestTopologyAccess, z as mergeParams } from "./runComplete-Du5wmOdB.js";
|
|
2
|
+
import { ErrorCode, LinkRpcConnection, RpcError, TransportPair, computeInterfaceHash, connectTransports, exportStaticHubSchema, generateTsContract, generateTsInterface, isAssignable, jcsCanonicalize } from "@hediet/linkrpc";
|
|
3
3
|
import { WebSocketTransport, connectNdjson, formatEndpointUri, isHubEndpoint, openWebSocket, parseEndpointUri, runInitializeHandshake, traceMessageTransport as traceMessageTransport$1 } from "@hediet/linkrpc/node";
|
|
4
4
|
import { SocketServer } from "@hediet/linkrpc-hub/hub/server/node";
|
|
5
5
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -1256,14 +1256,30 @@ function formatVerdict(v) {
|
|
|
1256
1256
|
//#region src/commands/codegen.ts
|
|
1257
1257
|
async function codegenCommand(options) {
|
|
1258
1258
|
if (/^https?:\/\//i.test(options.input)) throw new Error("codegen --input must be a local offline bundle");
|
|
1259
|
-
if (!/^[$A-Z_a-z][$\w]*$/.test(options.name)) throw new Error(`codegen --name must be a valid TypeScript identifier, got '${options.name}'`);
|
|
1260
|
-
const
|
|
1261
|
-
|
|
1262
|
-
if (
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1259
|
+
if (options.name !== void 0 && !/^[$A-Z_a-z][$\w]*$/.test(options.name)) throw new Error(`codegen --name must be a valid TypeScript identifier, got '${options.name}'`);
|
|
1260
|
+
const bundle = await loadStaticHubSchema(options.input);
|
|
1261
|
+
let generated;
|
|
1262
|
+
if (options.interfaceId === void 0) {
|
|
1263
|
+
if (options.name !== void 0) throw new Error("codegen --name requires --interface");
|
|
1264
|
+
let naming = {};
|
|
1265
|
+
if (options.names !== void 0) {
|
|
1266
|
+
const raw = JSON.parse(await readFile(options.names, "utf8"));
|
|
1267
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw) || Object.keys(raw).some((key) => key !== "interfaceNames" && key !== "bindingNames")) throw new Error("codegen --names must contain only interfaceNames and bindingNames maps");
|
|
1268
|
+
for (const map of Object.values(raw)) if (map === null || typeof map !== "object" || Array.isArray(map) || Object.values(map).some((name) => typeof name !== "string")) throw new Error("codegen --names values must be string maps");
|
|
1269
|
+
naming = raw;
|
|
1270
|
+
}
|
|
1271
|
+
generated = generateTsContract(bundle, naming);
|
|
1272
|
+
} else {
|
|
1273
|
+
if (options.name === void 0) throw new Error("codegen --interface requires --name");
|
|
1274
|
+
if (options.names !== void 0) throw new Error("codegen --names is only supported for whole contracts");
|
|
1275
|
+
const matches = bundle.interfaceSchemas.filter((schema) => schema.id === options.interfaceId);
|
|
1276
|
+
if (matches.length === 0) throw new Error(`Interface '${options.interfaceId}' was not found in bundle '${options.input}'`);
|
|
1277
|
+
if (matches.length > 1) throw new Error(`Interface '${options.interfaceId}' is ambiguous in bundle '${options.input}' (${matches.length} schema versions)`);
|
|
1278
|
+
generated = generateTsInterface(matches[0], {
|
|
1279
|
+
exportName: options.name,
|
|
1280
|
+
preserveWireSchema: options.preserveWireSchema === true
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1267
1283
|
if (options.check === true) {
|
|
1268
1284
|
let current;
|
|
1269
1285
|
try {
|
|
@@ -1279,6 +1295,17 @@ async function codegenCommand(options) {
|
|
|
1279
1295
|
await writeFile(options.output, generated, "utf8");
|
|
1280
1296
|
}
|
|
1281
1297
|
//#endregion
|
|
1298
|
+
//#region src/commands/contract.ts
|
|
1299
|
+
async function exportContractCommand(channel, options) {
|
|
1300
|
+
const document = await exportStaticHubSchema(channel, options);
|
|
1301
|
+
const text = `${JSON.stringify(document, null, 2)}\n`;
|
|
1302
|
+
if (options.output === "-") process.stdout.write(text);
|
|
1303
|
+
else {
|
|
1304
|
+
await mkdir(dirname(options.output), { recursive: true });
|
|
1305
|
+
await writeFile(options.output, text, "utf8");
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
//#endregion
|
|
1282
1309
|
//#region src/completions/shellScripts.ts
|
|
1283
1310
|
const SUPPORTED = /* @__PURE__ */ new Set(["powershell"]);
|
|
1284
1311
|
function isSupportedShell(name) {
|
|
@@ -5140,16 +5167,29 @@ async function main(rawArgv, executableName = "linkrpc") {
|
|
|
5140
5167
|
process.stdout.write(out + "\n");
|
|
5141
5168
|
});
|
|
5142
5169
|
});
|
|
5143
|
-
program.command("codegen").description("Generate
|
|
5170
|
+
program.command("codegen").description("Generate reusable TypeScript interfaces and bindings from an offline contract.").requiredOption("--input <bundle>", "local static hub schema bundle").option("--interface <id>", "generate only this interface (requires --name)").option("--name <name>", "single-interface exported TypeScript const name").option("--names <file>", "whole-contract JSON interfaceNames/bindingNames overrides").requiredOption("--output <file>", "generated TypeScript output file").option("--preserve-wire-schema", "freeze the canonical input schema verbatim in the generated definition").option("--check", "fail if the output is missing or stale without overwriting it").action(async (opts) => {
|
|
5144
5171
|
await codegenCommand({
|
|
5145
5172
|
input: opts.input,
|
|
5146
5173
|
interfaceId: opts.interface,
|
|
5147
5174
|
name: opts.name,
|
|
5148
5175
|
output: opts.output,
|
|
5149
5176
|
preserveWireSchema: opts.preserveWireSchema === true,
|
|
5150
|
-
check: opts.check === true
|
|
5177
|
+
check: opts.check === true,
|
|
5178
|
+
names: opts.names
|
|
5151
5179
|
});
|
|
5152
5180
|
});
|
|
5181
|
+
program.command("contract").description("Export reusable static interface and binding contracts.").command("export").requiredOption("--output <file>", "contract JSON destination, or - for stdout").option("--service <id>", "reflection scope (defaults to the endpoint root)").option("--max-depth <depth>", "maximum directory referral depth", (value) => {
|
|
5182
|
+
if (!/^\d+$/.test(value)) throw new InvalidArgumentError("depth must be a non-negative integer");
|
|
5183
|
+
return Number(value);
|
|
5184
|
+
}).action(async (opts) => {
|
|
5185
|
+
await withChannel(endpoint, getPrincipalSpec(), async (channel) => {
|
|
5186
|
+
await exportContractCommand(channel, {
|
|
5187
|
+
output: opts.output,
|
|
5188
|
+
serviceId: opts.service,
|
|
5189
|
+
maxDepth: opts.maxDepth
|
|
5190
|
+
});
|
|
5191
|
+
}, { requestReflectionAccess: true });
|
|
5192
|
+
});
|
|
5153
5193
|
const schema = program.command("schema").description("Inspect, hash, and compare LinkRPC interface schemas.");
|
|
5154
5194
|
schema.command("show <interfaceRef>").description("Print an interface schema. `<interfaceRef>` is `id[@hash]`.").option("--method <name>", "show only this method").option("--service <id>", "route the lookup to this service (form-3); needed behind a hub").option("--json", "raw JSON output").action(async (interfaceRef, opts) => {
|
|
5155
5195
|
const { id, hash } = parseInterfaceRef(interfaceRef);
|
|
@@ -5625,7 +5665,7 @@ Batch options:
|
|
|
5625
5665
|
process.once("SIGINT", onSignal);
|
|
5626
5666
|
process.once("SIGTERM", onSignal);
|
|
5627
5667
|
try {
|
|
5628
|
-
const { runApprovalUi } = await import("./runApprovalUi-
|
|
5668
|
+
const { runApprovalUi } = await import("./runApprovalUi-CTyhiDpa.js");
|
|
5629
5669
|
await runApprovalUi({
|
|
5630
5670
|
client,
|
|
5631
5671
|
signal: stop.signal
|
|
@@ -5639,7 +5679,7 @@ Batch options:
|
|
|
5639
5679
|
}
|
|
5640
5680
|
program.command("ui").description("Launch the terminal UI (form-based browser of services + methods).").action(async () => {
|
|
5641
5681
|
const acquired = await acquireConnection(endpoint);
|
|
5642
|
-
const { runUi } = await import("./runUi-
|
|
5682
|
+
const { runUi } = await import("./runUi-CuJr8_tY.js");
|
|
5643
5683
|
try {
|
|
5644
5684
|
await runUi({
|
|
5645
5685
|
endpoint: acquired.ep,
|
|
@@ -6070,4 +6110,4 @@ function safeJson(value) {
|
|
|
6070
6110
|
//#endregion
|
|
6071
6111
|
export { observableValue as a, Disposable as c, ObservablePromise as i, approvalDetailLines as n, autorun as o, ObservableLazyPromise as r, derived as s, runCli as t };
|
|
6072
6112
|
|
|
6073
|
-
//# sourceMappingURL=cli-
|
|
6113
|
+
//# sourceMappingURL=cli-FDKN1ydZ.js.map
|