@medicine-wheel/events 0.0.0-stage → 0.18.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 +121 -2
- package/dist/catalog.d.ts +747 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +278 -0
- package/dist/catalog.js.map +1 -0
- package/dist/decide.d.ts +109 -0
- package/dist/decide.d.ts.map +1 -0
- package/dist/decide.js +275 -0
- package/dist/decide.js.map +1 -0
- package/dist/envelope.d.ts +81 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +77 -0
- package/dist/envelope.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +18 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +107 -0
- package/dist/log.js.map +1 -0
- package/dist/publish.d.ts +109 -0
- package/dist/publish.d.ts.map +1 -0
- package/dist/publish.js +239 -0
- package/dist/publish.js.map +1 -0
- package/dist/schema.d.ts +31 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +174 -0
- package/dist/schema.js.map +1 -0
- package/package.json +63 -4
- package/schema/asyncapi.json +2374 -0
- package/schema/wheel-events.schema.json +1581 -0
package/README.md
CHANGED
|
@@ -1,3 +1,122 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @medicine-wheel/events
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The events a Medicine Wheel writes when something happens on it: a cycle
|
|
4
|
+
opened, a beat recorded, a ceremony closed, a circle created, a chronicle
|
|
5
|
+
episode registered, a relation woven. One catalog, the envelope the events
|
|
6
|
+
travel in, the files that describe them for any consumer, the log they wait in,
|
|
7
|
+
and the seam a broker plugs into.
|
|
8
|
+
|
|
9
|
+
The wheel keeps each record's latest state in its store. This package keeps the
|
|
10
|
+
moments: every write the wheel commits leaves one line in `events.jsonl`
|
|
11
|
+
beside the store. Nothing leaves the machine until a publisher is configured.
|
|
12
|
+
Episode 548 of the Miadi Chronicle is choosing the broker
|
|
13
|
+
(jgwill/medicine-wheel#164, miadisabelle/kherix-hermeneia#70).
|
|
14
|
+
|
|
15
|
+
## For a consumer
|
|
16
|
+
|
|
17
|
+
| file | what it is |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `schema/wheel-events.schema.json` | One JSON Schema (draft-07) that validates any wheel event: the envelope, plus each event's type, subject kind and payload. |
|
|
20
|
+
| `schema/asyncapi.json` | An AsyncAPI 3.0 document: one channel per event, addressed by its topic (`medicine-wheel.cycle.opened`). AsyncAPI is to events what OpenAPI is to HTTP; AsyncAPI Studio renders it and generators read it. It names no server, because no broker is chosen. |
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
const schema = require('@medicine-wheel/events/schema/wheel-events.schema.json');
|
|
24
|
+
const { WHEEL_EVENT_CATALOG, filterEvents } = require('@medicine-wheel/events');
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A payload carries references and labels — ids, a direction, a type — never a
|
|
28
|
+
person's words. A cycle's question, a beat's prose and a diary entry's text
|
|
29
|
+
stay in the wheel. To read one, fetch the record by `subject.id` from the wheel
|
|
30
|
+
that wrote the event (`source.instance`).
|
|
31
|
+
|
|
32
|
+
## The envelope
|
|
33
|
+
|
|
34
|
+
jgwill/Miadi's `MiadiEventEnvelope` 0.1.0
|
|
35
|
+
(`rispecs/events/00-miadi-event-spine.rispec.md`):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"id": "mwev:1792019860666:4c509d0b",
|
|
40
|
+
"schema_version": "0.1.0",
|
|
41
|
+
"event_type": "medicine-wheel.cycle.opened",
|
|
42
|
+
"source": { "kind": "miadi", "system": "medicine-wheel", "instance": "ilex:8040" },
|
|
43
|
+
"subject": { "kind": "cycle", "id": "cycle-1792019860642-hzqvkk" },
|
|
44
|
+
"occurred_at": "2026-10-14T23:17:40.666Z",
|
|
45
|
+
"observed_at": "2026-10-14T23:17:40.666Z",
|
|
46
|
+
"correlation_id": "cycle-1792019860642-hzqvkk",
|
|
47
|
+
"idempotency_key": "mwev:1792019860666:4c509d0b",
|
|
48
|
+
"privacy": { "classification": "internal", "content_included": false },
|
|
49
|
+
"payload": { "current_direction": "east" }
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- `idempotency_key` equals `id`. A resend of the same line is the same
|
|
54
|
+
occurrence; a receiver that keeps keys recognises it.
|
|
55
|
+
- `correlation_id` groups: a cycle and the beats recorded in it, a ceremony and
|
|
56
|
+
its closing, a conclusion and the person it is about.
|
|
57
|
+
- An amendment names what moved in `payload.changed`. A write that changes
|
|
58
|
+
nothing writes no event.
|
|
59
|
+
|
|
60
|
+
## The events
|
|
61
|
+
|
|
62
|
+
| family | events |
|
|
63
|
+
|---|---|
|
|
64
|
+
| cycle | `cycle.opened`, `cycle.amended`, `cycle.archived` |
|
|
65
|
+
| beat | `beat.recorded`, `beat.amended`, `beat.witnessed` |
|
|
66
|
+
| ceremony | `ceremony.opened`, `ceremony.closed`, `ceremony.amended`, `ceremony.removed` |
|
|
67
|
+
| diary | `diary.written`, `diary.amended`, `diary.removed` |
|
|
68
|
+
| circle | `circle.created`, `circle.amended`, `circle.removed` |
|
|
69
|
+
| chronicle episode | `chronicle.episode.registered`, `chronicle.episode.amended`, `chronicle.episode.removed` |
|
|
70
|
+
| memory conclusion | `memory.conclusion.recorded`, `memory.conclusion.judged`, `memory.conclusion.amended`, `memory.conclusion.removed` |
|
|
71
|
+
| node | `node.created`, `node.amended`, `node.removed` |
|
|
72
|
+
| relation | `relation.made`, `relation.amended`, `relation.removed` |
|
|
73
|
+
|
|
74
|
+
`WHEEL_EVENT_CATALOG` says, for each: what happened, which write produces it,
|
|
75
|
+
what its correlation groups, and every payload field. `PayloadOf<'beat.recorded'>`
|
|
76
|
+
is its payload type.
|
|
77
|
+
|
|
78
|
+
## For a producer
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { buildEvent, cycleWritten } from '@medicine-wheel/events';
|
|
82
|
+
import { appendEvent, eventLogPath } from '@medicine-wheel/events/log';
|
|
83
|
+
|
|
84
|
+
const input = cycleWritten(before, after, Object.keys(patch)); // null when nothing moved
|
|
85
|
+
if (input) appendEvent(eventLogPath(dataDir), buildEvent(input, { instance: process.env.MW_INSTANCE }));
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The deciders (`cycleWritten`, `beatWritten`, `beatWitnessed`, `ceremonyWritten`,
|
|
89
|
+
`diaryWritten`, `nodeWritten`, `conclusionJudged`, `relationWritten` and the
|
|
90
|
+
`*Removed` ones) are shared by the wheel's HTTP routes and the MCP server's
|
|
91
|
+
local store, so the same act leaves the same event whichever door it used.
|
|
92
|
+
|
|
93
|
+
## Publishing
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { drainLog, httpPublisher, rewind, publisherStatus } from '@medicine-wheel/events/publish';
|
|
97
|
+
|
|
98
|
+
await drainLog(logFile, httpPublisher({ url, token }));
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Episode 548 draws an event's path as Named → Sent → Arrived | Failed →
|
|
102
|
+
Replayed. An event in the log is Named. `drainLog` sends each event after the
|
|
103
|
+
publisher's cursor, in order, and writes the outcome to `events-receipts.jsonl`:
|
|
104
|
+
|
|
105
|
+
- `arrived`: a 2xx answer.
|
|
106
|
+
- `failed`: unreachable, timed out, 408, 429 or 5xx. The pass stops, and the
|
|
107
|
+
next one starts from the same event.
|
|
108
|
+
- `refused`: any other answer. It is recorded and passed, so one bad event does
|
|
109
|
+
not hold back the rest.
|
|
110
|
+
|
|
111
|
+
`rewind` is Replay: it moves the cursor back, and the same lines go out again
|
|
112
|
+
with the same idempotency keys. Each publisher keeps its own cursor
|
|
113
|
+
(`events-cursor.<name>.json`).
|
|
114
|
+
|
|
115
|
+
`httpPublisher` POSTs the envelope as JSON with `Idempotency-Key` and
|
|
116
|
+
`X-Event-Type` headers. Each of these can receive it: a webhook endpoint, a
|
|
117
|
+
Hookdeck source, a Cloudflare Worker in front of a queue, or the Miadi
|
|
118
|
+
hooks-gateway once it accepts this envelope. A broker client would be another
|
|
119
|
+
`Publisher` beside it. The events and their names stay the same.
|
|
120
|
+
|
|
121
|
+
In the wheel, set `MW_EVENTS_PUBLISH_URL` (and `MW_EVENTS_PUBLISH_TOKEN`) to turn
|
|
122
|
+
publishing on. `GET /api/health` then reports how many events are still owed.
|