@loomwork/blueprint-runtime 0.0.0-stage → 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 (117) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +83 -2
  4. package/dist/Blueprint.d.ts +14 -0
  5. package/dist/Blueprint.d.ts.map +1 -0
  6. package/dist/Blueprint.js +18 -0
  7. package/dist/Blueprint.js.map +1 -0
  8. package/dist/RendererRegistry.d.ts +9 -0
  9. package/dist/RendererRegistry.d.ts.map +1 -0
  10. package/dist/RendererRegistry.js +39 -0
  11. package/dist/RendererRegistry.js.map +1 -0
  12. package/dist/catalog.d.ts +129 -0
  13. package/dist/catalog.d.ts.map +1 -0
  14. package/dist/catalog.js +435 -0
  15. package/dist/catalog.js.map +1 -0
  16. package/dist/coverage.d.ts +18 -0
  17. package/dist/coverage.d.ts.map +1 -0
  18. package/dist/coverage.js +22 -0
  19. package/dist/coverage.js.map +1 -0
  20. package/dist/customWidget.d.ts +10 -0
  21. package/dist/customWidget.d.ts.map +1 -0
  22. package/dist/customWidget.js +34 -0
  23. package/dist/customWidget.js.map +1 -0
  24. package/dist/esm/Blueprint.js +15 -0
  25. package/dist/esm/Blueprint.js.map +1 -0
  26. package/dist/esm/RendererRegistry.js +35 -0
  27. package/dist/esm/RendererRegistry.js.map +1 -0
  28. package/dist/esm/catalog.js +430 -0
  29. package/dist/esm/catalog.js.map +1 -0
  30. package/dist/esm/coverage.js +19 -0
  31. package/dist/esm/coverage.js.map +1 -0
  32. package/dist/esm/customWidget.js +31 -0
  33. package/dist/esm/customWidget.js.map +1 -0
  34. package/dist/esm/identity.js +116 -0
  35. package/dist/esm/identity.js.map +1 -0
  36. package/dist/esm/index.js +15 -0
  37. package/dist/esm/index.js.map +1 -0
  38. package/dist/esm/irVersion.js +150 -0
  39. package/dist/esm/irVersion.js.map +1 -0
  40. package/dist/esm/layout.js +63 -0
  41. package/dist/esm/layout.js.map +1 -0
  42. package/dist/esm/normalize.js +115 -0
  43. package/dist/esm/normalize.js.map +1 -0
  44. package/dist/esm/pins.js +82 -0
  45. package/dist/esm/pins.js.map +1 -0
  46. package/dist/esm/traverseBlueprint.js +38 -0
  47. package/dist/esm/traverseBlueprint.js.map +1 -0
  48. package/dist/esm/traverseBlueprintAsync.js +48 -0
  49. package/dist/esm/traverseBlueprintAsync.js.map +1 -0
  50. package/dist/esm/types.js +2 -0
  51. package/dist/esm/types.js.map +1 -0
  52. package/dist/esm/widgetStatus.js +137 -0
  53. package/dist/esm/widgetStatus.js.map +1 -0
  54. package/dist/esm/widgets.js +105 -0
  55. package/dist/esm/widgets.js.map +1 -0
  56. package/dist/identity.d.ts +58 -0
  57. package/dist/identity.d.ts.map +1 -0
  58. package/dist/identity.js +122 -0
  59. package/dist/identity.js.map +1 -0
  60. package/dist/index.d.ts +24 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +61 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/irVersion.d.ts +23 -0
  65. package/dist/irVersion.d.ts.map +1 -0
  66. package/dist/irVersion.js +153 -0
  67. package/dist/irVersion.js.map +1 -0
  68. package/dist/layout.d.ts +57 -0
  69. package/dist/layout.d.ts.map +1 -0
  70. package/dist/layout.js +71 -0
  71. package/dist/layout.js.map +1 -0
  72. package/dist/normalize.d.ts +29 -0
  73. package/dist/normalize.d.ts.map +1 -0
  74. package/dist/normalize.js +126 -0
  75. package/dist/normalize.js.map +1 -0
  76. package/dist/pins.d.ts +27 -0
  77. package/dist/pins.d.ts.map +1 -0
  78. package/dist/pins.js +86 -0
  79. package/dist/pins.js.map +1 -0
  80. package/dist/traverseBlueprint.d.ts +27 -0
  81. package/dist/traverseBlueprint.d.ts.map +1 -0
  82. package/dist/traverseBlueprint.js +40 -0
  83. package/dist/traverseBlueprint.js.map +1 -0
  84. package/dist/traverseBlueprintAsync.d.ts +18 -0
  85. package/dist/traverseBlueprintAsync.d.ts.map +1 -0
  86. package/dist/traverseBlueprintAsync.js +51 -0
  87. package/dist/traverseBlueprintAsync.js.map +1 -0
  88. package/dist/types.d.ts +176 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +3 -0
  91. package/dist/types.js.map +1 -0
  92. package/dist/widgetStatus.d.ts +66 -0
  93. package/dist/widgetStatus.d.ts.map +1 -0
  94. package/dist/widgetStatus.js +141 -0
  95. package/dist/widgetStatus.js.map +1 -0
  96. package/dist/widgets.d.ts +101 -0
  97. package/dist/widgets.d.ts.map +1 -0
  98. package/dist/widgets.js +115 -0
  99. package/dist/widgets.js.map +1 -0
  100. package/package.json +60 -3
  101. package/src/Blueprint.ts +28 -0
  102. package/src/RendererRegistry.ts +38 -0
  103. package/src/catalog.ts +638 -0
  104. package/src/coverage.ts +52 -0
  105. package/src/customWidget.ts +42 -0
  106. package/src/identity.ts +178 -0
  107. package/src/index.ts +84 -0
  108. package/src/irVersion.ts +195 -0
  109. package/src/layout.ts +105 -0
  110. package/src/normalize.ts +130 -0
  111. package/src/pins.ts +84 -0
  112. package/src/traverseBlueprint.bench.ts +47 -0
  113. package/src/traverseBlueprint.ts +94 -0
  114. package/src/traverseBlueprintAsync.ts +92 -0
  115. package/src/types.ts +195 -0
  116. package/src/widgetStatus.ts +231 -0
  117. package/src/widgets.ts +213 -0
@@ -0,0 +1,435 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.builtinCatalog = exports.BUILTIN_CATALOG_ID = void 0;
4
+ exports.defineWidgetCatalog = defineWidgetCatalog;
5
+ exports.validateBlueprint = validateBlueprint;
6
+ const layout_1 = require("./layout");
7
+ const normalize_1 = require("./normalize");
8
+ /** Identity helper — declare a catalogue with inferred types. */
9
+ function defineWidgetCatalog(catalog) {
10
+ return catalog;
11
+ }
12
+ exports.BUILTIN_CATALOG_ID = "loom.builtin.v1";
13
+ /**
14
+ * The eight widgets `@loomwork/blueprint-runtime` ships, as a catalogue.
15
+ *
16
+ * `props` mirrors each builder's props interface minus `title` (hoisted onto
17
+ * `Widget.title`) and minus `binding` (reserved). Every built-in requires a
18
+ * binding — none of them render anything without one.
19
+ */
20
+ exports.builtinCatalog = {
21
+ id: exports.BUILTIN_CATALOG_ID,
22
+ entries: [
23
+ { kind: "MetricCard", props: ["unit", "format"], binding: "required" },
24
+ { kind: "Timeline", props: ["maxItems"], binding: "required" },
25
+ { kind: "ApprovalCard", props: ["approveLabel", "rejectLabel"], binding: "required" },
26
+ { kind: "StatusBadge", props: [], binding: "required" },
27
+ { kind: "ProgressBar", props: ["max"], binding: "required" },
28
+ { kind: "DataTable", props: ["columns"], binding: "required" },
29
+ { kind: "AlertCard", props: ["severity"], binding: "required" },
30
+ { kind: "StreamingText", props: ["placeholder"], binding: "required" },
31
+ ],
32
+ };
33
+ /** Duplicated into `props` by every built-in builder; never a payload. */
34
+ const RESERVED_PROPS = new Set(["binding"]);
35
+ const KNOWN_IR_VERSIONS = new Set([normalize_1.IR_VERSION_LEGACY, ...normalize_1.IR_VERSIONS_READ_AS_IS]);
36
+ const DATA_CLASSES = new Set(["secret", "sensitive", "internal"]);
37
+ const DOTTED = /^[^.\s]+(\.[^.\s]+)*$/;
38
+ /**
39
+ * A blueprint is DATA a model may have composed, so the walk cannot assume its own types hold.
40
+ * A `Layout` here is structural: an object with a `type` and an array of `children`. Anything
41
+ * else reaching the stack — `null`, a string, a `GridCell` stranded in a flex/stack — is a
42
+ * `malformed-node` finding, never a property access on a non-object.
43
+ */
44
+ const isLayoutNode = (n) => typeof n === "object" &&
45
+ n !== null &&
46
+ "type" in n &&
47
+ Array.isArray(n.children);
48
+ /**
49
+ * Iterative walk — an explicit stack, so a deep tree cannot blow the call stack.
50
+ * Visits widgets (pre-order) and grid cells. A grid's cells are visited in
51
+ * forward sibling order (so findings on them read in document order) before
52
+ * their nodes are pushed onto the stack in reverse, which keeps the overall
53
+ * widget walk pre-order.
54
+ *
55
+ * The loop is length-driven rather than `pop() !== undefined`: a literal `undefined` child is
56
+ * one of the malformed shapes this walk must REPORT, and a sentinel loop would silently end the
57
+ * walk on it instead.
58
+ */
59
+ function eachNode(root, visit) {
60
+ const stack = [root];
61
+ while (stack.length > 0) {
62
+ const node = stack.pop();
63
+ if ((0, normalize_1.isWidget)(node)) {
64
+ visit({ widget: node });
65
+ continue;
66
+ }
67
+ if (!isLayoutNode(node)) {
68
+ visit({ malformed: { node } });
69
+ continue;
70
+ }
71
+ // `undefined` is absent (it does not survive serialisation, and every builder omits it).
72
+ // A malformed id is ABSENT for every other purpose: it names nothing and collides with nothing.
73
+ const id = node.id;
74
+ const nodeId = (0, layout_1.hasLayoutId)(node) ? node.id : "<layout>";
75
+ if ((0, layout_1.hasLayoutId)(node))
76
+ visit({ layoutId: { id: node.id } });
77
+ else if (id !== undefined)
78
+ visit({ layoutIdInvalid: { id } });
79
+ const role = node.role;
80
+ if (role !== undefined && !(0, layout_1.isLayoutRole)(role))
81
+ visit({ roleInvalid: { role, nodeId } });
82
+ if (node.type === "grid") {
83
+ const children = node.children;
84
+ const columns = node.columns;
85
+ // A grid with no usable column count cannot place ANY cell, so every span would be
86
+ // "out of range" against it. Report the cause once and skip the cascade.
87
+ const columnsOk = Number.isInteger(columns) && columns >= 1;
88
+ if (!columnsOk) {
89
+ visit({ columnsInvalid: { columns, nodeId } });
90
+ }
91
+ else {
92
+ for (let i = 0; i < children.length; i++) {
93
+ const c = (0, normalize_1.asCell)(children[i]);
94
+ visit({
95
+ cell: {
96
+ span: c.span ?? 1,
97
+ columns: columns,
98
+ cellNodeId: (0, normalize_1.isWidget)(c.node)
99
+ ? c.node.id
100
+ : (0, layout_1.hasLayoutId)(c.node)
101
+ ? c.node.id
102
+ : undefined,
103
+ row: c.row,
104
+ rowSpan: c.rowSpan,
105
+ column: c.column,
106
+ },
107
+ });
108
+ }
109
+ }
110
+ for (let i = children.length - 1; i >= 0; i--) {
111
+ stack.push((0, normalize_1.asCell)(children[i]).node);
112
+ }
113
+ }
114
+ else {
115
+ const children = node.children;
116
+ for (let i = children.length - 1; i >= 0; i--) {
117
+ stack.push(children[i]);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ /** A bounded description of a malformed role or id: a model-composed value can be any size. */
123
+ function describeValue(value) {
124
+ if (typeof value !== "string") {
125
+ if (value === null)
126
+ return "null";
127
+ return Array.isArray(value) ? "(an array)" : `(a ${typeof value})`;
128
+ }
129
+ return value.length > 64
130
+ ? `${JSON.stringify(value.slice(0, 64))}… (${value.length} chars)`
131
+ : JSON.stringify(value);
132
+ }
133
+ /** A short, safe description of a malformed node for a finding message. */
134
+ function describeNode(node) {
135
+ if (node === null)
136
+ return "null";
137
+ if (Array.isArray(node))
138
+ return "an array";
139
+ const t = typeof node;
140
+ if (t !== "object")
141
+ return `a ${t}`;
142
+ if ("node" in node)
143
+ return "a GridCell outside a grid";
144
+ return "an object with no layout `type` or `children`";
145
+ }
146
+ const isPositiveInt = (v) => Number.isInteger(v) && v >= 1;
147
+ const show = (v) => JSON.stringify(v) ?? String(v);
148
+ /**
149
+ * Why a cell's placement cannot be laid out — empty when it can. `spanOk` gates the overflow
150
+ * test so an invalid span is reported once (as `span-out-of-range`), not again as an overflow.
151
+ */
152
+ function placementProblems(c) {
153
+ const out = [];
154
+ if (c.row !== undefined && !isPositiveInt(c.row))
155
+ out.push(`row ${show(c.row)} is not a positive integer`);
156
+ if (c.rowSpan !== undefined && !isPositiveInt(c.rowSpan))
157
+ out.push(`rowSpan ${show(c.rowSpan)} is not a positive integer`);
158
+ if (c.column !== undefined) {
159
+ if (!isPositiveInt(c.column) || c.column > c.columns)
160
+ out.push(`column ${show(c.column)} is outside 1..${c.columns}`);
161
+ else if (c.spanOk && c.column + c.span - 1 > c.columns)
162
+ out.push(`column ${c.column} + span ${c.span} overflows the ${c.columns}-column grid`);
163
+ }
164
+ return out;
165
+ }
166
+ /**
167
+ * Check a blueprint against a catalogue. Never throws; returns every finding it
168
+ * can see in one pass, so a caller degrades or records a gap on the whole report
169
+ * rather than on the first failure.
170
+ */
171
+ function validateBlueprint(blueprint, catalog) {
172
+ const entries = new Map();
173
+ for (const entry of catalog.entries)
174
+ entries.set(entry.kind, entry);
175
+ const projections = new Set(blueprint.projections);
176
+ const findings = [];
177
+ // ONE namespace: widget ids and layout ids (IR 2.4.0) are both node identity.
178
+ // The value records which kind of node claimed the id first, so a widget↔widget collision keeps
179
+ // its message and a collision involving a layout says so.
180
+ const seenIds = new Map();
181
+ let widgets = 0;
182
+ if (blueprint.irVersion !== undefined && !KNOWN_IR_VERSIONS.has(blueprint.irVersion)) {
183
+ findings.push({
184
+ code: "ir-version-unknown",
185
+ severity: "error",
186
+ nodeId: "<layout>",
187
+ kind: "<layout>",
188
+ message: `irVersion "${blueprint.irVersion}" is not a version this module recognizes — a reader may not know how to interpret the artifact`,
189
+ });
190
+ }
191
+ eachNode(blueprint.layout, (v) => {
192
+ if (v.layoutId) {
193
+ const { id } = v.layoutId;
194
+ if (seenIds.has(id)) {
195
+ findings.push({
196
+ code: "duplicate-node-id",
197
+ severity: "error",
198
+ nodeId: id,
199
+ kind: "<layout>",
200
+ message: `a layout shares the id "${id}" with an earlier node — widget and layout ids are one namespace, so node identity and the renderer's key collide`,
201
+ });
202
+ }
203
+ if (!seenIds.has(id))
204
+ seenIds.set(id, "layout");
205
+ return;
206
+ }
207
+ if (v.layoutIdInvalid) {
208
+ findings.push({
209
+ code: "layout-id-invalid",
210
+ severity: "warn",
211
+ nodeId: "<layout>",
212
+ kind: "<layout>",
213
+ message: `layout id ${describeValue(v.layoutIdInvalid.id)} is not a non-empty string — renderers treat it as absent and key this container by position, so its state is not kept across a recompose`,
214
+ });
215
+ return;
216
+ }
217
+ if (v.columnsInvalid) {
218
+ findings.push({
219
+ code: "columns-invalid",
220
+ severity: "error",
221
+ nodeId: v.columnsInvalid.nodeId,
222
+ kind: "<layout>",
223
+ message: `grid columns ${JSON.stringify(v.columnsInvalid.columns) ?? "undefined"} is not a positive integer — there is no column count to place cells into, so this grid's spans are not checked`,
224
+ });
225
+ return;
226
+ }
227
+ if (v.roleInvalid) {
228
+ findings.push({
229
+ code: "role-invalid",
230
+ severity: "warn",
231
+ nodeId: v.roleInvalid.nodeId,
232
+ kind: "<layout>",
233
+ message: `layout role ${describeValue(v.roleInvalid.role)} is not a well-formed role (a lowercase letter, then lowercase letters, digits or hyphens, at most 64 characters) — renderers draw the plain container`,
234
+ });
235
+ return;
236
+ }
237
+ if (v.malformed) {
238
+ findings.push({
239
+ code: "malformed-node",
240
+ severity: "error",
241
+ nodeId: "<layout>",
242
+ kind: "<layout>",
243
+ message: `a layout child is neither a Widget nor a Layout (${describeNode(v.malformed.node)}) — it renders nothing, and the subtree below it is not validated`,
244
+ });
245
+ return;
246
+ }
247
+ if (v.cell) {
248
+ const { span, columns, cellNodeId, row, rowSpan, column } = v.cell;
249
+ const spanOk = Number.isInteger(span) && span >= 1 && span <= columns;
250
+ if (!spanOk) {
251
+ findings.push({
252
+ code: "span-out-of-range",
253
+ severity: "error",
254
+ nodeId: cellNodeId ?? "<layout>",
255
+ kind: "<layout>",
256
+ message: `cell span ${span} is outside 1..${columns} — a renderer cannot lay this cell out`,
257
+ });
258
+ }
259
+ const problems = placementProblems({ row, rowSpan, column, span, spanOk, columns });
260
+ if (problems.length > 0) {
261
+ findings.push({
262
+ code: "placement-out-of-range",
263
+ severity: "error",
264
+ nodeId: cellNodeId ?? "<layout>",
265
+ kind: "<layout>",
266
+ message: `cell placement cannot be laid out — ${problems.join("; ")}`,
267
+ });
268
+ }
269
+ return;
270
+ }
271
+ const widget = v.widget;
272
+ if (!widget)
273
+ return;
274
+ widgets++;
275
+ const { id, kind } = widget;
276
+ const earlier = seenIds.get(id);
277
+ if (earlier !== undefined) {
278
+ findings.push({
279
+ code: "duplicate-node-id",
280
+ severity: "error",
281
+ nodeId: id,
282
+ kind,
283
+ message: earlier === "widget"
284
+ ? `two widgets share the id "${id}" — node identity and the renderer's key collide, so one silently replaces the other`
285
+ : `a widget shares the id "${id}" with an earlier layout — widget and layout ids are one namespace, so node identity and the renderer's key collide`,
286
+ });
287
+ }
288
+ else {
289
+ seenIds.set(id, "widget");
290
+ }
291
+ // IR 2.5.0: `source.redacted` is `true` or absent (an explicit `undefined` is absent), and a
292
+ // redacted widget carries nothing it withheld: no binding, no title, no props, no degradedFrom,
293
+ // and the constant source type/version. Runs BEFORE the unknown-kind return, so a redacted
294
+ // widget of an unknown kind that still carries data is caught too.
295
+ {
296
+ const rs = widget.source;
297
+ if (rs !== null && typeof rs === "object" && rs.redacted !== undefined) {
298
+ const bad = (message) => findings.push({ code: "redacted-invalid", severity: "error", nodeId: id, kind, message });
299
+ if (rs.redacted !== true) {
300
+ bad(`widget.source.redacted must be true or absent, got ${JSON.stringify(rs.redacted)}`);
301
+ }
302
+ else {
303
+ const leaks = [];
304
+ if (widget.binding !== undefined)
305
+ leaks.push("binding");
306
+ if (widget.title !== undefined)
307
+ leaks.push("title");
308
+ if (widget.props && Object.keys(widget.props).length > 0)
309
+ leaks.push("props");
310
+ if (rs.degradedFrom !== undefined)
311
+ leaks.push("source.degradedFrom");
312
+ if (rs.type !== "redacted" || rs.version !== "1")
313
+ leaks.push(`original source type/version (must be "redacted"/"1")`);
314
+ if (leaks.length > 0)
315
+ bad(`a redacted widget must carry no ${leaks.join(" and no ")} — it would leave the withheld content on the artifact`);
316
+ }
317
+ }
318
+ }
319
+ const entry = entries.get(kind);
320
+ if (!entry) {
321
+ findings.push({
322
+ code: "unknown-kind",
323
+ severity: "error",
324
+ nodeId: id,
325
+ kind,
326
+ message: `"${kind}" is not in catalogue "${catalog.id}" — a composer may only assemble from the audited set`,
327
+ });
328
+ // Nothing further is checkable without an entry: the allow-list and the
329
+ // binding requirement both come from it. Reporting invented follow-on
330
+ // findings here would inflate the count for one real defect.
331
+ return;
332
+ }
333
+ if (entry.binding === "required" && !widget.binding) {
334
+ findings.push({
335
+ code: "missing-binding",
336
+ severity: "error",
337
+ nodeId: id,
338
+ kind,
339
+ message: `"${kind}" renders bound data but carries no binding — it would render blank with no error`,
340
+ });
341
+ }
342
+ if (entry.binding === "none" && widget.binding) {
343
+ findings.push({
344
+ code: "unexpected-binding",
345
+ severity: "warn",
346
+ nodeId: id,
347
+ kind,
348
+ message: `"${kind}" is declared as taking no binding, but this widget carries one`,
349
+ });
350
+ }
351
+ if (widget.binding && !projections.has(widget.binding.projectionId)) {
352
+ findings.push({
353
+ code: "undeclared-projection",
354
+ severity: "error",
355
+ nodeId: id,
356
+ kind,
357
+ message: `binds to projection "${widget.binding.projectionId}", which the blueprint does not declare — renderers hydrate only declared projections, so this widget resolves to undefined and renders blank`,
358
+ });
359
+ }
360
+ const allowed = new Set(entry.props);
361
+ for (const prop of Object.keys(widget.props)) {
362
+ if (RESERVED_PROPS.has(prop) || allowed.has(prop))
363
+ continue;
364
+ findings.push({
365
+ code: "undeclared-prop",
366
+ severity: "error",
367
+ nodeId: id,
368
+ kind,
369
+ message: `prop "${prop}" is not declared by "${kind}" in catalogue "${catalog.id}" — a blueprint carries bindings, never fetched data, and an undeclared prop is how data gets inlined into a shared artifact`,
370
+ });
371
+ }
372
+ // `binding` and `source` are typed, but a blueprint is data a model can compose —
373
+ // a malformed value (null, a string, ...) must be a finding, never a property
374
+ // access on a non-object, so every read below goes through a typeof guard first.
375
+ const status = widget.binding?.status;
376
+ if (status !== undefined) {
377
+ const path = status !== null && typeof status === "object"
378
+ ? status.path
379
+ : undefined;
380
+ if (typeof path !== "string" || path === "" || !DOTTED.test(path)) {
381
+ findings.push({
382
+ code: "status-path-invalid",
383
+ severity: "error",
384
+ nodeId: id,
385
+ kind,
386
+ message: `binding.status.path ${JSON.stringify(path)} is not a non-empty dotted path`,
387
+ });
388
+ }
389
+ }
390
+ const sensitivity = widget.binding?.sensitivity;
391
+ if (sensitivity !== undefined && !DATA_CLASSES.has(sensitivity)) {
392
+ findings.push({
393
+ code: "sensitivity-unknown",
394
+ severity: "error",
395
+ nodeId: id,
396
+ kind,
397
+ message: `binding.sensitivity ${JSON.stringify(sensitivity)} is not a @loomwork/classify DataClass`,
398
+ });
399
+ }
400
+ const source = widget.source;
401
+ if (source !== undefined) {
402
+ const src = source !== null && typeof source === "object"
403
+ ? source
404
+ : undefined;
405
+ const degradedFrom = Array.isArray(src?.degradedFrom) ? src.degradedFrom : undefined;
406
+ // Typed as `string`, so a NON-string is exactly what a hand-assembled artifact gets wrong.
407
+ // A truthiness test would accept `type: 123` and `version: {}` — both render as garbage.
408
+ const notAName = (v) => typeof v !== "string" || v === "";
409
+ const invalid = src === undefined ||
410
+ notAName(src.type) ||
411
+ notAName(src.version) ||
412
+ (src.degradedFrom !== undefined && degradedFrom === undefined) ||
413
+ (degradedFrom?.some((d) => typeof d !== "object" ||
414
+ d === null ||
415
+ notAName(d.type) ||
416
+ notAName(d.version)) ??
417
+ false);
418
+ if (invalid) {
419
+ findings.push({
420
+ code: "source-invalid",
421
+ severity: "error",
422
+ nodeId: id,
423
+ kind,
424
+ message: `widget.source is missing a non-empty string "type" or "version" — either on the source itself or a degradedFrom entry (which must be an array)`,
425
+ });
426
+ }
427
+ }
428
+ });
429
+ return {
430
+ ok: findings.every((f) => f.severity !== "error"),
431
+ findings,
432
+ widgets,
433
+ };
434
+ }
435
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { RendererRegistry } from "./RendererRegistry";
2
+ import type { WidgetCatalog } from "./catalog";
3
+ export interface CoverageReport {
4
+ /** True iff every catalogue kind has a renderer. */
5
+ readonly ok: boolean;
6
+ /** Catalogue kinds with no registered renderer — these render as a placeholder. */
7
+ readonly missing: readonly string[];
8
+ /** Registered kinds absent from the catalogue — reported, not failed. */
9
+ readonly extra: readonly string[];
10
+ }
11
+ /**
12
+ * Which of a catalogue's components this registry can actually render.
13
+ *
14
+ * Use it as a test in any package that ships a renderer, so adding a kind to the
15
+ * vocabulary without a renderer fails the build rather than the viewer.
16
+ */
17
+ export declare function catalogCoverage(catalog: WidgetCatalog, registry: RendererRegistry<unknown>): CoverageReport;
18
+ //# sourceMappingURL=coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAmB/C,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAClC,cAAc,CAahB"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.catalogCoverage = catalogCoverage;
4
+ /**
5
+ * Which of a catalogue's components this registry can actually render.
6
+ *
7
+ * Use it as a test in any package that ships a renderer, so adding a kind to the
8
+ * vocabulary without a renderer fails the build rather than the viewer.
9
+ */
10
+ function catalogCoverage(catalog, registry) {
11
+ const registered = new Set(registry.kinds());
12
+ const missing = [];
13
+ const declared = new Set();
14
+ for (const entry of catalog.entries) {
15
+ declared.add(entry.kind);
16
+ if (!registered.has(entry.kind))
17
+ missing.push(entry.kind);
18
+ }
19
+ const extra = [...registered].filter((kind) => !declared.has(kind));
20
+ return { ok: missing.length === 0, missing, extra };
21
+ }
22
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":";;AAmCA,0CAgBC;AAtBD;;;;;GAKG;AACH,SAAgB,eAAe,CAC7B,OAAsB,EACtB,QAAmC;IAEnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACtD,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { DataBinding, Widget } from "./types";
2
+ export interface CustomWidgetConfig {
3
+ kind: string;
4
+ title?: string;
5
+ binding?: DataBinding;
6
+ props?: Record<string, unknown>;
7
+ id?: string;
8
+ }
9
+ export declare function customWidget$(config: CustomWidgetConfig): Widget;
10
+ //# sourceMappingURL=customWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customWidget.d.ts","sourceRoot":"","sources":["../src/customWidget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAWnD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAYD,wBAAgB,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAYhE"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.customWidget$ = customWidget$;
4
+ function stableId(kind, props) {
5
+ const str = kind + JSON.stringify(props, Object.keys(props).sort());
6
+ let hash = 0;
7
+ for (let i = 0; i < str.length; i++) {
8
+ hash = (Math.imul(31, hash) + str.charCodeAt(i)) | 0;
9
+ }
10
+ return `${kind}-${(hash >>> 0).toString(16)}`;
11
+ }
12
+ // Builder for user-defined widget kinds that live outside the WidgetKind union.
13
+ // Register a matching renderer in your RendererRegistry under the same `kind` string.
14
+ //
15
+ // const HeatmapWidget = customWidget$({
16
+ // kind: "Heatmap",
17
+ // title: "CPU Heatmap",
18
+ // binding: { projectionId: "metrics", path: "cpu.history" },
19
+ // props: { buckets: 20 },
20
+ // });
21
+ // registry.register("Heatmap", HeatmapComponent);
22
+ function customWidget$(config) {
23
+ const propsRecord = config.props ?? {};
24
+ return {
25
+ _tag: "Widget",
26
+ id: config.id ??
27
+ stableId(config.kind, { title: config.title, binding: config.binding, ...propsRecord }),
28
+ kind: config.kind,
29
+ ...(config.title !== undefined && { title: config.title }),
30
+ props: propsRecord,
31
+ ...(config.binding !== undefined && { binding: config.binding }),
32
+ };
33
+ }
34
+ //# sourceMappingURL=customWidget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customWidget.js","sourceRoot":"","sources":["../src/customWidget.ts"],"names":[],"mappings":";;AA6BA,sCAYC;AAvCD,SAAS,QAAQ,CAAC,IAAY,EAAE,KAAa;IAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/F,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AAChD,CAAC;AAUD,gFAAgF;AAChF,sFAAsF;AACtF,EAAE;AACF,0CAA0C;AAC1C,uBAAuB;AACvB,4BAA4B;AAC5B,iEAAiE;AACjE,8BAA8B;AAC9B,QAAQ;AACR,oDAAoD;AACpD,SAAgB,aAAa,CAAC,MAA0B;IACtD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IACvC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,EAAE,EACA,MAAM,CAAC,EAAE;YACT,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;QACzF,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1D,KAAK,EAAE,WAAW;QAClB,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;KACjE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { BLUEPRINT_IR_VERSION } from "./irVersion";
2
+ export function blueprint$(config) {
3
+ return {
4
+ _tag: "Blueprint",
5
+ irVersion: BLUEPRINT_IR_VERSION,
6
+ id: config.id,
7
+ title: config.title,
8
+ layout: config.layout,
9
+ projections: config.projections,
10
+ ...(config.projectionVersions !== undefined && {
11
+ projectionVersions: config.projectionVersions,
12
+ }),
13
+ };
14
+ }
15
+ //# sourceMappingURL=Blueprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Blueprint.js","sourceRoot":"","sources":["../../src/Blueprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAenD,MAAM,UAAU,UAAU,CAAC,MAAuB;IAChD,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,oBAAoB;QAC/B,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,GAAG,CAAC,MAAM,CAAC,kBAAkB,KAAK,SAAS,IAAI;YAC7C,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;SAC9C,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ // Generic widget registry — framework-agnostic.
2
+ // TRenderer is narrowed by each framework adapter:
3
+ // React: RendererRegistry<React.FC<WidgetRendererProps>>
4
+ // Angular: RendererRegistry<Type<unknown>>
5
+ // DOM: RendererRegistry<(el: HTMLElement, props: WidgetRendererProps) => void>
6
+ export class RendererRegistry {
7
+ renderers = new Map();
8
+ register(kind, renderer) {
9
+ this.renderers.set(kind, renderer);
10
+ return this;
11
+ }
12
+ get(kind) {
13
+ return this.renderers.get(kind);
14
+ }
15
+ has(kind) {
16
+ return this.renderers.has(kind);
17
+ }
18
+ kinds() {
19
+ return Array.from(this.renderers.keys());
20
+ }
21
+ // Returns a new registry that contains all renderers from both registries.
22
+ // Entries in `other` win on conflicts.
23
+ merge(other) {
24
+ const merged = new RendererRegistry();
25
+ for (const [kind, r] of this.renderers)
26
+ merged.register(kind, r);
27
+ for (const kind of other.kinds()) {
28
+ const r = other.get(kind);
29
+ if (r !== undefined)
30
+ merged.register(kind, r);
31
+ }
32
+ return merged;
33
+ }
34
+ }
35
+ //# sourceMappingURL=RendererRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RendererRegistry.js","sourceRoot":"","sources":["../../src/RendererRegistry.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,mDAAmD;AACnD,6DAA6D;AAC7D,6CAA6C;AAC7C,qFAAqF;AAErF,MAAM,OAAO,gBAAgB;IACV,SAAS,GAAG,IAAI,GAAG,EAAqB,CAAC;IAE1D,QAAQ,CAAC,IAAY,EAAE,QAAmB;QACxC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK;QACH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,2EAA2E;IAC3E,uCAAuC;IACvC,KAAK,CAAC,KAAkC;QACtC,MAAM,MAAM,GAAG,IAAI,gBAAgB,EAAa,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACjE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,SAAS;gBAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}