@warlock.js/herald 5.29.0 → 5.31.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/CHANGELOG.md +15 -2
- package/README.md +17 -16
- package/cjs/index.cjs +10 -10
- package/cjs/index.cjs.map +1 -1
- package/esm/communicators/broker-registry.d.mts +1 -1
- package/esm/communicators/broker-registry.d.mts.map +1 -1
- package/esm/communicators/broker-registry.mjs +1 -1
- package/esm/communicators/broker-registry.mjs.map +1 -1
- package/esm/communicators/broker.d.mts +1 -1
- package/esm/communicators/broker.d.mts.map +1 -1
- package/esm/communicators/broker.mjs +1 -1
- package/esm/communicators/broker.mjs.map +1 -1
- package/esm/contracts/broker-driver.contract.d.mts +1 -1
- package/esm/contracts/broker-driver.contract.d.mts.map +1 -1
- package/esm/contracts/channel.contract.d.mts +1 -1
- package/esm/contracts/channel.contract.d.mts.map +1 -1
- package/esm/decorators/consumable.d.mts +1 -1
- package/esm/decorators/consumable.d.mts.map +1 -1
- package/esm/decorators/consumable.mjs +1 -1
- package/esm/decorators/consumable.mjs.map +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-channel.d.mts +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-channel.d.mts.map +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-channel.mjs +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-channel.mjs.map +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-driver.d.mts +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-driver.d.mts.map +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-driver.mjs +1 -1
- package/esm/drivers/rabbitmq/rabbitmq-driver.mjs.map +1 -1
- package/esm/message-managers/event-consumer.d.mts +1 -1
- package/esm/message-managers/event-consumer.d.mts.map +1 -1
- package/esm/message-managers/event-consumer.mjs +1 -1
- package/esm/message-managers/event-consumer.mjs.map +1 -1
- package/esm/message-managers/event-message.d.mts +1 -1
- package/esm/message-managers/event-message.d.mts.map +1 -1
- package/esm/message-managers/event-message.mjs +1 -1
- package/esm/message-managers/event-message.mjs.map +1 -1
- package/esm/message-managers/prepare-consumer-subscription.mjs +1 -1
- package/esm/message-managers/prepare-consumer-subscription.mjs.map +1 -1
- package/esm/message-managers/types.d.mts +1 -1
- package/esm/message-managers/types.d.mts.map +1 -1
- package/esm/types/channel.types.d.mts +2 -2
- package/esm/types/channel.types.d.mts.map +1 -1
- package/esm/types/connection.types.d.mts +1 -1
- package/esm/types/connection.types.d.mts.map +1 -1
- package/esm/types/driver.types.d.mts +1 -1
- package/esm/types/driver.types.d.mts.map +1 -1
- package/esm/types/message.types.d.mts +1 -1
- package/esm/types/message.types.d.mts.map +1 -1
- package/esm/types/publish.types.d.mts +1 -1
- package/esm/types/publish.types.d.mts.map +1 -1
- package/esm/types/registry.types.d.mts +1 -1
- package/esm/types/registry.types.d.mts.map +1 -1
- package/esm/types/subscribe.types.d.mts +1 -1
- package/esm/types/subscribe.types.d.mts.map +1 -1
- package/esm/use-case-broadcast.d.mts +1 -1
- package/esm/use-case-broadcast.d.mts.map +1 -1
- package/esm/use-case-broadcast.mjs +1 -1
- package/esm/use-case-broadcast.mjs.map +1 -1
- package/esm/utils/connect-to-broker.d.mts +1 -1
- package/esm/utils/connect-to-broker.d.mts.map +1 -1
- package/esm/utils/connect-to-broker.mjs +1 -1
- package/esm/utils/connect-to-broker.mjs.map +1 -1
- package/llms-full.txt +62 -57
- package/package.json +5 -4
- package/skills/consume-message/SKILL.md +30 -28
- package/skills/herald-basics/SKILL.md +8 -8
- package/skills/index.md +4 -1
- package/skills/publish-message/SKILL.md +19 -16
- package/skills/request-and-respond/SKILL.md +5 -5
package/skills/index.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 'Message bus over RabbitMQ (Kafka planned): publish, subscribe, and request-response between services. Exports `connectToBroker`, `herald`, `heraldChannel`, `Broker`, `defineEvent`, `defineConsumer`, `EventMessage`, `EventConsumer`, `Consumable`, `brokerRegistry`. Use for: "publish an event to RabbitMQ", "subscribe to a channel", "ack or nack a message", "request and reply over the bus", "cross-service messaging". Not this package: durable retried background jobs on Redis → @warlock.js/queue; cron/recurring work → @warlock.js/scheduler.'
|
|
3
3
|
---
|
|
4
|
+
|
|
4
5
|
# @warlock.js/herald
|
|
5
6
|
|
|
6
7
|
Herald is the broker-agnostic message bus. `connectToBroker(config)` boots a broker once; `herald()` returns it (`herald("name")` for a named one); `.channel(name)` is the queue/topic you publish into and subscribe from. Channels are typed with generics and can validate with a seal schema. Server-only.
|
|
7
8
|
|
|
8
9
|
## The 80% path
|
|
10
|
+
|
|
9
11
|
1. Orient with `herald-basics.md` (the map and foundations).
|
|
10
12
|
2. Connect at startup, then publish: `publish-message.md`.
|
|
11
13
|
3. Consume with `subscribe` handlers or consumer classes: `consume-message.md`.
|
|
12
14
|
4. Need a reply? `request-and-respond.md`.
|
|
13
15
|
|
|
14
16
|
## Conventions and pitfalls
|
|
17
|
+
|
|
15
18
|
- Call `connectToBroker` once before any publish or subscribe.
|
|
16
19
|
- Smart auto-ack is the default: a clean return acks, a throw nacks with requeue. `autoAck: true` loses messages on a crash; avoid it.
|
|
17
20
|
- Use `ctx.reject()` / `ctx.retry(ms)` only for a non-default outcome.
|
|
@@ -27,8 +27,8 @@ type UserPayload = { userId: number; email: string };
|
|
|
27
27
|
|
|
28
28
|
const channel = herald().channel<UserPayload>("user.created");
|
|
29
29
|
|
|
30
|
-
await channel.publish({ userId: 1, email: "test@example.com" });
|
|
31
|
-
await channel.publish({ userId: "1" } as never);
|
|
30
|
+
await channel.publish({ userId: 1, email: "test@example.com" }); // ✅ typed
|
|
31
|
+
await channel.publish({ userId: "1" } as never); // ❌ compile error
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Share the payload type between producer and consumer via a common `types/` file.
|
|
@@ -45,7 +45,7 @@ const userSchema = v.object({
|
|
|
45
45
|
|
|
46
46
|
const channel = herald().channel("user.created", { schema: userSchema });
|
|
47
47
|
|
|
48
|
-
await channel.publish({ userId: 1, email: "invalid" });
|
|
48
|
+
await channel.publish({ userId: 1, email: "invalid" }); // Throws — fails .email()
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
The schema runs `validate()` before the message hits the broker. Invalid payloads never leave the producer. See the `seal-basics` topic of the `warlock-js-seal` skill.
|
|
@@ -54,10 +54,10 @@ The schema runs `validate()` before the message hits the broker. Invalid payload
|
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
56
|
await channel.publish(payload, {
|
|
57
|
-
priority: 5,
|
|
58
|
-
expiration: 60_000,
|
|
59
|
-
delay: 5_000,
|
|
60
|
-
persistent: true,
|
|
57
|
+
priority: 5, // 0-9, higher = served first
|
|
58
|
+
expiration: 60_000, // ms — message expires if not consumed (RabbitMQ uses `expiration`, not `ttl`)
|
|
59
|
+
delay: 5_000, // ms — delayed delivery (requires RabbitMQ delay plugin)
|
|
60
|
+
persistent: true, // survive broker restart (default true)
|
|
61
61
|
correlationId: "uuid", // for tracking across services
|
|
62
62
|
headers: {
|
|
63
63
|
tenantId: "42",
|
|
@@ -71,14 +71,17 @@ The headers field is free-form — consumers read `message.metadata.headers?.ten
|
|
|
71
71
|
## Batch publishing
|
|
72
72
|
|
|
73
73
|
```ts
|
|
74
|
-
await channel.publishBatch(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
await channel.publishBatch(
|
|
75
|
+
[
|
|
76
|
+
{ userId: 1, email: "a@example.com" },
|
|
77
|
+
{ userId: 2, email: "b@example.com" },
|
|
78
|
+
{ userId: 3, email: "c@example.com" },
|
|
79
|
+
],
|
|
80
|
+
{
|
|
81
|
+
// Options apply to every message in the batch
|
|
82
|
+
persistent: true,
|
|
83
|
+
},
|
|
84
|
+
);
|
|
82
85
|
```
|
|
83
86
|
|
|
84
87
|
Under the hood `publishBatch` iterates and calls `.publish()` per message — there's no AMQP-level batching today. It's an ergonomic shape for "emit these N items" (bulk import, fanout to many recipients), not a throughput optimization. The same `options` apply to every message.
|
|
@@ -128,7 +131,7 @@ export default {
|
|
|
128
131
|
```ts
|
|
129
132
|
// The use case opts in — channel name defaults to the use case name.
|
|
130
133
|
export const createUserUseCase = useCase({
|
|
131
|
-
name: "users.create",
|
|
134
|
+
name: "users.create", // → publishes to channel "users.create"
|
|
132
135
|
schema: createUserSchema,
|
|
133
136
|
handler: async (data) => User.create(data),
|
|
134
137
|
broadcast: true,
|
|
@@ -36,12 +36,12 @@ The promise rejects if no reply arrives within `timeout` ms. Pick a sane number
|
|
|
36
36
|
|
|
37
37
|
## When to use it vs HTTP
|
|
38
38
|
|
|
39
|
-
| Use HTTP
|
|
40
|
-
|
|
|
39
|
+
| Use HTTP | Use request/respond |
|
|
40
|
+
| ------------------------------- | ------------------------------------------- |
|
|
41
41
|
| Stateless, fast, idempotent ops | Slow / queued ops where the caller can wait |
|
|
42
|
-
| Public API surface
|
|
43
|
-
| Frontend consumption
|
|
44
|
-
| Synchronous user-facing flow
|
|
42
|
+
| Public API surface | Internal service-to-service |
|
|
43
|
+
| Frontend consumption | Backend orchestration |
|
|
44
|
+
| Synchronous user-facing flow | Async-but-needs-result patterns |
|
|
45
45
|
|
|
46
46
|
The bus adds queue persistence and retry. HTTP is faster for sub-100ms ops; the bus shines when the operation has variable duration or needs a queue's backpressure.
|
|
47
47
|
|