@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.
@@ -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: 'price-ticker',
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: 'bespoke-contact-form',
40
+ from: 'intake-form',
40
41
  event: 'submission-created',
41
42
  field: 'id',
42
43
  fieldType: 'string',
43
- to: 'bespoke-contact-dashboard',
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: 'bespoke-contact-dashboard',
54
+ from: 'intake-backend',
54
55
  event: 'definition-changed',
55
56
  field: 'version',
56
57
  fieldType: 'number',
57
- to: 'bespoke-contact-form',
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: 'bespoke-contact-dashboard',
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('price-ticker', 'quote-changed', { symbol: 'ZZZZ', cents: 1 })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('bespoke-contact-form')
255
+ const form = mount('intake-form')
232
256
  attach({ topology: { wires: DEMO_WIRES, watch: [] } })
233
257
 
234
- dispatch('bespoke-contact-dashboard', 'definition-changed', { version: 7 })
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('bespoke-contact-form')
270
+ const form = mount('intake-form')
247
271
  attach({ topology: { wires: DEMO_WIRES, watch: [] } })
248
272
 
249
- dispatch('bespoke-contact-dashboard', 'definition-changed', { version: 7 })
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('bespoke-contact-dashboard', 'definition-changed', { version: 7 })
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('price-ticker', 'quote-changed', {
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('bespoke-contact-form')
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('bespoke-contact-dashboard', 'definition-changed', 'seven')
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('bespoke-contact-form')
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('bespoke-contact-dashboard', 'definition-changed', { revision: 7 })
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('bespoke-contact-form')
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('bespoke-contact-dashboard', 'definition-changed', {
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('bespoke-contact-dashboard', 'snapshot-changed', {
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('bespoke-contact-dashboard', 'snapshot-changed', {
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', linked: false })
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('price-ticker', 'quote-changed', { symbol: 'EFCT', linked: true })
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('bespoke-contact-form', 'submission-created', { id: 'sub-42' })
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: 'bespoke-contact-dashboard',
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('price-ticker', 'quote-changed', { symbol: 'EFCT', cents: 12345 })
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: 'bespoke-contact-form',
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: 'bespoke-contact-dashboard',
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('bespoke-contact-form'),
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 will consume both.
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
- onTrace({ _tag: 'watch', event: name, payload })
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
- onTrace({
452
+ publish({
443
453
  _tag: 'wire',
444
454
  event: name,
445
455
  wireId: outcome.wireId,