@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
package/src/config.ts ADDED
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ import { Id, Label, Lens, SchemaVersionField } from "./primitives.js";
3
+
4
+ /**
5
+ * Which inferred elements a correction applies to.
6
+ *
7
+ * `id:<node-id>` addresses one node exactly. Anything else is a path glob
8
+ * matched against the node's file paths, so a correction survives the model
9
+ * renaming the node between runs.
10
+ */
11
+ export const Selector = z
12
+ .string()
13
+ .min(1)
14
+ .max(256)
15
+ .describe("`id:<node-id>` for an exact node, otherwise a repository-relative path glob.");
16
+ export type Selector = z.infer<typeof Selector>;
17
+
18
+ /**
19
+ * Human corrections to the inferred map. They are an overlay: inference never
20
+ * writes back here, and every run re-applies the overlay on top of fresh
21
+ * inference, so a correction keeps holding as the code moves.
22
+ */
23
+ export const MapCorrections = z
24
+ .strictObject({
25
+ rename: z
26
+ .array(z.strictObject({ match: Selector, to: Label }))
27
+ .max(128)
28
+ .default([])
29
+ .describe("Replace the inferred label."),
30
+ exclude: z
31
+ .array(Selector)
32
+ .max(128)
33
+ .default([])
34
+ .describe("Drop matching nodes, and any edge or flow step that touched them."),
35
+ lane: z
36
+ .array(z.strictObject({ match: Selector, lane: Id }))
37
+ .max(128)
38
+ .default([])
39
+ .describe("Move matching nodes into a lane."),
40
+ group: z
41
+ .array(z.strictObject({ match: Selector, group: Id }))
42
+ .max(128)
43
+ .default([])
44
+ .describe("Cluster matching nodes under a sub-group within their lane."),
45
+ })
46
+ .describe("Overlay applied over inference, never mutated by it.");
47
+ export type MapCorrections = z.infer<typeof MapCorrections>;
48
+
49
+ /** The `.github/pr-lens.yml` a repository may commit. Every field is optional. */
50
+ export const Config = z
51
+ .strictObject({
52
+ schemaVersion: SchemaVersionField.describe(
53
+ "Declared explicitly so a repository's corrections keep their meaning across contract versions.",
54
+ ),
55
+ lenses: z
56
+ .array(Lens)
57
+ .min(1)
58
+ .max(8)
59
+ .default(["architecture", "data-flow"])
60
+ .describe("Lenses to render for this repository."),
61
+ map: MapCorrections.default({ rename: [], exclude: [], lane: [], group: [] }),
62
+ branding: z
63
+ .boolean()
64
+ .default(true)
65
+ .describe("Show the 'Rendered by PR Lens' footer on comments."),
66
+ })
67
+ .describe("Repository configuration for PR Lens.");
68
+ export type Config = z.infer<typeof Config>;
69
+ export type ConfigInput = z.input<typeof Config>;
package/src/errors.ts ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Codes are the stable half of a failure; messages are not. Callers switch on
3
+ * the code, and every code stays meaningful across contract versions.
4
+ */
5
+ export type SchemaErrorCode =
6
+ | "INVALID_DOCUMENT"
7
+ | "BROKEN_REFERENCE"
8
+ | "DUPLICATE_ID"
9
+ | "UNSUPPORTED_SCHEMA_VERSION"
10
+ | "PATCH_CONFLICT"
11
+ | "NOT_A_SNAPSHOT";
12
+
13
+ export type SchemaIssue = {
14
+ code: SchemaErrorCode;
15
+ path: string;
16
+ message: string;
17
+ };
18
+
19
+ export class PrLensSchemaError extends Error {
20
+ readonly code: SchemaErrorCode;
21
+ readonly issues: readonly SchemaIssue[];
22
+
23
+ constructor(code: SchemaErrorCode, message: string, issues: readonly SchemaIssue[] = []) {
24
+ super(message);
25
+ this.name = "PrLensSchemaError";
26
+ this.code = code;
27
+ this.issues = issues;
28
+ }
29
+ }
30
+
31
+ export type Parsed<T> = { ok: true; value: T } | { ok: false; error: PrLensSchemaError };
32
+
33
+ export const formatIssues = (issues: readonly SchemaIssue[]): string =>
34
+ issues.map((issue) => ` ${issue.path || "<root>"}: ${issue.message} [${issue.code}]`).join("\n");
@@ -0,0 +1,437 @@
1
+ import type { GraphDocInput } from "../graph.js";
2
+ import type { PatchDocInput } from "../patch.js";
3
+ import { SCHEMA_VERSION } from "../version.js";
4
+
5
+ const BASE_SHA = "3f5c1ab9d24e7f08c6b1a5d3e9074c2b8a6f1d40";
6
+ const HEAD_SHA = "b71e0d4c8a92f5361de7c0b4a8f2593d6c1e8a77";
7
+
8
+ /**
9
+ * The stored baseline map for the broadcast subsystem as `main` stood before
10
+ * the refactor. A map describes a system rather than a change, so everything
11
+ * in it is `unchanged` and its provenance names the single commit it reflects.
12
+ */
13
+ export const broadcastBaselineGraphInput: GraphDocInput = {
14
+ schemaVersion: SCHEMA_VERSION,
15
+ kind: "graph",
16
+ id: "bestregards-broadcast-baseline",
17
+ generatedAt: "2026-08-12T09:02:00.000Z",
18
+ title: "Broadcast sending",
19
+ summary: "How a broadcast reaches its recipients: queued from the web app, sent one message at a time by a Firestore trigger.",
20
+ lenses: ["architecture", "data-flow"],
21
+ provenance: {
22
+ repo: { owner: "ohansemmanuel", name: "bestregards", host: "github.com" },
23
+ base: { sha: BASE_SHA, ref: "main" },
24
+ head: { sha: BASE_SHA, ref: "main" },
25
+ generator: { name: "pr-lens-examples", version: "0.1.0" },
26
+ },
27
+ lanes: [
28
+ { id: "web", label: "Next.js", subtitle: "Vercel", order: 0 },
29
+ { id: "functions", label: "Cloud Functions", subtitle: "Firebase", order: 1 },
30
+ { id: "external", label: "External", subtitle: "Postmark", order: 2 },
31
+ ],
32
+ nodes: [
33
+ {
34
+ id: "broadcast-composer",
35
+ label: "Broadcast composer",
36
+ kind: "ui",
37
+ delta: "unchanged",
38
+ lane: "web",
39
+ subtitle: "app/broadcasts/new",
40
+ files: [{ path: "app/broadcasts/new/page.tsx" }],
41
+ },
42
+ {
43
+ id: "queue-route",
44
+ label: "POST /api/broadcasts/queue",
45
+ kind: "route",
46
+ delta: "unchanged",
47
+ lane: "web",
48
+ files: [{ path: "app/api/broadcasts/queue/route.ts" }],
49
+ },
50
+ {
51
+ id: "broadcast-queue",
52
+ label: "broadcastQueue",
53
+ kind: "datastore",
54
+ delta: "unchanged",
55
+ lane: "functions",
56
+ subtitle: "Firestore collection",
57
+ files: [{ path: "functions/src/broadcast/schema.ts" }],
58
+ },
59
+ {
60
+ id: "process-broadcast",
61
+ label: "processBroadcast",
62
+ kind: "function",
63
+ delta: "unchanged",
64
+ lane: "functions",
65
+ subtitle: "onWrite trigger",
66
+ summary: "Walks the recipient list and sends one message at a time.",
67
+ files: [{ path: "functions/src/broadcast/processBroadcast.ts" }],
68
+ },
69
+ {
70
+ id: "send-single-email",
71
+ label: "sendSingleEmail",
72
+ kind: "function",
73
+ delta: "unchanged",
74
+ lane: "functions",
75
+ files: [{ path: "functions/src/broadcast/sendSingleEmail.ts" }],
76
+ },
77
+ {
78
+ id: "postmark",
79
+ label: "Postmark",
80
+ kind: "external",
81
+ delta: "unchanged",
82
+ lane: "external",
83
+ subtitle: "Email API",
84
+ },
85
+ ],
86
+ edges: [
87
+ {
88
+ id: "composer-to-queue",
89
+ from: "broadcast-composer",
90
+ to: "queue-route",
91
+ kind: "http",
92
+ delta: "unchanged",
93
+ label: "send broadcast",
94
+ },
95
+ {
96
+ id: "queue-to-firestore",
97
+ from: "queue-route",
98
+ to: "broadcast-queue",
99
+ kind: "data",
100
+ delta: "unchanged",
101
+ label: "enqueue job",
102
+ },
103
+ {
104
+ id: "firestore-to-process",
105
+ from: "broadcast-queue",
106
+ to: "process-broadcast",
107
+ kind: "event",
108
+ delta: "unchanged",
109
+ label: "onWrite",
110
+ },
111
+ {
112
+ id: "process-to-single",
113
+ from: "process-broadcast",
114
+ to: "send-single-email",
115
+ kind: "call",
116
+ delta: "unchanged",
117
+ label: "per recipient",
118
+ },
119
+ {
120
+ id: "single-to-postmark",
121
+ from: "send-single-email",
122
+ to: "postmark",
123
+ kind: "http",
124
+ delta: "unchanged",
125
+ label: "POST /email · 1 msg/call",
126
+ },
127
+ ],
128
+ flows: [
129
+ {
130
+ id: "send-pipeline",
131
+ title: "Sending a broadcast",
132
+ delta: "unchanged",
133
+ participants: [
134
+ { node: "queue-route", label: "queue route" },
135
+ { node: "broadcast-queue", label: "Firestore" },
136
+ { node: "process-broadcast", label: "processBroadcast" },
137
+ { node: "postmark", label: "Postmark" },
138
+ ],
139
+ messages: [
140
+ {
141
+ id: "enqueue",
142
+ from: "queue-route",
143
+ to: "broadcast-queue",
144
+ label: "enqueue broadcast job",
145
+ kind: "async",
146
+ delta: "unchanged",
147
+ },
148
+ {
149
+ id: "trigger",
150
+ from: "broadcast-queue",
151
+ to: "process-broadcast",
152
+ label: "onWrite trigger",
153
+ kind: "async",
154
+ delta: "unchanged",
155
+ },
156
+ {
157
+ id: "single-post",
158
+ from: "process-broadcast",
159
+ to: "postmark",
160
+ label: "POST /email",
161
+ kind: "sync",
162
+ delta: "unchanged",
163
+ repeat: 2000,
164
+ note: "One request per recipient.",
165
+ },
166
+ {
167
+ id: "single-result",
168
+ from: "postmark",
169
+ to: "process-broadcast",
170
+ label: "message id",
171
+ kind: "return",
172
+ delta: "unchanged",
173
+ },
174
+ {
175
+ id: "write-result",
176
+ from: "process-broadcast",
177
+ to: "broadcast-queue",
178
+ label: "write result",
179
+ kind: "async",
180
+ delta: "unchanged",
181
+ repeat: 2000,
182
+ },
183
+ ],
184
+ },
185
+ ],
186
+ views: [
187
+ {
188
+ id: "overview",
189
+ title: "Broadcast sending",
190
+ lens: "architecture",
191
+ defaultOpen: true,
192
+ scope: { kind: "all" },
193
+ },
194
+ ],
195
+ layout: { direction: "right", laneOrder: ["web", "functions", "external"] },
196
+ };
197
+
198
+ /**
199
+ * The refactor folded back into the baseline map, which is what happens once
200
+ * the pull request merges: the batch path joins the map as ordinary
201
+ * `unchanged` structure, and the single-send path leaves it.
202
+ *
203
+ * The old flow is removed before its participants are, so the removal is a
204
+ * deliberate replacement rather than a side effect of cascade.
205
+ */
206
+ export const broadcastBaselinePatchInput: PatchDocInput = {
207
+ schemaVersion: SCHEMA_VERSION,
208
+ kind: "patch",
209
+ generatedAt: "2026-08-19T18:31:00.000Z",
210
+ summary: "Fold the batch send path into the baseline map and retire the single-send path.",
211
+ target: {
212
+ graphId: "bestregards-broadcast-baseline",
213
+ fromSha: BASE_SHA,
214
+ toSha: HEAD_SHA,
215
+ },
216
+ ops: [
217
+ {
218
+ op: "add_node",
219
+ node: {
220
+ id: "send-broadcast-bulk",
221
+ label: "sendBroadcastBulk",
222
+ kind: "function",
223
+ delta: "unchanged",
224
+ lane: "functions",
225
+ subtitle: "onWrite trigger",
226
+ summary: "Fetches suppressions once, then posts batched payloads of 500 to Postmark.",
227
+ files: [{ path: "functions/src/broadcast/sendBroadcastBulk.ts" }],
228
+ },
229
+ },
230
+ {
231
+ op: "add_node",
232
+ node: {
233
+ id: "build-bulk-payload",
234
+ label: "buildBulkPayload",
235
+ kind: "function",
236
+ delta: "unchanged",
237
+ lane: "functions",
238
+ files: [{ path: "packages/broadcast-lib/src/buildBulkPayload.ts" }],
239
+ },
240
+ },
241
+ {
242
+ op: "add_node",
243
+ node: {
244
+ id: "get-suppressed-emails",
245
+ label: "getSuppressedEmails",
246
+ kind: "function",
247
+ delta: "unchanged",
248
+ lane: "functions",
249
+ files: [{ path: "packages/broadcast-lib/src/getSuppressedEmails.ts" }],
250
+ },
251
+ },
252
+ {
253
+ op: "add_node",
254
+ node: {
255
+ id: "broadcast-lib",
256
+ label: "broadcast-lib",
257
+ kind: "package",
258
+ delta: "unchanged",
259
+ lane: "functions",
260
+ subtitle: "packages/broadcast-lib",
261
+ files: [{ path: "packages/broadcast-lib/src/index.ts" }],
262
+ },
263
+ },
264
+ {
265
+ op: "add_edge",
266
+ edge: {
267
+ id: "firestore-to-bulk",
268
+ from: "broadcast-queue",
269
+ to: "send-broadcast-bulk",
270
+ kind: "event",
271
+ delta: "unchanged",
272
+ label: "onWrite",
273
+ },
274
+ },
275
+ {
276
+ op: "add_edge",
277
+ edge: {
278
+ id: "bulk-to-payload",
279
+ from: "send-broadcast-bulk",
280
+ to: "build-bulk-payload",
281
+ kind: "call",
282
+ delta: "unchanged",
283
+ },
284
+ },
285
+ {
286
+ op: "add_edge",
287
+ edge: {
288
+ id: "bulk-to-suppressions",
289
+ from: "send-broadcast-bulk",
290
+ to: "get-suppressed-emails",
291
+ kind: "call",
292
+ delta: "unchanged",
293
+ },
294
+ },
295
+ {
296
+ op: "add_edge",
297
+ edge: {
298
+ id: "bulk-to-lib",
299
+ from: "send-broadcast-bulk",
300
+ to: "broadcast-lib",
301
+ kind: "dependency",
302
+ delta: "unchanged",
303
+ },
304
+ },
305
+ {
306
+ op: "add_edge",
307
+ edge: {
308
+ id: "queue-to-lib",
309
+ from: "queue-route",
310
+ to: "broadcast-lib",
311
+ kind: "dependency",
312
+ delta: "unchanged",
313
+ label: "batch size",
314
+ },
315
+ },
316
+ {
317
+ op: "add_edge",
318
+ edge: {
319
+ id: "suppressions-to-postmark",
320
+ from: "get-suppressed-emails",
321
+ to: "postmark",
322
+ kind: "http",
323
+ delta: "unchanged",
324
+ label: "GET suppression dump",
325
+ },
326
+ },
327
+ {
328
+ op: "add_edge",
329
+ edge: {
330
+ id: "bulk-to-postmark",
331
+ from: "send-broadcast-bulk",
332
+ to: "postmark",
333
+ kind: "http",
334
+ delta: "unchanged",
335
+ label: "500 msgs/call",
336
+ },
337
+ },
338
+ {
339
+ op: "add_edge",
340
+ edge: {
341
+ id: "bulk-to-firestore",
342
+ from: "send-broadcast-bulk",
343
+ to: "broadcast-queue",
344
+ kind: "data",
345
+ delta: "unchanged",
346
+ label: "write results",
347
+ },
348
+ },
349
+ { op: "remove_flow", id: "send-pipeline" },
350
+ { op: "remove_node", id: "process-broadcast" },
351
+ { op: "remove_node", id: "send-single-email" },
352
+ {
353
+ op: "update_node",
354
+ id: "broadcast-queue",
355
+ patch: {
356
+ summary: "Queue documents carry the batch size and suppressed count the sender works from.",
357
+ },
358
+ },
359
+ {
360
+ op: "add_flow",
361
+ flow: {
362
+ id: "send-pipeline",
363
+ title: "Sending a broadcast",
364
+ delta: "unchanged",
365
+ participants: [
366
+ { node: "queue-route", label: "queue route" },
367
+ { node: "broadcast-queue", label: "Firestore" },
368
+ { node: "send-broadcast-bulk", label: "sendBroadcastBulk" },
369
+ { node: "postmark", label: "Postmark" },
370
+ ],
371
+ messages: [
372
+ {
373
+ id: "enqueue",
374
+ from: "queue-route",
375
+ to: "broadcast-queue",
376
+ label: "enqueue broadcast job",
377
+ kind: "async",
378
+ delta: "unchanged",
379
+ },
380
+ {
381
+ id: "trigger",
382
+ from: "broadcast-queue",
383
+ to: "send-broadcast-bulk",
384
+ label: "onWrite trigger",
385
+ kind: "async",
386
+ delta: "unchanged",
387
+ },
388
+ {
389
+ id: "suppressions-request",
390
+ from: "send-broadcast-bulk",
391
+ to: "postmark",
392
+ label: "GET suppression dump",
393
+ kind: "sync",
394
+ delta: "unchanged",
395
+ },
396
+ {
397
+ id: "suppressions-response",
398
+ from: "postmark",
399
+ to: "send-broadcast-bulk",
400
+ label: "suppressed addresses",
401
+ kind: "return",
402
+ delta: "unchanged",
403
+ },
404
+ {
405
+ id: "batch-post",
406
+ from: "send-broadcast-bulk",
407
+ to: "postmark",
408
+ label: "POST /email/batch · 500 msgs",
409
+ kind: "sync",
410
+ delta: "unchanged",
411
+ repeat: 4,
412
+ },
413
+ {
414
+ id: "batch-results",
415
+ from: "postmark",
416
+ to: "send-broadcast-bulk",
417
+ label: "per-message results",
418
+ kind: "return",
419
+ delta: "unchanged",
420
+ },
421
+ {
422
+ id: "write-results",
423
+ from: "send-broadcast-bulk",
424
+ to: "broadcast-queue",
425
+ label: "write results",
426
+ kind: "async",
427
+ delta: "unchanged",
428
+ },
429
+ ],
430
+ },
431
+ },
432
+ {
433
+ op: "set_stats",
434
+ stats: { chips: [{ label: "Batch size", value: "500", tone: "neutral" }] },
435
+ },
436
+ ],
437
+ };
@@ -0,0 +1,25 @@
1
+ import { parseConfig, parseGraphDoc, parsePatchDoc, parseRenderManifest } from "../validate.js";
2
+ import { broadcastBaselineGraphInput, broadcastBaselinePatchInput } from "./baseline.js";
3
+ import { minimalGraphInput } from "./minimal.js";
4
+ import {
5
+ exampleConfigInput,
6
+ postmarkRefactorGraphInput,
7
+ postmarkRefactorManifestInput,
8
+ } from "./postmark-refactor.js";
9
+
10
+ export const postmarkRefactorGraph = parseGraphDoc(postmarkRefactorGraphInput);
11
+ export const postmarkRefactorManifest = parseRenderManifest(postmarkRefactorManifestInput);
12
+ export const broadcastBaselineGraph = parseGraphDoc(broadcastBaselineGraphInput);
13
+ export const broadcastBaselinePatch = parsePatchDoc(broadcastBaselinePatchInput);
14
+ export const exampleConfig = parseConfig(exampleConfigInput);
15
+ export const minimalGraph = parseGraphDoc(minimalGraphInput);
16
+
17
+ /** Every golden, keyed by the filename it is published under in `examples/`. */
18
+ export const goldenDocuments = {
19
+ "postmark-refactor.graph.json": postmarkRefactorGraph,
20
+ "postmark-refactor.render-manifest.json": postmarkRefactorManifest,
21
+ "broadcast-baseline.graph.json": broadcastBaselineGraph,
22
+ "broadcast-baseline.patch.json": broadcastBaselinePatch,
23
+ "pr-lens.config.json": exampleConfig,
24
+ "minimal.graph.json": minimalGraph,
25
+ } as const;
@@ -0,0 +1,26 @@
1
+ import type { GraphDocInput } from "../graph.js";
2
+ import { SCHEMA_VERSION } from "../version.js";
3
+
4
+ /** The smallest document that validates: one lane, one node, one lens. */
5
+ export const minimalGraphInput: GraphDocInput = {
6
+ schemaVersion: SCHEMA_VERSION,
7
+ kind: "graph",
8
+ title: "Touch the health check",
9
+ lenses: ["architecture"],
10
+ provenance: {
11
+ repo: { owner: "coldteadotai", name: "pr-lens" },
12
+ base: { sha: "1111111" },
13
+ head: { sha: "2222222" },
14
+ },
15
+ lanes: [{ id: "api", label: "API" }],
16
+ nodes: [
17
+ {
18
+ id: "health-route",
19
+ label: "GET /health",
20
+ kind: "route",
21
+ delta: "modified",
22
+ lane: "api",
23
+ files: [{ path: "src/routes/health.ts" }],
24
+ },
25
+ ],
26
+ };