Client Usage
Learn how to use the type-safe AMQP client to publish messages.
NestJS Users
If you're building a NestJS application, check out the NestJS Client Usage guide for automatic lifecycle management and dependency injection.
Installation
Install the required packages:
bash
pnpm add @amqp-contract/clientbash
npm install @amqp-contract/clientbash
yarn add @amqp-contract/clientCreating a Client
Create a type-safe client from your contract. The client automatically connects to RabbitMQ:
typescript
import { TypedAmqpClient } from '@amqp-contract/client';
import { contract } from './contract';
// Create client from contract (automatically connects)
const client = await TypedAmqpClient.create({
contract,
connection: 'amqp://localhost'
});Publishing Messages
The client provides type-safe publishing based on your contract publishers:
typescript
// TypeScript knows the available publishers and their message schemas
await client.publish('orderCreated', {
orderId: 'ORD-123',
customerId: 'CUST-456',
amount: 99.99,
items: [
{ productId: 'PROD-A', quantity: 2 },
],
});Type Safety
The client enforces:
- ✅ Valid publisher names - Only publishers defined in the contract
- ✅ Message schema - Messages must match the Zod schema
- ✅ Autocomplete - Full IDE support for publisher names and message fields
typescript
// ❌ TypeScript error: 'unknownPublisher' not in contract
await client.publish('unknownPublisher', { ... });
// ❌ TypeScript error: missing required field 'orderId'
await client.publish('orderCreated', {
customerId: 'CUST-456',
});
// ❌ Runtime error: Zod validation fails
await client.publish('orderCreated', {
orderId: 123, // should be string
customerId: 'CUST-456',
});Publishing Options
Custom Routing Key
Override the routing key for a specific message:
typescript
await client.publish(
'orderCreated',
{ orderId: 'ORD-123', amount: 99.99 },
{ routingKey: 'order.created.urgent' }
);Message Properties
Set AMQP message properties:
typescript
await client.publish(
'orderCreated',
{ orderId: 'ORD-123', amount: 99.99 },
{
persistent: true,
priority: 10,
contentType: 'application/json',
headers: {
'x-request-id': 'req-123',
},
}
);Connection Management
Closing the Connection
typescript
// Close the client (closes the channel)
await client.close();
// Close the connection
await connection.close();Error Handling
typescript
try {
await client.publish('orderCreated', {
orderId: 'ORD-123',
amount: 99.99,
});
} catch (error) {
if (error.name === 'ZodError') {
console.error('Validation failed:', error.issues);
} else {
console.error('Publishing failed:', error);
}
}Advanced Usage
Multiple Clients
You can create multiple clients from the same contract:
typescript
const client1 = await TypedAmqpClient.create({ contract, connection: connection1 });
const client2 = await TypedAmqpClient.create({ contract, connection: connection2 });Reusing Connections
Share a single connection across clients:
typescript
const connection = await connect('amqp://localhost');
const orderClient = await TypedAmqpClient.create({
contract: orderContract,
connection,
});
const paymentClient = await TypedAmqpClient.create({
contract: paymentContract,
connection,
});Best Practices
- Validate Early - Let Zod catch invalid data before publishing
- Handle Errors - Always wrap publish calls in try-catch
- Reuse Clients - Share clients when possible for the same contract
- Close Cleanly - Always close clients on shutdown (closes both channel and connection)
- Use Persistent Messages - Set
persistent: truefor important messages
Complete Example
typescript
import { TypedAmqpClient } from '@amqp-contract/client';
import { contract } from './contract';
async function main() {
let client;
try {
// Connect
client = await TypedAmqpClient.create({
contract,
connection: 'amqp://localhost'
});
// Publish messages
await client.publish('orderCreated', {
orderId: 'ORD-123',
customerId: 'CUST-456',
amount: 99.99,
items: [
{ productId: 'PROD-A', quantity: 2 },
],
});
console.log('Message published successfully');
} catch (error) {
console.error('Error:', error);
} finally {
// Cleanup - closes both channel and connection
await client?.close();
}
}
main();Next Steps
- Learn about Worker Usage for consuming messages
- Explore Defining Contracts
- See Examples for complete implementations