@saolabs/client 1.0.0 → 1.0.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.
Files changed (378) hide show
  1. package/README.md +52 -195
  2. package/dist/index.d.ts +20 -5
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +14 -3
  5. package/dist/index.js.map +1 -1
  6. package/dist/plugins.d.ts +2 -2
  7. package/dist/plugins.js +2 -2
  8. package/dist/src/core/app/Application.d.ts +17 -15
  9. package/dist/src/core/app/Application.d.ts.map +1 -1
  10. package/dist/src/core/app/Application.js +41 -18
  11. package/dist/src/core/app/Application.js.map +1 -1
  12. package/dist/src/core/bootstrap/app.d.ts +1 -1
  13. package/dist/src/core/bootstrap/app.d.ts.map +1 -1
  14. package/dist/src/core/bootstrap/app.js +74 -4
  15. package/dist/src/core/bootstrap/app.js.map +1 -1
  16. package/dist/src/core/bootstrap/bundle.d.ts +41 -0
  17. package/dist/src/core/bootstrap/bundle.d.ts.map +1 -0
  18. package/dist/src/core/bootstrap/bundle.js +98 -0
  19. package/dist/src/core/bootstrap/bundle.js.map +1 -0
  20. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +1 -1
  21. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -1
  22. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +3 -3
  23. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -1
  24. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +1 -1
  25. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -1
  26. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +11 -8
  27. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -1
  28. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +3 -1
  29. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -1
  30. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +8 -3
  31. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -1
  32. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +2 -1
  33. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -1
  34. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +14 -4
  35. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -1
  36. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +4 -4
  37. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -1
  38. package/dist/src/core/bootstrap/providers/ServiceProvider.js +5 -5
  39. package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -1
  40. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +1 -1
  41. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -1
  42. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +3 -3
  43. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -1
  44. package/dist/src/core/bootstrap/providers/default-providers.d.ts +1 -1
  45. package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -1
  46. package/dist/src/core/bootstrap/providers/default-providers.js +44 -11
  47. package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -1
  48. package/dist/src/core/bootstrap/providers/index.d.ts +9 -9
  49. package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -1
  50. package/dist/src/core/bootstrap/providers/index.js +8 -8
  51. package/dist/src/core/bootstrap/providers/index.js.map +1 -1
  52. package/dist/src/core/bootstrap/providers/provider-order.d.ts +1 -1
  53. package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -1
  54. package/dist/src/core/bootstrap/ssr.d.ts +47 -0
  55. package/dist/src/core/bootstrap/ssr.d.ts.map +1 -0
  56. package/dist/src/core/bootstrap/ssr.js +125 -0
  57. package/dist/src/core/bootstrap/ssr.js.map +1 -0
  58. package/dist/src/core/cache/ViewCache.d.ts +1 -1
  59. package/dist/src/core/cache/ViewCache.d.ts.map +1 -1
  60. package/dist/src/core/cache/index.d.ts +1 -1
  61. package/dist/src/core/cache/index.d.ts.map +1 -1
  62. package/dist/src/core/cache/index.js +1 -1
  63. package/dist/src/core/cache/index.js.map +1 -1
  64. package/dist/src/core/contracts/ApplicationInterface.d.ts +13 -11
  65. package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -1
  66. package/dist/src/core/contracts/BlockInterface.d.ts +10 -10
  67. package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -1
  68. package/dist/src/core/contracts/BundleInterface.d.ts +38 -0
  69. package/dist/src/core/contracts/BundleInterface.d.ts.map +1 -0
  70. package/dist/src/core/contracts/BundleInterface.js +2 -0
  71. package/dist/src/core/contracts/BundleInterface.js.map +1 -0
  72. package/dist/src/core/contracts/ComponentInterface.d.ts +7 -6
  73. package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -1
  74. package/dist/src/core/contracts/ElementInterface.d.ts +91 -27
  75. package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -1
  76. package/dist/src/core/contracts/HeadServiceInterface.d.ts +37 -0
  77. package/dist/src/core/contracts/HeadServiceInterface.d.ts.map +1 -0
  78. package/dist/src/core/contracts/HeadServiceInterface.js +3 -0
  79. package/dist/src/core/contracts/HeadServiceInterface.js.map +1 -0
  80. package/dist/src/core/contracts/HelperInterface.d.ts +9 -1
  81. package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -1
  82. package/dist/src/core/contracts/HttpServiceInterface.d.ts +3 -0
  83. package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -1
  84. package/dist/src/core/contracts/MarkerInterface.d.ts +29 -44
  85. package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -1
  86. package/dist/src/core/contracts/ReactiveInterface.d.ts +9 -9
  87. package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -1
  88. package/dist/src/core/contracts/RouterInterface.d.ts +5 -2
  89. package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -1
  90. package/dist/src/core/contracts/SectionInterface.d.ts +48 -0
  91. package/dist/src/core/contracts/SectionInterface.d.ts.map +1 -0
  92. package/dist/src/core/contracts/SectionInterface.js +2 -0
  93. package/dist/src/core/contracts/SectionInterface.js.map +1 -0
  94. package/dist/src/core/contracts/ServiceProviderInterface.d.ts +3 -3
  95. package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -1
  96. package/dist/src/core/contracts/ViewControllerInterface.d.ts +116 -15
  97. package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -1
  98. package/dist/src/core/contracts/ViewInterface.d.ts +31 -5
  99. package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -1
  100. package/dist/src/core/contracts/ViewManagerInterface.d.ts +47 -5
  101. package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -1
  102. package/dist/src/core/contracts/ViewStateInterface.d.ts +39 -2
  103. package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -1
  104. package/dist/src/core/contracts/common.d.ts +3 -3
  105. package/dist/src/core/contracts/common.js +3 -3
  106. package/dist/src/core/contracts/utils.d.ts +19 -19
  107. package/dist/src/core/contracts/utils.d.ts.map +1 -1
  108. package/dist/src/core/contracts/views.d.ts +1 -22
  109. package/dist/src/core/contracts/views.d.ts.map +1 -1
  110. package/dist/src/core/devtools/hook.d.ts +66 -0
  111. package/dist/src/core/devtools/hook.d.ts.map +1 -0
  112. package/dist/src/core/devtools/hook.js +114 -0
  113. package/dist/src/core/devtools/hook.js.map +1 -0
  114. package/dist/src/core/devtools/index.d.ts +34 -0
  115. package/dist/src/core/devtools/index.d.ts.map +1 -0
  116. package/dist/src/core/devtools/index.js +33 -0
  117. package/dist/src/core/devtools/index.js.map +1 -0
  118. package/dist/src/core/devtools/inspector.d.ts +31 -0
  119. package/dist/src/core/devtools/inspector.d.ts.map +1 -0
  120. package/dist/src/core/devtools/inspector.js +249 -0
  121. package/dist/src/core/devtools/inspector.js.map +1 -0
  122. package/dist/src/core/elements/Block.d.ts +9 -7
  123. package/dist/src/core/elements/Block.d.ts.map +1 -1
  124. package/dist/src/core/elements/Block.js +33 -9
  125. package/dist/src/core/elements/Block.js.map +1 -1
  126. package/dist/src/core/elements/BlockOutlet.d.ts +19 -8
  127. package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -1
  128. package/dist/src/core/elements/BlockOutlet.js +57 -13
  129. package/dist/src/core/elements/BlockOutlet.js.map +1 -1
  130. package/dist/src/core/elements/Component.d.ts +83 -11
  131. package/dist/src/core/elements/Component.d.ts.map +1 -1
  132. package/dist/src/core/elements/Component.js +334 -13
  133. package/dist/src/core/elements/Component.js.map +1 -1
  134. package/dist/src/core/elements/ForeachSlotCache.d.ts +95 -0
  135. package/dist/src/core/elements/ForeachSlotCache.d.ts.map +1 -0
  136. package/dist/src/core/elements/ForeachSlotCache.js +149 -0
  137. package/dist/src/core/elements/ForeachSlotCache.js.map +1 -0
  138. package/dist/src/core/elements/Fragment.d.ts +19 -13
  139. package/dist/src/core/elements/Fragment.d.ts.map +1 -1
  140. package/dist/src/core/elements/Fragment.js +43 -20
  141. package/dist/src/core/elements/Fragment.js.map +1 -1
  142. package/dist/src/core/elements/Html.d.ts +89 -12
  143. package/dist/src/core/elements/Html.d.ts.map +1 -1
  144. package/dist/src/core/elements/Html.js +707 -106
  145. package/dist/src/core/elements/Html.js.map +1 -1
  146. package/dist/src/core/elements/Output.d.ts +34 -10
  147. package/dist/src/core/elements/Output.d.ts.map +1 -1
  148. package/dist/src/core/elements/Output.js +141 -26
  149. package/dist/src/core/elements/Output.js.map +1 -1
  150. package/dist/src/core/elements/Reactive.d.ts +85 -14
  151. package/dist/src/core/elements/Reactive.d.ts.map +1 -1
  152. package/dist/src/core/elements/Reactive.js +315 -41
  153. package/dist/src/core/elements/Reactive.js.map +1 -1
  154. package/dist/src/core/elements/TextElement.d.ts +11 -7
  155. package/dist/src/core/elements/TextElement.d.ts.map +1 -1
  156. package/dist/src/core/elements/TextElement.js +18 -11
  157. package/dist/src/core/elements/TextElement.js.map +1 -1
  158. package/dist/src/core/elements/Wrapper.d.ts +24 -13
  159. package/dist/src/core/elements/Wrapper.d.ts.map +1 -1
  160. package/dist/src/core/elements/Wrapper.js +65 -8
  161. package/dist/src/core/elements/Wrapper.js.map +1 -1
  162. package/dist/src/core/elements/Yield.d.ts +10 -9
  163. package/dist/src/core/elements/Yield.d.ts.map +1 -1
  164. package/dist/src/core/elements/Yield.js +31 -19
  165. package/dist/src/core/elements/Yield.js.map +1 -1
  166. package/dist/src/core/elements/helpers.d.ts +7 -7
  167. package/dist/src/core/elements/helpers.d.ts.map +1 -1
  168. package/dist/src/core/elements/helpers.js +4 -4
  169. package/dist/src/core/elements/index.d.ts +12 -11
  170. package/dist/src/core/elements/index.d.ts.map +1 -1
  171. package/dist/src/core/elements/index.js +12 -11
  172. package/dist/src/core/elements/index.js.map +1 -1
  173. package/dist/src/core/elements/reconcileChildren.d.ts +7 -0
  174. package/dist/src/core/elements/reconcileChildren.d.ts.map +1 -0
  175. package/dist/src/core/elements/reconcileChildren.js +74 -0
  176. package/dist/src/core/elements/reconcileChildren.js.map +1 -0
  177. package/dist/src/core/hellpers/utils.d.ts +2 -2
  178. package/dist/src/core/hellpers/utils.js +4 -4
  179. package/dist/src/core/helpers/ApiClient.d.ts +58 -0
  180. package/dist/src/core/helpers/ApiClient.d.ts.map +1 -0
  181. package/dist/src/core/helpers/ApiClient.js +131 -0
  182. package/dist/src/core/helpers/ApiClient.js.map +1 -0
  183. package/dist/src/core/helpers/app.d.ts +3 -0
  184. package/dist/src/core/helpers/app.d.ts.map +1 -0
  185. package/dist/src/core/helpers/app.js +63 -0
  186. package/dist/src/core/helpers/app.js.map +1 -0
  187. package/dist/src/core/helpers/transition.d.ts +34 -0
  188. package/dist/src/core/helpers/transition.d.ts.map +1 -0
  189. package/dist/src/core/helpers/transition.js +118 -0
  190. package/dist/src/core/helpers/transition.js.map +1 -0
  191. package/dist/src/core/helpers/utils.d.ts +26 -0
  192. package/dist/src/core/helpers/utils.d.ts.map +1 -0
  193. package/dist/src/core/helpers/utils.js +96 -0
  194. package/dist/src/core/helpers/utils.js.map +1 -0
  195. package/dist/src/core/helpers/view.d.ts +39 -0
  196. package/dist/src/core/helpers/view.d.ts.map +1 -0
  197. package/dist/src/core/helpers/view.js +286 -0
  198. package/dist/src/core/helpers/view.js.map +1 -0
  199. package/dist/src/core/routers/Router.d.ts +108 -7
  200. package/dist/src/core/routers/Router.d.ts.map +1 -1
  201. package/dist/src/core/routers/Router.js +444 -68
  202. package/dist/src/core/routers/Router.js.map +1 -1
  203. package/dist/src/core/routers/index.d.ts +2 -2
  204. package/dist/src/core/routers/index.d.ts.map +1 -1
  205. package/dist/src/core/routers/index.js +1 -1
  206. package/dist/src/core/routers/index.js.map +1 -1
  207. package/dist/src/core/services/AssetManager.d.ts +112 -0
  208. package/dist/src/core/services/AssetManager.d.ts.map +1 -0
  209. package/dist/src/core/services/AssetManager.js +361 -0
  210. package/dist/src/core/services/AssetManager.js.map +1 -0
  211. package/dist/src/core/services/BlockManager.d.ts +73 -2
  212. package/dist/src/core/services/BlockManager.d.ts.map +1 -1
  213. package/dist/src/core/services/BlockManager.js +270 -48
  214. package/dist/src/core/services/BlockManager.js.map +1 -1
  215. package/dist/src/core/services/DomService.js +3 -3
  216. package/dist/src/core/services/DomService.js.map +1 -1
  217. package/dist/src/core/services/HeadService.d.ts +24 -0
  218. package/dist/src/core/services/HeadService.d.ts.map +1 -0
  219. package/dist/src/core/services/HeadService.js +120 -0
  220. package/dist/src/core/services/HeadService.js.map +1 -0
  221. package/dist/src/core/services/HelperService.d.ts +14 -3
  222. package/dist/src/core/services/HelperService.d.ts.map +1 -1
  223. package/dist/src/core/services/HelperService.js +32 -2
  224. package/dist/src/core/services/HelperService.js.map +1 -1
  225. package/dist/src/core/services/HttpService.d.ts +8 -0
  226. package/dist/src/core/services/HttpService.d.ts.map +1 -1
  227. package/dist/src/core/services/HttpService.js +121 -47
  228. package/dist/src/core/services/HttpService.js.map +1 -1
  229. package/dist/src/core/services/MarkerRegistry.d.ts +51 -8
  230. package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -1
  231. package/dist/src/core/services/MarkerRegistry.js +135 -14
  232. package/dist/src/core/services/MarkerRegistry.js.map +1 -1
  233. package/dist/src/core/services/PageCache.d.ts +101 -0
  234. package/dist/src/core/services/PageCache.d.ts.map +1 -0
  235. package/dist/src/core/services/PageCache.js +184 -0
  236. package/dist/src/core/services/PageCache.js.map +1 -0
  237. package/dist/src/core/services/SectionManager.d.ts +100 -0
  238. package/dist/src/core/services/SectionManager.d.ts.map +1 -0
  239. package/dist/src/core/services/SectionManager.js +408 -0
  240. package/dist/src/core/services/SectionManager.js.map +1 -0
  241. package/dist/src/core/services/StorageService.js +1 -1
  242. package/dist/src/core/services/TranslationService.d.ts +21 -0
  243. package/dist/src/core/services/TranslationService.d.ts.map +1 -0
  244. package/dist/src/core/services/TranslationService.js +95 -0
  245. package/dist/src/core/services/TranslationService.js.map +1 -0
  246. package/dist/src/core/services/index.d.ts +11 -8
  247. package/dist/src/core/services/index.d.ts.map +1 -1
  248. package/dist/src/core/services/index.js +11 -8
  249. package/dist/src/core/services/index.js.map +1 -1
  250. package/dist/src/core/types/utils.d.ts +8 -8
  251. package/dist/src/core/types/utils.d.ts.map +1 -1
  252. package/dist/src/core/view/LoopContext.d.ts +21 -1
  253. package/dist/src/core/view/LoopContext.d.ts.map +1 -1
  254. package/dist/src/core/view/LoopContext.js +36 -0
  255. package/dist/src/core/view/LoopContext.js.map +1 -1
  256. package/dist/src/core/view/ResourceScope.d.ts +38 -0
  257. package/dist/src/core/view/ResourceScope.d.ts.map +1 -0
  258. package/dist/src/core/view/ResourceScope.js +167 -0
  259. package/dist/src/core/view/ResourceScope.js.map +1 -0
  260. package/dist/src/core/view/Section.d.ts +17 -32
  261. package/dist/src/core/view/Section.d.ts.map +1 -1
  262. package/dist/src/core/view/Section.js +14 -55
  263. package/dist/src/core/view/Section.js.map +1 -1
  264. package/dist/src/core/view/View.d.ts +43 -7
  265. package/dist/src/core/view/View.d.ts.map +1 -1
  266. package/dist/src/core/view/View.js +22 -4
  267. package/dist/src/core/view/View.js.map +1 -1
  268. package/dist/src/core/view/ViewController.d.ts +313 -40
  269. package/dist/src/core/view/ViewController.d.ts.map +1 -1
  270. package/dist/src/core/view/ViewController.js +1002 -147
  271. package/dist/src/core/view/ViewController.js.map +1 -1
  272. package/dist/src/core/view/ViewManager.d.ts +318 -27
  273. package/dist/src/core/view/ViewManager.d.ts.map +1 -1
  274. package/dist/src/core/view/ViewManager.js +1199 -258
  275. package/dist/src/core/view/ViewManager.js.map +1 -1
  276. package/dist/src/core/view/ViewState.d.ts +185 -6
  277. package/dist/src/core/view/ViewState.d.ts.map +1 -1
  278. package/dist/src/core/view/ViewState.js +851 -123
  279. package/dist/src/core/view/ViewState.js.map +1 -1
  280. package/dist/src/core/view/index.d.ts +5 -5
  281. package/dist/src/core/view/index.d.ts.map +1 -1
  282. package/dist/src/core/view/index.js +5 -5
  283. package/dist/src/core/view/index.js.map +1 -1
  284. package/dist/src/testing/index.d.ts +69 -0
  285. package/dist/src/testing/index.d.ts.map +1 -0
  286. package/dist/src/testing/index.js +140 -0
  287. package/dist/src/testing/index.js.map +1 -0
  288. package/index.ts +29 -5
  289. package/package.json +30 -21
  290. package/plugins.ts +2 -2
  291. package/src/core/app/Application.ts +58 -31
  292. package/src/core/bootstrap/app.ts +80 -6
  293. package/src/core/bootstrap/bundle.ts +101 -0
  294. package/src/core/bootstrap/providers/ApiServiceProvider.ts +4 -4
  295. package/src/core/bootstrap/providers/CoreServiceProvider.ts +14 -8
  296. package/src/core/bootstrap/providers/HelperServiceProvider.ts +8 -3
  297. package/src/core/bootstrap/providers/RouteServiceProvider.ts +15 -4
  298. package/src/core/bootstrap/providers/ServiceProvider.ts +8 -8
  299. package/src/core/bootstrap/providers/ViewServiceProvider.ts +3 -3
  300. package/src/core/bootstrap/providers/default-providers.ts +51 -16
  301. package/src/core/bootstrap/providers/index.ts +9 -9
  302. package/src/core/bootstrap/providers/provider-order.test.ts +16 -27
  303. package/src/core/bootstrap/providers/provider-order.ts +1 -1
  304. package/src/core/bootstrap/ssr.ts +136 -0
  305. package/src/core/cache/ViewCache.ts +1 -1
  306. package/src/core/cache/index.ts +1 -1
  307. package/src/core/contracts/ApplicationInterface.ts +13 -11
  308. package/src/core/contracts/BlockInterface.ts +18 -18
  309. package/src/core/contracts/BundleInterface.ts +40 -0
  310. package/src/core/contracts/ComponentInterface.ts +7 -6
  311. package/src/core/contracts/ElementInterface.ts +95 -27
  312. package/src/core/contracts/HeadServiceInterface.ts +41 -0
  313. package/src/core/contracts/HelperInterface.ts +9 -1
  314. package/src/core/contracts/HttpServiceInterface.ts +3 -0
  315. package/src/core/contracts/MarkerInterface.ts +22 -49
  316. package/src/core/contracts/ReactiveInterface.ts +9 -9
  317. package/src/core/contracts/RouterInterface.ts +5 -2
  318. package/src/core/contracts/SectionInterface.ts +49 -0
  319. package/src/core/contracts/ServiceProviderInterface.ts +3 -3
  320. package/src/core/contracts/ViewControllerInterface.ts +124 -16
  321. package/src/core/contracts/ViewInterface.ts +34 -5
  322. package/src/core/contracts/ViewManagerInterface.ts +40 -5
  323. package/src/core/contracts/ViewStateInterface.ts +39 -2
  324. package/src/core/contracts/common.ts +3 -3
  325. package/src/core/contracts/utils.ts +19 -19
  326. package/src/core/contracts/views.ts +2 -22
  327. package/src/core/devtools/hook.ts +142 -0
  328. package/src/core/devtools/index.ts +38 -0
  329. package/src/core/devtools/inspector.ts +270 -0
  330. package/src/core/elements/Block.ts +43 -21
  331. package/src/core/elements/BlockOutlet.ts +61 -21
  332. package/src/core/elements/Component.ts +352 -18
  333. package/src/core/elements/ElementManager.ts +9 -9
  334. package/src/core/elements/ForeachSlotCache.ts +170 -0
  335. package/src/core/elements/Fragment.ts +50 -32
  336. package/src/core/elements/Html.ts +696 -117
  337. package/src/core/elements/Output.ts +147 -30
  338. package/src/core/elements/Reactive.ts +329 -52
  339. package/src/core/elements/TextElement.ts +25 -16
  340. package/src/core/elements/Wrapper.ts +84 -18
  341. package/src/core/elements/Yield.ts +35 -24
  342. package/src/core/elements/helpers.ts +12 -12
  343. package/src/core/elements/index.ts +25 -24
  344. package/src/core/elements/reconcileChildren.ts +70 -0
  345. package/src/core/{hellpers → helpers}/ApiClient.ts +8 -1
  346. package/src/core/{hellpers → helpers}/app.ts +13 -2
  347. package/src/core/helpers/transition.ts +127 -0
  348. package/src/core/{hellpers → helpers}/utils.ts +4 -4
  349. package/src/core/helpers/view.ts +283 -0
  350. package/src/core/routers/Router.ts +458 -64
  351. package/src/core/routers/index.ts +2 -2
  352. package/src/core/services/AssetManager.ts +387 -0
  353. package/src/core/services/BlockManager.ts +272 -50
  354. package/src/core/services/DomService.ts +3 -3
  355. package/src/core/services/HeadService.ts +124 -0
  356. package/src/core/services/HelperService.ts +34 -4
  357. package/src/core/services/HttpService.ts +116 -55
  358. package/src/core/services/MarkerRegistry.ts +142 -16
  359. package/src/core/services/PageCache.ts +239 -0
  360. package/src/core/services/SectionManager.ts +387 -0
  361. package/src/core/services/StorageService.ts +1 -1
  362. package/src/core/services/TranslationService.ts +91 -0
  363. package/src/core/services/index.ts +11 -8
  364. package/src/core/types/utils.ts +8 -8
  365. package/src/core/view/LoopContext.ts +38 -1
  366. package/src/core/view/ResourceScope.ts +174 -0
  367. package/src/core/view/Section.ts +21 -68
  368. package/src/core/view/View.ts +57 -8
  369. package/src/core/view/ViewController.ts +1070 -186
  370. package/src/core/view/ViewManager.ts +1346 -272
  371. package/src/core/view/ViewState.ts +834 -116
  372. package/src/core/view/index.ts +5 -5
  373. package/src/testing/index.ts +184 -0
  374. package/dist/src/core/services/MarkerService.d.ts +0 -299
  375. package/dist/src/core/services/MarkerService.d.ts.map +0 -1
  376. package/dist/src/core/services/MarkerService.js +0 -723
  377. package/dist/src/core/services/MarkerService.js.map +0 -1
  378. package/src/core/services/MarkerService.ts +0 -923
@@ -1,923 +0,0 @@
1
- import { MarkerFilter, MarkerRecord, RegistryIDOrAttributes } from "../contracts/MarkerInterface";
2
- import { app } from "../hellpers/app";
3
- import { generateUUID } from "../hellpers/utils";
4
- import { MarkerRegistry, MarkerRegistryService } from "./MarkerRegistry";
5
-
6
-
7
- /**
8
- * OneMarker Model - Represents a custom marker element
9
- * Supports both:
10
- * - Generic markup: <tag>...</tag> or <!--tag-->...<!--/tag-->
11
- * - Registry tags: <!--o:r:id-->...<!--/o:r:id-->
12
- */
13
- export class MarkerModel {
14
- private __openTag: Comment;
15
- private __closeTag: Comment;
16
- private __attributes: Record<string, any>;
17
- private __nodes: Array<Node>;
18
- private __definedAttributes: string[];
19
- private __tagName: string;
20
- private __fullName: string;
21
- private __registryID?: string | undefined | null;
22
- // Registry tag specific properties (optional)
23
- private __systemPrefix?: string;
24
- private __tag?: string;
25
- private __id?: string;
26
- private __key?: string;
27
-
28
- constructor(
29
- data: MarkerRecord
30
- ) {
31
- this.__fullName = data.name;
32
- this.__tagName = data.name.split(':')[1] || data.name;
33
- this.__registryID = data.registryID;
34
- this.__openTag = data.openTag;
35
- this.__closeTag = data.closeTag;
36
- this.__attributes = data.attributes;
37
- this.__nodes = data.children || [];
38
- this.__definedAttributes = [];
39
- this.__defineAttributes(Object.keys(data.attributes));
40
- }
41
-
42
- /**
43
- * Update model data
44
- */
45
- __update(
46
- data: Record<string, any>
47
- ): this {
48
- this.__fullName = data.name;
49
- this.__tagName = data.name.split(':')[1] || data.name;
50
- this.__registryID = data.registryID;
51
- this.__openTag = data.openTag;
52
- this.__closeTag = data.closeTag;
53
- this.__attributes = data.attributes;
54
- this.__nodes = data.children || [];
55
- this.__defineAttributes(Object.keys(data.attributes));
56
- return this;
57
- }
58
-
59
- /**
60
- * Define dynamic property accessors for attributes
61
- * @private
62
- */
63
- private __defineAttributes(attributeKeys: string[]): this {
64
- attributeKeys.forEach(key => this.__defineAttribute(key));
65
- return this;
66
- }
67
-
68
- /**
69
- * Define single attribute accessor
70
- * @private
71
- */
72
- private __defineAttribute(name: string): this {
73
- if (this.__definedAttributes.includes(name)) {
74
- return this;
75
- }
76
-
77
- this.__definedAttributes.push(name);
78
- Object.defineProperty(this, name, {
79
- get: () => this.__attributes[name],
80
- set: (value: any) => {
81
- this.__attributes[name] = value;
82
- },
83
- enumerable: true,
84
- configurable: true,
85
- });
86
-
87
- return this;
88
- }
89
-
90
- /**
91
- * Get tag name (without namespace)
92
- */
93
- get tagName(): string {
94
- return this.__tagName;
95
- }
96
-
97
- /**
98
- * Get full name (with namespace)
99
- */
100
- get fullName(): string {
101
- return this.__fullName;
102
- }
103
-
104
- get registryID(): string | undefined | null {
105
- return this.__registryID;
106
- }
107
- /**
108
- * Get open tag node
109
- */
110
- get openTag(): Comment {
111
- return this.__openTag;
112
- }
113
-
114
- /**
115
- * Get close tag node
116
- */
117
- get closeTag(): Comment {
118
- return this.__closeTag;
119
- }
120
-
121
- /**
122
- * Get all attributes
123
- */
124
- get attributes(): Record<string, any> {
125
- return this.__attributes;
126
- }
127
-
128
- /**
129
- * Get nodes between open and close tags
130
- */
131
- get nodes(): Array<Node> {
132
- return this.__nodes;
133
- }
134
-
135
- /**
136
- * Get system prefix (registry tags only)
137
- */
138
- get systemPrefix(): string | undefined {
139
- return this.__systemPrefix;
140
- }
141
-
142
- /**
143
- * Get tag (registry tags only)
144
- */
145
- get tag(): string | undefined {
146
- return this.__tag;
147
- }
148
-
149
- /**
150
- * Get ID (registry tags only)
151
- */
152
- get id(): string | undefined {
153
- return this.__id;
154
- }
155
-
156
- /**
157
- * Get full key (registry tags only)
158
- */
159
- get key(): string | undefined {
160
- return this.__key;
161
- }
162
-
163
- /**
164
- * Get full data (registry tags only)
165
- */
166
- get data(): Record<string, any> | undefined {
167
- if (!this.__systemPrefix) return undefined;
168
- return {
169
- systemPrefix: this.__systemPrefix!,
170
- tag: this.__tag!,
171
- id: this.__id!,
172
- key: this.__key!,
173
- attributes: this.__attributes,
174
- nodes: this.__nodes
175
- };
176
- }
177
-
178
- /**
179
- * Get outer HTML including open/close tags and content
180
- */
181
- get outerHTML(): string {
182
- let html = '';
183
- html += this.__getNodeHTML(this.__openTag);
184
-
185
- let currentNode = this.__openTag.nextSibling;
186
- while (currentNode && currentNode !== this.__closeTag) {
187
- html += this.__getNodeHTML(currentNode);
188
- currentNode = currentNode.nextSibling;
189
- }
190
-
191
- html += this.__getNodeHTML(this.__closeTag);
192
- return html;
193
- }
194
-
195
- /**
196
- * Get inner HTML (content only, without open/close tags)
197
- */
198
- get innerHTML(): string {
199
- let html = '';
200
- let currentNode = this.__openTag.nextSibling;
201
-
202
- while (currentNode && currentNode !== this.__closeTag) {
203
- html += this.__getNodeHTML(currentNode);
204
- currentNode = currentNode.nextSibling;
205
- }
206
-
207
- return html;
208
- }
209
-
210
- /**
211
- * Get HTML representation of a node
212
- * @private
213
- */
214
- private __getNodeHTML(node: Node | null): string {
215
- if (!node) return '';
216
-
217
- switch (node.nodeType) {
218
- case Node.COMMENT_NODE:
219
- return `<!--${(node as Comment).nodeValue}-->`;
220
- case Node.TEXT_NODE:
221
- return node.textContent || '';
222
- case Node.ELEMENT_NODE:
223
- return (node as Element).outerHTML || '';
224
- default:
225
- return node.textContent || '';
226
- }
227
- }
228
-
229
- /**
230
- * Get attribute value
231
- */
232
- getAttribute(name: string): string | undefined {
233
- return this.__attributes[name];
234
- }
235
-
236
- /**
237
- * Set attribute value
238
- */
239
- setAttribute(name: string, value: string): this {
240
- this.__defineAttribute(name);
241
- this.__attributes[name] = value;
242
- return this;
243
- }
244
-
245
- /**
246
- * Check if model matches query attributes
247
- * @private
248
- */
249
- __match(attributes: Record<string, any>): boolean {
250
- for (const [key, value] of Object.entries(attributes)) {
251
- if (key === 'tagName') {
252
- if (this.__tagName !== value) return false;
253
- } else if (key === 'openTag') {
254
- if (this.__openTag !== value) return false;
255
- } else if (key === 'closeTag') {
256
- if (this.__closeTag !== value) return false;
257
- } else if (key === 'attributes' || key === 'nodes') {
258
- continue;
259
- } else if (this.__attributes[key] !== value) {
260
- return false;
261
- }
262
- }
263
- return true;
264
- }
265
-
266
- /**
267
- * Check if model matches given attributes (for registry tag filtering)
268
- */
269
- matchesAttributes(attributes: Record<string, any>): boolean {
270
- if (!attributes || Object.keys(attributes).length === 0) {
271
- return true;
272
- }
273
-
274
- for (const [key, value] of Object.entries(attributes)) {
275
- if (this.__attributes?.[key] !== value) {
276
- return false;
277
- }
278
- }
279
-
280
- return true;
281
- }
282
-
283
- /**
284
- * Set attributes from registry
285
- */
286
- setAttributes(attributes: Record<string, any>): this {
287
- Object.assign(this.__attributes, attributes);
288
- this.__defineAttributes(Object.keys(attributes));
289
- return this;
290
- }
291
-
292
- /**
293
- * Scan and update nodes between open/close tags
294
- */
295
- __scan(): Array<Node> {
296
- const nodes: Array<Node> = [];
297
- let currentNode = this.__openTag.nextSibling;
298
-
299
- while (currentNode && currentNode !== this.__closeTag) {
300
- nodes.push(currentNode);
301
- currentNode = currentNode.nextSibling;
302
- }
303
-
304
- this.__nodes = nodes;
305
- return this.__nodes;
306
- }
307
-
308
- /**
309
- * Sync with DOM (re-query and update)
310
- */
311
- __sync(): boolean {
312
- // Placeholder for sync logic
313
- // In V1, this uses oms.find() which requires OneMarkerService
314
- return false;
315
- }
316
-
317
- /**
318
- * Update nodes array
319
- */
320
- updateNodes(nodes: Array<Node>): this {
321
- this.__nodes = nodes;
322
- return this;
323
- }
324
-
325
- /**
326
- * Replace content between open and close tags
327
- */
328
- replaceContent(content: string | Node | Array<Node>): this {
329
- // Remove existing nodes
330
- this.__nodes.forEach(node => {
331
- if (node.parentNode) {
332
- node.parentNode.removeChild(node);
333
- }
334
- });
335
- this.__nodes = [];
336
-
337
- // Insert new content
338
- const closeTag = this.__closeTag;
339
- if (typeof content === 'string') {
340
- const temp = document.createElement('div');
341
- temp.innerHTML = content;
342
- const fragment = document.createDocumentFragment();
343
- Array.from(temp.childNodes).forEach(node => fragment.appendChild(node));
344
-
345
- if (closeTag.parentNode) {
346
- closeTag.parentNode.insertBefore(fragment, closeTag);
347
- }
348
- } else if (content instanceof Node) {
349
- if (closeTag.parentNode) {
350
- closeTag.parentNode.insertBefore(content, closeTag);
351
- }
352
- } else if (Array.isArray(content)) {
353
- const fragment = document.createDocumentFragment();
354
- content.forEach(node => fragment.appendChild(node));
355
- if (closeTag.parentNode) {
356
- closeTag.parentNode.insertBefore(fragment, closeTag);
357
- }
358
- }
359
-
360
- // Rescan nodes
361
- this.__scan();
362
- return this;
363
- }
364
-
365
- /**
366
- * Remove element and its content from DOM
367
- */
368
- remove(): void {
369
- // Remove all nodes
370
- this.__nodes.forEach(node => {
371
- if (node.parentNode) {
372
- node.parentNode.removeChild(node);
373
- }
374
- });
375
-
376
- // Remove open and close tags
377
- if (this.__openTag.parentNode) {
378
- this.__openTag.parentNode.removeChild(this.__openTag);
379
- }
380
- if (this.__closeTag.parentNode) {
381
- this.__closeTag.parentNode.removeChild(this.__closeTag);
382
- }
383
-
384
- this.__nodes = [];
385
- }
386
- }
387
-
388
-
389
- /**
390
- * OneMarkerCollection - Collection of OneMarkerModel instances
391
- * Provides array-like operations with type safety
392
- */
393
- export class MarkerCollection {
394
- private __models: MarkerModel[];
395
-
396
- constructor(elements: Array<MarkerModel | MarkerRecord> = []) {
397
- this.__models = elements.map(element =>
398
- (element instanceof MarkerModel) ? element : new MarkerModel(element)
399
- );
400
- }
401
-
402
- get models(): MarkerModel[] {
403
- return this.__models;
404
- }
405
-
406
- get length(): number {
407
- return this.__models.length;
408
- }
409
-
410
- /**
411
- * Get the first model in the collection
412
- */
413
- get first(): MarkerModel | undefined {
414
- return this.__models[0];
415
- }
416
-
417
- /**
418
- * Get the last model in the collection
419
- */
420
- get last(): MarkerModel | undefined {
421
- return this.__models[this.__models.length - 1];
422
- }
423
-
424
- /**
425
- * Get the model at the given index
426
- */
427
- get(index: number): MarkerModel | undefined {
428
- return this.__models[index];
429
- }
430
-
431
- /**
432
- * Set the model at the given index
433
- */
434
- set(index: number, model: MarkerModel): this {
435
- this.__models[index] = model;
436
- return this;
437
- }
438
-
439
- push(model: MarkerModel | MarkerRecord): this {
440
- if (!(model instanceof MarkerModel)) {
441
- model = new MarkerModel(model);
442
- }
443
- this.__models.push(model as MarkerModel);
444
- return this;
445
- }
446
-
447
- pop(): MarkerModel | undefined {
448
- return this.__models.pop();
449
- }
450
-
451
- shift(): MarkerModel | undefined {
452
- return this.__models.shift();
453
- }
454
-
455
- unshift(model: MarkerModel | MarkerRecord): this {
456
- if (!(model instanceof MarkerModel)) {
457
- model = new MarkerModel(model);
458
- }
459
- this.__models.unshift(model as MarkerModel);
460
- return this;
461
- }
462
-
463
- splice(start: number, deleteCount: number, ...items: MarkerModel[]): MarkerModel[] {
464
- return this.__models.splice(start, deleteCount, ...items);
465
- }
466
-
467
- slice(start?: number, end?: number): MarkerModel[] {
468
- return this.__models.slice(start, end);
469
- }
470
-
471
- concat(models: MarkerCollection | MarkerModel[]): MarkerCollection {
472
- const otherModels = (models instanceof MarkerCollection) ? models.__models : models;
473
- return new MarkerCollection(this.__models.concat(otherModels));
474
- }
475
-
476
- reverse(): MarkerCollection {
477
- return new MarkerCollection([...this.__models].reverse());
478
- }
479
-
480
- map<T>(callback: (model: MarkerModel, index: number, array: MarkerModel[]) => T): T[] {
481
- return this.__models.map(callback);
482
- }
483
-
484
- filter(callback: (model: MarkerModel, index: number, array: MarkerModel[]) => boolean): MarkerModel[] {
485
- return this.__models.filter(callback);
486
- }
487
-
488
- reduce<T>(callback: (accumulator: T, model: MarkerModel, index: number, array: MarkerModel[]) => T, initialValue: T): T {
489
- return this.__models.reduce(callback, initialValue);
490
- }
491
-
492
- forEach(callback: (model: MarkerModel, index: number, array: MarkerModel[]) => void): void {
493
- this.__models.forEach(callback);
494
- }
495
-
496
- some(callback: (model: MarkerModel, index: number, array: MarkerModel[]) => boolean): boolean {
497
- return this.__models.some(callback);
498
- }
499
-
500
- every(callback: (model: MarkerModel, index: number, array: MarkerModel[]) => boolean): boolean {
501
- return this.__models.every(callback);
502
- }
503
-
504
- /**
505
- * Query the collection by attributes
506
- */
507
- query(attributes: Record<string, any> = {}): MarkerModel[] {
508
- return this.__models.filter(model => model.__match(attributes));
509
- }
510
-
511
- /**
512
- * Find first model matching attributes
513
- */
514
- find(attributes: Record<string, any> = {}): MarkerModel | null {
515
- return this.query(attributes)[0] || null;
516
- }
517
- }
518
-
519
-
520
-
521
- /**
522
- * Marker Service - Manages custom markup elements
523
- * Supports both HydrationMarker (comments)
524
- */
525
- export class MarkerService {
526
-
527
- static class: string = 'HydrationMarker';
528
-
529
- private prefix: string = 'o';
530
- private delimiter: string = ':';
531
- private closeTagSuffix: string = '/';
532
- private rootElement: Element;
533
- private markerRegistry: MarkerRegistryService;
534
- private walker: TreeWalker;
535
-
536
- constructor(rootElement?: Element) {
537
- this.markerRegistry = MarkerRegistry;
538
- this.rootElement = (rootElement instanceof Element) ? rootElement : document.body;
539
- this.walker = document.createTreeWalker(
540
- this.rootElement,
541
- NodeFilter.SHOW_COMMENT,
542
- null
543
- );
544
- }
545
- refreshWalker() {
546
- this.walker = document.createTreeWalker(
547
- this.rootElement,
548
- NodeFilter.SHOW_COMMENT,
549
- null
550
- );
551
-
552
- return this;
553
- }
554
-
555
- addRegistry(tag: string, id?: string, attributes: Record<string, any> = {}): string {
556
- return this.markerRegistry.register(tag, id, attributes);
557
- }
558
-
559
- resolveTagName(tagShortcut: string): string {
560
- return this.markerRegistry.fullTag(tagShortcut);
561
- }
562
- getShortcut(tagName: string): string {
563
- return this.markerRegistry.shortcut(tagName);
564
- }
565
-
566
- /**
567
- * Check if registryIDOrAttributes is a registryID (string) or attributes (object)
568
- */
569
- private parseRegistryIDOrAttributes(
570
- value?: MarkerFilter
571
- ): { registryID?: string; attributes?: Record<string, any> } {
572
- if (typeof value === 'string') {
573
- return { registryID: value };
574
- }
575
- if (typeof value === 'object' && value !== null) {
576
- const registryID = typeof value['registryID'] === 'string' ? value['registryID'] : undefined;
577
- if (registryID) {
578
- delete value['registryID'];
579
- }
580
- return { registryID, attributes: value };
581
- }
582
- return {};
583
- }
584
-
585
- /**
586
- * Get attributes from MarkerRegistry if registryID provided
587
- */
588
- private getAttributesFromRegistry(
589
- tagName: string,
590
- registryID: string
591
- ): Record<string, any> {
592
- const record = this.markerRegistry.getByTagAndId(tagName, registryID);
593
- return record?.attributes || {};
594
- }
595
-
596
- /**
597
- * Check if attributes match filter
598
- */
599
- private attributesMatch(
600
- tagAttributes: Record<string, any>,
601
- filter?: Record<string, any>
602
- ): boolean {
603
- if (!filter) return true;
604
-
605
- for (const [key, value] of Object.entries(filter)) {
606
- if (value !== undefined && tagAttributes[key] !== value) {
607
- return false;
608
- }
609
- }
610
-
611
- return true;
612
- }
613
-
614
- createMarker(tag: string, id?: string, attributes: Record<string, any> = {}): MarkerModel {
615
- const name = this.markerRegistry.fullTag(tag);
616
- const registryID = id ?? generateUUID();
617
- const key = this.markerRegistry.register(tag, registryID, attributes);
618
- const openTag = this.markerRegistry.createMarkerStart(tag, registryID);
619
- const closeTag = this.markerRegistry.createMarkerEnd(tag, registryID);
620
-
621
-
622
- // Register in MarkerRegistry
623
-
624
- return new MarkerModel({
625
- name,
626
- tagName: (this.prefix? this.prefix + this.delimiter : '') + tag,
627
- registryID,
628
- openTag,
629
- closeTag,
630
- attributes,
631
- children: []
632
- });
633
- }
634
-
635
- createOpenMarker(tag: string, id?: string): Comment {
636
- return this.markerRegistry.createMarkerStart(tag, id);
637
- }
638
- createCloseMarker(tag: string, id?: string): Comment {
639
- return this.markerRegistry.createMarkerEnd(tag, id);
640
- }
641
-
642
-
643
- /**
644
- * Query hydration markers in HTML comments
645
- * Works with format: <!--prefix:shortcutTag:registryID-->
646
- *
647
- * @param tagOrShortcut - Tag name or shortcut (r, v, c, etc.)
648
- * @param where - Registry ID (string) or attributes filter (object)
649
- * @returns Array of matched markers
650
- *
651
- * @example
652
- * query("r", "1234") // Find o:r:1234
653
- * query("reactive", "1234") // Find o:r:1234 (resolved from shortcut)
654
- * query("r", { userId: "123" }) // Find o:r:* with userId="123"
655
- */
656
- query(
657
- tagOrShortcut: string,
658
- where?: MarkerFilter,
659
- useCache: boolean = true
660
- ): MarkerRecord[] {
661
- const { registryID, attributes: attributeFilter } = this.parseRegistryIDOrAttributes(
662
- where
663
- );
664
-
665
- const results: MarkerRecord[] = [];
666
- if (!(useCache === true)) {
667
- this.refreshWalker();
668
- }
669
- const walker = this.walker;
670
-
671
- const commentNodes: Comment[] = [];
672
- let comment: Comment | null;
673
- while ((comment = walker.nextNode() as Comment | null)) {
674
- commentNodes.push(comment);
675
- }
676
-
677
- const tagShortcut = this.markerRegistry.shortcut(tagOrShortcut);
678
- const stack: Array<{
679
- index: number;
680
- shortcut: string;
681
- registryID: string;
682
- attributes: Record<string, any>;
683
- }> = [];
684
-
685
- // Process comments with stack-based matching
686
- for (let i = 0; i < commentNodes.length; i++) {
687
- const commentText = commentNodes[i].nodeValue?.trim() || '';
688
-
689
- // Check if open tag: prefix:shortcut:registryID
690
- const openMatch = commentText.match(
691
- new RegExp(`^${this.prefix}${this.delimiter}([^${this.delimiter}/]+)${this.delimiter}(.+)$`)
692
- );
693
- if (openMatch) {
694
- const shortcut = openMatch[1];
695
- const id = openMatch[2];
696
-
697
- // Check if matches requested tag and registryID
698
- if (shortcut === tagShortcut) {
699
- if (registryID && id !== registryID) {
700
- continue; // Skip if specific registryID requested
701
- }
702
-
703
- const attrs = this.getAttributesFromRegistry(tagOrShortcut, id);
704
- if (!this.attributesMatch(attrs, attributeFilter)) {
705
- continue; // Skip if attributes don't match
706
- }
707
-
708
- stack.push({
709
- index: i,
710
- shortcut,
711
- registryID: id,
712
- attributes: attrs
713
- });
714
- }
715
- continue;
716
- }
717
-
718
- // Check if close tag: /prefix:shortcut:registryID
719
- const closeMatch = commentText.match(
720
- new RegExp(`^${this.closeTagSuffix}${this.prefix}${this.delimiter}([^${this.delimiter}/]+)${this.delimiter}(.+)$`)
721
- );
722
- if (closeMatch) {
723
- const shortcut = closeMatch[1];
724
- const id = closeMatch[2];
725
-
726
- // Find matching open tag in stack (LIFO)
727
- let foundIndex = -1;
728
- for (let s = stack.length - 1; s >= 0; s--) {
729
- if (stack[s].shortcut === shortcut && stack[s].registryID === id) {
730
- foundIndex = s;
731
- break;
732
- }
733
- }
734
-
735
- if (foundIndex !== -1) {
736
- const openTag = stack[foundIndex];
737
-
738
- // Get children between open and close
739
- let currentNode: Node | null = commentNodes[openTag.index].nextSibling;
740
- const children: Node[] = [];
741
-
742
- while (currentNode && currentNode !== commentNodes[i]) {
743
- children.push(currentNode);
744
- currentNode = currentNode.nextSibling;
745
- }
746
-
747
- const fullTagName = this.resolveTagName(openTag.shortcut);
748
-
749
- results.push({
750
- name: fullTagName,
751
- tagName: openTag.shortcut,
752
- registryID: openTag.registryID,
753
- attributes: openTag.attributes,
754
- openTag: commentNodes[openTag.index],
755
- closeTag: commentNodes[i],
756
- children
757
- });
758
-
759
- stack.splice(foundIndex, 1);
760
- }
761
- }
762
- }
763
-
764
- return results;
765
- }
766
-
767
-
768
- /**
769
- * Find multiple hydration markers by tag and optional ID/attributes
770
- * Flexible API supporting multiple query styles
771
- *
772
- * @param tagOrShortcut - Tag name or shortcut (r, v, c, etc.)
773
- * @param registryIDOrAttributes - Optional registry ID (string) or attributes filter (object)
774
- * @returns Array of all matched markers
775
- *
776
- * @example
777
- * find("r") // All o:r:*
778
- * find("reactive") // All o:r:* (resolved from shortcut)
779
- * find("r", "1234") // All o:r:1234 (usually one)
780
- * find("r", { userId: "123" }) // All o:r:* with userId="123"
781
- */
782
- find(
783
- tagOrShortcut: string,
784
- where?: RegistryIDOrAttributes,
785
- useCache: boolean = true
786
- ): MarkerCollection {
787
- return this.collect(this.query(tagOrShortcut, where, useCache));
788
- }
789
-
790
-
791
- getResults(
792
- tagOrShortcut: string,
793
- where?: RegistryIDOrAttributes,
794
- index?: number,
795
- length?: number,
796
- useCache: boolean = true
797
- ): MarkerRecord[] {
798
- const startIndex = (typeof index === 'number' && index !== null) ? index : 0;
799
- const takeLength = (typeof length === 'number' && length !== null && length > 0) ? length : 0;
800
-
801
- const allResults = this.query(tagOrShortcut, where, useCache);
802
-
803
- // Handle positive index
804
- if (startIndex >= 0) {
805
- const sliced = allResults.slice(startIndex);
806
- if (takeLength > 0) {
807
- return sliced.slice(0, takeLength);
808
- }
809
- return sliced;
810
- }
811
-
812
- // Handle negative index
813
- const sliced = allResults.slice(startIndex);
814
- if (takeLength > 0) {
815
- return sliced.slice(0, takeLength);
816
- }
817
- return sliced;
818
- }
819
-
820
- /**
821
- * Get hydration markers with index and length support
822
- *
823
- * @param tagOrShortcut - Tag name or shortcut
824
- * @param where - Registry ID or attributes filter
825
- * @param index - Start position (default 0): >= 0 positive, < 0 negative from end
826
- * @param length - Number to return (default 0 = all): > 0 returns exactly that many
827
- * @returns Array of matched markers
828
- *
829
- * @example
830
- * get("r", "1234") // All o:r:1234
831
- * get("r", "1234", 1) // From index 1
832
- * get("r", "1234", 0, 2) // First 2 items
833
- * get("r", {}, -1) // Last item
834
- */
835
- get(
836
- tagOrShortcut: string,
837
- where?: RegistryIDOrAttributes,
838
- index?: number,
839
- length?: number,
840
- useCache: boolean = true
841
- ): MarkerCollection {
842
- const results = this.getResults(tagOrShortcut, where, index, length, useCache);
843
- return this.collect(results);
844
- }
845
-
846
- /**
847
- * Get first matching hydration marker
848
- *
849
- * @param tagOrShortcut - Tag name or shortcut
850
- * @param where - Registry ID or attributes filter
851
- * @returns First matched marker or null
852
- */
853
- first(
854
- tagOrShortcut: string,
855
- where?: RegistryIDOrAttributes,
856
- useCache: boolean = true
857
- ): MarkerModel | null {
858
- const results = this.getResults(tagOrShortcut, where, 0, 1, useCache);
859
- return results.length > 0 ? this.toModel(results[0]) : null;
860
- }
861
-
862
- /**
863
- * Get last matching hydration marker
864
- *
865
- * @param tagOrShortcut - Tag name or shortcut
866
- * @param where - Registry ID or attributes filter
867
- * @returns Last matched marker or null
868
- */
869
- last(
870
- tagOrShortcut: string,
871
- where?: RegistryIDOrAttributes,
872
- useCache: boolean = true
873
- ): MarkerModel | null {
874
- const results = this.getResults(tagOrShortcut, where, -1, 1, useCache);
875
- return results.length > 0 ? this.toModel(results[0]) : null;
876
- }
877
-
878
- /**
879
- * Get exactly one matching hydration marker
880
- * Throws error if not found or multiple matches found
881
- *
882
- * @param tagOrShortcut - Tag name or shortcut
883
- * @param where - Registry ID or attributes filter
884
- * @param index - Start position (default 0)
885
- * @returns Exactly one matched marker
886
- * @throws Error if no match or multiple matches
887
- */
888
- once(
889
- tagOrShortcut: string,
890
- where?: RegistryIDOrAttributes,
891
- index?: number,
892
- useCache: boolean = true
893
- ): MarkerModel | null {
894
- const startIndex = (typeof index === 'number' && index !== null) ? index : 0;
895
- const results = this.getResults(tagOrShortcut, where, startIndex, 1, useCache);
896
-
897
- if (!results || results.length === 0) {
898
- return null; // Or throw new Error(`HydrationMarker: No marker found for "${tagOrShortcut}" with specified criteria`);
899
- }
900
-
901
- return this.toModel(results[0]);
902
- }
903
-
904
-
905
-
906
- /**
907
- * Create MarkerCollection from query results
908
- */
909
- collect(models: MarkerRecord[]): MarkerCollection {
910
- return new MarkerCollection(models);
911
- }
912
-
913
- /**
914
- * Convert raw tag to MarkerModel
915
- */
916
- toModel(tag: MarkerRecord): MarkerModel {
917
- return new MarkerModel(
918
- tag
919
- );
920
- }
921
- }
922
-
923
- export const OneMarker: MarkerService = app<MarkerService>(MarkerService) as MarkerService;