@xtr-dev/zod-rpc
Version:
Simple, type-safe RPC library with Zod validation and automatic TypeScript inference
130 lines • 4.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRpcClient = exports.RpcClientBuilder = exports.connect = exports.RPCClientBuilder = exports.createRPCClient = void 0;
const channel_1 = require("./channel");
const transports_1 = require("./transports");
const service_1 = require("./service");
/**
* Create a type-safe RPC client for calling remote services.
*
* @param config - Client configuration including URL, services, and options
* @returns Promise that resolves to a fully typed RPC client
*
* @example
* ```typescript
* const client = await createRPCClient({
* url: 'ws://localhost:8080',
* services: { user: userService, math: mathService }
* });
*
* const user = await client.user.get({ userId: '123' });
* ```
* @group Client API
*/
async function createRPCClient(config) {
const { url, services, defaultTarget = 'auto', timeout = 30000, clientId = 'client' } = config;
const transport = url.startsWith('ws://') || url.startsWith('wss://')
? (0, transports_1.createWebSocketTransport)(url)
: (0, transports_1.createHTTPTransport)({ baseUrl: url });
const channel = new channel_1.Channel(clientId, timeout);
await channel.connect(transport);
let currentDefaultTarget = defaultTarget;
const client = {};
for (const [serviceName, serviceDefinition] of Object.entries(services)) {
const contracts = (0, service_1.createServiceContracts)(serviceDefinition);
const targetId = currentDefaultTarget === 'auto' ? serviceDefinition.id : currentDefaultTarget;
const enhancedClient = {};
for (const [methodName, contract] of Object.entries(contracts)) {
enhancedClient[methodName] = async (input, options) => {
const actualTarget = options?.target || targetId;
const actualTimeout = options?.timeout;
return channel.invoke(actualTarget, contract.id, input, contract.input, contract.output, actualTimeout);
};
}
client[serviceName] = enhancedClient;
}
client.disconnect = () => channel.disconnect();
client.isConnected = () => transport.isConnected();
client.setDefaultTarget = (target) => {
currentDefaultTarget = target;
};
return client;
}
exports.createRPCClient = createRPCClient;
exports.createRpcClient = createRPCClient;
/**
* Fluent builder pattern for creating RPC clients with advanced configurations.
* Provides a chainable API for setting client options before building the final client.
*
* @example
* ```typescript
* const client = await connect('ws://localhost:8080')
* .withId('my-client')
* .withTimeout(10000)
* .withServices({ user: userService, math: mathService })
* .build();
* ```
*
* @group Client API
*/
class RPCClientBuilder {
constructor(url) {
this.config = {};
this.services = {};
this.url = '';
this.url = url;
this.config.transport =
url.startsWith('ws://') || url.startsWith('wss://') ? 'websocket' : 'http';
}
withId(clientId) {
const newBuilder = new RPCClientBuilder(this.url);
newBuilder.config = { ...this.config, clientId };
newBuilder.services = { ...this.services };
return newBuilder;
}
withTimeout(timeout) {
const newBuilder = new RPCClientBuilder(this.url);
newBuilder.config = { ...this.config, timeout };
newBuilder.services = { ...this.services };
return newBuilder;
}
withServices(services) {
const newBuilder = new RPCClientBuilder(this.url);
newBuilder.config = { ...this.config };
newBuilder.services = services;
return newBuilder;
}
async build() {
return createRPCClient({
url: this.url,
services: this.services,
clientId: this.config.clientId,
timeout: this.config.timeout,
});
}
}
exports.RPCClientBuilder = RPCClientBuilder;
exports.RpcClientBuilder = RPCClientBuilder;
/**
* Create a new RPC client builder for fluent configuration.
* This is the preferred way to create clients with custom settings.
*
* @param url - WebSocket or HTTP URL to connect to
* @returns A new RPCClientBuilder instance for chaining configuration
*
* @example
* ```typescript
* const client = await connect('ws://localhost:8080')
* .withId('my-client')
* .withTimeout(10000)
* .withServices({ user: userService })
* .build();
* ```
*
* @group Client API
*/
function connect(url) {
return new RPCClientBuilder(url);
}
exports.connect = connect;
//# sourceMappingURL=client.js.map