@amqp-contract/contract 0.20.0 → 0.22.0

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 CHANGED
@@ -26,6 +26,7 @@ For robust contract definitions with guaranteed consistency, use Event or Comman
26
26
  | ----------- | ------------------------------------------ | -------------------------------------------------- |
27
27
  | **Event** | One publisher, many consumers (broadcast) | `defineEventPublisher` → `defineEventConsumer` |
28
28
  | **Command** | Many publishers, one consumer (task queue) | `defineCommandConsumer` → `defineCommandPublisher` |
29
+ | **RPC** | Request / response with typed reply | `defineRpc` (single bidirectional definition) |
29
30
 
30
31
  ```typescript
31
32
  import {
@@ -41,7 +42,7 @@ import {
41
42
  import { z } from "zod";
42
43
 
43
44
  // Event pattern: publisher broadcasts, consumers subscribe
44
- const ordersExchange = defineExchange("orders", "topic", { durable: true });
45
+ const ordersExchange = defineExchange("orders");
45
46
  const orderMessage = defineMessage(
46
47
  z.object({
47
48
  orderId: z.string(),
@@ -55,8 +56,8 @@ const orderCreatedEvent = defineEventPublisher(ordersExchange, orderMessage, {
55
56
  });
56
57
 
57
58
  // Multiple queues can consume the same event
58
- const orderQueue = defineQueue("order-processing", { durable: true });
59
- const analyticsQueue = defineQueue("analytics", { durable: true });
59
+ const orderQueue = defineQueue("order-processing");
60
+ const analyticsQueue = defineQueue("analytics");
60
61
 
61
62
  // Compose contract - exchanges, queues, bindings auto-extracted
62
63
  const contract = defineContract({
@@ -75,12 +76,41 @@ const contract = defineContract({
75
76
  });
76
77
  ```
77
78
 
79
+ ### RPC Pattern
80
+
81
+ Use `defineRpc` for typed request/response calls. RPC is bidirectional on both
82
+ ends — the worker handler consumes the request and produces a typed response;
83
+ the client awaits it via `client.call(name, request, { timeoutMs })`. Both
84
+ ends share the same definition, and RPCs live in their own `rpcs` slot of the
85
+ contract (not `publishers` or `consumers`). RabbitMQ direct reply-to is used
86
+ under the hood, so no reply queue declaration is needed.
87
+
88
+ ```typescript
89
+ import { defineContract, defineMessage, defineQueue, defineRpc } from "@amqp-contract/contract";
90
+ import { z } from "zod";
91
+
92
+ const calculate = defineRpc(defineQueue("rpc.calculate"), {
93
+ request: defineMessage(z.object({ a: z.number(), b: z.number() })),
94
+ response: defineMessage(z.object({ sum: z.number() })),
95
+ });
96
+
97
+ const contract = defineContract({
98
+ rpcs: { calculate },
99
+ });
100
+
101
+ // Server handler returns the response value, not void:
102
+ // handlers: { calculate: ({ payload }) => Future.value(Result.Ok({ sum: payload.a + payload.b })) }
103
+ //
104
+ // Client invokes with a required timeout:
105
+ // const result = await client.call("calculate", { a: 1, b: 2 }, { timeoutMs: 5_000 }).toPromise();
106
+ ```
107
+
78
108
  **Benefits:**
79
109
 
80
110
  - ✅ Guaranteed message schema consistency between publishers and consumers
81
111
  - ✅ Routing key validation and type safety
82
112
  - ✅ Full type safety with TypeScript inference
83
- - ✅ Event-oriented and command-oriented patterns
113
+ - ✅ Event, command, and RPC patterns
84
114
  - ✅ Flexible routing key patterns for topic exchanges
85
115
 
86
116
  ## Documentation