@bespokeagentics/microdots-host 0.1.0 → 0.1.2
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/evals/topology-regressions.p5.v1.json +105 -0
- package/package.json +6 -4
- package/src/composeFromSelection.test.ts +277 -0
- package/src/composeFromSelection.ts +376 -0
- package/src/compositionSpec.test.ts +311 -0
- package/src/compositionSpec.ts +802 -0
- package/src/compositionSpec.v2.test.ts +216 -0
- package/src/fillComposition.test.ts +240 -0
- package/src/fillComposition.ts +159 -0
- package/src/index.ts +140 -2
- package/src/mountedRegistry.test.ts +196 -0
- package/src/mounting.test.ts +8 -8
- package/src/mounting.ts +116 -0
- package/src/placementChecks.test.ts +12 -12
- package/src/rules.test.ts +4 -4
- package/src/rules.ts +1 -1
- package/src/slotDom.test.ts +151 -0
- package/src/slotDom.ts +111 -0
- package/src/slotResize.test.ts +392 -0
- package/src/slotResize.ts +367 -0
- package/src/slots.test.ts +53 -0
- package/src/slots.ts +30 -3
- package/src/topologyRegression.test.ts +37 -0
- package/src/topologyRegression.ts +143 -0
- package/src/topologySource.test.ts +137 -0
- package/src/topologySource.ts +97 -0
- package/src/tracePublisher.test.ts +95 -0
- package/src/tracePublisher.ts +117 -0
- package/src/wire.test.ts +13 -11
- package/src/wireEngine.test.ts +60 -36
- package/src/wireEngine.ts +13 -3
package/src/wireEngine.test.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type WireEngine,
|
|
7
7
|
type WireEngineOptions,
|
|
8
8
|
type WireTrace,
|
|
9
|
+
WIRE_TRACE_EVENT,
|
|
9
10
|
applyTransform,
|
|
10
11
|
attachWireEngine,
|
|
11
12
|
planWires,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
|
|
19
20
|
const w1: Wire = {
|
|
20
21
|
id: 'w1',
|
|
21
|
-
from: '
|
|
22
|
+
from: 'readout-view',
|
|
22
23
|
event: 'quote-changed',
|
|
23
24
|
field: 'symbol',
|
|
24
25
|
fieldType: 'string',
|
|
@@ -36,11 +37,11 @@ const w1: Wire = {
|
|
|
36
37
|
|
|
37
38
|
const w2: Wire = {
|
|
38
39
|
id: 'w2',
|
|
39
|
-
from: '
|
|
40
|
+
from: 'intake-form',
|
|
40
41
|
event: 'submission-created',
|
|
41
42
|
field: 'id',
|
|
42
43
|
fieldType: 'string',
|
|
43
|
-
to: '
|
|
44
|
+
to: 'intake-backend',
|
|
44
45
|
input: 'refresh-token',
|
|
45
46
|
inputType: 'string',
|
|
46
47
|
transform: { _tag: 'direct' },
|
|
@@ -50,11 +51,11 @@ const w2: Wire = {
|
|
|
50
51
|
|
|
51
52
|
const w3: Wire = {
|
|
52
53
|
id: 'w3',
|
|
53
|
-
from: '
|
|
54
|
+
from: 'intake-backend',
|
|
54
55
|
event: 'definition-changed',
|
|
55
56
|
field: 'version',
|
|
56
57
|
fieldType: 'number',
|
|
57
|
-
to: '
|
|
58
|
+
to: 'intake-form',
|
|
58
59
|
input: 'definition-token',
|
|
59
60
|
inputType: 'number',
|
|
60
61
|
transform: { _tag: 'direct' },
|
|
@@ -107,7 +108,7 @@ const pg7: Wire = { ...pg6, id: 'pg7', to: 'pages-inspector' }
|
|
|
107
108
|
/** A `json` wire — the one declared fieldType the demo records never use. */
|
|
108
109
|
const wJson: Wire = {
|
|
109
110
|
id: 'w-json',
|
|
110
|
-
from: '
|
|
111
|
+
from: 'intake-backend',
|
|
111
112
|
event: 'snapshot-changed',
|
|
112
113
|
field: 'snapshot',
|
|
113
114
|
fieldType: 'json',
|
|
@@ -186,16 +187,39 @@ describe('attachWireEngine', () => {
|
|
|
186
187
|
const fleet = mount('fleet-health')
|
|
187
188
|
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
188
189
|
|
|
189
|
-
dispatch('
|
|
190
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
190
191
|
|
|
191
192
|
expect(fleet.getAttribute('region')).toBe('eu-west')
|
|
192
193
|
})
|
|
193
194
|
|
|
195
|
+
test('broadcasts every wire trace on document so Watch/Trace can listen without importing the host', () => {
|
|
196
|
+
const seen: Array<unknown> = []
|
|
197
|
+
const listener = (event: Event): void => {
|
|
198
|
+
if (event instanceof CustomEvent) seen.push(event.detail)
|
|
199
|
+
}
|
|
200
|
+
document.addEventListener(WIRE_TRACE_EVENT, listener)
|
|
201
|
+
mount('fleet-health')
|
|
202
|
+
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
203
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
204
|
+
document.removeEventListener(WIRE_TRACE_EVENT, listener)
|
|
205
|
+
expect(seen).toEqual([
|
|
206
|
+
{
|
|
207
|
+
_tag: 'wire',
|
|
208
|
+
event: 'quote-changed',
|
|
209
|
+
wireId: 'w1',
|
|
210
|
+
delivery: {
|
|
211
|
+
_tag: 'written',
|
|
212
|
+
write: { toTag: 'fleet-health', input: 'region', value: 'eu-west' },
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
])
|
|
216
|
+
})
|
|
217
|
+
|
|
194
218
|
test('falls back to us-east for a symbol outside the lookup rows', () => {
|
|
195
219
|
const fleet = mount('fleet-health')
|
|
196
220
|
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
197
221
|
|
|
198
|
-
dispatch('
|
|
222
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'ZZZZ', cents: 1 })
|
|
199
223
|
|
|
200
224
|
expect(fleet.getAttribute('region')).toBe('us-east')
|
|
201
225
|
})
|
|
@@ -209,7 +233,7 @@ describe('attachWireEngine', () => {
|
|
|
209
233
|
})
|
|
210
234
|
|
|
211
235
|
engine.setEnabled('w1', false)
|
|
212
|
-
dispatch('
|
|
236
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
213
237
|
|
|
214
238
|
expect(fleet.getAttribute('region')).toBeNull()
|
|
215
239
|
expect(traces).toEqual([
|
|
@@ -223,15 +247,15 @@ describe('attachWireEngine', () => {
|
|
|
223
247
|
|
|
224
248
|
// The kill switch is not a detach: flipping it back restores the wire.
|
|
225
249
|
engine.setEnabled('w1', true)
|
|
226
|
-
dispatch('
|
|
250
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
227
251
|
expect(fleet.getAttribute('region')).toBe('eu-west')
|
|
228
252
|
})
|
|
229
253
|
|
|
230
254
|
test('encodes the numeric version 7 as the attribute string "7"', () => {
|
|
231
|
-
const form = mount('
|
|
255
|
+
const form = mount('intake-form')
|
|
232
256
|
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
233
257
|
|
|
234
|
-
dispatch('
|
|
258
|
+
dispatch('intake-backend', 'definition-changed', { version: 7 })
|
|
235
259
|
|
|
236
260
|
expect(form.getAttribute('definition-token')).toBe('7')
|
|
237
261
|
})
|
|
@@ -243,14 +267,14 @@ describe('attachWireEngine', () => {
|
|
|
243
267
|
* it (apps/host/src/loader.test.ts pins the same guard directly).
|
|
244
268
|
*/
|
|
245
269
|
test('two identical events produce exactly one setAttribute call', () => {
|
|
246
|
-
const form = mount('
|
|
270
|
+
const form = mount('intake-form')
|
|
247
271
|
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
248
272
|
|
|
249
|
-
dispatch('
|
|
273
|
+
dispatch('intake-backend', 'definition-changed', { version: 7 })
|
|
250
274
|
expect(form.getAttribute('definition-token')).toBe('7')
|
|
251
275
|
|
|
252
276
|
const spy = vi.spyOn(form, 'setAttribute')
|
|
253
|
-
dispatch('
|
|
277
|
+
dispatch('intake-backend', 'definition-changed', { version: 7 })
|
|
254
278
|
|
|
255
279
|
expect(spy).not.toHaveBeenCalled()
|
|
256
280
|
spy.mockRestore()
|
|
@@ -263,7 +287,7 @@ describe('attachWireEngine', () => {
|
|
|
263
287
|
const fleet = mount('fleet-health')
|
|
264
288
|
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
265
289
|
|
|
266
|
-
dispatch('
|
|
290
|
+
dispatch('readout-view', 'quote-changed', {
|
|
267
291
|
symbol: 'constructor',
|
|
268
292
|
cents: 1,
|
|
269
293
|
})
|
|
@@ -272,14 +296,14 @@ describe('attachWireEngine', () => {
|
|
|
272
296
|
})
|
|
273
297
|
|
|
274
298
|
test('a payload that is not a record skips as no-field', () => {
|
|
275
|
-
const form = mount('
|
|
299
|
+
const form = mount('intake-form')
|
|
276
300
|
const traces: Array<WireTrace> = []
|
|
277
301
|
attach({
|
|
278
302
|
topology: { wires: DEMO_WIRES, watch: [] },
|
|
279
303
|
onTrace: trace => traces.push(trace),
|
|
280
304
|
})
|
|
281
305
|
|
|
282
|
-
dispatch('
|
|
306
|
+
dispatch('intake-backend', 'definition-changed', 'seven')
|
|
283
307
|
|
|
284
308
|
expect(form.getAttribute('definition-token')).toBeNull()
|
|
285
309
|
expect(traces).toEqual([
|
|
@@ -293,14 +317,14 @@ describe('attachWireEngine', () => {
|
|
|
293
317
|
})
|
|
294
318
|
|
|
295
319
|
test("a payload missing the wire's field skips as no-field", () => {
|
|
296
|
-
const form = mount('
|
|
320
|
+
const form = mount('intake-form')
|
|
297
321
|
const traces: Array<WireTrace> = []
|
|
298
322
|
attach({
|
|
299
323
|
topology: { wires: DEMO_WIRES, watch: [] },
|
|
300
324
|
onTrace: trace => traces.push(trace),
|
|
301
325
|
})
|
|
302
326
|
|
|
303
|
-
dispatch('
|
|
327
|
+
dispatch('intake-backend', 'definition-changed', { revision: 7 })
|
|
304
328
|
|
|
305
329
|
expect(form.getAttribute('definition-token')).toBeNull()
|
|
306
330
|
expect(traces).toEqual([
|
|
@@ -314,14 +338,14 @@ describe('attachWireEngine', () => {
|
|
|
314
338
|
})
|
|
315
339
|
|
|
316
340
|
test('a value that fails its declared fieldType decode skips as no-field', () => {
|
|
317
|
-
const form = mount('
|
|
341
|
+
const form = mount('intake-form')
|
|
318
342
|
const traces: Array<WireTrace> = []
|
|
319
343
|
attach({
|
|
320
344
|
topology: { wires: DEMO_WIRES, watch: [] },
|
|
321
345
|
onTrace: trace => traces.push(trace),
|
|
322
346
|
})
|
|
323
347
|
|
|
324
|
-
dispatch('
|
|
348
|
+
dispatch('intake-backend', 'definition-changed', {
|
|
325
349
|
version: 'seven',
|
|
326
350
|
})
|
|
327
351
|
|
|
@@ -340,7 +364,7 @@ describe('attachWireEngine', () => {
|
|
|
340
364
|
const fleet = mount('fleet-health')
|
|
341
365
|
attach({ topology: { wires: [wJson], watch: [] } })
|
|
342
366
|
|
|
343
|
-
dispatch('
|
|
367
|
+
dispatch('intake-backend', 'snapshot-changed', {
|
|
344
368
|
snapshot: { id: 7, tags: ['a'] },
|
|
345
369
|
})
|
|
346
370
|
|
|
@@ -368,7 +392,7 @@ describe('attachWireEngine', () => {
|
|
|
368
392
|
|
|
369
393
|
const cyclic: Record<string, unknown> = {}
|
|
370
394
|
cyclic['self'] = cyclic
|
|
371
|
-
dispatch('
|
|
395
|
+
dispatch('intake-backend', 'snapshot-changed', {
|
|
372
396
|
snapshot: cyclic,
|
|
373
397
|
label: 'ok',
|
|
374
398
|
})
|
|
@@ -401,7 +425,7 @@ describe('attachWireEngine', () => {
|
|
|
401
425
|
const second = mount('fleet-health')
|
|
402
426
|
attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
403
427
|
|
|
404
|
-
dispatch('
|
|
428
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
405
429
|
|
|
406
430
|
expect(first.getAttribute('region')).toBe('eu-west')
|
|
407
431
|
expect(second.getAttribute('region')).toBe('eu-west')
|
|
@@ -418,7 +442,7 @@ describe('attachWireEngine', () => {
|
|
|
418
442
|
onTrace: trace => traces.push(trace),
|
|
419
443
|
})
|
|
420
444
|
|
|
421
|
-
dispatch('
|
|
445
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
422
446
|
|
|
423
447
|
expect(fleet.getAttribute('region')).toBe('eu-west')
|
|
424
448
|
expect(traces).toEqual([
|
|
@@ -455,7 +479,7 @@ describe('attachWireEngine', () => {
|
|
|
455
479
|
onTrace: trace => traces.push(trace),
|
|
456
480
|
})
|
|
457
481
|
|
|
458
|
-
dispatch('
|
|
482
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
459
483
|
|
|
460
484
|
expect(fleet.getAttribute('region')).toBe('eu-west')
|
|
461
485
|
expect(traces).toEqual([
|
|
@@ -494,7 +518,7 @@ describe('attachWireEngine', () => {
|
|
|
494
518
|
onTrace: trace => traces.push(trace),
|
|
495
519
|
})
|
|
496
520
|
|
|
497
|
-
dispatch('
|
|
521
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
498
522
|
|
|
499
523
|
expect(traces.map(trace => trace._tag)).toEqual(['watch', 'wire'])
|
|
500
524
|
})
|
|
@@ -517,7 +541,7 @@ describe('attachWireEngine', () => {
|
|
|
517
541
|
onTrace: trace => traces.push(trace),
|
|
518
542
|
})
|
|
519
543
|
|
|
520
|
-
dispatch('
|
|
544
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', linked: false })
|
|
521
545
|
|
|
522
546
|
expect(fleet.getAttribute('region')).toBeNull()
|
|
523
547
|
expect(traces).toEqual([
|
|
@@ -530,7 +554,7 @@ describe('attachWireEngine', () => {
|
|
|
530
554
|
])
|
|
531
555
|
|
|
532
556
|
// The condition holding is the whole difference: same event, one write.
|
|
533
|
-
dispatch('
|
|
557
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', linked: true })
|
|
534
558
|
expect(fleet.getAttribute('region')).toBe('EFCT')
|
|
535
559
|
})
|
|
536
560
|
|
|
@@ -563,7 +587,7 @@ describe('attachWireEngine', () => {
|
|
|
563
587
|
onTrace: trace => traces.push(trace),
|
|
564
588
|
})
|
|
565
589
|
|
|
566
|
-
dispatch('
|
|
590
|
+
dispatch('intake-form', 'submission-created', { id: 'sub-42' })
|
|
567
591
|
|
|
568
592
|
expect(traces).toEqual([
|
|
569
593
|
{
|
|
@@ -573,7 +597,7 @@ describe('attachWireEngine', () => {
|
|
|
573
597
|
delivery: {
|
|
574
598
|
_tag: 'target-unmounted',
|
|
575
599
|
write: {
|
|
576
|
-
toTag: '
|
|
600
|
+
toTag: 'intake-backend',
|
|
577
601
|
input: 'refresh-token',
|
|
578
602
|
value: 'sub-42',
|
|
579
603
|
},
|
|
@@ -670,7 +694,7 @@ describe('attachWireEngine', () => {
|
|
|
670
694
|
const engine = attach({ topology: { wires: DEMO_WIRES, watch: [] } })
|
|
671
695
|
|
|
672
696
|
engine.detach()
|
|
673
|
-
dispatch('
|
|
697
|
+
dispatch('readout-view', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
|
|
674
698
|
|
|
675
699
|
expect(fleet.getAttribute('region')).toBeNull()
|
|
676
700
|
})
|
|
@@ -725,7 +749,7 @@ describe('planWires', () => {
|
|
|
725
749
|
const envelope = {
|
|
726
750
|
version: 1,
|
|
727
751
|
type: 'submission-created',
|
|
728
|
-
from: '
|
|
752
|
+
from: 'intake-form',
|
|
729
753
|
submissionId: 'sub-42',
|
|
730
754
|
}
|
|
731
755
|
const bridgeWire: Wire = { ...w2, field: 'submissionId' }
|
|
@@ -742,7 +766,7 @@ describe('planWires', () => {
|
|
|
742
766
|
|
|
743
767
|
expect(plan.writes).toEqual([
|
|
744
768
|
{
|
|
745
|
-
toTag: '
|
|
769
|
+
toTag: 'intake-backend',
|
|
746
770
|
input: 'refresh-token',
|
|
747
771
|
value: 'sub-42',
|
|
748
772
|
},
|
|
@@ -796,7 +820,7 @@ describe('planWires', () => {
|
|
|
796
820
|
[devOnly],
|
|
797
821
|
{
|
|
798
822
|
name: 'submission-created',
|
|
799
|
-
sourceTag: Option.some('
|
|
823
|
+
sourceTag: Option.some('intake-form'),
|
|
800
824
|
payload: { id: 'sub-1' },
|
|
801
825
|
},
|
|
802
826
|
{ env: 'prod', isEnabled: () => true },
|
package/src/wireEngine.ts
CHANGED
|
@@ -307,8 +307,12 @@ export type WireDelivery =
|
|
|
307
307
|
/**
|
|
308
308
|
* What `onTrace` surfaces: every wire firing with its delivery, and every
|
|
309
309
|
* `watch[]` tap with the raw payload. The host's log formatter consumes the
|
|
310
|
-
* taps; the Wiring screen's Watch mode
|
|
310
|
+
* taps; the Wiring screen's Watch mode and Trace tab consume both via the
|
|
311
|
+
* document event below — they cannot share a module-level bus with the host
|
|
312
|
+
* because the MicroDot bundle is a separate module graph.
|
|
311
313
|
*/
|
|
314
|
+
export const WIRE_TRACE_EVENT = 'microdots:wire-trace'
|
|
315
|
+
|
|
312
316
|
export type WireTrace =
|
|
313
317
|
| {
|
|
314
318
|
readonly _tag: 'wire'
|
|
@@ -348,6 +352,12 @@ export type WireEngine = {
|
|
|
348
352
|
export const attachWireEngine = (options: WireEngineOptions): WireEngine => {
|
|
349
353
|
const { wires, watch } = options.topology
|
|
350
354
|
const onTrace = options.onTrace ?? (() => undefined)
|
|
355
|
+
const publish = (trace: WireTrace): void => {
|
|
356
|
+
onTrace(trace)
|
|
357
|
+
document.dispatchEvent(
|
|
358
|
+
new CustomEvent(WIRE_TRACE_EVENT, { detail: trace }),
|
|
359
|
+
)
|
|
360
|
+
}
|
|
351
361
|
|
|
352
362
|
// Target resolution is pinned: by tag name, among mounted elements, EVERY
|
|
353
363
|
// instance — not an injection point. `wire.to` is record data the schema
|
|
@@ -431,7 +441,7 @@ export const attachWireEngine = (options: WireEngineOptions): WireEngine => {
|
|
|
431
441
|
// HOST'S LOG, not a wire — it fires for every emitter of the name, and
|
|
432
442
|
// an unidentifiable source does not silence it.
|
|
433
443
|
if (watched.has(name)) {
|
|
434
|
-
|
|
444
|
+
publish({ _tag: 'watch', event: name, payload })
|
|
435
445
|
}
|
|
436
446
|
const plan = planWires(
|
|
437
447
|
wires,
|
|
@@ -439,7 +449,7 @@ export const attachWireEngine = (options: WireEngineOptions): WireEngine => {
|
|
|
439
449
|
{ env: options.env, isEnabled },
|
|
440
450
|
)
|
|
441
451
|
plan.outcomes.forEach(outcome => {
|
|
442
|
-
|
|
452
|
+
publish({
|
|
443
453
|
_tag: 'wire',
|
|
444
454
|
event: name,
|
|
445
455
|
wireId: outcome.wireId,
|