typebulb 0.14.9 → 0.15.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.
package/dist/render.js CHANGED
@@ -455,6 +455,11 @@ const something = require('module-name') // NOT SUPPORTED!
455
455
  // Read from window each time so updates are visible
456
456
  const getData = () => window.__TB_DATA__ || [];
457
457
 
458
+ // tb.onMessage subscribers, fed by the events-SSE 'message' channel (typebulb send). A message is
459
+ // JSON-or-string: parse as JSON, else hand back the raw string; '' (a bare \`send\`) \u21D2 undefined.
460
+ const messageHandlers = new Set();
461
+ const parseMsg = (s) => { if (s === '' || s == null) return undefined; try { return JSON.parse(s); } catch { return s; } };
462
+
458
463
  // Filesystem API - calls back to the local server.
459
464
  // The server returns raw bytes (no JSON envelope); read() decodes as UTF-8.
460
465
  const failIfNotOk = async (resp, action, path) => {
@@ -612,6 +617,14 @@ const something = require('module-name') // NOT SUPPORTED!
612
617
  // Filesystem - local CLI extension
613
618
  fs,
614
619
 
620
+ // Receive a value pushed from the terminal via \`typebulb send\` (data-in, the dual of the
621
+ // ungated tb.server.log). Returns an unsubscribe fn. Inert when embedded \u2014 no server, so no
622
+ // sender; the handler is registered but never fires (cf. tb.models returning []).
623
+ onMessage: (handler) => {
624
+ if (typeof handler === 'function') messageHandlers.add(handler);
625
+ return () => messageHandlers.delete(handler);
626
+ },
627
+
615
628
  // Environment ('embedded' when running as a bulb-in-a-bulb)
616
629
  mode: isEmbedded ? 'embedded' : 'local',
617
630
 
@@ -622,13 +635,22 @@ const something = require('module-name') // NOT SUPPORTED!
622
635
  set theme(v) { if (window.__tbTheme) window.__tbTheme.set(v); }
623
636
  });
624
637
 
625
- // Hot reload listener
626
- if (window.__TYPEBULB_WATCH__) {
638
+ // Events channel (dev server only): 'reload' drives hot reload (only emitted when watching),
639
+ // 'message' delivers \`typebulb send\` pushes to tb.onMessage. Connect for a CLI-served page (http
640
+ // origin, not an embed); a srcdoc embed or a file:// static export has no server, so onMessage just
641
+ // stays inert there. Opening it independent of watch is what lets send reach a --no-watch page.
642
+ if (!isEmbedded && location.protocol.indexOf('http') === 0) {
627
643
  const es = new EventSource('/__reload');
628
644
  es.addEventListener('reload', () => {
629
645
  console.log('[typebulb] Reloading...');
630
646
  window.location.reload();
631
647
  });
648
+ es.addEventListener('message', (e) => {
649
+ // Wire payload is JSON-encoded (SSE-line-safe); decode it, then interpret JSON-or-string.
650
+ let value;
651
+ try { value = parseMsg(JSON.parse(e.data)); } catch { value = undefined; }
652
+ messageHandlers.forEach((h) => { try { h(value); } catch (err) { console.error(err); } });
653
+ });
632
654
  es.onerror = () => {
633
655
  // Server closed, stop trying
634
656
  es.close();
@@ -674,30 +696,29 @@ const something = require('module-name') // NOT SUPPORTED!
674
696
  });
675
697
  } catch (e) {}
676
698
  })();
677
- <\/script>`}function Kf(t){let{name:e,code:s,css:n,html:o,data:i,insight:a,importMap:l,watch:u,theme:f,embedded:d}=t,h=o.trim()||'<div id="app"></div>',A=d?"":`
678
- html, body { height: 100%; }`,y=k=>k.replace(/<\/script/gi,"<\\/script"),I={imports:Hy(l.imports)};return`<!DOCTYPE html>
699
+ <\/script>`}function Kf(t){let{name:e,code:s,css:n,html:o,data:i,insight:a,importMap:l,theme:u,embedded:f}=t,d=o.trim()||'<div id="app"></div>',h=f?"":`
700
+ html, body { height: 100%; }`,A=I=>I.replace(/<\/script/gi,"<\\/script"),y={imports:Hy(l.imports)};return`<!DOCTYPE html>
679
701
  <html>
680
702
  <head>
681
703
  <meta charset="utf-8">
682
704
  <meta name="viewport" content="width=device-width, initial-scale=1">
683
705
  <title>${Mf(e)} - typebulb</title>
684
- ${jf(e,f)}
706
+ ${jf(e,u)}
685
707
  <script type="importmap">
686
- ${JSON.stringify(I,null,2)}
708
+ ${JSON.stringify(y,null,2)}
687
709
  <\/script>
688
710
  <style>
689
- ${qf}${A}
711
+ ${qf}${h}
690
712
  </style>
691
713
  <style>
692
714
  ${n}
693
715
  </style>
694
716
  </head>
695
717
  <body>
696
- ${h}
718
+ ${d}
697
719
 
698
- ${i.length>0?`<script>window.__TB_DATA__ = ${y(JSON.stringify(i))};<\/script>`:""}
699
- ${a?`<script>window.__TB_INSIGHT__ = ${y(JSON.stringify(a))};<\/script>`:""}
700
- ${u?"<script>window.__TYPEBULB_WATCH__ = true;<\/script>":""}
720
+ ${i.length>0?`<script>window.__TB_DATA__ = ${A(JSON.stringify(i))};<\/script>`:""}
721
+ ${a?`<script>window.__TB_INSIGHT__ = ${A(JSON.stringify(a))};<\/script>`:""}
701
722
 
702
723
  <script>
703
724
  ${Ff}
@@ -706,7 +727,7 @@ ${Ff}
706
727
  ${Gy}
707
728
 
708
729
  <script type="module">
709
- ${y(s)}
730
+ ${A(s)}
710
731
  globalThis.__tbEntryRan = true; /* load-failure backstop \u2014 see embedProtocol */
711
732
  <\/script>
712
733
  </body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebulb",
3
- "version": "0.14.9",
3
+ "version": "0.15.0",
4
4
  "description": "Typebulb CLI to run single-file markdown apps called bulbs, either as standalone web apps or embedded in agent responses.",
5
5
  "license": "MIT",
6
6
  "repository": {