sygnal 6.5.0 → 6.6.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 (56) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/astro/index.cjs.js +398 -25
  3. package/dist/astro/index.cjs.js.map +1 -1
  4. package/dist/astro/index.mjs +398 -25
  5. package/dist/astro/index.mjs.map +1 -1
  6. package/dist/astro/server.cjs.js.map +1 -1
  7. package/dist/astro/server.mjs.map +1 -1
  8. package/dist/devtools.cjs.js +141 -3
  9. package/dist/devtools.cjs.js.map +1 -1
  10. package/dist/devtools.esm.js +141 -4
  11. package/dist/devtools.esm.js.map +1 -1
  12. package/dist/diagnostics.cjs.js +82 -10
  13. package/dist/diagnostics.cjs.js.map +1 -1
  14. package/dist/diagnostics.esm.js +82 -10
  15. package/dist/diagnostics.esm.js.map +1 -1
  16. package/dist/index.cjs.js +9 -2
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.d.ts +122 -13
  19. package/dist/index.esm.js +9 -2
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/sygnal.min.js +1 -1
  22. package/dist/sygnal.min.js.map +1 -1
  23. package/dist/vike/config/package.json +1 -1
  24. package/dist/vike/onRenderClient.cjs.js +63 -43
  25. package/dist/vike/onRenderClient.cjs.js.map +1 -1
  26. package/dist/vike/onRenderClient.mjs +63 -43
  27. package/dist/vike/onRenderClient.mjs.map +1 -1
  28. package/dist/vike/onRenderHtml.cjs.js +21 -25
  29. package/dist/vike/onRenderHtml.cjs.js.map +1 -1
  30. package/dist/vike/onRenderHtml.mjs +21 -25
  31. package/dist/vike/onRenderHtml.mjs.map +1 -1
  32. package/dist/vite/plugin.cjs.js +398 -25
  33. package/dist/vite/plugin.cjs.js.map +1 -1
  34. package/dist/vite/plugin.mjs +398 -25
  35. package/dist/vite/plugin.mjs.map +1 -1
  36. package/package.json +1 -1
  37. package/src/core/hooks.ts +6 -0
  38. package/src/core/view.ts +2 -0
  39. package/src/cycle/dom/utils.ts +4 -2
  40. package/src/devtools.d.ts +13 -0
  41. package/src/devtools.ts +3 -0
  42. package/src/extra/devGraph.ts +111 -0
  43. package/src/extra/devMcp.ts +1 -1
  44. package/src/extra/devtools.ts +18 -0
  45. package/src/extra/diagnostics/checks/index.ts +1 -1
  46. package/src/extra/diagnostics/checks/inspect.ts +68 -6
  47. package/src/extra/diagnostics/checks/public.d.ts +121 -12
  48. package/src/extra/diagnostics/codes.ts +6 -0
  49. package/src/index.d.ts +2 -0
  50. package/src/vike/onRenderClient.ts +44 -46
  51. package/src/vike/onRenderHtml.ts +5 -26
  52. package/src/vike/shell.ts +33 -0
  53. package/src/vite/graph.ts +247 -0
  54. package/src/vite/mcp.ts +3 -3
  55. package/src/vite/plugin.d.ts +12 -0
  56. package/src/vite/plugin.ts +136 -22
@@ -873,6 +873,25 @@ class SygnalDevTools {
873
873
  case 'GET_STATE':
874
874
  this._sendComponentState(msg.payload.componentId);
875
875
  break;
876
+ case 'GET_GRAPH':
877
+ this._post('GRAPH', this._graph(msg.payload));
878
+ break;
879
+ }
880
+ }
881
+ /**
882
+ * PLAN-10 P-1: the runtime app graph for the panel's App graph view: inspect() with the recent
883
+ * actions, JSON-safe. inspect() is on this object only when 'sygnal/diagnostics' is loaded
884
+ * (sygnal/vite loads it in dev); without it the panel shows why.
885
+ */
886
+ _graph(opts) {
887
+ const inspect = this.inspect;
888
+ if (typeof inspect !== 'function')
889
+ return { graph: null, reason: 'no-diagnostics' };
890
+ try {
891
+ return { graph: JSON.parse(JSON.stringify(inspect({ actions: opts?.actions ?? 200 }))) };
892
+ }
893
+ catch (e) {
894
+ return { graph: null, reason: 'error', message: String(e?.message ?? e) };
876
895
  }
877
896
  }
878
897
  onComponentCreated(componentNumber, name, instance) {
@@ -1748,15 +1767,15 @@ function pageTools(o, notifyWaiting = () => { }) {
1748
1767
  };
1749
1768
  return tools;
1750
1769
  }
1751
- let installed = null;
1770
+ let installed$1 = null;
1752
1771
  /**
1753
1772
  * Connect this page to the dev server's MCP endpoint (sygnal/vite with `mcp: true` calls it from
1754
1773
  * 'virtual:sygnal/mcp'). Once per page; no-op without a hot channel.
1755
1774
  */
1756
1775
  function installMcpBridge(hot, options = {}) {
1757
- if (!hot || installed === hot)
1776
+ if (!hot || installed$1 === hot)
1758
1777
  return;
1759
- installed = hot;
1778
+ installed$1 = hot;
1760
1779
  if (!options.app)
1761
1780
  trackApps();
1762
1781
  const tools = pageTools(options, (id) => hot.send(MCP_RESPONSE, { id, waiting: true }));
@@ -1802,6 +1821,124 @@ function installMcpBridge(hot, options = {}) {
1802
1821
  }
1803
1822
  }
1804
1823
 
1824
+ /**
1825
+ * PLAN-10 P-2 (D544): the app side of the graph page's "Live data" (sygnal/vite serves the page at
1826
+ * `/__sygnal/graph` in dev, W-2 / D543). Dev only: it is part of the 'sygnal/devtools' entry, and
1827
+ * sygnal/vite's 'virtual:sygnal/graph' module (served by the dev server, never in a build) calls
1828
+ * installGraphBridge().
1829
+ *
1830
+ * The page is served by the dev server on the app's own origin, so the two talk over a
1831
+ * BroadcastChannel ('sygnal:graph'): no server round trip, no HMR traffic, nothing a page on
1832
+ * another origin can join. Every message carries `v: 1`.
1833
+ *
1834
+ * page → apps { type: 'who', watch? } every 2 s while the page is open; `watch` names
1835
+ * the tab the page follows (it keeps that tab
1836
+ * sending for 6 s)
1837
+ * app → page { type: 'here', tab, url, title, at, ok } the answer, and on load / focus
1838
+ * (`at`: when the tab was last loaded or focused;
1839
+ * `ok`: inspect() is there, i.e. diagnostics on)
1840
+ * app → page { type: 'graph', tab, graph } inspect({ actions: 200 }) of the page's apps, JSON
1841
+ * safe: when it starts being watched, then 150 ms
1842
+ * after the last action or component change
1843
+ * app → page { type: 'action', tab, record } { type, instance, component } at once (a flash)
1844
+ * page → app { type: 'get-state', tab, req, id } an instance's state
1845
+ * app → page { type: 'state', tab, req, id, value?, error? }
1846
+ * app → page { type: 'bye', tab } the tab is going away (pagehide)
1847
+ *
1848
+ * State values go through the DevTools preview (JSON safe, as the MCP tools send them). The static
1849
+ * keys the page joins on are on the component functions (sygnal/vite's dev transform) and come out
1850
+ * of inspect() as `key`.
1851
+ */
1852
+ const GRAPH_CHANNEL = 'sygnal:graph';
1853
+ const WATCH_MS = 6000;
1854
+ const SETTLE_MS = 150;
1855
+ let installed = false;
1856
+ /** Connect this page to the graph page's "Live data" (sygnal/vite calls it in dev). Once per page. */
1857
+ function installGraphBridge(options = {}) {
1858
+ const g = globalThis;
1859
+ if (installed || typeof g.BroadcastChannel != 'function' || !g.window)
1860
+ return;
1861
+ installed = true;
1862
+ trackApps();
1863
+ const bc = new g.BroadcastChannel(options.channel || GRAPH_CHANNEL);
1864
+ const tab = Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
1865
+ const tools = pageTools({});
1866
+ let at = Date.now();
1867
+ let watchedUntil = 0;
1868
+ let timer = 0;
1869
+ const inspect = () => {
1870
+ const f = g.__SYGNAL_DIAGNOSTICS__?.inspect || getDevTools()?.inspect;
1871
+ return typeof f == 'function' ? f : null;
1872
+ };
1873
+ const post = (m) => { try {
1874
+ bc.postMessage({ v: 1, tab, ...m });
1875
+ }
1876
+ catch (_) { /* closed */ } };
1877
+ const here = () => post({ type: 'here', url: String(g.location?.href || ''), title: String(g.document?.title || ''), at, ok: !!inspect() });
1878
+ const watched = () => Date.now() < watchedUntil;
1879
+ const sendGraph = () => {
1880
+ clearTimeout(timer);
1881
+ timer = 0;
1882
+ const f = inspect();
1883
+ if (!watched() || !f)
1884
+ return;
1885
+ let graph;
1886
+ try {
1887
+ graph = JSON.parse(JSON.stringify(f({ actions: 200 })));
1888
+ }
1889
+ catch (_) {
1890
+ return;
1891
+ }
1892
+ post({ type: 'graph', graph });
1893
+ };
1894
+ const settle = () => {
1895
+ if (!watched())
1896
+ return;
1897
+ clearTimeout(timer);
1898
+ timer = setTimeout(sendGraph, SETTLE_MS);
1899
+ };
1900
+ const watch = () => {
1901
+ const was = watched();
1902
+ watchedUntil = Date.now() + WATCH_MS;
1903
+ if (!was)
1904
+ sendGraph();
1905
+ };
1906
+ bc.onmessage = (e) => {
1907
+ const m = e && e.data;
1908
+ if (!m || m.v !== 1 || typeof m.type != 'string')
1909
+ return;
1910
+ if (m.type == 'who') {
1911
+ if (m.watch === tab)
1912
+ watch();
1913
+ here();
1914
+ }
1915
+ else if (m.type == 'get-state' && m.tab === tab) {
1916
+ let value, error;
1917
+ try {
1918
+ value = tools.get_state({ component: String(m.id) }, m.req).state;
1919
+ }
1920
+ catch (err) {
1921
+ error = String(err?.message || err);
1922
+ }
1923
+ post({ type: 'state', req: m.req, id: m.id, ...(error ? { error } : { value }) });
1924
+ }
1925
+ };
1926
+ onAction((a, kind) => {
1927
+ if (!watched())
1928
+ return;
1929
+ if (kind == 'add' && a)
1930
+ post({ type: 'action', record: { type: a.type, instance: String(a.instance), component: a.component } });
1931
+ settle();
1932
+ });
1933
+ addLayer(() => ({ onCreate: settle, onDispose: settle }));
1934
+ const seen = () => { at = Date.now(); here(); };
1935
+ g.addEventListener?.('focus', seen);
1936
+ g.document?.addEventListener?.('visibilitychange', () => { if (g.document.visibilityState == 'visible')
1937
+ seen(); });
1938
+ g.addEventListener?.('pagehide', () => post({ type: 'bye' }));
1939
+ here();
1940
+ }
1941
+
1805
1942
  // 'sygnal/devtools' (D77): the DevTools bridge for the browser extension, a dev-only
1806
1943
  // entry. Importing it installs window.__SYGNAL_DEVTOOLS__ (run() did this before 6.0),
1807
1944
  // so import it before run(): components created earlier are not in the tree.
@@ -1833,6 +1970,7 @@ exports.getActions = getActions;
1833
1970
  exports.getDevTools = getDevTools;
1834
1971
  exports.getSession = getSession;
1835
1972
  exports.installDevTools = installDevTools;
1973
+ exports.installGraphBridge = installGraphBridge;
1836
1974
  exports.installMcpBridge = installMcpBridge;
1837
1975
  exports.isRecording = isRecording;
1838
1976
  exports.onAction = onAction;