@coldtea/pr-lens-schema 0.1.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/apply.d.ts +42 -0
  4. package/dist/apply.d.ts.map +1 -0
  5. package/dist/apply.js +315 -0
  6. package/dist/apply.js.map +1 -0
  7. package/dist/config.d.ts +58 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +61 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/errors.d.ts +24 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +12 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/examples/baseline.d.ts +18 -0
  16. package/dist/examples/baseline.d.ts.map +1 -0
  17. package/dist/examples/baseline.js +433 -0
  18. package/dist/examples/baseline.js.map +1 -0
  19. package/dist/examples/index.d.ts +1194 -0
  20. package/dist/examples/index.d.ts.map +1 -0
  21. package/dist/examples/index.js +20 -0
  22. package/dist/examples/index.js.map +1 -0
  23. package/dist/examples/minimal.d.ts +4 -0
  24. package/dist/examples/minimal.d.ts.map +1 -0
  25. package/dist/examples/minimal.js +25 -0
  26. package/dist/examples/minimal.js.map +1 -0
  27. package/dist/examples/postmark-refactor.d.ts +16 -0
  28. package/dist/examples/postmark-refactor.d.ts.map +1 -0
  29. package/dist/examples/postmark-refactor.js +468 -0
  30. package/dist/examples/postmark-refactor.js.map +1 -0
  31. package/dist/graph.d.ts +568 -0
  32. package/dist/graph.d.ts.map +1 -0
  33. package/dist/graph.js +266 -0
  34. package/dist/graph.js.map +1 -0
  35. package/dist/index.d.ts +12 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +12 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/integrity.d.ts +20 -0
  40. package/dist/integrity.d.ts.map +1 -0
  41. package/dist/integrity.js +167 -0
  42. package/dist/integrity.js.map +1 -0
  43. package/dist/manifest.d.ts +65 -0
  44. package/dist/manifest.d.ts.map +1 -0
  45. package/dist/manifest.js +60 -0
  46. package/dist/manifest.js.map +1 -0
  47. package/dist/patch.d.ts +824 -0
  48. package/dist/patch.d.ts.map +1 -0
  49. package/dist/patch.js +84 -0
  50. package/dist/patch.js.map +1 -0
  51. package/dist/primitives.d.ts +92 -0
  52. package/dist/primitives.d.ts.map +1 -0
  53. package/dist/primitives.js +120 -0
  54. package/dist/primitives.js.map +1 -0
  55. package/dist/utils.d.ts +6 -0
  56. package/dist/utils.d.ts.map +1 -0
  57. package/dist/utils.js +8 -0
  58. package/dist/utils.js.map +1 -0
  59. package/dist/validate.d.ts +18 -0
  60. package/dist/validate.d.ts.map +1 -0
  61. package/dist/validate.js +95 -0
  62. package/dist/validate.js.map +1 -0
  63. package/dist/version.d.ts +21 -0
  64. package/dist/version.d.ts.map +1 -0
  65. package/dist/version.js +24 -0
  66. package/dist/version.js.map +1 -0
  67. package/examples/broadcast-baseline.graph.json +289 -0
  68. package/examples/broadcast-baseline.patch.json +321 -0
  69. package/examples/minimal.graph.json +45 -0
  70. package/examples/postmark-refactor.graph.json +580 -0
  71. package/examples/postmark-refactor.render-manifest.json +67 -0
  72. package/examples/pr-lens.config.json +32 -0
  73. package/json-schema/config.schema.json +153 -0
  74. package/json-schema/graph-doc.schema.json +1032 -0
  75. package/json-schema/patch-doc.schema.json +1383 -0
  76. package/json-schema/render-manifest.schema.json +183 -0
  77. package/package.json +66 -0
  78. package/src/apply.ts +399 -0
  79. package/src/config.ts +69 -0
  80. package/src/errors.ts +34 -0
  81. package/src/examples/baseline.ts +437 -0
  82. package/src/examples/index.ts +25 -0
  83. package/src/examples/minimal.ts +26 -0
  84. package/src/examples/postmark-refactor.ts +480 -0
  85. package/src/graph.ts +331 -0
  86. package/src/index.ts +82 -0
  87. package/src/integrity.ts +216 -0
  88. package/src/manifest.ts +64 -0
  89. package/src/patch.ts +100 -0
  90. package/src/primitives.ts +146 -0
  91. package/src/utils.ts +7 -0
  92. package/src/validate.ts +132 -0
  93. package/src/version.ts +31 -0
@@ -0,0 +1,289 @@
1
+ {
2
+ "schemaVersion": "0.1.0",
3
+ "kind": "graph",
4
+ "id": "bestregards-broadcast-baseline",
5
+ "generatedAt": "2026-08-12T09:02:00.000Z",
6
+ "title": "Broadcast sending",
7
+ "summary": "How a broadcast reaches its recipients: queued from the web app, sent one message at a time by a Firestore trigger.",
8
+ "lenses": [
9
+ "architecture",
10
+ "data-flow"
11
+ ],
12
+ "provenance": {
13
+ "repo": {
14
+ "owner": "ohansemmanuel",
15
+ "name": "bestregards",
16
+ "host": "github.com"
17
+ },
18
+ "base": {
19
+ "sha": "3f5c1ab9d24e7f08c6b1a5d3e9074c2b8a6f1d40",
20
+ "ref": "main"
21
+ },
22
+ "head": {
23
+ "sha": "3f5c1ab9d24e7f08c6b1a5d3e9074c2b8a6f1d40",
24
+ "ref": "main"
25
+ },
26
+ "generator": {
27
+ "name": "pr-lens-examples",
28
+ "version": "0.1.0"
29
+ }
30
+ },
31
+ "lanes": [
32
+ {
33
+ "id": "web",
34
+ "label": "Next.js",
35
+ "subtitle": "Vercel",
36
+ "order": 0
37
+ },
38
+ {
39
+ "id": "functions",
40
+ "label": "Cloud Functions",
41
+ "subtitle": "Firebase",
42
+ "order": 1
43
+ },
44
+ {
45
+ "id": "external",
46
+ "label": "External",
47
+ "subtitle": "Postmark",
48
+ "order": 2
49
+ }
50
+ ],
51
+ "nodes": [
52
+ {
53
+ "id": "broadcast-composer",
54
+ "label": "Broadcast composer",
55
+ "kind": "ui",
56
+ "delta": "unchanged",
57
+ "lane": "web",
58
+ "subtitle": "app/broadcasts/new",
59
+ "files": [
60
+ {
61
+ "path": "app/broadcasts/new/page.tsx"
62
+ }
63
+ ],
64
+ "badges": []
65
+ },
66
+ {
67
+ "id": "queue-route",
68
+ "label": "POST /api/broadcasts/queue",
69
+ "kind": "route",
70
+ "delta": "unchanged",
71
+ "lane": "web",
72
+ "files": [
73
+ {
74
+ "path": "app/api/broadcasts/queue/route.ts"
75
+ }
76
+ ],
77
+ "badges": []
78
+ },
79
+ {
80
+ "id": "broadcast-queue",
81
+ "label": "broadcastQueue",
82
+ "kind": "datastore",
83
+ "delta": "unchanged",
84
+ "lane": "functions",
85
+ "subtitle": "Firestore collection",
86
+ "files": [
87
+ {
88
+ "path": "functions/src/broadcast/schema.ts"
89
+ }
90
+ ],
91
+ "badges": []
92
+ },
93
+ {
94
+ "id": "process-broadcast",
95
+ "label": "processBroadcast",
96
+ "kind": "function",
97
+ "delta": "unchanged",
98
+ "lane": "functions",
99
+ "subtitle": "onWrite trigger",
100
+ "summary": "Walks the recipient list and sends one message at a time.",
101
+ "files": [
102
+ {
103
+ "path": "functions/src/broadcast/processBroadcast.ts"
104
+ }
105
+ ],
106
+ "badges": []
107
+ },
108
+ {
109
+ "id": "send-single-email",
110
+ "label": "sendSingleEmail",
111
+ "kind": "function",
112
+ "delta": "unchanged",
113
+ "lane": "functions",
114
+ "files": [
115
+ {
116
+ "path": "functions/src/broadcast/sendSingleEmail.ts"
117
+ }
118
+ ],
119
+ "badges": []
120
+ },
121
+ {
122
+ "id": "postmark",
123
+ "label": "Postmark",
124
+ "kind": "external",
125
+ "delta": "unchanged",
126
+ "lane": "external",
127
+ "subtitle": "Email API",
128
+ "files": [],
129
+ "badges": []
130
+ }
131
+ ],
132
+ "edges": [
133
+ {
134
+ "id": "composer-to-queue",
135
+ "from": "broadcast-composer",
136
+ "to": "queue-route",
137
+ "kind": "http",
138
+ "delta": "unchanged",
139
+ "label": "send broadcast",
140
+ "emphasis": "normal",
141
+ "animated": false,
142
+ "files": []
143
+ },
144
+ {
145
+ "id": "queue-to-firestore",
146
+ "from": "queue-route",
147
+ "to": "broadcast-queue",
148
+ "kind": "data",
149
+ "delta": "unchanged",
150
+ "label": "enqueue job",
151
+ "emphasis": "normal",
152
+ "animated": false,
153
+ "files": []
154
+ },
155
+ {
156
+ "id": "firestore-to-process",
157
+ "from": "broadcast-queue",
158
+ "to": "process-broadcast",
159
+ "kind": "event",
160
+ "delta": "unchanged",
161
+ "label": "onWrite",
162
+ "emphasis": "normal",
163
+ "animated": false,
164
+ "files": []
165
+ },
166
+ {
167
+ "id": "process-to-single",
168
+ "from": "process-broadcast",
169
+ "to": "send-single-email",
170
+ "kind": "call",
171
+ "delta": "unchanged",
172
+ "label": "per recipient",
173
+ "emphasis": "normal",
174
+ "animated": false,
175
+ "files": []
176
+ },
177
+ {
178
+ "id": "single-to-postmark",
179
+ "from": "send-single-email",
180
+ "to": "postmark",
181
+ "kind": "http",
182
+ "delta": "unchanged",
183
+ "label": "POST /email · 1 msg/call",
184
+ "emphasis": "normal",
185
+ "animated": false,
186
+ "files": []
187
+ }
188
+ ],
189
+ "flows": [
190
+ {
191
+ "id": "send-pipeline",
192
+ "title": "Sending a broadcast",
193
+ "delta": "unchanged",
194
+ "participants": [
195
+ {
196
+ "node": "queue-route",
197
+ "label": "queue route"
198
+ },
199
+ {
200
+ "node": "broadcast-queue",
201
+ "label": "Firestore"
202
+ },
203
+ {
204
+ "node": "process-broadcast",
205
+ "label": "processBroadcast"
206
+ },
207
+ {
208
+ "node": "postmark",
209
+ "label": "Postmark"
210
+ }
211
+ ],
212
+ "messages": [
213
+ {
214
+ "id": "enqueue",
215
+ "from": "queue-route",
216
+ "to": "broadcast-queue",
217
+ "label": "enqueue broadcast job",
218
+ "kind": "async",
219
+ "delta": "unchanged",
220
+ "animated": true,
221
+ "files": []
222
+ },
223
+ {
224
+ "id": "trigger",
225
+ "from": "broadcast-queue",
226
+ "to": "process-broadcast",
227
+ "label": "onWrite trigger",
228
+ "kind": "async",
229
+ "delta": "unchanged",
230
+ "animated": true,
231
+ "files": []
232
+ },
233
+ {
234
+ "id": "single-post",
235
+ "from": "process-broadcast",
236
+ "to": "postmark",
237
+ "label": "POST /email",
238
+ "kind": "sync",
239
+ "delta": "unchanged",
240
+ "animated": true,
241
+ "repeat": 2000,
242
+ "note": "One request per recipient.",
243
+ "files": []
244
+ },
245
+ {
246
+ "id": "single-result",
247
+ "from": "postmark",
248
+ "to": "process-broadcast",
249
+ "label": "message id",
250
+ "kind": "return",
251
+ "delta": "unchanged",
252
+ "animated": true,
253
+ "files": []
254
+ },
255
+ {
256
+ "id": "write-result",
257
+ "from": "process-broadcast",
258
+ "to": "broadcast-queue",
259
+ "label": "write result",
260
+ "kind": "async",
261
+ "delta": "unchanged",
262
+ "animated": true,
263
+ "repeat": 2000,
264
+ "files": []
265
+ }
266
+ ]
267
+ }
268
+ ],
269
+ "views": [
270
+ {
271
+ "id": "overview",
272
+ "title": "Broadcast sending",
273
+ "lens": "architecture",
274
+ "scope": {
275
+ "kind": "all"
276
+ },
277
+ "defaultOpen": true,
278
+ "children": []
279
+ }
280
+ ],
281
+ "layout": {
282
+ "direction": "right",
283
+ "laneOrder": [
284
+ "web",
285
+ "functions",
286
+ "external"
287
+ ]
288
+ }
289
+ }
@@ -0,0 +1,321 @@
1
+ {
2
+ "schemaVersion": "0.1.0",
3
+ "kind": "patch",
4
+ "generatedAt": "2026-08-19T18:31:00.000Z",
5
+ "summary": "Fold the batch send path into the baseline map and retire the single-send path.",
6
+ "target": {
7
+ "graphId": "bestregards-broadcast-baseline",
8
+ "fromSha": "3f5c1ab9d24e7f08c6b1a5d3e9074c2b8a6f1d40",
9
+ "toSha": "b71e0d4c8a92f5361de7c0b4a8f2593d6c1e8a77"
10
+ },
11
+ "ops": [
12
+ {
13
+ "op": "add_node",
14
+ "node": {
15
+ "id": "send-broadcast-bulk",
16
+ "label": "sendBroadcastBulk",
17
+ "kind": "function",
18
+ "delta": "unchanged",
19
+ "lane": "functions",
20
+ "subtitle": "onWrite trigger",
21
+ "summary": "Fetches suppressions once, then posts batched payloads of 500 to Postmark.",
22
+ "files": [
23
+ {
24
+ "path": "functions/src/broadcast/sendBroadcastBulk.ts"
25
+ }
26
+ ],
27
+ "badges": []
28
+ }
29
+ },
30
+ {
31
+ "op": "add_node",
32
+ "node": {
33
+ "id": "build-bulk-payload",
34
+ "label": "buildBulkPayload",
35
+ "kind": "function",
36
+ "delta": "unchanged",
37
+ "lane": "functions",
38
+ "files": [
39
+ {
40
+ "path": "packages/broadcast-lib/src/buildBulkPayload.ts"
41
+ }
42
+ ],
43
+ "badges": []
44
+ }
45
+ },
46
+ {
47
+ "op": "add_node",
48
+ "node": {
49
+ "id": "get-suppressed-emails",
50
+ "label": "getSuppressedEmails",
51
+ "kind": "function",
52
+ "delta": "unchanged",
53
+ "lane": "functions",
54
+ "files": [
55
+ {
56
+ "path": "packages/broadcast-lib/src/getSuppressedEmails.ts"
57
+ }
58
+ ],
59
+ "badges": []
60
+ }
61
+ },
62
+ {
63
+ "op": "add_node",
64
+ "node": {
65
+ "id": "broadcast-lib",
66
+ "label": "broadcast-lib",
67
+ "kind": "package",
68
+ "delta": "unchanged",
69
+ "lane": "functions",
70
+ "subtitle": "packages/broadcast-lib",
71
+ "files": [
72
+ {
73
+ "path": "packages/broadcast-lib/src/index.ts"
74
+ }
75
+ ],
76
+ "badges": []
77
+ }
78
+ },
79
+ {
80
+ "op": "add_edge",
81
+ "edge": {
82
+ "id": "firestore-to-bulk",
83
+ "from": "broadcast-queue",
84
+ "to": "send-broadcast-bulk",
85
+ "kind": "event",
86
+ "delta": "unchanged",
87
+ "label": "onWrite",
88
+ "emphasis": "normal",
89
+ "animated": false,
90
+ "files": []
91
+ }
92
+ },
93
+ {
94
+ "op": "add_edge",
95
+ "edge": {
96
+ "id": "bulk-to-payload",
97
+ "from": "send-broadcast-bulk",
98
+ "to": "build-bulk-payload",
99
+ "kind": "call",
100
+ "delta": "unchanged",
101
+ "emphasis": "normal",
102
+ "animated": false,
103
+ "files": []
104
+ }
105
+ },
106
+ {
107
+ "op": "add_edge",
108
+ "edge": {
109
+ "id": "bulk-to-suppressions",
110
+ "from": "send-broadcast-bulk",
111
+ "to": "get-suppressed-emails",
112
+ "kind": "call",
113
+ "delta": "unchanged",
114
+ "emphasis": "normal",
115
+ "animated": false,
116
+ "files": []
117
+ }
118
+ },
119
+ {
120
+ "op": "add_edge",
121
+ "edge": {
122
+ "id": "bulk-to-lib",
123
+ "from": "send-broadcast-bulk",
124
+ "to": "broadcast-lib",
125
+ "kind": "dependency",
126
+ "delta": "unchanged",
127
+ "emphasis": "normal",
128
+ "animated": false,
129
+ "files": []
130
+ }
131
+ },
132
+ {
133
+ "op": "add_edge",
134
+ "edge": {
135
+ "id": "queue-to-lib",
136
+ "from": "queue-route",
137
+ "to": "broadcast-lib",
138
+ "kind": "dependency",
139
+ "delta": "unchanged",
140
+ "label": "batch size",
141
+ "emphasis": "normal",
142
+ "animated": false,
143
+ "files": []
144
+ }
145
+ },
146
+ {
147
+ "op": "add_edge",
148
+ "edge": {
149
+ "id": "suppressions-to-postmark",
150
+ "from": "get-suppressed-emails",
151
+ "to": "postmark",
152
+ "kind": "http",
153
+ "delta": "unchanged",
154
+ "label": "GET suppression dump",
155
+ "emphasis": "normal",
156
+ "animated": false,
157
+ "files": []
158
+ }
159
+ },
160
+ {
161
+ "op": "add_edge",
162
+ "edge": {
163
+ "id": "bulk-to-postmark",
164
+ "from": "send-broadcast-bulk",
165
+ "to": "postmark",
166
+ "kind": "http",
167
+ "delta": "unchanged",
168
+ "label": "500 msgs/call",
169
+ "emphasis": "normal",
170
+ "animated": false,
171
+ "files": []
172
+ }
173
+ },
174
+ {
175
+ "op": "add_edge",
176
+ "edge": {
177
+ "id": "bulk-to-firestore",
178
+ "from": "send-broadcast-bulk",
179
+ "to": "broadcast-queue",
180
+ "kind": "data",
181
+ "delta": "unchanged",
182
+ "label": "write results",
183
+ "emphasis": "normal",
184
+ "animated": false,
185
+ "files": []
186
+ }
187
+ },
188
+ {
189
+ "op": "remove_flow",
190
+ "id": "send-pipeline"
191
+ },
192
+ {
193
+ "op": "remove_node",
194
+ "id": "process-broadcast"
195
+ },
196
+ {
197
+ "op": "remove_node",
198
+ "id": "send-single-email"
199
+ },
200
+ {
201
+ "op": "update_node",
202
+ "id": "broadcast-queue",
203
+ "patch": {
204
+ "summary": "Queue documents carry the batch size and suppressed count the sender works from.",
205
+ "files": [],
206
+ "badges": []
207
+ }
208
+ },
209
+ {
210
+ "op": "add_flow",
211
+ "flow": {
212
+ "id": "send-pipeline",
213
+ "title": "Sending a broadcast",
214
+ "delta": "unchanged",
215
+ "participants": [
216
+ {
217
+ "node": "queue-route",
218
+ "label": "queue route"
219
+ },
220
+ {
221
+ "node": "broadcast-queue",
222
+ "label": "Firestore"
223
+ },
224
+ {
225
+ "node": "send-broadcast-bulk",
226
+ "label": "sendBroadcastBulk"
227
+ },
228
+ {
229
+ "node": "postmark",
230
+ "label": "Postmark"
231
+ }
232
+ ],
233
+ "messages": [
234
+ {
235
+ "id": "enqueue",
236
+ "from": "queue-route",
237
+ "to": "broadcast-queue",
238
+ "label": "enqueue broadcast job",
239
+ "kind": "async",
240
+ "delta": "unchanged",
241
+ "animated": true,
242
+ "files": []
243
+ },
244
+ {
245
+ "id": "trigger",
246
+ "from": "broadcast-queue",
247
+ "to": "send-broadcast-bulk",
248
+ "label": "onWrite trigger",
249
+ "kind": "async",
250
+ "delta": "unchanged",
251
+ "animated": true,
252
+ "files": []
253
+ },
254
+ {
255
+ "id": "suppressions-request",
256
+ "from": "send-broadcast-bulk",
257
+ "to": "postmark",
258
+ "label": "GET suppression dump",
259
+ "kind": "sync",
260
+ "delta": "unchanged",
261
+ "animated": true,
262
+ "files": []
263
+ },
264
+ {
265
+ "id": "suppressions-response",
266
+ "from": "postmark",
267
+ "to": "send-broadcast-bulk",
268
+ "label": "suppressed addresses",
269
+ "kind": "return",
270
+ "delta": "unchanged",
271
+ "animated": true,
272
+ "files": []
273
+ },
274
+ {
275
+ "id": "batch-post",
276
+ "from": "send-broadcast-bulk",
277
+ "to": "postmark",
278
+ "label": "POST /email/batch · 500 msgs",
279
+ "kind": "sync",
280
+ "delta": "unchanged",
281
+ "animated": true,
282
+ "repeat": 4,
283
+ "files": []
284
+ },
285
+ {
286
+ "id": "batch-results",
287
+ "from": "postmark",
288
+ "to": "send-broadcast-bulk",
289
+ "label": "per-message results",
290
+ "kind": "return",
291
+ "delta": "unchanged",
292
+ "animated": true,
293
+ "files": []
294
+ },
295
+ {
296
+ "id": "write-results",
297
+ "from": "send-broadcast-bulk",
298
+ "to": "broadcast-queue",
299
+ "label": "write results",
300
+ "kind": "async",
301
+ "delta": "unchanged",
302
+ "animated": true,
303
+ "files": []
304
+ }
305
+ ]
306
+ }
307
+ },
308
+ {
309
+ "op": "set_stats",
310
+ "stats": {
311
+ "chips": [
312
+ {
313
+ "label": "Batch size",
314
+ "value": "500",
315
+ "tone": "neutral"
316
+ }
317
+ ]
318
+ }
319
+ }
320
+ ]
321
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "schemaVersion": "0.1.0",
3
+ "kind": "graph",
4
+ "title": "Touch the health check",
5
+ "lenses": [
6
+ "architecture"
7
+ ],
8
+ "provenance": {
9
+ "repo": {
10
+ "owner": "coldteadotai",
11
+ "name": "pr-lens",
12
+ "host": "github.com"
13
+ },
14
+ "base": {
15
+ "sha": "1111111"
16
+ },
17
+ "head": {
18
+ "sha": "2222222"
19
+ }
20
+ },
21
+ "lanes": [
22
+ {
23
+ "id": "api",
24
+ "label": "API"
25
+ }
26
+ ],
27
+ "nodes": [
28
+ {
29
+ "id": "health-route",
30
+ "label": "GET /health",
31
+ "kind": "route",
32
+ "delta": "modified",
33
+ "lane": "api",
34
+ "files": [
35
+ {
36
+ "path": "src/routes/health.ts"
37
+ }
38
+ ],
39
+ "badges": []
40
+ }
41
+ ],
42
+ "edges": [],
43
+ "flows": [],
44
+ "views": []
45
+ }