sygnal 5.3.7 → 6.0.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 (438) hide show
  1. package/CHANGELOG.md +646 -0
  2. package/README.md +77 -47
  3. package/dist/astro/client.cjs.js +33 -8114
  4. package/dist/astro/client.cjs.js.map +1 -0
  5. package/dist/astro/client.mjs +33 -8114
  6. package/dist/astro/client.mjs.map +1 -0
  7. package/dist/astro/index.cjs.js +1039 -9
  8. package/dist/astro/index.cjs.js.map +1 -0
  9. package/dist/astro/index.mjs +1038 -9
  10. package/dist/astro/index.mjs.map +1 -0
  11. package/dist/astro/server.cjs.js +3400 -166
  12. package/dist/astro/server.cjs.js.map +1 -0
  13. package/dist/astro/server.mjs +3400 -166
  14. package/dist/astro/server.mjs.map +1 -0
  15. package/dist/devtools.cjs.js +1431 -0
  16. package/dist/devtools.cjs.js.map +1 -0
  17. package/dist/devtools.esm.js +1419 -0
  18. package/dist/devtools.esm.js.map +1 -0
  19. package/dist/diagnostics.cjs.js +4033 -0
  20. package/dist/diagnostics.cjs.js.map +1 -0
  21. package/dist/diagnostics.esm.js +4003 -0
  22. package/dist/diagnostics.esm.js.map +1 -0
  23. package/dist/element.cjs.js +230 -0
  24. package/dist/element.cjs.js.map +1 -0
  25. package/dist/element.esm.js +228 -0
  26. package/dist/element.esm.js.map +1 -0
  27. package/dist/guide/accessibility.md +257 -0
  28. package/dist/guide/adapters.md +221 -0
  29. package/dist/guide/behaviors.md +312 -0
  30. package/dist/guide/browser-sources.md +203 -0
  31. package/dist/guide/drag-and-drop.md +342 -0
  32. package/dist/guide/element-commands.md +306 -0
  33. package/dist/guide/error-boundaries.md +169 -0
  34. package/dist/guide/forms-reference.md +381 -0
  35. package/dist/guide/forms.md +250 -0
  36. package/dist/guide/http.md +299 -0
  37. package/dist/guide/inputs.md +173 -0
  38. package/dist/guide/persistence.md +245 -0
  39. package/dist/guide/recipes/carousel.md +155 -0
  40. package/dist/guide/recipes/charts.md +177 -0
  41. package/dist/guide/recipes/code-editor.md +135 -0
  42. package/dist/guide/recipes/data-grid.md +155 -0
  43. package/dist/guide/recipes/data-table.md +196 -0
  44. package/dist/guide/recipes/i18n.md +222 -0
  45. package/dist/guide/recipes/icons.md +115 -0
  46. package/dist/guide/recipes/overview.md +33 -0
  47. package/dist/guide/recipes/rich-text.md +154 -0
  48. package/dist/guide/resources.md +471 -0
  49. package/dist/guide/ssr.md +255 -0
  50. package/dist/guide/timers.md +178 -0
  51. package/dist/guide/ui/accordion.md +93 -0
  52. package/dist/guide/ui/combobox.md +144 -0
  53. package/dist/guide/ui/dialog.md +124 -0
  54. package/dist/guide/ui/disclosure.md +60 -0
  55. package/dist/guide/ui/menu.md +125 -0
  56. package/dist/guide/ui/overview.md +166 -0
  57. package/dist/guide/ui/popover.md +101 -0
  58. package/dist/guide/ui/select.md +114 -0
  59. package/dist/guide/ui/tabs.md +161 -0
  60. package/dist/guide/ui/toaster.md +152 -0
  61. package/dist/guide/ui/tooltip.md +103 -0
  62. package/dist/guide/undo.md +178 -0
  63. package/dist/guide/virtual-collections.md +183 -0
  64. package/dist/guide/web-components.md +179 -0
  65. package/dist/guide/widgets.md +217 -0
  66. package/dist/index.cjs.js +15283 -6279
  67. package/dist/index.cjs.js.map +1 -0
  68. package/dist/index.d.ts +3739 -370
  69. package/dist/index.esm.js +15230 -6274
  70. package/dist/index.esm.js.map +1 -0
  71. package/dist/jsx-dev-runtime.cjs.js +27 -329
  72. package/dist/jsx-dev-runtime.cjs.js.map +1 -0
  73. package/dist/jsx-dev-runtime.esm.js +20 -322
  74. package/dist/jsx-dev-runtime.esm.js.map +1 -0
  75. package/dist/jsx-runtime.cjs.js +27 -329
  76. package/dist/jsx-runtime.cjs.js.map +1 -0
  77. package/dist/jsx-runtime.esm.js +20 -322
  78. package/dist/jsx-runtime.esm.js.map +1 -0
  79. package/dist/jsx.cjs.js +11 -309
  80. package/dist/jsx.cjs.js.map +1 -0
  81. package/dist/jsx.esm.js +9 -310
  82. package/dist/jsx.esm.js.map +1 -0
  83. package/dist/react.cjs.js +117 -0
  84. package/dist/react.cjs.js.map +1 -0
  85. package/dist/react.esm.js +115 -0
  86. package/dist/react.esm.js.map +1 -0
  87. package/dist/shims/globalthis.cjs +20 -0
  88. package/dist/sygnal.min.js +2 -1
  89. package/dist/sygnal.min.js.map +1 -0
  90. package/dist/ui-combobox.cjs.js +169 -0
  91. package/dist/ui-combobox.cjs.js.map +1 -0
  92. package/dist/ui-combobox.esm.js +148 -0
  93. package/dist/ui-combobox.esm.js.map +1 -0
  94. package/dist/ui-menu.cjs.js +87 -0
  95. package/dist/ui-menu.cjs.js.map +1 -0
  96. package/dist/ui-menu.esm.js +66 -0
  97. package/dist/ui-menu.esm.js.map +1 -0
  98. package/dist/ui-select.cjs.js +104 -0
  99. package/dist/ui-select.cjs.js.map +1 -0
  100. package/dist/ui-select.esm.js +83 -0
  101. package/dist/ui-select.esm.js.map +1 -0
  102. package/dist/ui.cjs.js +738 -0
  103. package/dist/ui.cjs.js.map +1 -0
  104. package/dist/ui.esm.js +727 -0
  105. package/dist/ui.esm.js.map +1 -0
  106. package/dist/vike/ClientOnly.cjs.js +5 -14
  107. package/dist/vike/ClientOnly.cjs.js.map +1 -0
  108. package/dist/vike/ClientOnly.mjs +5 -14
  109. package/dist/vike/ClientOnly.mjs.map +1 -0
  110. package/dist/vike/{+config.js → config/+config.js} +10 -1
  111. package/dist/vike/config/+config.js.map +1 -0
  112. package/dist/vike/config/package.json +6 -0
  113. package/dist/vike/onRenderClient.cjs.js +166 -95
  114. package/dist/vike/onRenderClient.cjs.js.map +1 -0
  115. package/dist/vike/onRenderClient.mjs +166 -95
  116. package/dist/vike/onRenderClient.mjs.map +1 -0
  117. package/dist/vike/onRenderHtml.cjs.js +60 -24
  118. package/dist/vike/onRenderHtml.cjs.js.map +1 -0
  119. package/dist/vike/onRenderHtml.mjs +61 -25
  120. package/dist/vike/onRenderHtml.mjs.map +1 -0
  121. package/dist/vite/plugin.cjs.js +926 -65
  122. package/dist/vite/plugin.cjs.js.map +1 -0
  123. package/dist/vite/plugin.mjs +925 -65
  124. package/dist/vite/plugin.mjs.map +1 -0
  125. package/dist/zag.cjs.js +408 -0
  126. package/dist/zag.cjs.js.map +1 -0
  127. package/dist/zag.esm.js +405 -0
  128. package/dist/zag.esm.js.map +1 -0
  129. package/llms.txt +313 -0
  130. package/package.json +109 -16
  131. package/src/astro/client.ts +40 -18
  132. package/src/astro/index.d.ts +48 -1
  133. package/src/astro/index.ts +106 -9
  134. package/src/astro/server.ts +11 -3
  135. package/src/collection.ts +6 -90
  136. package/src/core/actions.ts +134 -0
  137. package/src/core/cell.ts +202 -0
  138. package/src/core/debug.ts +23 -0
  139. package/src/core/define.ts +242 -0
  140. package/src/core/hooks.ts +314 -0
  141. package/src/core/hosts/collection.ts +325 -0
  142. package/src/core/hosts/switchable.ts +146 -0
  143. package/src/core/instance.ts +592 -0
  144. package/src/core/markers/clientonly.ts +13 -0
  145. package/src/core/markers/lazy.ts +40 -0
  146. package/src/core/markers/portal.ts +96 -0
  147. package/src/core/markers/suspense.ts +41 -0
  148. package/src/core/markers/transition.ts +70 -0
  149. package/src/core/registry.ts +25 -0
  150. package/src/core/runtime.ts +573 -0
  151. package/src/core/statics.ts +104 -0
  152. package/src/core/teardown.ts +60 -0
  153. package/src/core/view.ts +37 -0
  154. package/src/cycle/dom/DocumentDOMSource.ts +13 -8
  155. package/src/cycle/dom/ElementFinder.ts +7 -9
  156. package/src/cycle/dom/EventDelegator.ts +174 -223
  157. package/src/cycle/dom/IsolateModule.ts +65 -35
  158. package/src/cycle/dom/MainDOMSource.ts +13 -2
  159. package/src/cycle/dom/PriorityQueue.ts +4 -2
  160. package/src/cycle/dom/SymbolTree.ts +18 -47
  161. package/src/cycle/dom/classNameModule.ts +76 -0
  162. package/src/cycle/dom/controlledInputModule.ts +50 -0
  163. package/src/cycle/dom/enrichEventStream.ts +29 -45
  164. package/src/cycle/dom/fragment.ts +7 -0
  165. package/src/cycle/dom/isolate.ts +30 -27
  166. package/src/cycle/dom/makeDOMDriver.ts +115 -57
  167. package/src/cycle/dom/mockDOMSource.ts +83 -9
  168. package/src/cycle/dom/modules.ts +21 -4
  169. package/src/cycle/dom/propsModule.ts +65 -0
  170. package/src/cycle/dom/selectModule.ts +22 -17
  171. package/src/cycle/dom/snabbdom.ts +1 -6
  172. package/src/cycle/dom/thunk.ts +3 -0
  173. package/src/cycle/dom/utils.ts +98 -0
  174. package/src/cycle/dom/viewTransition.ts +43 -0
  175. package/src/cycle/state/StateSource.ts +20 -4
  176. package/src/cycle/state/objIsEqual.ts +50 -0
  177. package/src/cycle/state/types.ts +0 -10
  178. package/src/defineComponent.ts +34 -0
  179. package/src/devtools.d.ts +151 -0
  180. package/src/devtools.ts +34 -0
  181. package/src/element.d.ts +59 -0
  182. package/src/element.ts +235 -0
  183. package/src/extra/backoff.ts +9 -0
  184. package/src/extra/behaviors.ts +169 -0
  185. package/src/extra/browserSignals.ts +23 -0
  186. package/src/extra/browserSources.ts +326 -0
  187. package/src/extra/command.ts +3 -3
  188. package/src/extra/controls.ts +47 -0
  189. package/src/extra/copyAsTest.ts +286 -0
  190. package/src/extra/devtools.ts +109 -31
  191. package/src/extra/devtoolsActions.ts +379 -0
  192. package/src/extra/devtoolsHook.ts +9 -0
  193. package/src/extra/devtoolsNext.ts +83 -0
  194. package/src/extra/diagnostics/checks/actionLog.ts +108 -0
  195. package/src/extra/diagnostics/checks/behaviors.ts +49 -0
  196. package/src/extra/diagnostics/checks/browserSources.ts +96 -0
  197. package/src/extra/diagnostics/checks/collections.ts +67 -0
  198. package/src/extra/diagnostics/checks/controls.ts +148 -0
  199. package/src/extra/diagnostics/checks/dataset.ts +57 -0
  200. package/src/extra/diagnostics/checks/dom.ts +250 -0
  201. package/src/extra/diagnostics/checks/elementCommands.ts +175 -0
  202. package/src/extra/diagnostics/checks/events.ts +83 -0
  203. package/src/extra/diagnostics/checks/fetch.ts +135 -0
  204. package/src/extra/diagnostics/checks/forms.ts +163 -0
  205. package/src/extra/diagnostics/checks/index.ts +202 -0
  206. package/src/extra/diagnostics/checks/inspect.ts +427 -0
  207. package/src/extra/diagnostics/checks/next.ts +417 -0
  208. package/src/extra/diagnostics/checks/persist.ts +54 -0
  209. package/src/extra/diagnostics/checks/props.ts +56 -0
  210. package/src/extra/diagnostics/checks/public.d.ts +302 -0
  211. package/src/extra/diagnostics/checks/replies.ts +128 -0
  212. package/src/extra/diagnostics/checks/router.ts +100 -0
  213. package/src/extra/diagnostics/checks/rxjsHints.ts +88 -0
  214. package/src/extra/diagnostics/checks/shared.ts +203 -0
  215. package/src/extra/diagnostics/checks/shorthand.ts +115 -0
  216. package/src/extra/diagnostics/checks/sortable.ts +129 -0
  217. package/src/extra/diagnostics/checks/state.ts +148 -0
  218. package/src/extra/diagnostics/checks/statics.ts +48 -0
  219. package/src/extra/diagnostics/checks/strict.ts +55 -0
  220. package/src/extra/diagnostics/checks/timers.ts +80 -0
  221. package/src/extra/diagnostics/checks/viewTransitions.ts +47 -0
  222. package/src/extra/diagnostics/checks/virtual.ts +73 -0
  223. package/src/extra/diagnostics/checks/widgets.ts +109 -0
  224. package/src/extra/diagnostics/checks/wiring.ts +121 -0
  225. package/src/extra/diagnostics/codes.ts +477 -0
  226. package/src/extra/diagnostics/index.ts +353 -0
  227. package/src/extra/diagnostics/legacy.ts +76 -0
  228. package/src/extra/driverFactories.ts +172 -60
  229. package/src/extra/elementCommands.ts +53 -0
  230. package/src/extra/eventDriver.ts +4 -0
  231. package/src/extra/fetchDriver.ts +519 -0
  232. package/src/extra/flatten.ts +75 -0
  233. package/src/extra/focusWithin.ts +27 -0
  234. package/src/extra/form.ts +268 -0
  235. package/src/extra/formHelpers.ts +139 -0
  236. package/src/extra/head.ts +106 -0
  237. package/src/extra/hmr.ts +2 -3
  238. package/src/extra/owned.ts +24 -0
  239. package/src/extra/pager.ts +50 -0
  240. package/src/extra/persist.ts +133 -0
  241. package/src/extra/pwa.ts +1 -1
  242. package/src/extra/queryCache.ts +107 -0
  243. package/src/extra/reducers.ts +13 -6
  244. package/src/extra/reduxDevtools.ts +92 -0
  245. package/src/extra/replies.ts +54 -0
  246. package/src/extra/router.ts +323 -0
  247. package/src/extra/run.ts +94 -210
  248. package/src/extra/selection.ts +76 -0
  249. package/src/extra/socketDriver.ts +265 -0
  250. package/src/extra/sortable.ts +377 -0
  251. package/src/extra/ssr.ts +427 -160
  252. package/src/extra/standardSchema.ts +27 -0
  253. package/src/extra/testing.ts +3158 -190
  254. package/src/extra/timers.ts +95 -0
  255. package/src/extra/undo.ts +261 -0
  256. package/src/extra/viewTransitions.ts +38 -0
  257. package/src/extra/virtual.ts +513 -0
  258. package/src/extra/widget.ts +201 -0
  259. package/src/extra/xstreamExtras.ts +269 -0
  260. package/src/index.d.ts +3012 -87
  261. package/src/index.ts +32 -10
  262. package/src/jsx-runtime.ts +15 -1
  263. package/src/jsx.ts +2 -1
  264. package/src/lazy.ts +50 -7
  265. package/src/portal.ts +3 -1
  266. package/src/pragma/index.ts +262 -134
  267. package/src/react-peers.d.ts +5 -0
  268. package/src/react.d.ts +43 -0
  269. package/src/react.ts +110 -0
  270. package/src/shared.ts +48 -0
  271. package/src/slot.ts +1 -1
  272. package/src/suspense.ts +3 -1
  273. package/src/switchable.ts +6 -119
  274. package/src/transition.ts +3 -1
  275. package/src/ui/accordion.ts +64 -0
  276. package/src/ui/dialog.ts +129 -0
  277. package/src/ui/disclosure.ts +35 -0
  278. package/src/ui/popover.ts +45 -0
  279. package/src/ui/shared.ts +94 -0
  280. package/src/ui/tabs.ts +82 -0
  281. package/src/ui/toaster.ts +198 -0
  282. package/src/ui/tooltip.ts +70 -0
  283. package/src/ui/zag/combobox.ts +115 -0
  284. package/src/ui/zag/menu.ts +40 -0
  285. package/src/ui/zag/select.ts +54 -0
  286. package/src/ui/zag/shared.ts +43 -0
  287. package/src/ui-combobox.d.ts +20 -0
  288. package/src/ui-combobox.ts +6 -0
  289. package/src/ui-menu.d.ts +30 -0
  290. package/src/ui-menu.ts +6 -0
  291. package/src/ui-select.d.ts +17 -0
  292. package/src/ui-select.ts +6 -0
  293. package/src/ui-zag-types.d.ts +42 -0
  294. package/src/ui.d.ts +208 -0
  295. package/src/ui.ts +15 -0
  296. package/src/vike/+config.ts +9 -1
  297. package/src/vike/ClientOnly.ts +1 -1
  298. package/src/vike/onRenderClient.ts +144 -96
  299. package/src/vike/onRenderHtml.ts +69 -26
  300. package/src/vike/types.ts +27 -4
  301. package/src/vite/globalthis-shim.ts +18 -0
  302. package/src/vite/globalthis.ts +56 -0
  303. package/src/vite/plugin.d.ts +114 -2
  304. package/src/vite/plugin.ts +920 -56
  305. package/src/zag.d.ts +64 -0
  306. package/src/zag.ts +238 -0
  307. package/dist/astro/astro/client.d.ts +0 -5
  308. package/dist/astro/astro/index.d.ts +0 -16
  309. package/dist/astro/astro/server.d.ts +0 -12
  310. package/dist/astro/client.d.ts +0 -5
  311. package/dist/astro/client.esm.js +0 -4665
  312. package/dist/astro/collection.d.ts +0 -12
  313. package/dist/astro/component.d.ts +0 -22
  314. package/dist/astro/cycle/dom/BodyDOMSource.d.ts +0 -10
  315. package/dist/astro/cycle/dom/DOMSource.d.ts +0 -11
  316. package/dist/astro/cycle/dom/DocumentDOMSource.d.ts +0 -12
  317. package/dist/astro/cycle/dom/ElementFinder.d.ts +0 -8
  318. package/dist/astro/cycle/dom/EventDelegator.d.ts +0 -34
  319. package/dist/astro/cycle/dom/IsolateModule.d.ts +0 -23
  320. package/dist/astro/cycle/dom/MainDOMSource.d.ts +0 -32
  321. package/dist/astro/cycle/dom/PriorityQueue.d.ts +0 -7
  322. package/dist/astro/cycle/dom/ScopeChecker.d.ts +0 -9
  323. package/dist/astro/cycle/dom/SymbolTree.d.ts +0 -9
  324. package/dist/astro/cycle/dom/VNodeWrapper.d.ts +0 -8
  325. package/dist/astro/cycle/dom/enrichEventStream.d.ts +0 -24
  326. package/dist/astro/cycle/dom/fromEvent.d.ts +0 -6
  327. package/dist/astro/cycle/dom/index.d.ts +0 -8
  328. package/dist/astro/cycle/dom/isolate.d.ts +0 -9
  329. package/dist/astro/cycle/dom/makeDOMDriver.d.ts +0 -11
  330. package/dist/astro/cycle/dom/mockDOMSource.d.ts +0 -17
  331. package/dist/astro/cycle/dom/modules.d.ts +0 -5
  332. package/dist/astro/cycle/dom/snabbdom.d.ts +0 -22
  333. package/dist/astro/cycle/dom/styleModule.d.ts +0 -13
  334. package/dist/astro/cycle/dom/thunk.d.ts +0 -11
  335. package/dist/astro/cycle/dom/utils.d.ts +0 -8
  336. package/dist/astro/cycle/isolate/index.d.ts +0 -42
  337. package/dist/astro/cycle/run/adapt.d.ts +0 -6
  338. package/dist/astro/cycle/run/index.d.ts +0 -36
  339. package/dist/astro/cycle/run/internals.d.ts +0 -8
  340. package/dist/astro/cycle/run/types.d.ts +0 -49
  341. package/dist/astro/cycle/state/Collection.d.ts +0 -29
  342. package/dist/astro/cycle/state/StateSource.d.ts +0 -20
  343. package/dist/astro/cycle/state/index.d.ts +0 -5
  344. package/dist/astro/cycle/state/pickCombine.d.ts +0 -3
  345. package/dist/astro/cycle/state/pickMerge.d.ts +0 -3
  346. package/dist/astro/cycle/state/types.d.ts +0 -18
  347. package/dist/astro/cycle/state/withState.d.ts +0 -17
  348. package/dist/astro/extra/classes.d.ts +0 -7
  349. package/dist/astro/extra/devtools.d.ts +0 -78
  350. package/dist/astro/extra/dragDriver.d.ts +0 -20
  351. package/dist/astro/extra/driverFactories.d.ts +0 -12
  352. package/dist/astro/extra/eventDriver.d.ts +0 -9
  353. package/dist/astro/extra/exactState.d.ts +0 -1
  354. package/dist/astro/extra/hmr.d.ts +0 -17
  355. package/dist/astro/extra/logDriver.d.ts +0 -2
  356. package/dist/astro/extra/processDrag.d.ts +0 -19
  357. package/dist/astro/extra/processForm.d.ts +0 -15
  358. package/dist/astro/extra/run.d.ts +0 -13
  359. package/dist/astro/extra/xstreamCompat.d.ts +0 -5
  360. package/dist/astro/index.d.ts +0 -19
  361. package/dist/astro/index.esm.js +0 -27
  362. package/dist/astro/jsx-dev-runtime.d.ts +0 -1
  363. package/dist/astro/jsx-runtime.d.ts +0 -4
  364. package/dist/astro/jsx.d.ts +0 -2
  365. package/dist/astro/pragma/fn.d.ts +0 -7
  366. package/dist/astro/pragma/index.d.ts +0 -7
  367. package/dist/astro/pragma/is.d.ts +0 -10
  368. package/dist/astro/server.d.ts +0 -12
  369. package/dist/astro/server.esm.js +0 -25
  370. package/dist/astro/switchable.d.ts +0 -7
  371. package/dist/collection.d.ts +0 -12
  372. package/dist/component.d.ts +0 -22
  373. package/dist/cycle/dom/BodyDOMSource.d.ts +0 -10
  374. package/dist/cycle/dom/DOMSource.d.ts +0 -11
  375. package/dist/cycle/dom/DocumentDOMSource.d.ts +0 -12
  376. package/dist/cycle/dom/ElementFinder.d.ts +0 -8
  377. package/dist/cycle/dom/EventDelegator.d.ts +0 -34
  378. package/dist/cycle/dom/IsolateModule.d.ts +0 -23
  379. package/dist/cycle/dom/MainDOMSource.d.ts +0 -32
  380. package/dist/cycle/dom/PriorityQueue.d.ts +0 -7
  381. package/dist/cycle/dom/ScopeChecker.d.ts +0 -9
  382. package/dist/cycle/dom/SymbolTree.d.ts +0 -9
  383. package/dist/cycle/dom/VNodeWrapper.d.ts +0 -8
  384. package/dist/cycle/dom/enrichEventStream.d.ts +0 -24
  385. package/dist/cycle/dom/fromEvent.d.ts +0 -6
  386. package/dist/cycle/dom/index.d.ts +0 -8
  387. package/dist/cycle/dom/isolate.d.ts +0 -9
  388. package/dist/cycle/dom/makeDOMDriver.d.ts +0 -11
  389. package/dist/cycle/dom/mockDOMSource.d.ts +0 -17
  390. package/dist/cycle/dom/modules.d.ts +0 -5
  391. package/dist/cycle/dom/snabbdom.d.ts +0 -22
  392. package/dist/cycle/dom/styleModule.d.ts +0 -13
  393. package/dist/cycle/dom/thunk.d.ts +0 -11
  394. package/dist/cycle/dom/utils.d.ts +0 -8
  395. package/dist/cycle/isolate/index.d.ts +0 -42
  396. package/dist/cycle/run/adapt.d.ts +0 -6
  397. package/dist/cycle/run/index.d.ts +0 -36
  398. package/dist/cycle/run/internals.d.ts +0 -8
  399. package/dist/cycle/run/types.d.ts +0 -49
  400. package/dist/cycle/state/Collection.d.ts +0 -29
  401. package/dist/cycle/state/StateSource.d.ts +0 -20
  402. package/dist/cycle/state/index.d.ts +0 -5
  403. package/dist/cycle/state/pickCombine.d.ts +0 -3
  404. package/dist/cycle/state/pickMerge.d.ts +0 -3
  405. package/dist/cycle/state/types.d.ts +0 -18
  406. package/dist/cycle/state/withState.d.ts +0 -17
  407. package/dist/extra/classes.d.ts +0 -7
  408. package/dist/extra/devtools.d.ts +0 -78
  409. package/dist/extra/dragDriver.d.ts +0 -20
  410. package/dist/extra/driverFactories.d.ts +0 -12
  411. package/dist/extra/eventDriver.d.ts +0 -9
  412. package/dist/extra/exactState.d.ts +0 -1
  413. package/dist/extra/hmr.d.ts +0 -17
  414. package/dist/extra/logDriver.d.ts +0 -2
  415. package/dist/extra/processDrag.d.ts +0 -19
  416. package/dist/extra/processForm.d.ts +0 -15
  417. package/dist/extra/run.d.ts +0 -13
  418. package/dist/extra/xstreamCompat.d.ts +0 -5
  419. package/dist/jsx-dev-runtime.d.ts +0 -1
  420. package/dist/jsx-dev-runtime.js +0 -224
  421. package/dist/jsx-runtime.d.ts +0 -4
  422. package/dist/jsx-runtime.js +0 -224
  423. package/dist/jsx.d.ts +0 -2
  424. package/dist/pragma/fn.d.ts +0 -7
  425. package/dist/pragma/index.d.ts +0 -7
  426. package/dist/pragma/is.d.ts +0 -10
  427. package/dist/switchable.d.ts +0 -7
  428. package/dist/vike/+config.cjs.js +0 -65
  429. package/src/component.ts +0 -2256
  430. package/src/cycle/isolate/index.ts +0 -196
  431. package/src/cycle/run/index.ts +0 -151
  432. package/src/cycle/run/internals.ts +0 -143
  433. package/src/cycle/state/Collection.ts +0 -174
  434. package/src/cycle/state/index.ts +0 -5
  435. package/src/cycle/state/pickCombine.ts +0 -167
  436. package/src/cycle/state/pickMerge.ts +0 -122
  437. package/src/cycle/state/withState.ts +0 -47
  438. package/src/pragma/fn.ts +0 -55
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Strict mode: canonical-form checks (PLAN-1 workstream 2A,
3
+ * dev-plans/PLAN-1-canonical-forms.md). Runtime half; sygnal-check --strict
4
+ * implements every rule statically.
5
+ *
6
+ * Off by default. Turn it on with any of:
7
+ * - configureStrict(true) (this entry)
8
+ * - renderComponent(C, { strict: true }) (tests)
9
+ * - globalThis.__SYGNAL_STRICT__ = true (e.g. injected by a dev tool)
10
+ * and diagnostics must be on (strict reports go through the same core).
11
+ * The flag lives on the core bridge object, so it is shared by every copy of
12
+ * this entry and by renderComponent.
13
+ *
14
+ * | Code | Rule (canonical form) | Runtime mechanism |
15
+ * |--------|------------------------------------------|-----------------------------------------|
16
+ * | SYG508 | reply actions, not select()/errors() | replies.ts: a request with a category |
17
+ * | | round trip (PLAN-3 §1.1) | the same instance select()ed on a |
18
+ * | | | reply-capable source |
19
+ *
20
+ * SYG501 (positional views) and SYG504 ('ACTION | SINK' keys) are forms Sygnal 6.0 removed
21
+ * (D164): at run time they are SYG612 (checks/next.ts, strict or not); `sygnal-check --strict`
22
+ * still reports them under their own codes, with --fix. SYG502 is retired (PLAN-4 GS-4). SYG503,
23
+ * SYG505, SYG506, SYG507: static only (sygnal-check --strict).
24
+ *
25
+ * Every finding is reported once per component name (+ action / key).
26
+ * The SYG5xx severities are registered here (registerCodes) and passed
27
+ * explicitly, so the main bundle doesn't carry them (D29).
28
+ */
29
+ import type {DiagnosticCheck} from '../index'
30
+ import {CODE_TITLES, STRICT_CODE_SEVERITY, registerCodes} from '../codes'
31
+ import type {DiagnosticSeverity} from '../codes'
32
+ import {bridge} from './shared'
33
+
34
+ registerCodes(Object.keys(STRICT_CODE_SEVERITY).map(code =>
35
+ [code, STRICT_CODE_SEVERITY[code], CODE_TITLES[code]] as [string, DiagnosticSeverity, string]))
36
+
37
+ /**
38
+ * Turn runtime strict checks on (true), off (false), or back to the default
39
+ * (undefined → globalThis.__SYGNAL_STRICT__ === true).
40
+ */
41
+ export function configureStrict(on?: boolean): void {
42
+ const core = bridge()
43
+ if (core) core.strict = on
44
+ }
45
+
46
+ /** Whether runtime strict checks are on. */
47
+ export function isStrictEnabled(): boolean {
48
+ const flag = bridge()?.strict
49
+ return flag === undefined ? (globalThis as any).__SYGNAL_STRICT__ === true : flag === true
50
+ }
51
+
52
+ /** The strict check's runtime half is SYG508 (replies.ts); this entry keeps the flag. */
53
+ export const strictCheck: DiagnosticCheck = {
54
+ id: 'strict',
55
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Timers and declaration statics without a driver (PLAN-4 GS-7). Dev-entry-only codes
3
+ * (DEV_CODE_SEVERITY):
4
+ *
5
+ * SYG643 — a component declares a static that only a registered driver acts on (`timers`:
6
+ * makeTimerDriver(), `connections`: makeSocketDriver(), `resources`: makeFetchDriver(),
7
+ * `browser`: makeBrowserDriver())
8
+ * and no source of the app takes it (no `__sygnalStatic` marker for it), so nothing
9
+ * happens and nothing else says so. Also closes PLAN-3's "connections without a driver
10
+ * report nothing" gap. (`route` and `head` are left out: renderComponent asks for the
11
+ * router itself, and `head` is also collected by renderToString without a driver.)
12
+ * SYG422 — a timer spec makeTimerDriver() can't run (non-positive `every`, negative `after`,
13
+ * `every` with `after`, no action, `frame` that isn't an action name): it isn't started.
14
+ * The driver calls `__SYGNAL_DIAGNOSTICS__.timerSpec(name, spec, componentName)`, which
15
+ * installTimerHooks() sets.
16
+ */
17
+ import type {DiagnosticCheck} from '../index'
18
+ import {bridge, devReport, once, nameOf} from './shared'
19
+
20
+ const NEEDS: Record<string, string> = {
21
+ timers: 'makeTimerDriver()',
22
+ connections: 'makeSocketDriver()',
23
+ resources: 'makeFetchDriver()',
24
+ browser: 'makeBrowserDriver()',
25
+ }
26
+ const KEY: Record<string, string> = {timers: 'TIMER', connections: 'WS', resources: 'HTTP', browser: 'BROWSER'}
27
+
28
+ const brief = (v: any) => { try { return JSON.stringify(v) } catch (_) { return String(v) } }
29
+
30
+ /** why a timer spec can't run ('' when it can; mirrors timers.ts's valid()) */
31
+ export function timerSpecProblem(s: any): string {
32
+ if (!s || typeof s != 'object') return 'is not an object ({ every, action }, { after, action } or { frame: action })'
33
+ if ('frame' in s && s.frame) return typeof s.frame == 'string' ? '' : 'frame must be the action name (a string)'
34
+ if (!s.action || typeof s.action != 'string') return 'has no action (a string)'
35
+ if (s.every == null && s.after == null) return 'has neither every nor after'
36
+ if (s.every != null && s.after != null) return 'has both every and after'
37
+ if (s.every != null) return s.every > 0 && s.every < 1 / 0 ? '' : `every must be a positive number of ms (got ${brief(s.every)})`
38
+ return s.after >= 0 && s.after < 1 / 0 ? '' : `after must be a number of ms, 0 or more (got ${brief(s.after)})`
39
+ }
40
+
41
+ function checkSpec(name: string, spec: any, component?: string) {
42
+ const problem = timerSpecProblem(spec) || 'is invalid'
43
+ if (!once(`SYG422:${component}:${name}:${brief(spec)}`)) return
44
+ devReport('SYG422', {
45
+ component,
46
+ message: `Timer '${name}' ${problem}; it is not started`,
47
+ fix: `Declare ${name}: { every: 100, action: 'TICK' }, { after: 5000, action: 'EXPIRE' } or { frame: 'FRAME' } (falsy to stop it)`,
48
+ data: {name, spec},
49
+ })
50
+ }
51
+
52
+ /** install the hook makeTimerDriver() calls for an invalid spec (removed by the returned function) */
53
+ export function installTimerHooks(): () => void {
54
+ const core = bridge()
55
+ if (!core) return () => {}
56
+ core.timerSpec = checkSpec
57
+ return () => { if (core.timerSpec === checkSpec) core.timerSpec = undefined }
58
+ }
59
+
60
+ export const timersCheck: DiagnosticCheck = {
61
+ id: 'timers',
62
+
63
+ onModel(component) {
64
+ const sources = component?.sources, view = component?.view
65
+ if (!sources || typeof sources != 'object' || !view) return
66
+ const names = component.sourceNames || Object.keys(sources)
67
+ for (const k in NEEDS) {
68
+ if (view[k] == null) continue
69
+ if (names.some((n: string) => sources[n]?.__sygnalStatic === k)) continue
70
+ const name = nameOf(component)
71
+ if (!once(`SYG643:${name}:${k}`)) continue
72
+ devReport('SYG643', {
73
+ component,
74
+ message: `${name} declares ${name}.${k}, but no ${NEEDS[k]} driver is registered, so ${k == 'timers' ? 'its timers never run' : k == 'connections' ? 'its connections never open' : k == 'browser' ? 'its browser sources never start' : 'its resources are never fetched'}`,
75
+ fix: `Register the driver: run(App, { ${KEY[k]}: ${NEEDS[k]} })`,
76
+ data: {static: k, driver: NEEDS[k]},
77
+ })
78
+ }
79
+ },
80
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * View Transitions (PLAN-4 GS-12, D129). Dev-entry-only code (DEV_CODE_SEVERITY):
3
+ *
4
+ * SYG645 — a component declares `viewTransitions`, but its app's DOM driver can't run them (run()'s
5
+ * default makeDOMDriver, not makeViewTransitionDOMDriver()), so its actions patch at once
6
+ * and nothing else says so. The helper marks its IsolateModule (`vtDriver`). Not reported
7
+ * for renderComponent's mock DOM (no IsolateModule) or its `dom: 'real'` container
8
+ * (`.sygnal-test`): tests don't animate.
9
+ * Also (G-228): the static is not an array (`true`, `'MOVE'`): no action is listed (the core
10
+ * reads it with `includes?.()`, so a string matches substrings; anything else matches none).
11
+ */
12
+ import type {DiagnosticCheck} from '../index'
13
+ import {devReport, once, nameOf} from './shared'
14
+
15
+ export const viewTransitionsCheck: DiagnosticCheck = {
16
+ id: 'viewTransitions',
17
+
18
+ onModel(component) {
19
+ const list = component?.view?.viewTransitions
20
+ if (list == null) return
21
+ if (!Array.isArray(list)) {
22
+ const name = nameOf(component)
23
+ if (!once(`SYG645:${name}`)) return
24
+ const actions = Object.keys(component.model || {}).filter(a => !a.includes('|'))
25
+ devReport('SYG645', {
26
+ component,
27
+ message: `${name}.viewTransitions is not an array (it is ${typeof list == 'string' ? `'${list}'` : typeof list}), so no action is listed for a View Transition`,
28
+ fix: `List the action names in an array: ${name}.viewTransitions = [${(typeof list == 'string' ? [list] : actions.slice(0, 2)).map(a => `'${a}'`).join(', ') || "'ACTION'"}] (an array of action names)`,
29
+ data: {value: list},
30
+ })
31
+ return
32
+ }
33
+ if (!list.length) return
34
+ const im = component.sources?.[component.DOMSourceName || 'DOM']?._isolateModule
35
+ // the core's DOM source proxy answers any unknown key with an event shorthand (a function)
36
+ if (typeof im != 'object' || !im || im.vtDriver) return
37
+ if (typeof document != 'undefined' && document.querySelector?.('.sygnal-test')) return
38
+ const name = nameOf(component)
39
+ if (!once(`SYG645:${name}`)) return
40
+ devReport('SYG645', {
41
+ component,
42
+ message: `${name} declares ${name}.viewTransitions (${list.map((a: any) => `'${a}'`).join(', ')}), but the app's DOM driver can't run View Transitions, so those actions patch without one`,
43
+ fix: `Give run() the View Transition DOM driver: run(App, { DOM: makeViewTransitionDOMDriver('#root') })`,
44
+ data: {actions: list},
45
+ })
46
+ },
47
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * PLAN-5 V-1: `<VirtualCollection>` diagnostics (dev entry; src/extra/virtual.ts carries no text).
3
+ *
4
+ * The VirtualCollection host calls `__SYGNAL_DIAGNOSTICS__.virtual(code, owner, extra)`:
5
+ * 430 the container has no bounded height: `extra.reason` 'height' (laid out 0 px tall) or
6
+ * 'grows' (as tall as all its rows and taller than the viewport, so it would render every
7
+ * row); the window is clamped to the viewport (once per host and reason)
8
+ * 431 items without `id` (index keys; once per host)
9
+ * 432 an item renders a fragment or text, not one element (once per host)
10
+ * 433 scrollToIndex / scrollToId for an index or id not in the (filtered) list
11
+ * 434 estimateSize / overscan not a positive number (or a function, for estimateSize)
12
+ */
13
+ import {devReport, nameOf} from './shared'
14
+
15
+ const tag = (owner: any) => `<VirtualCollection> in ${nameOf(owner)}`
16
+
17
+ export function reportVirtual(code: number, owner: any, x: any = {}): any {
18
+ const component = owner ? nameOf(owner) : 'VirtualCollection'
19
+ if (code == 430) {
20
+ const grows = x.reason == 'grows'
21
+ return devReport('SYG430', {
22
+ component,
23
+ message: grows
24
+ ? `${tag(owner)} grows with its rows (it is ${Math.round(x.height)} px tall, as tall as all of them), so it is not a scroll container; only the rows within the viewport's height render`
25
+ : `${tag(owner)} is 0 px tall, so no row is in view`,
26
+ fix: 'Give its className a bounded height (height or max-height, e.g. .rows { height: 400px }, or flex: 1 with min-height: 0 in a flex column); it scrolls itself (overflow-y: auto)',
27
+ data: x,
28
+ })
29
+ }
30
+ if (code == 431) {
31
+ return devReport('SYG431', {
32
+ component,
33
+ message: `${tag(owner)} has items without an id (${x.count} items): they are keyed by their index, so a row's instance and measured height follow its position, not its item, when items are added, removed or reordered`,
34
+ fix: "Give every item a unique id (e.g. rows: data.map((r, i) => ({ id: r.key ?? i, ...r })))",
35
+ data: x,
36
+ })
37
+ }
38
+ if (code == 432) {
39
+ return devReport('SYG432', {
40
+ component,
41
+ message: `${tag(owner)}: its item component ${x.component} renders a fragment or text, so its rows can't be measured, positioned or given aria-posinset`,
42
+ fix: `Make ${x.component}'s view return one element (wrap its content in a <div> or <li>)`,
43
+ data: x,
44
+ })
45
+ }
46
+ if (code == 433) {
47
+ const what = 'id' in x ? `id ${JSON.stringify(x.id) ?? String(x.id)}` : `index ${x.index}`
48
+ return devReport('SYG433', {
49
+ component,
50
+ message: `${tag(owner)}: ${'id' in x ? 'scrollToId' : 'scrollToIndex'} for ${what}, which is not in its list (${x.count} rows after filter); it didn't scroll`,
51
+ fix: 'id' in x
52
+ ? 'Send the id of an item in the array the filter keeps: { scrollToId: \'.rows\', id }'
53
+ : `Send an integer index from 0 to ${Math.max(0, x.count - 1)} into the shown (filtered, sorted) rows: { scrollToIndex: '.rows', index }`,
54
+ data: x,
55
+ })
56
+ }
57
+ if (code == 434) {
58
+ return devReport('SYG434', {
59
+ component,
60
+ message: `${tag(owner)}: ${x.prop}={${typeof x.value == 'string' ? JSON.stringify(x.value) : String(x.value)}} is not ${x.prop == 'overscan' ? 'a number ≥ 0; 5 is used' : 'a positive number or a function; 32 is used'}`,
61
+ fix: x.prop == 'overscan' ? 'Pass overscan={5} (rows rendered beyond each edge)' : 'Pass estimateSize={32} (about a row\'s height in px), or (item, index) => px',
62
+ data: x,
63
+ })
64
+ }
65
+ }
66
+
67
+ /** Publish the VirtualCollection hook on the core bridge. Returns an uninstall function. */
68
+ export function installVirtualHooks(): () => void {
69
+ const c = (globalThis as any).__SYGNAL_DIAGNOSTICS__
70
+ if (!c) return () => {}
71
+ c.virtual = reportVirtual
72
+ return () => { if (c.virtual === reportVirtual) c.virtual = undefined }
73
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * PLAN-5 W-1: widget diagnostics (dev entry; `defineWidget` in src/extra/widget.ts carries no text).
3
+ *
4
+ * The widget module calls `__SYGNAL_DIAGNOSTICS__.widget(code, widgetTag, owner, extra)`:
5
+ * 140 dispatch(name) (mount's third parameter) — SYG140 (warn) when `name` is not in the widget's `events`: sygnal-check and
6
+ * the docs read `events`, so an undeclared name is a typo or a missing declaration
7
+ * 143 the widget tag used as a selector (DOM.select(DatePicker), `${DatePicker}`) — SYG143
8
+ * (warn, once per widget): it matches nothing
9
+ * 144 a host mounted — SYG144 (info, once per widget): a declared event name the host element
10
+ * also fires natively (`'change'` on an `<input>` host), so the intent sees both; not
11
+ * for the first-party Zag parts (`def.$own`: Menu's `select`, D211)
12
+ * 660/661/662 mount / update / unmount threw (`extra` is the error) — SYG660–662 (error);
13
+ * 661 with a fifth argument (G-580): the widget reported the error through mount's
14
+ * error(e) (its own timer or callback), worded as such (data.phase 'error')
15
+ * 669 fromZag (G-410): its render returned Sygnal components / widget tags / special JSX
16
+ * (`extra`: their tags, e.g. ['<Badge>', '<Transition>']) — SYG669 (warn, once per widget)
17
+ * It returns the reported diagnostic (the widget module logs a bare `[Sygnal SYG66x]` otherwise).
18
+ *
19
+ * SYG141 (listening to an event a widget doesn't declare) is static only (sygnal-check): the
20
+ * runtime doesn't see which listener a selector serves. SYG142 for an undeclared command sent to a
21
+ * widget's host is reported by the element command check (checks/elementCommands.ts).
22
+ */
23
+ import {devReport, once, unsee, nameOf} from './shared'
24
+ import {DEV_CODE_SEVERITY} from '../codes'
25
+
26
+ /** a widget's name for messages: `name` from its definition, else its host tag */
27
+ export const widgetName = (w: any): string => w?.def?.name ? `widget ${w.def.name}` : `widget <${w?.def?.tag || 'div'}>`
28
+
29
+ const ids = new WeakMap<object, number>()
30
+ let next = 0
31
+ const idOf = (w: any): number => {
32
+ let id = ids.get(w)
33
+ if (id === undefined) ids.set(w, id = ++next)
34
+ return id
35
+ }
36
+
37
+ const PHASE: Record<number, string> = {660: 'mount', 661: 'update', 662: 'unmount'}
38
+
39
+ export function reportWidget(code: number, w: any, owner?: any, x?: any, reported?: any): any {
40
+ const name = widgetName(w), component = owner ? nameOf(owner) : name
41
+ if (code == 140) {
42
+ if (w.events.includes(x) || !once(`SYG140:${idOf(w)}:${x}`)) return
43
+ return devReport('SYG140', {
44
+ component,
45
+ message: `${name} dispatched '${x}', which is not one of its declared events (${w.events.length ? w.events.join(', ') : 'it declares none'})`,
46
+ fix: `Add '${x}' to the widget's events (defineWidget({ events: [${[...w.events, x].map((e: string) => `'${e}'`).join(', ')}] })), or dispatch a declared name`,
47
+ data: {event: x, events: w.events},
48
+ })
49
+ }
50
+ if (code == 143) {
51
+ if (!once(`SYG143:${idOf(w)}`)) return
52
+ return devReport('SYG143', {
53
+ component: name,
54
+ message: `${name} was used as a selector (DOM.select(${w.def.name || 'Widget'}) or in a template string); a widget tag matches nothing`,
55
+ fix: `Give the widget a className and select that (<${w.def.name || 'Widget'} className="due" />, DOM.select('.due')), or make it a control: controls({ Due: ${w.def.name || 'Widget'} })`,
56
+ })
57
+ }
58
+ if (code == 144) {
59
+ // D211: not for Sygnal's own parts (Menu's `select` is its documented event)
60
+ if (!x || w.def.$own || !once(`SYG144:${idOf(w)}`)) return
61
+ const native = w.events.filter((e: string) => 'on' + e in x)
62
+ if (!native.length) return
63
+ return devReport('SYG144', {
64
+ component: name,
65
+ message: `${name} declares ${native.map((e: string) => `'${e}'`).join(', ')}, which its <${x.localName}> host also fires natively, so a listener gets both the widget's events and the element's`,
66
+ fix: `Name the widget's event differently (e.g. 'pick' for a date picker's change), or read only what both carry`,
67
+ data: {events: native, element: x.localName},
68
+ })
69
+ }
70
+ if (code == 669) {
71
+ // G-470: once per widget tag, counted only when reported (not with diagnostics off)
72
+ const k = `SYG669:${idOf(w)}`
73
+ if (!once(k)) return
74
+ const d = devReport('SYG669', {
75
+ component: name,
76
+ message: `${name}'s fromZag render returned ${x.join(', ')}; the adapter patches its render outside the component tree, so they don't run there (a component isn't instantiated, a widget doesn't mount, special JSX renders as an unknown element)`,
77
+ fix: `Render plain elements in the fromZag render (with Zag's prop getters spread on them), pass data in through the widget's props, and put components, widgets and special JSX around the widget tag in the view`,
78
+ data: {found: x},
79
+ })
80
+ if (!d) unsee(k)
81
+ return d
82
+ }
83
+ const phase = PHASE[code]
84
+ if (!phase) return
85
+ const sev = DEV_CODE_SEVERITY[`SYG${code}`]
86
+ // G-580: a 661 from error(e) is not a throwing update()
87
+ const by = code == 661 && reported
88
+ const d = devReport(`SYG${code}`, {
89
+ component,
90
+ message: (by ? `${name} reported an error through error(e) (mount's fourth parameter)` : `${name}'s ${phase}() threw`) + `: ${x?.message ?? x}` +
91
+ (code < 662 ? `; ${owner ? `${nameOf(owner)}'s onError fallback renders in its place` : 'it is not mounted'}` : ''),
92
+ fix: code < 662
93
+ ? `Fix ${by ? 'the failure the widget reports through error(e) (its own timer, callback or redraw)' : `the widget's ${phase}()`}, or give ${owner ? nameOf(owner) : 'the component'} an .onError for a custom fallback`
94
+ : `Fix the widget's unmount()`,
95
+ data: {phase: by ? 'error' : phase, error: x},
96
+ severity: sev,
97
+ })
98
+ // the error with its stack (the text is printed by report() in 'warn' mode, collected otherwise)
99
+ if (d) console.error(x)
100
+ return d
101
+ }
102
+
103
+ /** Publish the widget hook on the core bridge. Returns an uninstall function. */
104
+ export function installWidgetHooks(): () => void {
105
+ const c = (globalThis as any).__SYGNAL_DIAGNOSTICS__
106
+ if (!c) return () => {}
107
+ c.widget = reportWidget
108
+ return () => { if (c.widget === reportWidget) c.widget = undefined }
109
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * SYG101 — intent action has no model entry (warn)
3
+ * SYG102 — model entry has no intent trigger (info; it may still be reached
4
+ * with next(), which is only known at call time). An action a request
5
+ * names as a reply action, or `connections` names (`ok: 'LOADED'`, PLAN-3) counts as
6
+ * triggered: replyNamesOf() reads the names from the sink functions'
7
+ * source. A behavior's own actions (D199: in `_behaviorActions`) are not
8
+ * reported
9
+ * SYG609 — a model sink or an intent source has no driver (warn; see below)
10
+ *
11
+ * Mechanism: onIntent records the intent's action names per component;
12
+ * onModel (always called right after, once per instance) compares them with
13
+ * the normalized model map (shorthand already expanded by the core).
14
+ * Synthetic actions (`__*`, e.g. renderComponent's `__TEST_ACTION__`) and the
15
+ * built-ins BOOTSTRAP/INITIALIZE/DISPOSE/READY are never reported (HYDRATE is an
16
+ * ordinary action since 6.0).
17
+ * Under renderComponent, intent streams injected for model actions (so that
18
+ * simulateAction can dispatch them by their real names) are listed on the
19
+ * intent object's non-enumerable `__sygnalTestActions` property. They are not
20
+ * user intent actions (never reported as SYG101), and SYG102 is not reported
21
+ * for those model actions (the test dispatches them with simulateAction).
22
+ */
23
+ import type {DiagnosticCheck} from '../index'
24
+ import {report, once, isInternalAction, nameOf, didYouMean, replyNamesOf} from './shared'
25
+
26
+ const intentActions = new WeakMap<object, string[]>()
27
+
28
+ // SYG609 (G-110, PLAN-2 E2): sinks/sources that no driver provides. Sinks the core handles
29
+ // itself never need one. renderComponent (mock DOM source) records such sinks and fakes such
30
+ // sources (t.requests / t.respond), so its components are skipped.
31
+ // PLAN-4 GS-2: ELEMENT (element commands) is built in; GS-5: PERSIST is persist()'s (an EFFECT)
32
+ const NO_DRIVER_NEEDED = /^(STATE|EFFECT|PARENT|READY|DOM|CHILD|ELEMENT|PERSIST)$/
33
+ const DRIVER_NAME = /^[A-Z][A-Z0-9_]*$/
34
+ // (`in`, not a read: the DOM source's shorthand Proxy returns a function for any property)
35
+ const underTest = (c: any) => {
36
+ const dom = c?.sources?.[c.DOMSourceName || 'DOM']
37
+ return !!dom && typeof dom == 'object' && '_hub' in dom
38
+ }
39
+ const driverFix = (sink: string) =>
40
+ `Pass a driver named ${sink} to run(): run(App, { ${sink}: makeFetchDriver() }) for HTTP, or driverFromAsync(fn) / your own driver. ` +
41
+ `Check the spelling against the drivers you pass`
42
+
43
+ export const wiringCheck: DiagnosticCheck = {
44
+ id: 'wiring',
45
+
46
+ onIntent(component, actionNames) {
47
+ intentActions.set(component, actionNames || [])
48
+ },
49
+
50
+ // SYG609: an intent that reads a source no driver provides (`HTTP.select(...)` with no HTTP
51
+ // driver) would crash with "Cannot read properties of undefined": say why first
52
+ sources(component, sources) {
53
+ if (underTest(component) || typeof Proxy != 'function') return
54
+ const name = nameOf(component)
55
+ return new Proxy(sources, {
56
+ get(t: any, k: any) {
57
+ if (typeof k == 'string' && !(k in t) && DRIVER_NAME.test(k) && once(`SYG609:${name}:source:${k}`)) {
58
+ report('SYG609', {
59
+ component,
60
+ message: `${name}.intent reads the ${k} source, but no driver named ${k} was passed to run(), so it is undefined`,
61
+ fix: driverFix(k),
62
+ data: {name: k, kind: 'source', drivers: Object.keys(t).filter(n => DRIVER_NAME.test(n))},
63
+ })
64
+ }
65
+ return t[k]
66
+ },
67
+ })
68
+ },
69
+
70
+ onModel(component, modelMap) {
71
+ const name = nameOf(component)
72
+ // SYG609: a sink no driver receives is dropped silently by run()
73
+ if (!underTest(component)) {
74
+ const own = new Set<string>(component?.sourceNames || [])
75
+ for (const action of Object.keys(modelMap || {})) {
76
+ for (const sink of modelMap[action] || []) {
77
+ if (own.has(sink) || NO_DRIVER_NEEDED.test(sink) || sink === component?.stateSourceName) continue
78
+ if (!once(`SYG609:${name}:sink:${sink}`)) continue
79
+ report('SYG609', {
80
+ component,
81
+ message: `Model entry '${action}' sends to the ${sink} sink, but no driver named ${sink} was passed to run(), so every value sent there is dropped`,
82
+ fix: driverFix(sink),
83
+ data: {name: sink, kind: 'sink', action, drivers: [...own].filter(n => DRIVER_NAME.test(n))},
84
+ })
85
+ }
86
+ }
87
+ }
88
+ const intent$ = component && component.intent$
89
+ const injected = new Set<string>(
90
+ (intent$ && typeof intent$ === 'object' && intent$.__sygnalTestActions) || [])
91
+ const actions = (intentActions.get(component) || []).filter(a => !injected.has(a))
92
+ intentActions.delete(component)
93
+ const modelActions = Object.keys(modelMap || {})
94
+
95
+ for (const action of actions) {
96
+ if (isInternalAction(action) || modelActions.includes(action)) continue
97
+ if (!once(`SYG101:${name}:${action}`)) continue
98
+ report('SYG101', {
99
+ component,
100
+ message: `Intent action '${action}' has no model entry, so it never does anything${didYouMean(action, modelActions)}`,
101
+ fix: `Add '${action}' to ${name}.model, or remove it from ${name}.intent`,
102
+ data: {action, modelActions},
103
+ })
104
+ }
105
+
106
+ const replies = replyNamesOf(component)
107
+ // D199: a behavior's own actions ('tip.SHOW') are its business: a timer, next() or a reply
108
+ // may trigger them (the behavior-owned map, behaviors.ts)
109
+ const owned = component?._behaviorActions || {}
110
+ for (const action of modelActions) {
111
+ if (isInternalAction(action) || actions.includes(action) || injected.has(action) || replies.has(action) || action in owned) continue
112
+ if (!once(`SYG102:${name}:${action}`)) continue
113
+ report('SYG102', {
114
+ component,
115
+ message: `Model entry '${action}' has no intent action with that name${didYouMean(action, actions)}`,
116
+ fix: `Add '${action}' to ${name}.intent, name it in a request (ok: '${action}'), or remove the model entry. If it is only dispatched with next('${action}'), ignore this`,
117
+ data: {action, intentActions: actions},
118
+ })
119
+ }
120
+ },
121
+ }