@saolabs/client 1.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 (383) hide show
  1. package/README.md +221 -0
  2. package/dist/index.d.ts +46 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +38 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/plugins.d.ts +38 -0
  7. package/dist/plugins.d.ts.map +1 -0
  8. package/dist/plugins.js +61 -0
  9. package/dist/plugins.js.map +1 -0
  10. package/dist/src/core/app/Application.d.ts +159 -0
  11. package/dist/src/core/app/Application.d.ts.map +1 -0
  12. package/dist/src/core/app/Application.js +338 -0
  13. package/dist/src/core/app/Application.js.map +1 -0
  14. package/dist/src/core/bootstrap/app.d.ts +4 -0
  15. package/dist/src/core/bootstrap/app.d.ts.map +1 -0
  16. package/dist/src/core/bootstrap/app.js +49 -0
  17. package/dist/src/core/bootstrap/app.js.map +1 -0
  18. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +9 -0
  19. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -0
  20. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +18 -0
  21. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -0
  22. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +6 -0
  23. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -0
  24. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +21 -0
  25. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -0
  26. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +7 -0
  27. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -0
  28. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +14 -0
  29. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -0
  30. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +9 -0
  31. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -0
  32. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +18 -0
  33. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -0
  34. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +38 -0
  35. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -0
  36. package/dist/src/core/bootstrap/providers/ServiceProvider.js +41 -0
  37. package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -0
  38. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +9 -0
  39. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -0
  40. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +18 -0
  41. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -0
  42. package/dist/src/core/bootstrap/providers/default-providers.d.ts +14 -0
  43. package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -0
  44. package/dist/src/core/bootstrap/providers/default-providers.js +79 -0
  45. package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -0
  46. package/dist/src/core/bootstrap/providers/index.d.ts +10 -0
  47. package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -0
  48. package/dist/src/core/bootstrap/providers/index.js +9 -0
  49. package/dist/src/core/bootstrap/providers/index.js.map +1 -0
  50. package/dist/src/core/bootstrap/providers/provider-order.d.ts +19 -0
  51. package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -0
  52. package/dist/src/core/bootstrap/providers/provider-order.js +51 -0
  53. package/dist/src/core/bootstrap/providers/provider-order.js.map +1 -0
  54. package/dist/src/core/cache/ViewCache.d.ts +46 -0
  55. package/dist/src/core/cache/ViewCache.d.ts.map +1 -0
  56. package/dist/src/core/cache/ViewCache.js +85 -0
  57. package/dist/src/core/cache/ViewCache.js.map +1 -0
  58. package/dist/src/core/cache/index.d.ts +2 -0
  59. package/dist/src/core/cache/index.d.ts.map +1 -0
  60. package/dist/src/core/cache/index.js +2 -0
  61. package/dist/src/core/cache/index.js.map +1 -0
  62. package/dist/src/core/contracts/ApiInterface.d.ts +11 -0
  63. package/dist/src/core/contracts/ApiInterface.d.ts.map +1 -0
  64. package/dist/src/core/contracts/ApiInterface.js +2 -0
  65. package/dist/src/core/contracts/ApiInterface.js.map +1 -0
  66. package/dist/src/core/contracts/ApplicationInterface.d.ts +66 -0
  67. package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -0
  68. package/dist/src/core/contracts/ApplicationInterface.js +3 -0
  69. package/dist/src/core/contracts/ApplicationInterface.js.map +1 -0
  70. package/dist/src/core/contracts/BlockInterface.d.ts +67 -0
  71. package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -0
  72. package/dist/src/core/contracts/BlockInterface.js +2 -0
  73. package/dist/src/core/contracts/BlockInterface.js.map +1 -0
  74. package/dist/src/core/contracts/ComponentInterface.d.ts +24 -0
  75. package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -0
  76. package/dist/src/core/contracts/ComponentInterface.js +2 -0
  77. package/dist/src/core/contracts/ComponentInterface.js.map +1 -0
  78. package/dist/src/core/contracts/ElementInterface.d.ts +117 -0
  79. package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -0
  80. package/dist/src/core/contracts/ElementInterface.js +2 -0
  81. package/dist/src/core/contracts/ElementInterface.js.map +1 -0
  82. package/dist/src/core/contracts/EventServiceInterface.d.ts +37 -0
  83. package/dist/src/core/contracts/EventServiceInterface.d.ts.map +1 -0
  84. package/dist/src/core/contracts/EventServiceInterface.js +3 -0
  85. package/dist/src/core/contracts/EventServiceInterface.js.map +1 -0
  86. package/dist/src/core/contracts/HelperInterface.d.ts +231 -0
  87. package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -0
  88. package/dist/src/core/contracts/HelperInterface.js +3 -0
  89. package/dist/src/core/contracts/HelperInterface.js.map +1 -0
  90. package/dist/src/core/contracts/HttpServiceInterface.d.ts +38 -0
  91. package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -0
  92. package/dist/src/core/contracts/HttpServiceInterface.js +3 -0
  93. package/dist/src/core/contracts/HttpServiceInterface.js.map +1 -0
  94. package/dist/src/core/contracts/LoggerServiceInterface.d.ts +37 -0
  95. package/dist/src/core/contracts/LoggerServiceInterface.d.ts.map +1 -0
  96. package/dist/src/core/contracts/LoggerServiceInterface.js +3 -0
  97. package/dist/src/core/contracts/LoggerServiceInterface.js.map +1 -0
  98. package/dist/src/core/contracts/LoopContextInterface.d.ts +14 -0
  99. package/dist/src/core/contracts/LoopContextInterface.d.ts.map +1 -0
  100. package/dist/src/core/contracts/LoopContextInterface.js +3 -0
  101. package/dist/src/core/contracts/LoopContextInterface.js.map +1 -0
  102. package/dist/src/core/contracts/MarkerInterface.d.ts +55 -0
  103. package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -0
  104. package/dist/src/core/contracts/MarkerInterface.js +2 -0
  105. package/dist/src/core/contracts/MarkerInterface.js.map +1 -0
  106. package/dist/src/core/contracts/ReactiveInterface.d.ts +38 -0
  107. package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -0
  108. package/dist/src/core/contracts/ReactiveInterface.js +2 -0
  109. package/dist/src/core/contracts/ReactiveInterface.js.map +1 -0
  110. package/dist/src/core/contracts/RouterInterface.d.ts +58 -0
  111. package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -0
  112. package/dist/src/core/contracts/RouterInterface.js +2 -0
  113. package/dist/src/core/contracts/RouterInterface.js.map +1 -0
  114. package/dist/src/core/contracts/ServiceProviderInterface.d.ts +12 -0
  115. package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -0
  116. package/dist/src/core/contracts/ServiceProviderInterface.js +2 -0
  117. package/dist/src/core/contracts/ServiceProviderInterface.js.map +1 -0
  118. package/dist/src/core/contracts/StorageServiceInterface.d.ts +43 -0
  119. package/dist/src/core/contracts/StorageServiceInterface.d.ts.map +1 -0
  120. package/dist/src/core/contracts/StorageServiceInterface.js +3 -0
  121. package/dist/src/core/contracts/StorageServiceInterface.js.map +1 -0
  122. package/dist/src/core/contracts/StoreServiceInterface.d.ts +45 -0
  123. package/dist/src/core/contracts/StoreServiceInterface.d.ts.map +1 -0
  124. package/dist/src/core/contracts/StoreServiceInterface.js +3 -0
  125. package/dist/src/core/contracts/StoreServiceInterface.js.map +1 -0
  126. package/dist/src/core/contracts/ViewCacheInterface.d.ts +13 -0
  127. package/dist/src/core/contracts/ViewCacheInterface.d.ts.map +1 -0
  128. package/dist/src/core/contracts/ViewCacheInterface.js +3 -0
  129. package/dist/src/core/contracts/ViewCacheInterface.js.map +1 -0
  130. package/dist/src/core/contracts/ViewControllerInterface.d.ts +115 -0
  131. package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -0
  132. package/dist/src/core/contracts/ViewControllerInterface.js +2 -0
  133. package/dist/src/core/contracts/ViewControllerInterface.js.map +1 -0
  134. package/dist/src/core/contracts/ViewInterface.d.ts +24 -0
  135. package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -0
  136. package/dist/src/core/contracts/ViewInterface.js +2 -0
  137. package/dist/src/core/contracts/ViewInterface.js.map +1 -0
  138. package/dist/src/core/contracts/ViewManagerInterface.d.ts +44 -0
  139. package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -0
  140. package/dist/src/core/contracts/ViewManagerInterface.js +2 -0
  141. package/dist/src/core/contracts/ViewManagerInterface.js.map +1 -0
  142. package/dist/src/core/contracts/ViewStateInterface.d.ts +40 -0
  143. package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -0
  144. package/dist/src/core/contracts/ViewStateInterface.js +3 -0
  145. package/dist/src/core/contracts/ViewStateInterface.js.map +1 -0
  146. package/dist/src/core/contracts/common.d.ts +28 -0
  147. package/dist/src/core/contracts/common.d.ts.map +1 -0
  148. package/dist/src/core/contracts/common.js +29 -0
  149. package/dist/src/core/contracts/common.js.map +1 -0
  150. package/dist/src/core/contracts/utils.d.ts +20 -0
  151. package/dist/src/core/contracts/utils.d.ts.map +1 -0
  152. package/dist/src/core/contracts/utils.js +4 -0
  153. package/dist/src/core/contracts/utils.js.map +1 -0
  154. package/dist/src/core/contracts/views.d.ts +23 -0
  155. package/dist/src/core/contracts/views.d.ts.map +1 -0
  156. package/dist/src/core/contracts/views.js +2 -0
  157. package/dist/src/core/contracts/views.js.map +1 -0
  158. package/dist/src/core/elements/Block.d.ts +58 -0
  159. package/dist/src/core/elements/Block.d.ts.map +1 -0
  160. package/dist/src/core/elements/Block.js +77 -0
  161. package/dist/src/core/elements/Block.js.map +1 -0
  162. package/dist/src/core/elements/BlockOutlet.d.ts +34 -0
  163. package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -0
  164. package/dist/src/core/elements/BlockOutlet.js +59 -0
  165. package/dist/src/core/elements/BlockOutlet.js.map +1 -0
  166. package/dist/src/core/elements/Component.d.ts +62 -0
  167. package/dist/src/core/elements/Component.d.ts.map +1 -0
  168. package/dist/src/core/elements/Component.js +72 -0
  169. package/dist/src/core/elements/Component.js.map +1 -0
  170. package/dist/src/core/elements/ElementManager.d.ts +23 -0
  171. package/dist/src/core/elements/ElementManager.d.ts.map +1 -0
  172. package/dist/src/core/elements/ElementManager.js +33 -0
  173. package/dist/src/core/elements/ElementManager.js.map +1 -0
  174. package/dist/src/core/elements/Fragment.d.ts +51 -0
  175. package/dist/src/core/elements/Fragment.d.ts.map +1 -0
  176. package/dist/src/core/elements/Fragment.js +133 -0
  177. package/dist/src/core/elements/Fragment.js.map +1 -0
  178. package/dist/src/core/elements/Html.d.ts +52 -0
  179. package/dist/src/core/elements/Html.d.ts.map +1 -0
  180. package/dist/src/core/elements/Html.js +299 -0
  181. package/dist/src/core/elements/Html.js.map +1 -0
  182. package/dist/src/core/elements/Output.d.ts +69 -0
  183. package/dist/src/core/elements/Output.d.ts.map +1 -0
  184. package/dist/src/core/elements/Output.js +121 -0
  185. package/dist/src/core/elements/Output.js.map +1 -0
  186. package/dist/src/core/elements/Reactive.d.ts +77 -0
  187. package/dist/src/core/elements/Reactive.d.ts.map +1 -0
  188. package/dist/src/core/elements/Reactive.js +199 -0
  189. package/dist/src/core/elements/Reactive.js.map +1 -0
  190. package/dist/src/core/elements/TextElement.d.ts +46 -0
  191. package/dist/src/core/elements/TextElement.d.ts.map +1 -0
  192. package/dist/src/core/elements/TextElement.js +94 -0
  193. package/dist/src/core/elements/TextElement.js.map +1 -0
  194. package/dist/src/core/elements/Wrapper.d.ts +50 -0
  195. package/dist/src/core/elements/Wrapper.d.ts.map +1 -0
  196. package/dist/src/core/elements/Wrapper.js +96 -0
  197. package/dist/src/core/elements/Wrapper.js.map +1 -0
  198. package/dist/src/core/elements/Yield.d.ts +34 -0
  199. package/dist/src/core/elements/Yield.d.ts.map +1 -0
  200. package/dist/src/core/elements/Yield.js +56 -0
  201. package/dist/src/core/elements/Yield.js.map +1 -0
  202. package/dist/src/core/elements/helpers.d.ts +8 -0
  203. package/dist/src/core/elements/helpers.d.ts.map +1 -0
  204. package/dist/src/core/elements/helpers.js +40 -0
  205. package/dist/src/core/elements/helpers.js.map +1 -0
  206. package/dist/src/core/elements/index.d.ts +12 -0
  207. package/dist/src/core/elements/index.d.ts.map +1 -0
  208. package/dist/src/core/elements/index.js +12 -0
  209. package/dist/src/core/elements/index.js.map +1 -0
  210. package/dist/src/core/hellpers/ApiClient.d.ts +58 -0
  211. package/dist/src/core/hellpers/ApiClient.d.ts.map +1 -0
  212. package/dist/src/core/hellpers/ApiClient.js +122 -0
  213. package/dist/src/core/hellpers/ApiClient.js.map +1 -0
  214. package/dist/src/core/hellpers/app.d.ts +3 -0
  215. package/dist/src/core/hellpers/app.d.ts.map +1 -0
  216. package/dist/src/core/hellpers/app.js +53 -0
  217. package/dist/src/core/hellpers/app.js.map +1 -0
  218. package/dist/src/core/hellpers/utils.d.ts +26 -0
  219. package/dist/src/core/hellpers/utils.d.ts.map +1 -0
  220. package/dist/src/core/hellpers/utils.js +96 -0
  221. package/dist/src/core/hellpers/utils.js.map +1 -0
  222. package/dist/src/core/routers/Router.d.ts +212 -0
  223. package/dist/src/core/routers/Router.d.ts.map +1 -0
  224. package/dist/src/core/routers/Router.js +623 -0
  225. package/dist/src/core/routers/Router.js.map +1 -0
  226. package/dist/src/core/routers/index.d.ts +3 -0
  227. package/dist/src/core/routers/index.d.ts.map +1 -0
  228. package/dist/src/core/routers/index.js +2 -0
  229. package/dist/src/core/routers/index.js.map +1 -0
  230. package/dist/src/core/services/BlockManager.d.ts +63 -0
  231. package/dist/src/core/services/BlockManager.d.ts.map +1 -0
  232. package/dist/src/core/services/BlockManager.js +191 -0
  233. package/dist/src/core/services/BlockManager.js.map +1 -0
  234. package/dist/src/core/services/DomService.d.ts +9 -0
  235. package/dist/src/core/services/DomService.d.ts.map +1 -0
  236. package/dist/src/core/services/DomService.js +18 -0
  237. package/dist/src/core/services/DomService.js.map +1 -0
  238. package/dist/src/core/services/EventService.d.ts +58 -0
  239. package/dist/src/core/services/EventService.d.ts.map +1 -0
  240. package/dist/src/core/services/EventService.js +212 -0
  241. package/dist/src/core/services/EventService.js.map +1 -0
  242. package/dist/src/core/services/HelperService.d.ts +443 -0
  243. package/dist/src/core/services/HelperService.d.ts.map +1 -0
  244. package/dist/src/core/services/HelperService.js +1650 -0
  245. package/dist/src/core/services/HelperService.js.map +1 -0
  246. package/dist/src/core/services/HttpService.d.ts +63 -0
  247. package/dist/src/core/services/HttpService.d.ts.map +1 -0
  248. package/dist/src/core/services/HttpService.js +182 -0
  249. package/dist/src/core/services/HttpService.js.map +1 -0
  250. package/dist/src/core/services/LoggerService.d.ts +56 -0
  251. package/dist/src/core/services/LoggerService.d.ts.map +1 -0
  252. package/dist/src/core/services/LoggerService.js +94 -0
  253. package/dist/src/core/services/LoggerService.js.map +1 -0
  254. package/dist/src/core/services/MarkerRegistry.d.ts +94 -0
  255. package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -0
  256. package/dist/src/core/services/MarkerRegistry.js +199 -0
  257. package/dist/src/core/services/MarkerRegistry.js.map +1 -0
  258. package/dist/src/core/services/MarkerService.d.ts +299 -0
  259. package/dist/src/core/services/MarkerService.d.ts.map +1 -0
  260. package/dist/src/core/services/MarkerService.js +723 -0
  261. package/dist/src/core/services/MarkerService.js.map +1 -0
  262. package/dist/src/core/services/StorageService.d.ts +69 -0
  263. package/dist/src/core/services/StorageService.d.ts.map +1 -0
  264. package/dist/src/core/services/StorageService.js +243 -0
  265. package/dist/src/core/services/StorageService.js.map +1 -0
  266. package/dist/src/core/services/StoreService.d.ts +80 -0
  267. package/dist/src/core/services/StoreService.d.ts.map +1 -0
  268. package/dist/src/core/services/StoreService.js +301 -0
  269. package/dist/src/core/services/StoreService.js.map +1 -0
  270. package/dist/src/core/services/index.d.ts +9 -0
  271. package/dist/src/core/services/index.d.ts.map +1 -0
  272. package/dist/src/core/services/index.js +9 -0
  273. package/dist/src/core/services/index.js.map +1 -0
  274. package/dist/src/core/types/utils.d.ts +29 -0
  275. package/dist/src/core/types/utils.d.ts.map +1 -0
  276. package/dist/src/core/types/utils.js +22 -0
  277. package/dist/src/core/types/utils.js.map +1 -0
  278. package/dist/src/core/view/LoopContext.d.ts +38 -0
  279. package/dist/src/core/view/LoopContext.d.ts.map +1 -0
  280. package/dist/src/core/view/LoopContext.js +100 -0
  281. package/dist/src/core/view/LoopContext.js.map +1 -0
  282. package/dist/src/core/view/Section.d.ts +41 -0
  283. package/dist/src/core/view/Section.d.ts.map +1 -0
  284. package/dist/src/core/view/Section.js +67 -0
  285. package/dist/src/core/view/Section.js.map +1 -0
  286. package/dist/src/core/view/View.d.ts +63 -0
  287. package/dist/src/core/view/View.d.ts.map +1 -0
  288. package/dist/src/core/view/View.js +85 -0
  289. package/dist/src/core/view/View.js.map +1 -0
  290. package/dist/src/core/view/ViewController.d.ts +277 -0
  291. package/dist/src/core/view/ViewController.d.ts.map +1 -0
  292. package/dist/src/core/view/ViewController.js +862 -0
  293. package/dist/src/core/view/ViewController.js.map +1 -0
  294. package/dist/src/core/view/ViewManager.d.ts +141 -0
  295. package/dist/src/core/view/ViewManager.d.ts.map +1 -0
  296. package/dist/src/core/view/ViewManager.js +565 -0
  297. package/dist/src/core/view/ViewManager.js.map +1 -0
  298. package/dist/src/core/view/ViewState.d.ts +117 -0
  299. package/dist/src/core/view/ViewState.d.ts.map +1 -0
  300. package/dist/src/core/view/ViewState.js +410 -0
  301. package/dist/src/core/view/ViewState.js.map +1 -0
  302. package/dist/src/core/view/index.d.ts +6 -0
  303. package/dist/src/core/view/index.d.ts.map +1 -0
  304. package/dist/src/core/view/index.js +6 -0
  305. package/dist/src/core/view/index.js.map +1 -0
  306. package/index.ts +62 -0
  307. package/package.json +70 -0
  308. package/plugins.ts +77 -0
  309. package/src/core/app/Application.ts +410 -0
  310. package/src/core/bootstrap/app.ts +58 -0
  311. package/src/core/bootstrap/providers/ApiServiceProvider.ts +18 -0
  312. package/src/core/bootstrap/providers/CoreServiceProvider.ts +19 -0
  313. package/src/core/bootstrap/providers/HelperServiceProvider.ts +12 -0
  314. package/src/core/bootstrap/providers/RouteServiceProvider.ts +17 -0
  315. package/src/core/bootstrap/providers/ServiceProvider.ts +51 -0
  316. package/src/core/bootstrap/providers/ViewServiceProvider.ts +17 -0
  317. package/src/core/bootstrap/providers/default-providers.ts +94 -0
  318. package/src/core/bootstrap/providers/index.ts +9 -0
  319. package/src/core/bootstrap/providers/provider-order.test.ts +67 -0
  320. package/src/core/bootstrap/providers/provider-order.ts +66 -0
  321. package/src/core/cache/ViewCache.ts +102 -0
  322. package/src/core/cache/index.ts +1 -0
  323. package/src/core/contracts/ApiInterface.ts +11 -0
  324. package/src/core/contracts/ApplicationInterface.ts +79 -0
  325. package/src/core/contracts/BlockInterface.ts +76 -0
  326. package/src/core/contracts/ComponentInterface.ts +26 -0
  327. package/src/core/contracts/ElementInterface.ts +140 -0
  328. package/src/core/contracts/EventServiceInterface.ts +47 -0
  329. package/src/core/contracts/HelperInterface.ts +256 -0
  330. package/src/core/contracts/HttpServiceInterface.ts +51 -0
  331. package/src/core/contracts/LoggerServiceInterface.ts +48 -0
  332. package/src/core/contracts/LoopContextInterface.ts +15 -0
  333. package/src/core/contracts/MarkerInterface.ts +77 -0
  334. package/src/core/contracts/ReactiveInterface.ts +45 -0
  335. package/src/core/contracts/RouterInterface.ts +65 -0
  336. package/src/core/contracts/ServiceProviderInterface.ts +12 -0
  337. package/src/core/contracts/StorageServiceInterface.ts +48 -0
  338. package/src/core/contracts/StoreServiceInterface.ts +50 -0
  339. package/src/core/contracts/ViewCacheInterface.ts +14 -0
  340. package/src/core/contracts/ViewControllerInterface.ts +135 -0
  341. package/src/core/contracts/ViewInterface.ts +31 -0
  342. package/src/core/contracts/ViewManagerInterface.ts +45 -0
  343. package/src/core/contracts/ViewStateInterface.ts +47 -0
  344. package/src/core/contracts/common.ts +27 -0
  345. package/src/core/contracts/utils.ts +23 -0
  346. package/src/core/contracts/views.ts +23 -0
  347. package/src/core/elements/Block.ts +113 -0
  348. package/src/core/elements/BlockOutlet.ts +83 -0
  349. package/src/core/elements/Component.ts +114 -0
  350. package/src/core/elements/ElementManager.ts +48 -0
  351. package/src/core/elements/Fragment.ts +168 -0
  352. package/src/core/elements/Html.ts +364 -0
  353. package/src/core/elements/Output.ts +167 -0
  354. package/src/core/elements/Reactive.ts +253 -0
  355. package/src/core/elements/TextElement.ts +110 -0
  356. package/src/core/elements/Wrapper.ts +131 -0
  357. package/src/core/elements/Yield.ts +70 -0
  358. package/src/core/elements/helpers.ts +56 -0
  359. package/src/core/elements/index.ts +26 -0
  360. package/src/core/hellpers/ApiClient.ts +145 -0
  361. package/src/core/hellpers/app.ts +57 -0
  362. package/src/core/hellpers/utils.ts +109 -0
  363. package/src/core/routers/Router.ts +765 -0
  364. package/src/core/routers/index.ts +2 -0
  365. package/src/core/services/BlockManager.ts +210 -0
  366. package/src/core/services/DomService.ts +26 -0
  367. package/src/core/services/EventService.ts +266 -0
  368. package/src/core/services/HelperService.ts +1653 -0
  369. package/src/core/services/HttpService.ts +235 -0
  370. package/src/core/services/LoggerService.ts +139 -0
  371. package/src/core/services/MarkerRegistry.ts +239 -0
  372. package/src/core/services/MarkerService.ts +923 -0
  373. package/src/core/services/StorageService.ts +268 -0
  374. package/src/core/services/StoreService.ts +338 -0
  375. package/src/core/services/index.ts +8 -0
  376. package/src/core/types/utils.ts +30 -0
  377. package/src/core/view/LoopContext.ts +109 -0
  378. package/src/core/view/Section.ts +86 -0
  379. package/src/core/view/View.ts +109 -0
  380. package/src/core/view/ViewController.ts +1002 -0
  381. package/src/core/view/ViewManager.ts +700 -0
  382. package/src/core/view/ViewState.ts +453 -0
  383. package/src/core/view/index.ts +5 -0
@@ -0,0 +1,1650 @@
1
+ import { app } from "../hellpers/app";
2
+ /**
3
+ * HelperService — PHP-compatible helper functions for OneView runtime.
4
+ *
5
+ * The compiler converts PHP function calls → `App.Helper.xxx()`.
6
+ * This class provides JavaScript implementations of those PHP functions
7
+ * so compiled .one templates work correctly at runtime.
8
+ *
9
+ * Categories:
10
+ * - Execution helpers (execute, exec)
11
+ * - Type checks (isset, empty, is_null, is_array, is_string, is_numeric, is_object, is_bool, is_int, is_float)
12
+ * - String functions (strlen, substr, trim, ltrim, rtrim, strtolower, strtoupper, ucfirst, lcfirst,
13
+ * str_replace, str_repeat, str_pad, str_contains, str_starts_with, str_ends_with,
14
+ * str_word_count, nl2br, wordwrap, chunk_split, sprintf, number_format, md5, sha1,
15
+ * base64_encode, base64_decode, urlencode, urldecode, htmlspecialchars, htmlspecialchars_decode,
16
+ * strip_tags, addslashes, stripslashes, str_split, substr_count, substr_replace,
17
+ * str_getcsv, quoted_printable_encode, quoted_printable_decode)
18
+ * - Array functions (count, array_push, array_pop, array_shift, array_unshift, array_merge,
19
+ * array_keys, array_values, array_reverse, array_unique, array_slice, array_splice,
20
+ * array_map, array_filter, array_reduce, array_find, array_find_key, array_column,
21
+ * array_combine, array_chunk, array_pad, array_flip, array_sum, array_product,
22
+ * array_count_values, array_fill, array_fill_keys, array_intersect, array_diff,
23
+ * array_search, in_array, array_key_exists, sort, rsort, ksort, krsort,
24
+ * usort, uasort, uksort, array_multisort, range, compact, extract, list, head, last)
25
+ * - Math functions (min, max, abs, ceil, floor, round, sqrt, pow, log, log10, exp,
26
+ * fmod, intdiv, pi, rand, mt_rand, array_rand)
27
+ * - JSON (json_encode, json_decode)
28
+ * - Date/Time (now, today, date, time, strtotime, mktime, microtime, date_create, date_format,
29
+ * date_diff, date_modify)
30
+ * - Formatting (number_format, formatDate, formatNumber, formatCurrency, truncate, slug)
31
+ * - Misc (collect, dd, dump, var_dump, print_r, class_exists, function_exists, sleep,
32
+ * uniqid, crc32, intval, floatval, strval, boolval, settype, gettype)
33
+ * - Output (escString, escapeHtml)
34
+ */
35
+ export class HelperService {
36
+ constructor(App) {
37
+ this.App = null;
38
+ this.config = {};
39
+ if (App)
40
+ this.App = App;
41
+ }
42
+ app(key, value) {
43
+ return app(key, value);
44
+ }
45
+ make(name, defaultValue) {
46
+ return app.make(name, defaultValue);
47
+ }
48
+ setApp(App) {
49
+ this.App = App;
50
+ }
51
+ setConfig(config) {
52
+ this.config = { ...this.config, ...config };
53
+ }
54
+ // ─── Execution ──────────────────────────────────────────────
55
+ /** Execute a function safely, return result or empty string on error */
56
+ execute(fn) {
57
+ try {
58
+ return fn();
59
+ }
60
+ catch (error) {
61
+ console.error('[Helper] execute error:', error);
62
+ return '';
63
+ }
64
+ }
65
+ /** Alias for execute with arguments */
66
+ exec(fn, ...args) {
67
+ try {
68
+ return fn(...args);
69
+ }
70
+ catch (error) {
71
+ console.error('[Helper] exec error:', error);
72
+ return null;
73
+ }
74
+ }
75
+ // ─── Type Checks (PHP-compatible) ───────────────────────────
76
+ /** PHP isset() — true if value is not null/undefined */
77
+ isset(...values) {
78
+ return values.every(v => v !== null && v !== undefined);
79
+ }
80
+ /** PHP empty() — true if value is falsy, empty string, empty array, empty object */
81
+ empty(value) {
82
+ if (value == null)
83
+ return true;
84
+ if (value === false || value === 0 || value === '' || value === '0')
85
+ return true;
86
+ if (Array.isArray(value))
87
+ return value.length === 0;
88
+ if (typeof value === 'object')
89
+ return Object.keys(value).length === 0;
90
+ return false;
91
+ }
92
+ /** PHP is_null() */
93
+ is_null(value) {
94
+ return value === null || value === undefined;
95
+ }
96
+ /** PHP is_array() — true for arrays and plain objects */
97
+ is_array(value) {
98
+ return Array.isArray(value);
99
+ }
100
+ /** PHP is_string() */
101
+ is_string(value) {
102
+ return typeof value === 'string';
103
+ }
104
+ /** PHP is_numeric() */
105
+ is_numeric(value) {
106
+ if (typeof value === 'number')
107
+ return !isNaN(value);
108
+ if (typeof value === 'string')
109
+ return value.trim() !== '' && !isNaN(Number(value));
110
+ return false;
111
+ }
112
+ /** PHP is_object() */
113
+ is_object(value) {
114
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
115
+ }
116
+ /** PHP is_bool() */
117
+ is_bool(value) {
118
+ return typeof value === 'boolean';
119
+ }
120
+ /** PHP is_int() / is_integer() / is_long() */
121
+ is_int(value) {
122
+ return typeof value === 'number' && Number.isInteger(value);
123
+ }
124
+ /** PHP is_float() / is_double() */
125
+ is_float(value) {
126
+ return typeof value === 'number' && !Number.isInteger(value);
127
+ }
128
+ // ─── Count / Length ─────────────────────────────────────────
129
+ /** PHP count() — length of string, array, or object keys */
130
+ count(value) {
131
+ if (value == null)
132
+ return 0;
133
+ if (typeof value === 'string' || Array.isArray(value))
134
+ return value.length;
135
+ if (typeof value === 'object')
136
+ return Object.keys(value).length;
137
+ if (typeof value === 'number')
138
+ return value;
139
+ if (typeof value === 'boolean')
140
+ return value ? 1 : 0;
141
+ return 0;
142
+ }
143
+ /** PHP sizeof() — alias for count */
144
+ sizeof(value) {
145
+ return this.count(value);
146
+ }
147
+ // ─── String Functions ───────────────────────────────────────
148
+ /** PHP strlen() */
149
+ strlen(str) {
150
+ return String(str ?? '').length;
151
+ }
152
+ /** PHP substr() */
153
+ substr(str, start, length) {
154
+ const s = String(str ?? '');
155
+ if (start < 0)
156
+ start = Math.max(0, s.length + start);
157
+ if (length === undefined)
158
+ return s.substring(start);
159
+ if (length < 0)
160
+ return s.substring(start, Math.max(0, s.length + length));
161
+ return s.substring(start, start + length);
162
+ }
163
+ /** PHP mb_substr() — alias for substr (JS strings are UTF-16) */
164
+ mb_substr(str, start, length) {
165
+ return this.substr(str, start, length);
166
+ }
167
+ /** PHP trim() */
168
+ trim(str, chars) {
169
+ const s = String(str ?? '');
170
+ if (!chars)
171
+ return s.trim();
172
+ const escaped = chars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
173
+ return s.replace(new RegExp(`^[${escaped}]+|[${escaped}]+$`, 'g'), '');
174
+ }
175
+ /** PHP ltrim() */
176
+ ltrim(str, chars) {
177
+ const s = String(str ?? '');
178
+ if (!chars)
179
+ return s.trimStart();
180
+ const escaped = chars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
181
+ return s.replace(new RegExp(`^[${escaped}]+`), '');
182
+ }
183
+ /** PHP rtrim() / chop() */
184
+ rtrim(str, chars) {
185
+ const s = String(str ?? '');
186
+ if (!chars)
187
+ return s.trimEnd();
188
+ const escaped = chars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
189
+ return s.replace(new RegExp(`[${escaped}]+$`), '');
190
+ }
191
+ /** PHP strtolower() */
192
+ strtolower(str) {
193
+ return String(str ?? '').toLowerCase();
194
+ }
195
+ /** PHP strtoupper() */
196
+ strtoupper(str) {
197
+ return String(str ?? '').toUpperCase();
198
+ }
199
+ /** PHP ucfirst() */
200
+ ucfirst(str) {
201
+ const s = String(str ?? '');
202
+ if (!s)
203
+ return s;
204
+ return s.charAt(0).toUpperCase() + s.slice(1);
205
+ }
206
+ /** PHP lcfirst() */
207
+ lcfirst(str) {
208
+ const s = String(str ?? '');
209
+ if (!s)
210
+ return s;
211
+ return s.charAt(0).toLowerCase() + s.slice(1);
212
+ }
213
+ /** PHP ucwords() */
214
+ ucwords(str, delimiters = " \t\r\n\f\v") {
215
+ const s = String(str ?? '');
216
+ const delimSet = new Set(delimiters.split(''));
217
+ let result = '';
218
+ let capitalizeNext = true;
219
+ for (const ch of s) {
220
+ if (delimSet.has(ch)) {
221
+ result += ch;
222
+ capitalizeNext = true;
223
+ }
224
+ else if (capitalizeNext) {
225
+ result += ch.toUpperCase();
226
+ capitalizeNext = false;
227
+ }
228
+ else {
229
+ result += ch;
230
+ }
231
+ }
232
+ return result;
233
+ }
234
+ /** PHP str_replace() */
235
+ str_replace(search, replace, subject) {
236
+ let s = String(subject ?? '');
237
+ if (Array.isArray(search)) {
238
+ for (let i = 0; i < search.length; i++) {
239
+ const rep = Array.isArray(replace) ? (replace[i] ?? '') : replace;
240
+ s = s.split(search[i]).join(rep);
241
+ }
242
+ return s;
243
+ }
244
+ return s.split(search).join(String(replace));
245
+ }
246
+ /** PHP str_ireplace() — case-insensitive str_replace */
247
+ str_ireplace(search, replace, subject) {
248
+ let s = String(subject ?? '');
249
+ const searches = Array.isArray(search) ? search : [search];
250
+ const replaces = Array.isArray(replace) ? replace : [replace];
251
+ for (let i = 0; i < searches.length; i++) {
252
+ const rep = replaces[i] ?? replaces[replaces.length - 1] ?? '';
253
+ s = s.replace(new RegExp(searches[i].replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'), 'gi'), rep);
254
+ }
255
+ return s;
256
+ }
257
+ /** PHP explode() */
258
+ explode(delimiter, str, limit) {
259
+ const s = String(str ?? '');
260
+ if (!delimiter)
261
+ return [s];
262
+ if (limit === undefined)
263
+ return s.split(delimiter);
264
+ if (limit > 0)
265
+ return s.split(delimiter).slice(0, limit).concat(limit <= s.split(delimiter).length ? [s.split(delimiter).slice(limit - 1).join(delimiter)] : []);
266
+ const parts = s.split(delimiter);
267
+ if (limit < 0)
268
+ return parts.slice(0, parts.length + limit);
269
+ return parts;
270
+ }
271
+ /** PHP implode() / join() */
272
+ implode(glue, pieces) {
273
+ // PHP allows implode(array) with no glue
274
+ if (Array.isArray(glue)) {
275
+ return glue.join('');
276
+ }
277
+ if (!pieces)
278
+ return '';
279
+ return pieces.join(glue);
280
+ }
281
+ /** PHP str_repeat() */
282
+ str_repeat(str, times) {
283
+ return String(str ?? '').repeat(Math.max(0, Math.floor(times)));
284
+ }
285
+ /** PHP str_pad() */
286
+ str_pad(input, length, padString = ' ', padType = 1) {
287
+ const s = String(input ?? '');
288
+ if (s.length >= length)
289
+ return s;
290
+ const pad = length - s.length;
291
+ const STR_PAD_RIGHT = 1, STR_PAD_LEFT = 0, STR_PAD_BOTH = 2;
292
+ switch (padType) {
293
+ case STR_PAD_LEFT:
294
+ return s.padStart(length, padString);
295
+ case STR_PAD_BOTH: {
296
+ const leftPad = Math.floor(pad / 2);
297
+ const rightPad = pad - leftPad;
298
+ return padString.repeat(Math.ceil(leftPad / padString.length)).slice(0, leftPad)
299
+ + s
300
+ + padString.repeat(Math.ceil(rightPad / padString.length)).slice(0, rightPad);
301
+ }
302
+ default: // STR_PAD_RIGHT
303
+ return s.padEnd(length, padString);
304
+ }
305
+ }
306
+ /** PHP str_contains() (PHP 8) */
307
+ str_contains(haystack, needle) {
308
+ return String(haystack ?? '').includes(needle);
309
+ }
310
+ /** PHP str_starts_with() (PHP 8) */
311
+ str_starts_with(haystack, needle) {
312
+ return String(haystack ?? '').startsWith(needle);
313
+ }
314
+ /** PHP str_ends_with() (PHP 8) */
315
+ str_ends_with(haystack, needle) {
316
+ return String(haystack ?? '').endsWith(needle);
317
+ }
318
+ /** PHP str_word_count() */
319
+ str_word_count(str, format = 0) {
320
+ const s = String(str ?? '').trim();
321
+ if (!s)
322
+ return format === 0 ? 0 : [];
323
+ const words = s.split(/\s+/);
324
+ return format === 0 ? words.length : words;
325
+ }
326
+ /** PHP str_split() */
327
+ str_split(str, length = 1) {
328
+ const s = String(str ?? '');
329
+ if (length < 1)
330
+ return [s];
331
+ const result = [];
332
+ for (let i = 0; i < s.length; i += length) {
333
+ result.push(s.substring(i, i + length));
334
+ }
335
+ return result.length ? result : [''];
336
+ }
337
+ /** PHP substr_count() */
338
+ substr_count(haystack, needle, offset = 0, length) {
339
+ let s = String(haystack ?? '');
340
+ if (offset)
341
+ s = s.substring(offset);
342
+ if (length !== undefined)
343
+ s = s.substring(0, length);
344
+ if (!needle)
345
+ return 0;
346
+ return s.split(needle).length - 1;
347
+ }
348
+ /** PHP substr_replace() */
349
+ substr_replace(str, replacement, start, length) {
350
+ const s = String(str ?? '');
351
+ const realStart = start < 0 ? Math.max(0, s.length + start) : Math.min(start, s.length);
352
+ const realLength = length === undefined ? s.length - realStart : (length < 0 ? Math.max(0, s.length + length - realStart) : length);
353
+ return s.substring(0, realStart) + replacement + s.substring(realStart + realLength);
354
+ }
355
+ /** PHP nl2br() */
356
+ nl2br(str, isXhtml = true) {
357
+ const br = isXhtml ? '<br />' : '<br>';
358
+ return String(str ?? '').replace(/\r\n|\n|\r/g, br + '\n');
359
+ }
360
+ /** PHP wordwrap() */
361
+ wordwrap(str, width = 75, breakStr = '\n', cutLongWords = false) {
362
+ const s = String(str ?? '');
363
+ if (!s)
364
+ return '';
365
+ const lines = [];
366
+ const words = s.split(' ');
367
+ let currentLine = '';
368
+ for (const word of words) {
369
+ if (cutLongWords && word.length > width) {
370
+ for (let i = 0; i < word.length; i += width) {
371
+ const chunk = word.substring(i, i + width);
372
+ if (currentLine.length + (currentLine ? 1 : 0) + chunk.length > width && currentLine) {
373
+ lines.push(currentLine);
374
+ currentLine = chunk;
375
+ }
376
+ else {
377
+ currentLine += (currentLine ? ' ' : '') + chunk;
378
+ }
379
+ }
380
+ }
381
+ else if (currentLine.length + 1 + word.length > width && currentLine) {
382
+ lines.push(currentLine);
383
+ currentLine = word;
384
+ }
385
+ else {
386
+ currentLine += (currentLine ? ' ' : '') + word;
387
+ }
388
+ }
389
+ if (currentLine)
390
+ lines.push(currentLine);
391
+ return lines.join(breakStr);
392
+ }
393
+ /** PHP chunk_split() */
394
+ chunk_split(body, chunklen = 76, end = '\r\n') {
395
+ const s = String(body ?? '');
396
+ let result = '';
397
+ for (let i = 0; i < s.length; i += chunklen) {
398
+ result += s.substring(i, i + chunklen) + end;
399
+ }
400
+ return result;
401
+ }
402
+ /** PHP sprintf() — basic implementation */
403
+ sprintf(format, ...args) {
404
+ let i = 0;
405
+ return format.replace(/%([+\-0 ]*)(\d+)?(?:\.(\d+))?([sdfc%bBoxXeEgG])/g, (match, flags, width, precision, type) => {
406
+ if (type === '%')
407
+ return '%';
408
+ const arg = args[i++];
409
+ let result;
410
+ switch (type) {
411
+ case 'd':
412
+ result = String(parseInt(arg, 10) || 0);
413
+ break;
414
+ case 'f':
415
+ result = (parseFloat(arg) || 0).toFixed(precision !== undefined ? parseInt(precision) : 6);
416
+ break;
417
+ case 's':
418
+ result = String(arg ?? '');
419
+ break;
420
+ case 'c':
421
+ result = String.fromCharCode(parseInt(arg, 10));
422
+ break;
423
+ case 'b':
424
+ result = (parseInt(arg, 10) >>> 0).toString(2);
425
+ break;
426
+ case 'o':
427
+ result = (parseInt(arg, 10) >>> 0).toString(8);
428
+ break;
429
+ case 'x':
430
+ result = (parseInt(arg, 10) >>> 0).toString(16);
431
+ break;
432
+ case 'X':
433
+ result = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase();
434
+ break;
435
+ case 'e':
436
+ case 'E':
437
+ result = (parseFloat(arg) || 0).toExponential(precision !== undefined ? parseInt(precision) : undefined);
438
+ if (type === 'E')
439
+ result = result.toUpperCase();
440
+ break;
441
+ default: result = String(arg ?? '');
442
+ }
443
+ const w = parseInt(width) || 0;
444
+ if (w > result.length) {
445
+ const padChar = flags.includes('0') ? '0' : ' ';
446
+ if (flags.includes('-')) {
447
+ result = result.padEnd(w, padChar);
448
+ }
449
+ else {
450
+ result = result.padStart(w, padChar);
451
+ }
452
+ }
453
+ return result;
454
+ });
455
+ }
456
+ /** PHP strtolower + first char upper — alias */
457
+ mb_strtolower(str) { return this.strtolower(str); }
458
+ mb_strtoupper(str) { return this.strtoupper(str); }
459
+ mb_strlen(str) { return this.strlen(str); }
460
+ /** PHP strpos() */
461
+ strpos(haystack, needle, offset = 0) {
462
+ const idx = String(haystack ?? '').indexOf(needle, offset);
463
+ return idx === -1 ? false : idx;
464
+ }
465
+ /** PHP strrpos() */
466
+ strrpos(haystack, needle, offset = 0) {
467
+ const idx = String(haystack ?? '').lastIndexOf(needle, offset || undefined);
468
+ return idx === -1 ? false : idx;
469
+ }
470
+ /** PHP stripos() */
471
+ stripos(haystack, needle, offset = 0) {
472
+ const idx = String(haystack ?? '').toLowerCase().indexOf(needle.toLowerCase(), offset);
473
+ return idx === -1 ? false : idx;
474
+ }
475
+ /** PHP str_getcsv() — basic */
476
+ str_getcsv(str, separator = ',', enclosure = '"', escape = '\\') {
477
+ const s = String(str ?? '');
478
+ const result = [];
479
+ let current = '';
480
+ let inQuote = false;
481
+ for (let i = 0; i < s.length; i++) {
482
+ const ch = s[i];
483
+ if (ch === escape && i + 1 < s.length && inQuote) {
484
+ current += s[++i];
485
+ }
486
+ else if (ch === enclosure) {
487
+ inQuote = !inQuote;
488
+ }
489
+ else if (ch === separator && !inQuote) {
490
+ result.push(current);
491
+ current = '';
492
+ }
493
+ else {
494
+ current += ch;
495
+ }
496
+ }
497
+ result.push(current);
498
+ return result;
499
+ }
500
+ // ─── HTML / Encoding ────────────────────────────────────────
501
+ /** PHP htmlspecialchars() */
502
+ htmlspecialchars(str, flags, encoding, doubleEncode = true) {
503
+ let s = String(str ?? '');
504
+ if (!doubleEncode) {
505
+ s = s.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#039;/g, "'");
506
+ }
507
+ s = s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
508
+ return s;
509
+ }
510
+ /** PHP htmlspecialchars_decode() */
511
+ htmlspecialchars_decode(str) {
512
+ return String(str ?? '')
513
+ .replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
514
+ .replace(/&quot;/g, '"').replace(/&#039;/g, "'");
515
+ }
516
+ /** Escape HTML — alias for htmlspecialchars */
517
+ escapeHtml(str) {
518
+ return this.htmlspecialchars(str);
519
+ }
520
+ /** escString — safe output escaping for template echo */
521
+ escString(value) {
522
+ if (value == null)
523
+ return '';
524
+ return this.htmlspecialchars(String(value));
525
+ }
526
+ /** PHP strip_tags() — basic implementation */
527
+ strip_tags(str, allowedTags) {
528
+ let s = String(str ?? '');
529
+ if (!allowedTags)
530
+ return s.replace(/<\/?[^>]+(>|$)/g, '');
531
+ const allowed = (allowedTags.match(/<[a-z][a-z0-9]*>/gi) || []).map(t => t.replace(/[<>]/g, '').toLowerCase());
532
+ return s.replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, (match, tag) => {
533
+ return allowed.includes(tag.toLowerCase()) ? match : '';
534
+ });
535
+ }
536
+ /** PHP addslashes() */
537
+ addslashes(str) {
538
+ return String(str ?? '').replace(/[\\"']/g, '\\$&').replace(/\0/g, '\\0');
539
+ }
540
+ /** PHP stripslashes() */
541
+ stripslashes(str) {
542
+ return String(str ?? '').replace(/\\(.)/g, '$1');
543
+ }
544
+ /** PHP urlencode() */
545
+ urlencode(str) {
546
+ return encodeURIComponent(String(str ?? '')).replace(/%20/g, '+');
547
+ }
548
+ /** PHP urldecode() */
549
+ urldecode(str) {
550
+ return decodeURIComponent(String(str ?? '').replace(/\+/g, '%20'));
551
+ }
552
+ /** PHP rawurlencode() */
553
+ rawurlencode(str) {
554
+ return encodeURIComponent(String(str ?? ''));
555
+ }
556
+ /** PHP rawurldecode() */
557
+ rawurldecode(str) {
558
+ return decodeURIComponent(String(str ?? ''));
559
+ }
560
+ /** PHP base64_encode() */
561
+ base64_encode(str) {
562
+ try {
563
+ return btoa(unescape(encodeURIComponent(String(str ?? ''))));
564
+ }
565
+ catch {
566
+ return btoa(String(str ?? ''));
567
+ }
568
+ }
569
+ /** PHP base64_decode() */
570
+ base64_decode(str) {
571
+ try {
572
+ return decodeURIComponent(escape(atob(String(str ?? ''))));
573
+ }
574
+ catch {
575
+ return atob(String(str ?? ''));
576
+ }
577
+ }
578
+ /** PHP md5() — simple hash (not cryptographic, for display only) */
579
+ md5(str) {
580
+ return this._simpleHash(String(str ?? ''), 32);
581
+ }
582
+ /** PHP sha1() — simple hash (not cryptographic, for display only) */
583
+ sha1(str) {
584
+ return this._simpleHash(String(str ?? ''), 40);
585
+ }
586
+ /** PHP crc32() — basic CRC32 */
587
+ crc32(str) {
588
+ const s = String(str ?? '');
589
+ let crc = 0xFFFFFFFF;
590
+ for (let i = 0; i < s.length; i++) {
591
+ crc ^= s.charCodeAt(i);
592
+ for (let j = 0; j < 8; j++) {
593
+ crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0);
594
+ }
595
+ }
596
+ return (crc ^ 0xFFFFFFFF) | 0;
597
+ }
598
+ /** Simple string hash for md5/sha1 approximation */
599
+ _simpleHash(str, len) {
600
+ let hash = 0;
601
+ for (let i = 0; i < str.length; i++) {
602
+ const char = str.charCodeAt(i);
603
+ hash = ((hash << 5) - hash) + char;
604
+ hash |= 0;
605
+ }
606
+ const hex = Math.abs(hash).toString(16);
607
+ return hex.padStart(len, '0').slice(0, len);
608
+ }
609
+ // ─── Array Functions ────────────────────────────────────────
610
+ /** PHP array_push() */
611
+ array_push(arr, ...items) {
612
+ if (!Array.isArray(arr))
613
+ return 0;
614
+ return arr.push(...items);
615
+ }
616
+ /** PHP array_pop() */
617
+ array_pop(arr) {
618
+ if (!Array.isArray(arr) || arr.length === 0)
619
+ return null;
620
+ return arr.pop();
621
+ }
622
+ /** PHP array_shift() */
623
+ array_shift(arr) {
624
+ if (!Array.isArray(arr) || arr.length === 0)
625
+ return null;
626
+ return arr.shift();
627
+ }
628
+ /** PHP array_unshift() */
629
+ array_unshift(arr, ...items) {
630
+ if (!Array.isArray(arr))
631
+ return 0;
632
+ return arr.unshift(...items);
633
+ }
634
+ /** PHP array_merge() */
635
+ array_merge(...arrays) {
636
+ // If all arrays → merge into flat array
637
+ if (arrays.every(a => Array.isArray(a))) {
638
+ return [].concat(...arrays);
639
+ }
640
+ // If objects → merge like PHP assoc arrays
641
+ const result = {};
642
+ for (const arr of arrays) {
643
+ if (Array.isArray(arr)) {
644
+ arr.forEach((v, i) => { result[Object.keys(result).length] = v; });
645
+ }
646
+ else if (arr && typeof arr === 'object') {
647
+ Object.assign(result, arr);
648
+ }
649
+ }
650
+ return result;
651
+ }
652
+ /** PHP array_keys() */
653
+ array_keys(arr) {
654
+ if (Array.isArray(arr))
655
+ return arr.map((_, i) => i);
656
+ if (arr && typeof arr === 'object')
657
+ return Object.keys(arr);
658
+ return [];
659
+ }
660
+ /** PHP array_values() */
661
+ array_values(arr) {
662
+ if (Array.isArray(arr))
663
+ return [...arr];
664
+ if (arr && typeof arr === 'object')
665
+ return Object.values(arr);
666
+ return [];
667
+ }
668
+ /** PHP array_reverse() */
669
+ array_reverse(arr, preserveKeys = false) {
670
+ if (!Array.isArray(arr))
671
+ return [];
672
+ return [...arr].reverse();
673
+ }
674
+ /** PHP array_unique() */
675
+ array_unique(arr) {
676
+ if (!Array.isArray(arr))
677
+ return [];
678
+ return [...new Set(arr)];
679
+ }
680
+ /** PHP array_slice() */
681
+ array_slice(arr, offset, length, preserveKeys = false) {
682
+ if (!Array.isArray(arr))
683
+ return [];
684
+ const start = offset < 0 ? Math.max(0, arr.length + offset) : offset;
685
+ if (length === undefined)
686
+ return arr.slice(start);
687
+ if (length < 0)
688
+ return arr.slice(start, arr.length + length);
689
+ return arr.slice(start, start + length);
690
+ }
691
+ /** PHP array_splice() */
692
+ array_splice(arr, offset, length, ...replacement) {
693
+ if (!Array.isArray(arr))
694
+ return [];
695
+ if (length === undefined)
696
+ return arr.splice(offset);
697
+ return arr.splice(offset, length, ...replacement);
698
+ }
699
+ /** PHP array_map() */
700
+ array_map(callback, arr, ...arrays) {
701
+ if (!arr)
702
+ return [];
703
+ if (Array.isArray(arr)) {
704
+ if (callback === null) {
705
+ // PHP: array_map(null, a, b) → zip arrays
706
+ if (arrays.length === 0)
707
+ return [...arr];
708
+ return arr.map((v, i) => [v, ...arrays.map(a => a?.[i] ?? null)]);
709
+ }
710
+ return arr.map((v, i) => callback(v, i));
711
+ }
712
+ if (typeof arr === 'object') {
713
+ return Object.entries(arr).map(([k, v]) => callback ? callback(v, k) : v);
714
+ }
715
+ return [];
716
+ }
717
+ /** PHP array_filter() */
718
+ array_filter(arr, callback) {
719
+ if (!arr)
720
+ return [];
721
+ if (Array.isArray(arr)) {
722
+ return callback ? arr.filter(callback) : arr.filter(Boolean);
723
+ }
724
+ if (typeof arr === 'object') {
725
+ const entries = Object.entries(arr);
726
+ const filtered = callback ? entries.filter(([k, v]) => callback(v, k)) : entries.filter(([_, v]) => Boolean(v));
727
+ return filtered.map(([_, v]) => v);
728
+ }
729
+ return [];
730
+ }
731
+ /** PHP array_reduce() */
732
+ array_reduce(arr, callback, initial = null) {
733
+ if (!Array.isArray(arr))
734
+ return initial;
735
+ return arr.reduce(callback, initial);
736
+ }
737
+ /** PHP array_find() (PHP 8.4) */
738
+ array_find(arr, callback) {
739
+ if (!Array.isArray(arr))
740
+ return null;
741
+ return arr.find(callback) ?? null;
742
+ }
743
+ /** PHP array_find_key() (PHP 8.4) */
744
+ array_find_key(arr, callback) {
745
+ if (!Array.isArray(arr))
746
+ return null;
747
+ const idx = arr.findIndex(callback);
748
+ return idx === -1 ? null : idx;
749
+ }
750
+ /** PHP array_column() */
751
+ array_column(arr, columnKey, indexKey) {
752
+ if (!Array.isArray(arr))
753
+ return [];
754
+ if (indexKey !== undefined) {
755
+ const result = {};
756
+ for (const item of arr) {
757
+ if (item && typeof item === 'object') {
758
+ const key = String(item[indexKey] ?? '');
759
+ result[key] = columnKey !== null ? item[columnKey] : item;
760
+ }
761
+ }
762
+ return result;
763
+ }
764
+ return arr.map(item => item && typeof item === 'object' ? item[columnKey] : null);
765
+ }
766
+ /** PHP array_combine() */
767
+ array_combine(keys, values) {
768
+ const result = {};
769
+ if (!Array.isArray(keys) || !Array.isArray(values))
770
+ return result;
771
+ for (let i = 0; i < keys.length; i++) {
772
+ result[String(keys[i])] = values[i] ?? null;
773
+ }
774
+ return result;
775
+ }
776
+ /** PHP array_chunk() */
777
+ array_chunk(arr, size, preserveKeys = false) {
778
+ if (!Array.isArray(arr) || size < 1)
779
+ return [];
780
+ const result = [];
781
+ for (let i = 0; i < arr.length; i += size) {
782
+ result.push(arr.slice(i, i + size));
783
+ }
784
+ return result;
785
+ }
786
+ /** PHP array_pad() */
787
+ array_pad(arr, size, value) {
788
+ if (!Array.isArray(arr))
789
+ return [];
790
+ const result = [...arr];
791
+ const absSize = Math.abs(size);
792
+ if (result.length >= absSize)
793
+ return result;
794
+ const padCount = absSize - result.length;
795
+ const padding = Array(padCount).fill(value);
796
+ return size > 0 ? result.concat(padding) : padding.concat(result);
797
+ }
798
+ /** PHP array_flip() */
799
+ array_flip(arr) {
800
+ const result = {};
801
+ if (Array.isArray(arr)) {
802
+ arr.forEach((v, i) => { result[String(v)] = i; });
803
+ }
804
+ else if (arr && typeof arr === 'object') {
805
+ Object.entries(arr).forEach(([k, v]) => { result[String(v)] = k; });
806
+ }
807
+ return result;
808
+ }
809
+ /** PHP array_sum() */
810
+ array_sum(arr) {
811
+ if (!Array.isArray(arr))
812
+ return 0;
813
+ return arr.reduce((sum, v) => sum + (Number(v) || 0), 0);
814
+ }
815
+ /** PHP array_product() */
816
+ array_product(arr) {
817
+ if (!Array.isArray(arr) || arr.length === 0)
818
+ return 0;
819
+ return arr.reduce((product, v) => product * (Number(v) || 0), 1);
820
+ }
821
+ /** PHP array_count_values() */
822
+ array_count_values(arr) {
823
+ const result = {};
824
+ if (!Array.isArray(arr))
825
+ return result;
826
+ for (const v of arr) {
827
+ const key = String(v);
828
+ result[key] = (result[key] || 0) + 1;
829
+ }
830
+ return result;
831
+ }
832
+ /** PHP array_fill() */
833
+ array_fill(startIndex, num, value) {
834
+ return Array(num).fill(value);
835
+ }
836
+ /** PHP array_fill_keys() */
837
+ array_fill_keys(keys, value) {
838
+ const result = {};
839
+ for (const k of keys)
840
+ result[String(k)] = value;
841
+ return result;
842
+ }
843
+ /** PHP array_intersect() */
844
+ array_intersect(arr, ...arrays) {
845
+ if (!Array.isArray(arr))
846
+ return [];
847
+ return arr.filter(v => arrays.every(a => a.includes(v)));
848
+ }
849
+ /** PHP array_diff() */
850
+ array_diff(arr, ...arrays) {
851
+ if (!Array.isArray(arr))
852
+ return [];
853
+ const others = new Set([].concat(...arrays));
854
+ return arr.filter(v => !others.has(v));
855
+ }
856
+ /** PHP array_intersect_key() */
857
+ array_intersect_key(obj, ...objects) {
858
+ const result = {};
859
+ const keySets = objects.map(o => new Set(Object.keys(o)));
860
+ for (const [k, v] of Object.entries(obj)) {
861
+ if (keySets.every(s => s.has(k)))
862
+ result[k] = v;
863
+ }
864
+ return result;
865
+ }
866
+ /** PHP array_diff_key() */
867
+ array_diff_key(obj, ...objects) {
868
+ const result = {};
869
+ const keySets = objects.map(o => new Set(Object.keys(o)));
870
+ for (const [k, v] of Object.entries(obj)) {
871
+ if (!keySets.some(s => s.has(k)))
872
+ result[k] = v;
873
+ }
874
+ return result;
875
+ }
876
+ /** PHP array_search() */
877
+ array_search(needle, haystack, strict = false) {
878
+ if (Array.isArray(haystack)) {
879
+ const idx = strict
880
+ ? haystack.findIndex(v => v === needle)
881
+ : haystack.findIndex(v => v == needle);
882
+ return idx === -1 ? false : idx;
883
+ }
884
+ return false;
885
+ }
886
+ /** PHP in_array() */
887
+ in_array(needle, haystack, strict = false) {
888
+ if (!Array.isArray(haystack))
889
+ return false;
890
+ return strict ? haystack.some(v => v === needle) : haystack.some(v => v == needle);
891
+ }
892
+ /** PHP array_key_exists() */
893
+ array_key_exists(key, arr) {
894
+ if (Array.isArray(arr))
895
+ return typeof key === 'number' && key >= 0 && key < arr.length;
896
+ if (arr && typeof arr === 'object')
897
+ return key in arr;
898
+ return false;
899
+ }
900
+ /** PHP sort() — sort array in-place ascending */
901
+ sort(arr) {
902
+ if (!Array.isArray(arr))
903
+ return false;
904
+ arr.sort((a, b) => {
905
+ if (typeof a === 'string' && typeof b === 'string')
906
+ return a.localeCompare(b);
907
+ return (a > b ? 1 : a < b ? -1 : 0);
908
+ });
909
+ return true;
910
+ }
911
+ /** PHP rsort() — sort array in-place descending */
912
+ rsort(arr) {
913
+ if (!Array.isArray(arr))
914
+ return false;
915
+ arr.sort((a, b) => {
916
+ if (typeof a === 'string' && typeof b === 'string')
917
+ return b.localeCompare(a);
918
+ return (b > a ? 1 : b < a ? -1 : 0);
919
+ });
920
+ return true;
921
+ }
922
+ /** PHP ksort() — sort object by keys ascending */
923
+ ksort(obj) {
924
+ const sorted = {};
925
+ Object.keys(obj).sort().forEach(k => { sorted[k] = obj[k]; });
926
+ return sorted;
927
+ }
928
+ /** PHP krsort() — sort object by keys descending */
929
+ krsort(obj) {
930
+ const sorted = {};
931
+ Object.keys(obj).sort().reverse().forEach(k => { sorted[k] = obj[k]; });
932
+ return sorted;
933
+ }
934
+ /** PHP usort() — sort using user comparison function */
935
+ usort(arr, compareFunc) {
936
+ if (!Array.isArray(arr))
937
+ return false;
938
+ arr.sort(compareFunc);
939
+ return true;
940
+ }
941
+ /** PHP uasort() — same as usort for JS arrays */
942
+ uasort(arr, compareFunc) {
943
+ return this.usort(arr, compareFunc);
944
+ }
945
+ /** PHP uksort() — sort object by keys using comparison function */
946
+ uksort(obj, compareFunc) {
947
+ const sorted = {};
948
+ Object.keys(obj).sort(compareFunc).forEach(k => { sorted[k] = obj[k]; });
949
+ return sorted;
950
+ }
951
+ /** PHP range() */
952
+ range(start, end, step = 1) {
953
+ if (typeof start === 'string' && typeof end === 'string' && start.length === 1 && end.length === 1) {
954
+ const result = [];
955
+ const s = start.charCodeAt(0), e = end.charCodeAt(0);
956
+ const dir = s <= e ? 1 : -1;
957
+ const actualStep = Math.max(1, Math.abs(step)) * dir;
958
+ for (let i = s; dir > 0 ? i <= e : i >= e; i += actualStep) {
959
+ result.push(String.fromCharCode(i));
960
+ }
961
+ return result;
962
+ }
963
+ const s = Number(start), e = Number(end);
964
+ const result = [];
965
+ step = Math.abs(step) || 1;
966
+ if (s <= e) {
967
+ for (let i = s; i <= e; i += step)
968
+ result.push(i);
969
+ }
970
+ else {
971
+ for (let i = s; i >= e; i -= step)
972
+ result.push(i);
973
+ }
974
+ return result;
975
+ }
976
+ /** PHP compact() — create object from variable names */
977
+ compact(...names) {
978
+ // Note: In browser context, this won't work like PHP's compact().
979
+ // Compiler should transform this to an object literal.
980
+ console.warn('[Helper] compact() requires compiler transformation. Use object literal instead.');
981
+ const result = {};
982
+ for (const name of names)
983
+ result[name] = undefined;
984
+ return result;
985
+ }
986
+ /** PHP head() — first element */
987
+ head(arr) {
988
+ if (!Array.isArray(arr))
989
+ return null;
990
+ return arr[0] ?? null;
991
+ }
992
+ /** PHP last() — last element */
993
+ last(arr) {
994
+ if (!Array.isArray(arr) || arr.length === 0)
995
+ return null;
996
+ return arr[arr.length - 1];
997
+ }
998
+ // ─── Math Functions ─────────────────────────────────────────
999
+ /** PHP min() */
1000
+ min(...values) {
1001
+ const flat = values.length === 1 && Array.isArray(values[0]) ? values[0] : values;
1002
+ return Math.min(...flat.map(Number));
1003
+ }
1004
+ /** PHP max() */
1005
+ max(...values) {
1006
+ const flat = values.length === 1 && Array.isArray(values[0]) ? values[0] : values;
1007
+ return Math.max(...flat.map(Number));
1008
+ }
1009
+ /** PHP abs() */
1010
+ abs(n) { return Math.abs(n); }
1011
+ /** PHP ceil() */
1012
+ ceil(n) { return Math.ceil(n); }
1013
+ /** PHP floor() */
1014
+ floor(n) { return Math.floor(n); }
1015
+ /** PHP round() */
1016
+ round(n, precision = 0) {
1017
+ if (precision === 0)
1018
+ return Math.round(n);
1019
+ const factor = Math.pow(10, precision);
1020
+ return Math.round(n * factor) / factor;
1021
+ }
1022
+ /** PHP sqrt() */
1023
+ sqrt(n) { return Math.sqrt(n); }
1024
+ /** PHP pow() */
1025
+ pow(base, exp) { return Math.pow(base, exp); }
1026
+ /** PHP log() */
1027
+ log(n, base) {
1028
+ if (base !== undefined)
1029
+ return Math.log(n) / Math.log(base);
1030
+ return Math.log(n);
1031
+ }
1032
+ /** PHP log10() */
1033
+ log10(n) { return Math.log10(n); }
1034
+ /** PHP exp() */
1035
+ exp(n) { return Math.exp(n); }
1036
+ /** PHP fmod() */
1037
+ fmod(x, y) { return x % y; }
1038
+ /** PHP intdiv() */
1039
+ intdiv(a, b) { return Math.trunc(a / b); }
1040
+ /** PHP pi() */
1041
+ pi() { return Math.PI; }
1042
+ /** PHP rand() / mt_rand() */
1043
+ rand(min, max) {
1044
+ if (min === undefined && max === undefined)
1045
+ return Math.floor(Math.random() * 2147483647);
1046
+ min = min ?? 0;
1047
+ max = max ?? 2147483647;
1048
+ return Math.floor(Math.random() * (max - min + 1)) + min;
1049
+ }
1050
+ /** PHP mt_rand() — alias for rand */
1051
+ mt_rand(min, max) { return this.rand(min, max); }
1052
+ /** PHP array_rand() */
1053
+ array_rand(arr, num = 1) {
1054
+ if (!Array.isArray(arr) || arr.length === 0)
1055
+ return num === 1 ? 0 : [];
1056
+ const indices = arr.map((_, i) => i);
1057
+ // Fisher-Yates shuffle
1058
+ for (let i = indices.length - 1; i > 0; i--) {
1059
+ const j = Math.floor(Math.random() * (i + 1));
1060
+ [indices[i], indices[j]] = [indices[j], indices[i]];
1061
+ }
1062
+ const selected = indices.slice(0, num);
1063
+ return num === 1 ? selected[0] : selected.sort((a, b) => a - b);
1064
+ }
1065
+ // ─── JSON ───────────────────────────────────────────────────
1066
+ /** PHP json_encode() */
1067
+ json_encode(value, options) {
1068
+ try {
1069
+ // options: JSON_PRETTY_PRINT = 128
1070
+ if (options && (options & 128)) {
1071
+ return JSON.stringify(value, null, 4);
1072
+ }
1073
+ return JSON.stringify(value);
1074
+ }
1075
+ catch {
1076
+ return 'null';
1077
+ }
1078
+ }
1079
+ /** PHP json_decode() */
1080
+ json_decode(json, assoc = true) {
1081
+ try {
1082
+ return JSON.parse(String(json ?? ''));
1083
+ }
1084
+ catch {
1085
+ return null;
1086
+ }
1087
+ }
1088
+ // ─── Number Formatting ──────────────────────────────────────
1089
+ /** PHP number_format() */
1090
+ number_format(number, decimals = 0, decimalSeparator = '.', thousandsSeparator = ',') {
1091
+ const num = typeof number === 'string' ? parseFloat(number) : number;
1092
+ if (typeof num !== 'number' || isNaN(num))
1093
+ return '0';
1094
+ const parts = num.toFixed(decimals).split('.');
1095
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
1096
+ return decimals > 0 ? parts.join(decimalSeparator) : parts[0];
1097
+ }
1098
+ /** Format number with options */
1099
+ formatNumber(num, options = {}) {
1100
+ const { decimals = 2, thousandsSeparator = ',', decimalSeparator = '.', prefix = '', suffix = '' } = options;
1101
+ return prefix + this.number_format(num, decimals, decimalSeparator, thousandsSeparator) + suffix;
1102
+ }
1103
+ /** Format as currency */
1104
+ formatCurrency(amount, currency = 'USD', locale = 'en-US') {
1105
+ try {
1106
+ return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);
1107
+ }
1108
+ catch {
1109
+ return `${currency} ${this.number_format(amount, 2)}`;
1110
+ }
1111
+ }
1112
+ // ─── Date / Time ────────────────────────────────────────────
1113
+ /** PHP now() — Carbon-like: returns current Date */
1114
+ now() {
1115
+ return new Date();
1116
+ }
1117
+ /** PHP today() — returns today at midnight */
1118
+ today() {
1119
+ const d = new Date();
1120
+ d.setHours(0, 0, 0, 0);
1121
+ return d;
1122
+ }
1123
+ /** PHP date() */
1124
+ date(format, timestamp) {
1125
+ const d = timestamp ? new Date(timestamp * 1000) : new Date();
1126
+ return this._formatDatePHP(d, format);
1127
+ }
1128
+ /** PHP time() — Unix timestamp in seconds */
1129
+ time() {
1130
+ return Math.floor(Date.now() / 1000);
1131
+ }
1132
+ /** PHP strtotime() — parse date string to Unix timestamp */
1133
+ strtotime(dateStr, baseTimestamp) {
1134
+ try {
1135
+ const base = baseTimestamp ? new Date(baseTimestamp * 1000) : new Date();
1136
+ // Handle relative expressions
1137
+ const relativeMatch = dateStr.match(/^([+-]?\d+)\s+(second|minute|hour|day|week|month|year)s?$/i);
1138
+ if (relativeMatch) {
1139
+ const amount = parseInt(relativeMatch[1]);
1140
+ const unit = relativeMatch[2].toLowerCase();
1141
+ const d = new Date(base);
1142
+ switch (unit) {
1143
+ case 'second':
1144
+ d.setSeconds(d.getSeconds() + amount);
1145
+ break;
1146
+ case 'minute':
1147
+ d.setMinutes(d.getMinutes() + amount);
1148
+ break;
1149
+ case 'hour':
1150
+ d.setHours(d.getHours() + amount);
1151
+ break;
1152
+ case 'day':
1153
+ d.setDate(d.getDate() + amount);
1154
+ break;
1155
+ case 'week':
1156
+ d.setDate(d.getDate() + amount * 7);
1157
+ break;
1158
+ case 'month':
1159
+ d.setMonth(d.getMonth() + amount);
1160
+ break;
1161
+ case 'year':
1162
+ d.setFullYear(d.getFullYear() + amount);
1163
+ break;
1164
+ }
1165
+ return Math.floor(d.getTime() / 1000);
1166
+ }
1167
+ // Handle "next/last" expressions
1168
+ const nextLastMatch = dateStr.match(/^(next|last)\s+(monday|tuesday|wednesday|thursday|friday|saturday|sunday)$/i);
1169
+ if (nextLastMatch) {
1170
+ const direction = nextLastMatch[1].toLowerCase() === 'next' ? 1 : -1;
1171
+ const days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
1172
+ const targetDay = days.indexOf(nextLastMatch[2].toLowerCase());
1173
+ const d = new Date(base);
1174
+ const currentDay = d.getDay();
1175
+ let diff = targetDay - currentDay;
1176
+ if (direction === 1) {
1177
+ if (diff <= 0)
1178
+ diff += 7;
1179
+ }
1180
+ else {
1181
+ if (diff >= 0)
1182
+ diff -= 7;
1183
+ }
1184
+ d.setDate(d.getDate() + diff);
1185
+ return Math.floor(d.getTime() / 1000);
1186
+ }
1187
+ // Handle special strings
1188
+ if (dateStr.toLowerCase() === 'now')
1189
+ return Math.floor(base.getTime() / 1000);
1190
+ if (dateStr.toLowerCase() === 'today') {
1191
+ base.setHours(0, 0, 0, 0);
1192
+ return Math.floor(base.getTime() / 1000);
1193
+ }
1194
+ if (dateStr.toLowerCase() === 'tomorrow') {
1195
+ base.setDate(base.getDate() + 1);
1196
+ base.setHours(0, 0, 0, 0);
1197
+ return Math.floor(base.getTime() / 1000);
1198
+ }
1199
+ if (dateStr.toLowerCase() === 'yesterday') {
1200
+ base.setDate(base.getDate() - 1);
1201
+ base.setHours(0, 0, 0, 0);
1202
+ return Math.floor(base.getTime() / 1000);
1203
+ }
1204
+ // Fall back to Date.parse
1205
+ const parsed = new Date(dateStr);
1206
+ if (isNaN(parsed.getTime()))
1207
+ return false;
1208
+ return Math.floor(parsed.getTime() / 1000);
1209
+ }
1210
+ catch {
1211
+ return false;
1212
+ }
1213
+ }
1214
+ /** PHP mktime() */
1215
+ mktime(hour = 0, minute = 0, second = 0, month, day, year) {
1216
+ const d = new Date();
1217
+ if (year !== undefined)
1218
+ d.setFullYear(year);
1219
+ if (month !== undefined)
1220
+ d.setMonth(month - 1);
1221
+ if (day !== undefined)
1222
+ d.setDate(day);
1223
+ d.setHours(hour, minute, second, 0);
1224
+ return Math.floor(d.getTime() / 1000);
1225
+ }
1226
+ /** PHP microtime() */
1227
+ microtime(asFloat = false) {
1228
+ const ms = performance.now();
1229
+ if (asFloat)
1230
+ return ms / 1000;
1231
+ const sec = Math.floor(ms / 1000);
1232
+ const frac = (ms % 1000) / 1000;
1233
+ return `${frac.toFixed(8)} ${sec}`;
1234
+ }
1235
+ /** Format date matching PHP date() format chars */
1236
+ formatDate(date, format = 'YYYY-MM-DD') {
1237
+ const d = new Date(date);
1238
+ if (isNaN(d.getTime()))
1239
+ return '';
1240
+ const tokens = {
1241
+ YYYY: String(d.getFullYear()),
1242
+ YY: String(d.getFullYear()).slice(-2),
1243
+ MM: String(d.getMonth() + 1).padStart(2, '0'),
1244
+ M: String(d.getMonth() + 1),
1245
+ DD: String(d.getDate()).padStart(2, '0'),
1246
+ D: String(d.getDate()),
1247
+ HH: String(d.getHours()).padStart(2, '0'),
1248
+ H: String(d.getHours()),
1249
+ mm: String(d.getMinutes()).padStart(2, '0'),
1250
+ m: String(d.getMinutes()),
1251
+ ss: String(d.getSeconds()).padStart(2, '0'),
1252
+ s: String(d.getSeconds()),
1253
+ };
1254
+ let result = format;
1255
+ // Replace longest tokens first
1256
+ for (const [token, value] of Object.entries(tokens).sort((a, b) => b[0].length - a[0].length)) {
1257
+ result = result.replace(new RegExp(token, 'g'), value);
1258
+ }
1259
+ return result;
1260
+ }
1261
+ /** Carbon-like: diffInDays */
1262
+ diffInDays(date1, date2) {
1263
+ const d1 = new Date(date1), d2 = date2 ? new Date(date2) : new Date();
1264
+ return Math.floor(Math.abs(d2.getTime() - d1.getTime()) / 86400000);
1265
+ }
1266
+ /** Carbon-like: diffInHours */
1267
+ diffInHours(date1, date2) {
1268
+ const d1 = new Date(date1), d2 = date2 ? new Date(date2) : new Date();
1269
+ return Math.floor(Math.abs(d2.getTime() - d1.getTime()) / 3600000);
1270
+ }
1271
+ /** Carbon-like: diffInMinutes */
1272
+ diffInMinutes(date1, date2) {
1273
+ const d1 = new Date(date1), d2 = date2 ? new Date(date2) : new Date();
1274
+ return Math.floor(Math.abs(d2.getTime() - d1.getTime()) / 60000);
1275
+ }
1276
+ /** Carbon-like: diffInSeconds */
1277
+ diffInSeconds(date1, date2) {
1278
+ const d1 = new Date(date1), d2 = date2 ? new Date(date2) : new Date();
1279
+ return Math.floor(Math.abs(d2.getTime() - d1.getTime()) / 1000);
1280
+ }
1281
+ /** Carbon-like: addDays */
1282
+ addDays(date, days) {
1283
+ const d = new Date(date);
1284
+ d.setDate(d.getDate() + days);
1285
+ return d;
1286
+ }
1287
+ /** Carbon-like: subDays */
1288
+ subDays(date, days) {
1289
+ return this.addDays(date, -days);
1290
+ }
1291
+ /** Carbon-like: addHours */
1292
+ addHours(date, hours) {
1293
+ const d = new Date(date);
1294
+ d.setHours(d.getHours() + hours);
1295
+ return d;
1296
+ }
1297
+ /** Carbon-like: subHours */
1298
+ subHours(date, hours) {
1299
+ return this.addHours(date, -hours);
1300
+ }
1301
+ /** Carbon-like: addMinutes */
1302
+ addMinutes(date, minutes) {
1303
+ const d = new Date(date);
1304
+ d.setMinutes(d.getMinutes() + minutes);
1305
+ return d;
1306
+ }
1307
+ /** Carbon-like: subMinutes */
1308
+ subMinutes(date, minutes) {
1309
+ return this.addMinutes(date, -minutes);
1310
+ }
1311
+ // ─── Misc Helpers ───────────────────────────────────────────
1312
+ /** PHP intval() */
1313
+ intval(value, base = 10) {
1314
+ return parseInt(value, base) || 0;
1315
+ }
1316
+ /** PHP floatval() */
1317
+ floatval(value) {
1318
+ return parseFloat(value) || 0;
1319
+ }
1320
+ /** PHP strval() */
1321
+ strval(value) {
1322
+ if (value == null)
1323
+ return '';
1324
+ return String(value);
1325
+ }
1326
+ /** PHP boolval() */
1327
+ boolval(value) {
1328
+ return Boolean(value);
1329
+ }
1330
+ /** PHP gettype() */
1331
+ gettype(value) {
1332
+ if (value === null)
1333
+ return 'NULL';
1334
+ if (Array.isArray(value))
1335
+ return 'array';
1336
+ const t = typeof value;
1337
+ switch (t) {
1338
+ case 'boolean': return 'boolean';
1339
+ case 'number': return Number.isInteger(value) ? 'integer' : 'double';
1340
+ case 'string': return 'string';
1341
+ case 'object': return 'object';
1342
+ case 'undefined': return 'NULL';
1343
+ default: return t;
1344
+ }
1345
+ }
1346
+ /** Laravel Str::slug() / slug helper */
1347
+ slug(str, separator = '-') {
1348
+ return String(str ?? '')
1349
+ .normalize('NFD')
1350
+ .replace(/[\u0300-\u036f]/g, '')
1351
+ .toLowerCase()
1352
+ .replace(/[^a-z0-9\s-]/g, '')
1353
+ .replace(/[\s_]+/g, separator)
1354
+ .replace(new RegExp(`[${separator}]+`, 'g'), separator)
1355
+ .replace(new RegExp(`^${separator}|${separator}$`, 'g'), '');
1356
+ }
1357
+ /** Truncate text */
1358
+ truncate(str, length = 100, suffix = '...') {
1359
+ const s = String(str ?? '');
1360
+ if (s.length <= length)
1361
+ return s;
1362
+ return s.substring(0, length - suffix.length) + suffix;
1363
+ }
1364
+ /** PHP uniqid() */
1365
+ uniqid(prefix = '', moreEntropy = false) {
1366
+ const id = Date.now().toString(16) + Math.random().toString(16).slice(2, 10);
1367
+ return prefix + id + (moreEntropy ? '.' + Math.random().toString(36).slice(2, 10) : '');
1368
+ }
1369
+ /** PHP collect() — Laravel Collection-like (simple wrapper) */
1370
+ collect(items) {
1371
+ return new CollectionProxy(items ?? []);
1372
+ }
1373
+ /** PHP dd() — dump and die (in browser: console.log + throw) */
1374
+ dd(...args) {
1375
+ console.log('[dd]', ...args);
1376
+ throw new Error('[dd] Dump and die');
1377
+ }
1378
+ /** PHP dump() — console.log */
1379
+ dump(...args) {
1380
+ console.log('[dump]', ...args);
1381
+ }
1382
+ /** PHP var_dump() */
1383
+ var_dump(...args) {
1384
+ for (const arg of args) {
1385
+ console.log(`${this.gettype(arg)}(${JSON.stringify(arg)})`);
1386
+ }
1387
+ }
1388
+ /** PHP print_r() */
1389
+ print_r(value, returnOutput = false) {
1390
+ const output = typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value);
1391
+ if (returnOutput)
1392
+ return output;
1393
+ console.log(output);
1394
+ }
1395
+ /** PHP class_exists() */
1396
+ class_exists(name) {
1397
+ try {
1398
+ return typeof globalThis[name] === 'function';
1399
+ }
1400
+ catch {
1401
+ return false;
1402
+ }
1403
+ }
1404
+ /** PHP function_exists() */
1405
+ function_exists(name) {
1406
+ try {
1407
+ return typeof globalThis[name] === 'function';
1408
+ }
1409
+ catch {
1410
+ return false;
1411
+ }
1412
+ }
1413
+ /** URL helper — build URL with base */
1414
+ url(path = '') {
1415
+ const baseUrl = this.config.base_url || '';
1416
+ if (!path)
1417
+ return baseUrl;
1418
+ return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
1419
+ }
1420
+ /** PHP asset() — generate asset URL */
1421
+ asset(path) {
1422
+ const baseUrl = this.config.asset_url || this.config.base_url || '';
1423
+ return `${baseUrl}/${path.replace(/^\//, '')}`;
1424
+ }
1425
+ /** Deep clone */
1426
+ deepClone(obj) {
1427
+ if (typeof structuredClone === 'function')
1428
+ return structuredClone(obj);
1429
+ if (obj === null || typeof obj !== 'object')
1430
+ return obj;
1431
+ try {
1432
+ return JSON.parse(JSON.stringify(obj));
1433
+ }
1434
+ catch {
1435
+ return obj;
1436
+ }
1437
+ }
1438
+ /** Get nested value by dot path */
1439
+ data_get(obj, path, defaultValue) {
1440
+ const keys = path.split('.');
1441
+ let result = obj;
1442
+ for (const key of keys) {
1443
+ if (result == null)
1444
+ return defaultValue;
1445
+ result = result[key];
1446
+ }
1447
+ return result !== undefined ? result : defaultValue;
1448
+ }
1449
+ /** Set nested value by dot path */
1450
+ data_set(obj, path, value) {
1451
+ const keys = path.split('.');
1452
+ const lastKey = keys.pop();
1453
+ let current = obj;
1454
+ for (const key of keys) {
1455
+ if (!(key in current))
1456
+ current[key] = {};
1457
+ current = current[key];
1458
+ }
1459
+ current[lastKey] = value;
1460
+ }
1461
+ /** PHP old() — get old form input (stub for client-side) */
1462
+ old(key, defaultValue = '') {
1463
+ return defaultValue;
1464
+ }
1465
+ // ─── Internal Date Formatting (PHP date() format) ───────────
1466
+ _formatDatePHP(d, format) {
1467
+ const pad = (n, w = 2) => String(n).padStart(w, '0');
1468
+ const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
1469
+ const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
1470
+ const tokens = {
1471
+ // Day
1472
+ d: () => pad(d.getDate()),
1473
+ D: () => days[d.getDay()].slice(0, 3),
1474
+ j: () => String(d.getDate()),
1475
+ l: () => days[d.getDay()],
1476
+ N: () => String(d.getDay() || 7),
1477
+ w: () => String(d.getDay()),
1478
+ // Month
1479
+ F: () => months[d.getMonth()],
1480
+ m: () => pad(d.getMonth() + 1),
1481
+ M: () => months[d.getMonth()].slice(0, 3),
1482
+ n: () => String(d.getMonth() + 1),
1483
+ t: () => String(new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate()),
1484
+ // Year
1485
+ Y: () => String(d.getFullYear()),
1486
+ y: () => String(d.getFullYear()).slice(-2),
1487
+ L: () => String(d.getFullYear() % 4 === 0 && (d.getFullYear() % 100 !== 0 || d.getFullYear() % 400 === 0) ? 1 : 0),
1488
+ // Time
1489
+ A: () => d.getHours() < 12 ? 'AM' : 'PM',
1490
+ a: () => d.getHours() < 12 ? 'am' : 'pm',
1491
+ g: () => String(d.getHours() % 12 || 12),
1492
+ G: () => String(d.getHours()),
1493
+ h: () => pad(d.getHours() % 12 || 12),
1494
+ H: () => pad(d.getHours()),
1495
+ i: () => pad(d.getMinutes()),
1496
+ s: () => pad(d.getSeconds()),
1497
+ u: () => pad(d.getMilliseconds() * 1000, 6),
1498
+ // Timezone
1499
+ U: () => String(Math.floor(d.getTime() / 1000)),
1500
+ };
1501
+ let result = '';
1502
+ let escaped = false;
1503
+ for (let i = 0; i < format.length; i++) {
1504
+ const ch = format[i];
1505
+ if (ch === '\\') {
1506
+ escaped = true;
1507
+ continue;
1508
+ }
1509
+ if (escaped) {
1510
+ result += ch;
1511
+ escaped = false;
1512
+ continue;
1513
+ }
1514
+ result += tokens[ch] ? tokens[ch]() : ch;
1515
+ }
1516
+ return result;
1517
+ }
1518
+ }
1519
+ // ─── Collection Proxy (Laravel Collection subset) ───────────
1520
+ /**
1521
+ * Lightweight Collection — wraps an array with chainable PHP/Laravel methods.
1522
+ */
1523
+ export class CollectionProxy {
1524
+ constructor(items) {
1525
+ this.items = Array.isArray(items) ? items : Object.values(items ?? {});
1526
+ }
1527
+ all() { return this.items; }
1528
+ toArray() { return [...this.items]; }
1529
+ count() { return this.items.length; }
1530
+ isEmpty() { return this.items.length === 0; }
1531
+ isNotEmpty() { return this.items.length > 0; }
1532
+ first(cb) { return cb ? this.items.find(cb) ?? null : this.items[0] ?? null; }
1533
+ last(cb) {
1534
+ if (cb) {
1535
+ for (let i = this.items.length - 1; i >= 0; i--)
1536
+ if (cb(this.items[i]))
1537
+ return this.items[i];
1538
+ return null;
1539
+ }
1540
+ return this.items[this.items.length - 1] ?? null;
1541
+ }
1542
+ get(index, defaultValue) { return this.items[index] ?? defaultValue ?? null; }
1543
+ map(cb) { return new CollectionProxy(this.items.map(cb)); }
1544
+ filter(cb) { return new CollectionProxy(cb ? this.items.filter(cb) : this.items.filter(Boolean)); }
1545
+ reject(cb) { return new CollectionProxy(this.items.filter(v => !cb(v))); }
1546
+ reduce(cb, initial) { return this.items.reduce(cb, initial); }
1547
+ each(cb) { this.items.forEach(cb); return this; }
1548
+ pluck(key) { return new CollectionProxy(this.items.map(item => item?.[key])); }
1549
+ where(key, value) { return new CollectionProxy(this.items.filter(item => item?.[key] === value)); }
1550
+ whereIn(key, values) { return new CollectionProxy(this.items.filter(item => values.includes(item?.[key]))); }
1551
+ whereNotIn(key, values) { return new CollectionProxy(this.items.filter(item => !values.includes(item?.[key]))); }
1552
+ sortBy(key) {
1553
+ const sorted = [...this.items].sort((a, b) => {
1554
+ const va = typeof key === 'function' ? key(a) : a?.[key];
1555
+ const vb = typeof key === 'function' ? key(b) : b?.[key];
1556
+ return va > vb ? 1 : va < vb ? -1 : 0;
1557
+ });
1558
+ return new CollectionProxy(sorted);
1559
+ }
1560
+ sortByDesc(key) {
1561
+ const sorted = [...this.items].sort((a, b) => {
1562
+ const va = typeof key === 'function' ? key(a) : a?.[key];
1563
+ const vb = typeof key === 'function' ? key(b) : b?.[key];
1564
+ return vb > va ? 1 : vb < va ? -1 : 0;
1565
+ });
1566
+ return new CollectionProxy(sorted);
1567
+ }
1568
+ reverse() { return new CollectionProxy([...this.items].reverse()); }
1569
+ unique(key) {
1570
+ if (!key)
1571
+ return new CollectionProxy([...new Set(this.items)]);
1572
+ const seen = new Set();
1573
+ return new CollectionProxy(this.items.filter(item => { const v = item?.[key]; if (seen.has(v))
1574
+ return false; seen.add(v); return true; }));
1575
+ }
1576
+ flatten(depth = Infinity) { return new CollectionProxy(this.items.flat(depth)); }
1577
+ chunk(size) {
1578
+ const chunks = [];
1579
+ for (let i = 0; i < this.items.length; i += size)
1580
+ chunks.push(this.items.slice(i, i + size));
1581
+ return new CollectionProxy(chunks);
1582
+ }
1583
+ take(count) { return count >= 0 ? new CollectionProxy(this.items.slice(0, count)) : new CollectionProxy(this.items.slice(count)); }
1584
+ skip(count) { return new CollectionProxy(this.items.slice(count)); }
1585
+ sum(key) {
1586
+ return this.items.reduce((total, item) => {
1587
+ const val = key ? (typeof key === 'function' ? key(item) : Number(item?.[key] ?? 0)) : Number(item ?? 0);
1588
+ return total + val;
1589
+ }, 0);
1590
+ }
1591
+ avg(key) {
1592
+ if (this.items.length === 0)
1593
+ return 0;
1594
+ return this.sum(key) / this.items.length;
1595
+ }
1596
+ min(key) {
1597
+ if (this.items.length === 0)
1598
+ return null;
1599
+ return this.items.reduce((m, item) => { const v = key ? item?.[key] : item; return v < m ? v : m; }, key ? this.items[0]?.[key] : this.items[0]);
1600
+ }
1601
+ max(key) {
1602
+ if (this.items.length === 0)
1603
+ return null;
1604
+ return this.items.reduce((m, item) => { const v = key ? item?.[key] : item; return v > m ? v : m; }, key ? this.items[0]?.[key] : this.items[0]);
1605
+ }
1606
+ contains(key, value) {
1607
+ if (value !== undefined)
1608
+ return this.items.some(item => item?.[key] === value);
1609
+ if (typeof key === 'function')
1610
+ return this.items.some(key);
1611
+ return this.items.includes(key);
1612
+ }
1613
+ groupBy(key) {
1614
+ const groups = {};
1615
+ for (const item of this.items) {
1616
+ const k = typeof key === 'function' ? key(item) : String(item?.[key] ?? '');
1617
+ if (!groups[k])
1618
+ groups[k] = [];
1619
+ groups[k].push(item);
1620
+ }
1621
+ return groups;
1622
+ }
1623
+ keyBy(key) {
1624
+ const result = {};
1625
+ for (const item of this.items) {
1626
+ const k = typeof key === 'function' ? key(item) : String(item?.[key] ?? '');
1627
+ result[k] = item;
1628
+ }
1629
+ return result;
1630
+ }
1631
+ join(glue, finalGlue) {
1632
+ if (finalGlue && this.items.length > 1) {
1633
+ const allButLast = this.items.slice(0, -1).join(glue);
1634
+ return allButLast + finalGlue + this.items[this.items.length - 1];
1635
+ }
1636
+ return this.items.join(glue);
1637
+ }
1638
+ push(...items) { return new CollectionProxy([...this.items, ...items]); }
1639
+ prepend(...items) { return new CollectionProxy([...items, ...this.items]); }
1640
+ pop() { const items = [...this.items]; return items.pop(); }
1641
+ shift() { const items = [...this.items]; return items.shift(); }
1642
+ merge(other) { return new CollectionProxy([...this.items, ...other]); }
1643
+ values() { return new CollectionProxy([...this.items]); }
1644
+ keys() { return new CollectionProxy(this.items.map((_, i) => i)); }
1645
+ tap(cb) { cb(this); return this; }
1646
+ pipe(cb) { return cb(this); }
1647
+ toJSON() { return this.toArray(); }
1648
+ toString() { return JSON.stringify(this.items); }
1649
+ }
1650
+ //# sourceMappingURL=HelperService.js.map