Adds examples/auth-showcase/app/services/greeter-client.ts so the showcase demonstrates both halves - the review noted the example was callee-only, so a developer had no working reference for making a call. Raises integration coverage to the planned 3 tests and adds the missing rpc-endpoint cases. Also wires the prod build path for services. 304 tests pass across rpc/router/dev-server/cli; typecheck, lint, format and check:public-api all clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@wrnexus/rpc
Define a service contract in a shared workspace package, then import that same contract from the caller and callee.
import {
defineService,
implement,
inProcessTransport,
procedure,
serviceClient,
} from "@wrnexus/rpc";
import { v } from "@wrnexus/validation";
const greeter = defineService({
name: "greeter",
procedures: {
greet: procedure
.input(v.object({ name: v.string() }))
.output<{ message: string }>()
.build(),
},
});
const service = implement(
greeter,
{ greet: async ({ name }) => ({ message: `Hello, ${name}` }) },
{ selfApp: "greeter" },
);
const client = serviceClient(greeter, {
app: "greeter",
transport: inProcessTransport({
"greeter/greet": (input, identity) => service.invoke("greet", input, identity),
}),
});
await client.greet({ name: "Ada" });
Service files default-export implement(...) from app/services. The development server mounts them under the private /__wrnexus/rpc prefix.
Pass { as: ctx } to serviceClient to propagate the subject. The signed token contains only subject and tenant identifiers; permissions are always checked by the callee. Set WRNEXUS_RPC_SECRET in every app, use at least 32 characters, and never reuse the session secret.
Calls time out by default. Retrying is intentionally deferred; when introduced, only procedures marked .idempotent() may be retried.