Skip to content

Commit 68f8c91

Browse files
committed
Update event naming and metadata based on review
1 parent 3164444 commit 68f8c91

27 files changed

+678
-324
lines changed

internal/events/README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This internal package defines CloudEvents-compatible schemas (with Zod) for the Supplier API domain – currently focusing on Letter Status Change events. It provides:
44

55
* A reusable CloudEvents envelope profile (`$EnvelopeProfile`)
6-
* Domain model schemas for letter status transitions (`$LetterStatus`, `$LetterStatusChange`)
6+
* Domain model schemas for letter status transitions (`$LetterStatus`, `$Letter`)
77
* Concrete per-status event schemas with strict `type`, `dataschema` URI and semantic version validation
88
* Utilities to programmatically access all status change event schemas (`statusChangeEvents`)
99

@@ -16,10 +16,10 @@ This internal package defines CloudEvents-compatible schemas (with Zod) for the
1616
```text
1717
src/
1818
domain/
19-
letter-status-change.ts # Domain model and status enum
19+
letter.ts # Domain model and status enum
2020
events/
2121
envelope-profile.ts # CloudEvents base envelope extensions & constraints
22-
letter-status-change-events.ts # Per status event schema generation
22+
letter-events.ts # Per status event schema generation
2323
cli/ # CLI scripts for bundling / codegen
2424
index.ts # (re-)exports (not shown above if generated later)
2525
```
@@ -43,26 +43,26 @@ Defines the constrained CloudEvents 1.0 envelope used across Notify. It enforces
4343

4444
### 2. Letter Status Domain
4545

46-
`letter-status-change.ts` introduces:
46+
`letter-change.ts` introduces:
4747

4848
* `$LetterStatus` enumeration covering lifecycle states:
4949
`PENDING | ACCEPTED | REJECTED | PRINTED | ENCLOSED | CANCELLED | DISPATCHED | FAILED | RETURNED | DESTROYED | FORWARDED | DELIVERED`
50-
* `$LetterStatusChange` domain object, extending a `DomainBase('LetterStatusChange')` (see helpers package) with:
50+
* `$Letter` domain object, extending a `DomainBase('Letter')` (see helpers package) with:
5151
* `domainId` (branded identifier)
5252
* `sourceSubject` – original resource subject
5353
* `status` – one of `$LetterStatus`
5454
* Optional `reasonCode`, `reasonText`
5555

5656
### 3. Per‑Status Event Schemas
5757

58-
`letter-status-change-events.ts` programmatically creates a schema per status by extending `$EnvelopeProfile` and replacing `data` with the domain payload. Each schema enforces:
58+
`letter-change-events.ts` programmatically creates a schema per status by extending `$EnvelopeProfile` and replacing `data` with the domain payload. Each schema enforces:
5959

60-
* `type = uk.nhs.notify.supplier-api.letter-status.<STATUS>.v1`
61-
* `dataschema` matches: `https://notify.nhs.uk/events/supplier-api/letter-status/<STATUS>/1.<minor>.<patch>.json`
60+
* `type = uk.nhs.notify.supplier-api.letter.<STATUS>.v1`
61+
* `dataschema` matches: `https://notify.nhs.uk/events/supplier-api/letter/<STATUS>/1.<minor>.<patch>.json`
6262
* `dataschemaversion` uses semantic version with major fixed to `1` (`1.x.y`)
6363
* `data.status` literal‑locked to the matching status
6464

65-
The export `statusChangeEvents` is a dictionary keyed by `letter-status.<STATUS>`.
65+
The export `letterEventMap` is a dictionary keyed by `letter.<STATUS>`.
6666

6767
---
6868

@@ -88,7 +88,7 @@ External `npm install` instructions are intentionally omitted (private package).
8888
```typescript
8989
import { statusChangeEvents } from '@nhsdigital/nhs-notify-event-schemas-supplier-api';
9090

91-
const schema = statusChangeEvents['letter-status.PRINTED'];
91+
const schema = statusChangeEvents['letter.PRINTED'];
9292
const parsed = schema.safeParse(incomingEventJson);
9393
if (!parsed.success) {
9494
// handle validation failure (log / DLQ)
@@ -99,14 +99,14 @@ if (!parsed.success) {
9999
}
100100
```
101101

102-
### Validating a generic letter-status.* event
102+
### Validating a generic letter.* event
103103

104104
```typescript
105105
```typescript
106-
import { $LetterStatusChangeEvent } from '@nhsdigital/nhs-notify-event-schemas-supplier-api';
106+
import { $LetterEvent } from '@nhsdigital/nhs-notify-event-schemas-supplier-api';
107107
108108
function validateLetterStatusEvent(e: unknown) {
109-
const result = $LetterStatusChangeEvent.safeParse(e);
109+
const result = $LetterEvent.safeParse(e);
110110
if (!result.success) {
111111
// handle validation failure (log / DLQ)
112112
return { ok: false as const, error: result.error };
@@ -123,16 +123,16 @@ import { statusChangeEvents } from '@nhsdigital/nhs-notify-event-schemas-supplie
123123
import { randomUUID } from 'crypto';
124124
125125
const status = 'ACCEPTED' as const;
126-
const schema = statusChangeEvents[`letter-status.${status}`];
126+
const schema = statusChangeEvents[`letter.${status}`];
127127
128128
const event = {
129129
specversion: '1.0',
130130
id: randomUUID(),
131131
source: '/data-plane/supplier-api',
132132
subject: 'customer/1b20f918-bb05-4c78-a4aa-5f6a3b8e0c91/letter/4a5a9cb5-1440-4a12-bd72-baa7cfecd111',
133-
type: 'uk.nhs.notify.supplier-api.letter-status.ACCEPTED.v1',
133+
type: 'uk.nhs.notify.supplier-api.letter.ACCEPTED.v1',
134134
time: new Date().toISOString(),
135-
dataschema: 'https://notify.nhs.uk/events/supplier-api/letter-status/ACCEPTED/1.0.0.json',
135+
dataschema: 'https://notify.nhs.uk/events/supplier-api/letter/ACCEPTED/1.0.0.json',
136136
dataschemaversion: '1.0.0',
137137
data: {
138138
domainId: 'abc123',
@@ -181,7 +181,7 @@ Execution order helpers:
181181
## Adding New Event Types (Future)
182182

183183
1. Extend the domain model under `src/domain/`
184-
2. Add a generator similar to `letter-status-change-events.ts`
184+
2. Add a generator similar to `letter-events.ts`
185185
3. Ensure `type` naming: `uk.nhs.notify.supplier-api.<area>.<action>.v1`
186186
4. Provide deterministic `dataschema` pattern with semantic versioning
187187
5. Export via `src/index.ts`

internal/events/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@
4040
"pregen:asyncapi": "npm run gen:jsonschema",
4141
"pregen:jsonschema": "rm -rf ./client-config/json",
4242
"prelint:schema": "npm run gen:jsonschema",
43+
"pretest:unit": "npm run gen:jsonschema",
4344
"start": "node dist/index.js",
44-
"test": "jest",
45+
"test": "npm run test:unit",
4546
"test:unit": "jest"
4647
},
4748
"types": "dist/index.d.ts",

internal/events/schemas/domain/letter-status-change.schema.json

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"domainId": {
5+
"title": "Letter ID",
6+
"description": "Unique identifier for the Letter",
7+
"examples": [
8+
"1y3q9v1zzzz"
9+
],
10+
"type": "string"
11+
},
12+
"origin": {
13+
"title": "Letter origin",
14+
"description": "The source and subject of the original event that introduced the letter to the supplier-api domain.",
15+
"type": "object",
16+
"properties": {
17+
"source": {
18+
"type": "string"
19+
},
20+
"subject": {
21+
"type": "string"
22+
}
23+
},
24+
"required": [
25+
"source",
26+
"subject"
27+
]
28+
},
29+
"status": {
30+
"title": "Letter Status",
31+
"description": "The status of a letter in the supplier-api domain.",
32+
"examples": [
33+
"ACCEPTED",
34+
"REJECTED",
35+
"PRINTED"
36+
],
37+
"type": "string",
38+
"enum": [
39+
"PENDING",
40+
"ACCEPTED",
41+
"REJECTED",
42+
"PRINTED",
43+
"ENCLOSED",
44+
"CANCELLED",
45+
"DISPATCHED",
46+
"FAILED",
47+
"RETURNED",
48+
"FORWARDED",
49+
"DELIVERED"
50+
]
51+
},
52+
"reasonCode": {
53+
"title": "Reason Code",
54+
"description": "Optional reason code for the status change, if applicable.",
55+
"examples": [
56+
"R01",
57+
"R08"
58+
],
59+
"type": "string"
60+
},
61+
"reasonText": {
62+
"title": "Reason Text",
63+
"description": "Optional human-readable reason for the status change, if applicable.",
64+
"examples": [
65+
"Undeliverable",
66+
"Recipient moved"
67+
],
68+
"type": "string"
69+
}
70+
},
71+
"required": [
72+
"domainId",
73+
"origin",
74+
"status"
75+
]
76+
}

internal/events/schemas/events/letter-status.ACCEPTED.schema.json renamed to internal/events/schemas/events/letter.ACCEPTED.schema.json

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"title": "letter-status.ACCEPTED Event",
2+
"title": "letter.ACCEPTED Event",
33
"description": "Event schema for letter status change to ACCEPTED",
44
"type": "object",
55
"properties": {
@@ -38,18 +38,18 @@
3838
},
3939
"subject": {
4040
"title": "Event Subject",
41-
"description": "Resource path (no leading slash) within the source made of lowercase segments separated by '/'.",
41+
"description": "Resource path (no leading slash) within the source made of segments separated by '/'.",
4242
"examples": [
4343
"customer/920fca11-596a-4eca-9c47-99f624614658/order/769acdd4-6a47-496f-999f-76a6fd2c3959/item/4f5e17c0-ec57-4cee-9a86-14580cf5af7d"
4444
],
4545
"type": "string",
4646
"minLength": 5,
47-
"pattern": "^[a-z0-9-]+(\\/[a-z0-9-]+)*$"
47+
"pattern": "^[^\\/]+(\\/[^\\/]+)*$"
4848
},
4949
"type": {
5050
"type": "string",
5151
"enum": [
52-
"uk.nhs.notify.supplier-api.letter-status.ACCEPTED.v1"
52+
"uk.nhs.notify.supplier-api.letter.ACCEPTED.v1"
5353
]
5454
},
5555
"time": {
@@ -75,21 +75,35 @@
7575
},
7676
"dataschema": {
7777
"type": "string",
78-
"pattern": "^https:\\/\\/notify\\.nhs\\.uk\\/events\\/supplier-api\\/letter-status\\/ACCEPTED\\/1\\.\\d+\\.\\d+\\.json$"
78+
"pattern": "^https:\\/\\/notify\\.nhs\\.uk\\/events\\/supplier-api\\/letter\\/ACCEPTED\\/1\\.\\d+\\.\\d+\\.json$"
7979
},
8080
"data": {
8181
"type": "object",
8282
"properties": {
8383
"domainId": {
84-
"title": "LetterStatusChange ID",
85-
"description": "Unique identifier for the LetterStatusChange",
84+
"title": "Letter ID",
85+
"description": "Unique identifier for the Letter",
8686
"examples": [
8787
"1y3q9v1zzzz"
8888
],
8989
"type": "string"
9090
},
91-
"sourceSubject": {
92-
"type": "string"
91+
"origin": {
92+
"title": "Letter origin",
93+
"description": "The source and subject of the original event that introduced the letter to the supplier-api domain.",
94+
"type": "object",
95+
"properties": {
96+
"source": {
97+
"type": "string"
98+
},
99+
"subject": {
100+
"type": "string"
101+
}
102+
},
103+
"required": [
104+
"source",
105+
"subject"
106+
]
93107
},
94108
"status": {
95109
"type": "string",
@@ -98,15 +112,27 @@
98112
]
99113
},
100114
"reasonCode": {
115+
"title": "Reason Code",
116+
"description": "Optional reason code for the status change, if applicable.",
117+
"examples": [
118+
"R01",
119+
"R08"
120+
],
101121
"type": "string"
102122
},
103123
"reasonText": {
124+
"title": "Reason Text",
125+
"description": "Optional human-readable reason for the status change, if applicable.",
126+
"examples": [
127+
"Undeliverable",
128+
"Recipient moved"
129+
],
104130
"type": "string"
105131
}
106132
},
107133
"required": [
108134
"domainId",
109-
"sourceSubject",
135+
"origin",
110136
"status"
111137
]
112138
},

0 commit comments

Comments
 (0)