@appport/client
The transport-independent application client.
import { createClient } from "@appport/client";
const client = createClient({ transport });
await client.connect();
await client.load(); // discovers capabilities and versions from the manifest
await client.call("documents.save", { documentId, content });
await client.capabilities.documents.save({ documentId, content });
for await (const chunk of client.stream("build.logs", { buildId })) console.log(chunk.line);
const unsubscribe = await client.events.subscribe("documents.changed", (payload) => refresh(payload));
The client builds envelopes, correlates responses, resolves capability versions
from the manifest, unwraps errors into AppPortError, and exposes capabilities
as a namespaced proxy. Application code never touches a protocol envelope.
If you use AppPort.discover() from @appport/client directly, pass the concrete
transport factories you want discovery to use. @appport/sdk keeps the built-in
HTTP and WebSocket factories wired in for the ergonomic aggregate entrypoint.
createDuplexTransport implements request correlation, subscriptions and stream
reassembly once, for every carrier that can push: WebSocket, Electron IPC, Tauri
IPC and the in-process bridge.
With a generated contract the client is fully typed:
import { createDocumentsClient } from "./appport/generated/client.ts";
const client = createDocumentsClient({ transport });
const { version } = await client.capabilities.documents.save({ documentId, content });
Secure discovery (1.1.0)
discoverApplication inspects an application's public description and verifies its references without connecting, authenticating or
invoking. discover now refuses redirects and cross-origin transport endpoints by default (redirects: "follow" and allowOrigins are the
explicit opt-ins), bounds the discovery document, and supports timeoutMs and signal. See @appport/sdk for the full description,
the behavior-change table and the limits.