slicejs-web-framework 2.4.8 → 3.1.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 (229) hide show
  1. package/.worktrees/bundling-v2-precompiled-registrars/LICENSE +21 -0
  2. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/ContextManager/ContextManager.js +369 -0
  3. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/ContextManager/ContextManagerDebugger.js +297 -0
  4. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Controller/Controller.js +972 -0
  5. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Debugger/Debugger.css +620 -0
  6. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Debugger/Debugger.html +73 -0
  7. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Debugger/Debugger.js +1548 -0
  8. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/EventManager/EventManager.js +338 -0
  9. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/EventManager/EventManagerDebugger.js +361 -0
  10. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Logger/Log.js +10 -0
  11. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Logger/Logger.js +146 -0
  12. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/Router/Router.js +721 -0
  13. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/StylesManager/StylesManager.js +78 -0
  14. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Components/Structural/StylesManager/ThemeManager/ThemeManager.js +84 -0
  15. package/.worktrees/bundling-v2-precompiled-registrars/Slice/Slice.js +504 -0
  16. package/.worktrees/bundling-v2-precompiled-registrars/Slice/tests/bundle-v2-runtime-contract.test.js +268 -0
  17. package/.worktrees/bundling-v2-precompiled-registrars/Slice/tests/router-loading-finally.test.js +68 -0
  18. package/.worktrees/bundling-v2-precompiled-registrars/api/index.js +286 -0
  19. package/.worktrees/bundling-v2-precompiled-registrars/api/middleware/securityMiddleware.js +253 -0
  20. package/.worktrees/bundling-v2-precompiled-registrars/package.json +37 -0
  21. package/.worktrees/bundling-v2-precompiled-registrars/sliceConfig.schema.json +109 -0
  22. package/.worktrees/bundling-v2-precompiled-registrars/src/App/index.html +22 -0
  23. package/.worktrees/bundling-v2-precompiled-registrars/src/App/index.js +23 -0
  24. package/.worktrees/bundling-v2-precompiled-registrars/src/App/style.css +40 -0
  25. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/AppComponents/HomePage/HomePage.css +201 -0
  26. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/AppComponents/HomePage/HomePage.html +37 -0
  27. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/AppComponents/HomePage/HomePage.js +210 -0
  28. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/AppComponents/Playground/Playground.css +12 -0
  29. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/AppComponents/Playground/Playground.html +0 -0
  30. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/AppComponents/Playground/Playground.js +111 -0
  31. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Service/FetchManager/FetchManager.js +133 -0
  32. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Service/IndexedDbManager/IndexedDbManager.js +141 -0
  33. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Service/LocalStorageManager/LocalStorageManager.js +45 -0
  34. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Button/Button.css +47 -0
  35. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Button/Button.html +5 -0
  36. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Button/Button.js +93 -0
  37. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Card/Card.css +68 -0
  38. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Card/Card.html +7 -0
  39. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Card/Card.js +107 -0
  40. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Checkbox/Checkbox.css +87 -0
  41. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Checkbox/Checkbox.html +8 -0
  42. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Checkbox/Checkbox.js +86 -0
  43. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/CodeVisualizer/CodeVisualizer.css +130 -0
  44. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/CodeVisualizer/CodeVisualizer.html +4 -0
  45. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/CodeVisualizer/CodeVisualizer.js +262 -0
  46. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Details/Details.css +70 -0
  47. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Details/Details.html +9 -0
  48. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Details/Details.js +76 -0
  49. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/DropDown/DropDown.css +60 -0
  50. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/DropDown/DropDown.html +5 -0
  51. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/DropDown/DropDown.js +63 -0
  52. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Grid/Grid.css +7 -0
  53. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Grid/Grid.html +1 -0
  54. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Grid/Grid.js +57 -0
  55. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/Icon.css +510 -0
  56. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/Icon.html +1 -0
  57. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/Icon.js +89 -0
  58. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.eot +0 -0
  59. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.json +555 -0
  60. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.styl +507 -0
  61. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.svg +1485 -0
  62. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.symbol.svg +1059 -0
  63. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.ttf +0 -0
  64. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.woff +0 -0
  65. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Icon/slc.woff2 +0 -0
  66. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Input/Input.css +91 -0
  67. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Input/Input.html +4 -0
  68. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Input/Input.js +215 -0
  69. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Layout/Layout.css +0 -0
  70. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Layout/Layout.html +0 -0
  71. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Layout/Layout.js +49 -0
  72. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Link/Link.css +8 -0
  73. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Link/Link.html +1 -0
  74. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Link/Link.js +63 -0
  75. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Loading/Loading.css +56 -0
  76. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Loading/Loading.html +83 -0
  77. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Loading/Loading.js +38 -0
  78. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/MultiRoute/MultiRoute.js +93 -0
  79. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Navbar/Navbar.css +115 -0
  80. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Navbar/Navbar.html +44 -0
  81. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Navbar/Navbar.js +141 -0
  82. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/NotFound/NotFound.css +117 -0
  83. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/NotFound/NotFound.html +24 -0
  84. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/NotFound/NotFound.js +16 -0
  85. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Route/Route.js +93 -0
  86. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Select/Select.css +84 -0
  87. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Select/Select.html +8 -0
  88. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Select/Select.js +195 -0
  89. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Switch/Switch.css +76 -0
  90. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Switch/Switch.html +8 -0
  91. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/Switch/Switch.js +102 -0
  92. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/TreeItem/TreeItem.css +36 -0
  93. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/TreeItem/TreeItem.html +1 -0
  94. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/TreeItem/TreeItem.js +126 -0
  95. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/TreeView/TreeView.css +8 -0
  96. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/TreeView/TreeView.html +1 -0
  97. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/Visual/TreeView/TreeView.js +48 -0
  98. package/.worktrees/bundling-v2-precompiled-registrars/src/Components/components.js +27 -0
  99. package/.worktrees/bundling-v2-precompiled-registrars/src/Styles/sliceStyles.css +34 -0
  100. package/.worktrees/bundling-v2-precompiled-registrars/src/Themes/Dark.css +42 -0
  101. package/.worktrees/bundling-v2-precompiled-registrars/src/Themes/Light.css +31 -0
  102. package/.worktrees/bundling-v2-precompiled-registrars/src/Themes/Slice.css +47 -0
  103. package/.worktrees/bundling-v2-precompiled-registrars/src/images/Slice.js-logo.png +0 -0
  104. package/.worktrees/bundling-v2-precompiled-registrars/src/images/favicon.ico +0 -0
  105. package/.worktrees/bundling-v2-precompiled-registrars/src/images/im2/Slice.js-logo.png +0 -0
  106. package/.worktrees/bundling-v2-precompiled-registrars/src/routes.js +16 -0
  107. package/.worktrees/bundling-v2-precompiled-registrars/src/sliceConfig.json +73 -0
  108. package/.worktrees/bundling-v2-precompiled-registrars/src/testing.js +888 -0
  109. package/.worktrees/public-env-browser-exposure/LICENSE +21 -0
  110. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/ContextManager/ContextManager.js +369 -0
  111. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/ContextManager/ContextManagerDebugger.js +297 -0
  112. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Controller/Controller.js +972 -0
  113. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Debugger/Debugger.css +620 -0
  114. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Debugger/Debugger.html +73 -0
  115. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Debugger/Debugger.js +1548 -0
  116. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/EventManager/EventManager.js +338 -0
  117. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/EventManager/EventManagerDebugger.js +361 -0
  118. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Logger/Log.js +10 -0
  119. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Logger/Logger.js +146 -0
  120. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/Router/Router.js +721 -0
  121. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/StylesManager/StylesManager.js +78 -0
  122. package/.worktrees/public-env-browser-exposure/Slice/Components/Structural/StylesManager/ThemeManager/ThemeManager.js +84 -0
  123. package/.worktrees/public-env-browser-exposure/Slice/Slice.js +533 -0
  124. package/.worktrees/public-env-browser-exposure/Slice/tests/bundle-v2-runtime-contract.test.js +268 -0
  125. package/.worktrees/public-env-browser-exposure/Slice/tests/public-env-runtime-accessors.test.js +44 -0
  126. package/.worktrees/public-env-browser-exposure/Slice/tests/router-loading-finally.test.js +68 -0
  127. package/.worktrees/public-env-browser-exposure/api/index.js +286 -0
  128. package/.worktrees/public-env-browser-exposure/api/middleware/securityMiddleware.js +253 -0
  129. package/.worktrees/public-env-browser-exposure/api/tests/public-env-resolver.test.js +193 -0
  130. package/.worktrees/public-env-browser-exposure/api/utils/publicEnvResolver.js +117 -0
  131. package/.worktrees/public-env-browser-exposure/package.json +37 -0
  132. package/.worktrees/public-env-browser-exposure/sliceConfig.schema.json +109 -0
  133. package/.worktrees/public-env-browser-exposure/src/App/index.html +22 -0
  134. package/.worktrees/public-env-browser-exposure/src/App/index.js +23 -0
  135. package/.worktrees/public-env-browser-exposure/src/App/style.css +40 -0
  136. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/HomePage/HomePage.css +201 -0
  137. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/HomePage/HomePage.html +37 -0
  138. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/HomePage/HomePage.js +210 -0
  139. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/Playground/Playground.css +12 -0
  140. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/Playground/Playground.html +0 -0
  141. package/.worktrees/public-env-browser-exposure/src/Components/AppComponents/Playground/Playground.js +111 -0
  142. package/.worktrees/public-env-browser-exposure/src/Components/Service/FetchManager/FetchManager.js +133 -0
  143. package/.worktrees/public-env-browser-exposure/src/Components/Service/IndexedDbManager/IndexedDbManager.js +141 -0
  144. package/.worktrees/public-env-browser-exposure/src/Components/Service/LocalStorageManager/LocalStorageManager.js +45 -0
  145. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Button/Button.css +47 -0
  146. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Button/Button.html +5 -0
  147. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Button/Button.js +93 -0
  148. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Card/Card.css +68 -0
  149. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Card/Card.html +7 -0
  150. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Card/Card.js +107 -0
  151. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Checkbox/Checkbox.css +87 -0
  152. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Checkbox/Checkbox.html +8 -0
  153. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Checkbox/Checkbox.js +86 -0
  154. package/.worktrees/public-env-browser-exposure/src/Components/Visual/CodeVisualizer/CodeVisualizer.css +130 -0
  155. package/.worktrees/public-env-browser-exposure/src/Components/Visual/CodeVisualizer/CodeVisualizer.html +4 -0
  156. package/.worktrees/public-env-browser-exposure/src/Components/Visual/CodeVisualizer/CodeVisualizer.js +262 -0
  157. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Details/Details.css +70 -0
  158. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Details/Details.html +9 -0
  159. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Details/Details.js +76 -0
  160. package/.worktrees/public-env-browser-exposure/src/Components/Visual/DropDown/DropDown.css +60 -0
  161. package/.worktrees/public-env-browser-exposure/src/Components/Visual/DropDown/DropDown.html +5 -0
  162. package/.worktrees/public-env-browser-exposure/src/Components/Visual/DropDown/DropDown.js +63 -0
  163. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Grid/Grid.css +7 -0
  164. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Grid/Grid.html +1 -0
  165. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Grid/Grid.js +57 -0
  166. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/Icon.css +510 -0
  167. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/Icon.html +1 -0
  168. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/Icon.js +89 -0
  169. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.eot +0 -0
  170. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.json +555 -0
  171. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.styl +507 -0
  172. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.svg +1485 -0
  173. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.symbol.svg +1059 -0
  174. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.ttf +0 -0
  175. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.woff +0 -0
  176. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Icon/slc.woff2 +0 -0
  177. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Input/Input.css +91 -0
  178. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Input/Input.html +4 -0
  179. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Input/Input.js +215 -0
  180. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Layout/Layout.css +0 -0
  181. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Layout/Layout.html +0 -0
  182. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Layout/Layout.js +49 -0
  183. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Link/Link.css +8 -0
  184. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Link/Link.html +1 -0
  185. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Link/Link.js +63 -0
  186. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Loading/Loading.css +56 -0
  187. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Loading/Loading.html +83 -0
  188. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Loading/Loading.js +38 -0
  189. package/.worktrees/public-env-browser-exposure/src/Components/Visual/MultiRoute/MultiRoute.js +93 -0
  190. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Navbar/Navbar.css +115 -0
  191. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Navbar/Navbar.html +44 -0
  192. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Navbar/Navbar.js +141 -0
  193. package/.worktrees/public-env-browser-exposure/src/Components/Visual/NotFound/NotFound.css +117 -0
  194. package/.worktrees/public-env-browser-exposure/src/Components/Visual/NotFound/NotFound.html +24 -0
  195. package/.worktrees/public-env-browser-exposure/src/Components/Visual/NotFound/NotFound.js +16 -0
  196. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Route/Route.js +93 -0
  197. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Select/Select.css +84 -0
  198. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Select/Select.html +8 -0
  199. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Select/Select.js +195 -0
  200. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Switch/Switch.css +76 -0
  201. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Switch/Switch.html +8 -0
  202. package/.worktrees/public-env-browser-exposure/src/Components/Visual/Switch/Switch.js +102 -0
  203. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeItem/TreeItem.css +36 -0
  204. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeItem/TreeItem.html +1 -0
  205. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeItem/TreeItem.js +126 -0
  206. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeView/TreeView.css +8 -0
  207. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeView/TreeView.html +1 -0
  208. package/.worktrees/public-env-browser-exposure/src/Components/Visual/TreeView/TreeView.js +48 -0
  209. package/.worktrees/public-env-browser-exposure/src/Components/components.js +27 -0
  210. package/.worktrees/public-env-browser-exposure/src/Styles/sliceStyles.css +34 -0
  211. package/.worktrees/public-env-browser-exposure/src/Themes/Dark.css +42 -0
  212. package/.worktrees/public-env-browser-exposure/src/Themes/Light.css +31 -0
  213. package/.worktrees/public-env-browser-exposure/src/Themes/Slice.css +47 -0
  214. package/.worktrees/public-env-browser-exposure/src/images/Slice.js-logo.png +0 -0
  215. package/.worktrees/public-env-browser-exposure/src/images/favicon.ico +0 -0
  216. package/.worktrees/public-env-browser-exposure/src/images/im2/Slice.js-logo.png +0 -0
  217. package/.worktrees/public-env-browser-exposure/src/routes.js +16 -0
  218. package/.worktrees/public-env-browser-exposure/src/sliceConfig.json +73 -0
  219. package/.worktrees/public-env-browser-exposure/src/testing.js +888 -0
  220. package/Slice/Components/Structural/Controller/Controller.js +51 -29
  221. package/Slice/Components/Structural/Router/Router.js +25 -24
  222. package/Slice/Slice.js +79 -46
  223. package/Slice/tests/bundle-v2-runtime-contract.test.js +268 -0
  224. package/Slice/tests/public-env-runtime-accessors.test.js +44 -0
  225. package/Slice/tests/router-loading-finally.test.js +68 -0
  226. package/api/index.js +12 -12
  227. package/api/tests/public-env-resolver.test.js +193 -0
  228. package/api/utils/publicEnvResolver.js +117 -0
  229. package/package.json +1 -1
@@ -64,6 +64,26 @@ export default class Controller {
64
64
  return importPromise;
65
65
  }
66
66
 
67
+ /**
68
+ * Validate Bundling V2 module contract.
69
+ * Requires named exports: SLICE_BUNDLE_META and registerAll.
70
+ * @param {any} bundleModule
71
+ * @param {string} [bundleName]
72
+ * @returns {{metadata: object, registerAll: Function}}
73
+ */
74
+ async validateBundleModule(bundleModule, bundleName = 'unknown') {
75
+ const metadata = bundleModule?.SLICE_BUNDLE_META;
76
+ const registerAll = bundleModule?.registerAll;
77
+
78
+ if (!metadata || typeof metadata !== 'object' || typeof registerAll !== 'function') {
79
+ throw new Error(
80
+ `Bundle "${bundleName}" missing Bundling V2 exports contract: requires SLICE_BUNDLE_META and registerAll`
81
+ );
82
+ }
83
+
84
+ return { metadata, registerAll };
85
+ }
86
+
67
87
  /**
68
88
  * 📦 Loads a bundle by name or category
69
89
  */
@@ -72,44 +92,46 @@ export default class Controller {
72
92
  return; // Already loaded
73
93
  }
74
94
 
75
- try {
76
- let bundleInfo = null;
95
+ let bundleInfo = null;
77
96
 
78
- if (bundleName === 'critical') {
79
- bundleInfo = this.bundleConfig?.bundles?.critical;
80
- } else {
81
- bundleInfo = this.bundleConfig?.bundles?.routes?.[bundleName];
82
- }
97
+ if (bundleName === 'critical') {
98
+ bundleInfo = this.bundleConfig?.bundles?.critical;
99
+ } else {
100
+ bundleInfo = this.bundleConfig?.bundles?.routes?.[bundleName];
101
+ }
83
102
 
84
- if (!bundleInfo && this.bundleConfig?.bundles?.routes && bundleName !== 'critical') {
85
- const normalizedName = bundleName?.toLowerCase();
86
- const matchedKey = Object.keys(this.bundleConfig.bundles.routes).find(
87
- (key) => key.toLowerCase() === normalizedName
88
- );
89
- if (matchedKey) {
90
- bundleInfo = this.bundleConfig.bundles.routes[matchedKey];
91
- }
103
+ if (!bundleInfo && this.bundleConfig?.bundles?.routes && bundleName !== 'critical') {
104
+ const normalizedName = bundleName?.toLowerCase();
105
+ const matchedKey = Object.keys(this.bundleConfig.bundles.routes).find(
106
+ (key) => key.toLowerCase() === normalizedName
107
+ );
108
+ if (matchedKey) {
109
+ bundleInfo = this.bundleConfig.bundles.routes[matchedKey];
92
110
  }
111
+ }
93
112
 
94
- if (!bundleInfo) {
95
- console.warn(`Bundle ${bundleName} not found in configuration`);
96
- return;
97
- }
113
+ if (!bundleInfo) {
114
+ console.warn(`Bundle ${bundleName} not found in configuration`);
115
+ return;
116
+ }
98
117
 
99
- const bundlePath = `/bundles/${bundleInfo.file}`;
118
+ const bundlePath = `/bundles/${bundleInfo.file}`;
100
119
 
101
- await this.importBundleOnce(bundlePath);
120
+ const bundleModule = await this.importBundleOnce(bundlePath);
121
+ const { metadata, registerAll } = await this.validateBundleModule(bundleModule, bundleName);
102
122
 
103
- if (window.__slicePendingRegistrations?.length) {
104
- await Promise.all(window.__slicePendingRegistrations);
105
- window.__slicePendingRegistrations = [];
106
- }
123
+ await registerAll(this, slice.stylesManager);
107
124
 
108
- this.loadedBundles.add(bundleName);
109
- } catch (error) {
110
- console.warn(`Failed to load bundle ${bundleName}:`, error);
125
+ this.loadedBundles.add(bundleName);
126
+ const loadedBundleKey = metadata.bundleKey;
127
+ if (loadedBundleKey && loadedBundleKey !== bundleName) {
128
+ this.loadedBundles.add(loadedBundleKey);
129
+ }
130
+
131
+ if (metadata.type === 'critical' || bundleName === 'critical') {
132
+ this.criticalBundleLoaded = true;
133
+ }
111
134
  }
112
- }
113
135
 
114
136
  /**
115
137
  * 📦 Registers a bundle's components (called automatically by bundle files)
@@ -419,34 +419,35 @@ export default class Router {
419
419
  slice.loading.start();
420
420
  }
421
421
 
422
- if (existingComponent) {
423
- targetElement.innerHTML = '';
424
- if (existingComponent.update) {
425
- existingComponent.props = { ...existingComponent.props, ...params };
426
- await existingComponent.update();
427
- }
428
- targetElement.appendChild(existingComponent);
429
- await this.renderRoutesInComponent(existingComponent);
430
- } else {
431
- const component = await slice.build(componentName, {
432
- params,
433
- sliceId: sliceId,
434
- });
435
-
436
- targetElement.innerHTML = '';
437
- targetElement.appendChild(component);
422
+ try {
423
+ if (existingComponent) {
424
+ targetElement.innerHTML = '';
425
+ if (existingComponent.update) {
426
+ existingComponent.props = { ...existingComponent.props, ...params };
427
+ await existingComponent.update();
428
+ }
429
+ targetElement.appendChild(existingComponent);
430
+ await this.renderRoutesInComponent(existingComponent);
431
+ } else {
432
+ const component = await slice.build(componentName, {
433
+ params,
434
+ sliceId: sliceId,
435
+ });
438
436
 
439
- await this.renderRoutesInComponent(component);
440
- }
437
+ targetElement.innerHTML = '';
438
+ targetElement.appendChild(component);
441
439
 
442
- // Invalidar caché después de cambios importantes en el DOM
443
- this.invalidateCache();
440
+ await this.renderRoutesInComponent(component);
441
+ }
444
442
 
445
- if (slice.loading) {
446
- slice.loading.stop();
443
+ // Invalidar caché después de cambios importantes en el DOM
444
+ this.invalidateCache();
445
+ slice.router.activeRoute = route;
446
+ } finally {
447
+ if (slice.loading) {
448
+ slice.loading.stop();
449
+ }
447
450
  }
448
-
449
- slice.router.activeRoute = route;
450
451
  }
451
452
 
452
453
  /**
package/Slice/Slice.js CHANGED
@@ -24,6 +24,7 @@ export default class Slice {
24
24
  // Default to production until init() resolves the actual mode.
25
25
  // Safe to call isProduction() before init() completes.
26
26
  this._mode = 'production';
27
+ this._publicEnv = {};
27
28
 
28
29
  // 📦 Bundle system is initialized automatically via import in index.js
29
30
  }
@@ -51,6 +52,33 @@ export default class Slice {
51
52
  return this._mode === 'production';
52
53
  }
53
54
 
55
+ setPublicEnv(envPayload = {}) {
56
+ const normalized = {};
57
+
58
+ for (const [key, value] of Object.entries(envPayload || {})) {
59
+ if (!key.startsWith('SLICE_PUBLIC_')) continue;
60
+ normalized[key] = String(value ?? '');
61
+ }
62
+
63
+ this._publicEnv = normalized;
64
+ }
65
+
66
+ getEnv(name, fallbackValue = undefined) {
67
+ if (!name || typeof name !== 'string') {
68
+ return fallbackValue;
69
+ }
70
+
71
+ if (Object.prototype.hasOwnProperty.call(this._publicEnv, name)) {
72
+ return this._publicEnv[name];
73
+ }
74
+
75
+ return fallbackValue;
76
+ }
77
+
78
+ getPublicEnv() {
79
+ return { ...this._publicEnv };
80
+ }
81
+
54
82
  /**
55
83
  * Get a component instance by sliceId.
56
84
  * @param {string} componentSliceId
@@ -279,11 +307,7 @@ async function init() {
279
307
  resolvedMode = 'development';
280
308
  }
281
309
 
282
- const criticalBundleUrl = (resolvedMode === 'production' && bundleConfigJson?.bundles?.critical?.file)
283
- ? `/bundles/${bundleConfigJson.bundles.critical.file}`
284
- : null;
285
-
286
- // 4. Load framework classes.
310
+ // 4. Load framework classes.
287
311
  // In production the bundler generates slice-bundle.framework.js which
288
312
  // sets window.SLICE_FRAMEWORK_CLASSES. In dev mode always use individual
289
313
  // imports so the live /Slice/ source is served directly without bundles.
@@ -318,53 +342,62 @@ async function init() {
318
342
  // 5. Create Slice instance and set resolved mode
319
343
  window.slice = new Slice(sliceConfig, frameworkClasses);
320
344
  window.slice._mode = resolvedMode;
345
+ window.slice.setPublicEnv(envResult?.env || {});
346
+
347
+ const createBundlingInitError = (step, error) => {
348
+ const detail = error instanceof Error ? error.message : String(error);
349
+ return new Error(`Bundling V2 initialization failed (${step}): ${detail}`, { cause: error });
350
+ };
321
351
 
322
352
  // Initialize bundles before building components.
323
353
  // Only in production — dev mode loads each component individually from source.
324
354
  // bundleConfigJson was already fetched above (step 2); reuse it.
325
- try {
326
- if (resolvedMode === 'production' && bundleConfigJson) {
327
- window.slice.controller.bundleConfig = bundleConfigJson;
355
+ if (resolvedMode === 'production' && bundleConfigJson) {
356
+ window.slice.controller.bundleConfig = bundleConfigJson;
357
+ }
358
+
359
+ if (resolvedMode === 'production' && window.slice.controller.bundleConfig) {
360
+ const config = window.slice.controller.bundleConfig;
361
+ const criticalFile = config?.bundles?.critical?.file;
362
+ if (criticalFile) {
363
+ try {
364
+ await window.slice.controller.loadBundle('critical');
365
+ } catch (error) {
366
+ throw createBundlingInitError(`critical bundle "${criticalFile}"`, error);
367
+ }
328
368
  }
329
369
 
330
- if (window.slice.controller.bundleConfig) {
331
- const config = window.slice.controller.bundleConfig;
332
-
333
- const criticalFile = config?.bundles?.critical?.file;
334
- if (criticalFile && criticalBundleUrl) {
335
- // Bundle auto-registers itself on import via its own registration block.
336
- // The block pushes its registerBundle() Promise to window.__slicePendingRegistrations
337
- // so we can await full chunk processing before continuing to build('Loading').
338
- await window.slice.controller.importBundleOnce(criticalBundleUrl);
339
- if (window.__slicePendingRegistrations?.length) {
340
- await Promise.all(window.__slicePendingRegistrations);
341
- window.__slicePendingRegistrations = [];
342
- }
343
- }
344
-
345
- const routeBundles = config?.routeBundles || {};
346
- const initialPath = window.location.pathname || '/';
347
- const bundlesForRoute = routeBundles[initialPath] || [];
348
-
349
- const loadRouteBundles = async () => {
350
- for (const bundleName of bundlesForRoute) {
351
- if (bundleName === 'critical') continue;
352
- const bundleInfo = config?.bundles?.routes?.[bundleName];
353
- if (!bundleInfo?.file) continue;
354
- // Bundle auto-registers itself on import.
355
- await window.slice.controller.importBundleOnce(`/bundles/${bundleInfo.file}`);
356
- }
357
- };
358
-
359
- if (typeof requestIdleCallback === 'function') {
360
- requestIdleCallback(() => loadRouteBundles());
361
- } else {
362
- setTimeout(() => loadRouteBundles(), 0);
363
- }
364
- }
365
- } catch (error) {
366
- console.log('📄 Using individual component loading (no bundles found)');
367
- }
370
+ const routeBundles = config?.routeBundles || {};
371
+ const initialPath = window.location.pathname || '/';
372
+ const bundlesForRoute = routeBundles[initialPath] || [];
373
+
374
+ const loadRouteBundles = async () => {
375
+ for (const bundleName of bundlesForRoute) {
376
+ if (bundleName === 'critical') continue;
377
+ const bundleInfo = config?.bundles?.routes?.[bundleName];
378
+ if (!bundleInfo?.file) continue;
379
+ await window.slice.controller.loadBundle(bundleName);
380
+ }
381
+ };
382
+
383
+ const preloadRouteBundles = () => {
384
+ loadRouteBundles().catch((error) => {
385
+ const bundlingError = createBundlingInitError(
386
+ `idle route preload "${initialPath}"`,
387
+ error
388
+ );
389
+ queueMicrotask(() => {
390
+ throw bundlingError;
391
+ });
392
+ });
393
+ };
394
+
395
+ if (typeof requestIdleCallback === 'function') {
396
+ requestIdleCallback(() => preloadRouteBundles());
397
+ } else {
398
+ setTimeout(() => preloadRouteBundles(), 0);
399
+ }
400
+ }
368
401
 
369
402
  slice.paths.structuralComponentFolderPath = '/Slice/Components/Structural';
370
403
 
@@ -0,0 +1,268 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtemp, rm, writeFile } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import path from 'node:path';
6
+ import { register } from 'node:module';
7
+ import { pathToFileURL } from 'node:url';
8
+
9
+ test('validateBundleModule rejects module missing Bundling V2 exports contract', async () => {
10
+ const tempDir = await mkdtemp(path.join(tmpdir(), 'slice-controller-loader-'));
11
+ const loaderPath = path.join(tempDir, 'components-alias-loader.mjs');
12
+ await writeFile(
13
+ loaderPath,
14
+ `export async function resolve(specifier, context, nextResolve) {
15
+ if (specifier === '/Components/components.js') {
16
+ return {
17
+ shortCircuit: true,
18
+ url: 'data:text/javascript,export default {};',
19
+ };
20
+ }
21
+ return nextResolve(specifier, context);
22
+ }
23
+ `,
24
+ 'utf8'
25
+ );
26
+ register(pathToFileURL(loaderPath).href);
27
+
28
+ const controllerModuleUrl = new URL('../Components/Structural/Controller/Controller.js', import.meta.url).href;
29
+ const { default: Controller } = await import(controllerModuleUrl);
30
+ const controller = new Controller();
31
+ const originalWindow = globalThis.window;
32
+
33
+ try {
34
+ globalThis.window = {
35
+ __slicePendingRegistrations: [],
36
+ };
37
+
38
+ assert.equal(
39
+ typeof controller.validateBundleModule,
40
+ 'function',
41
+ 'Controller must expose validateBundleModule for Bundling V2 runtime contract checks'
42
+ );
43
+
44
+ if (typeof controller.validateBundleModule === 'function') {
45
+ await assert.rejects(
46
+ () => Promise.resolve(controller.validateBundleModule({ default: {} }, 'critical.js')),
47
+ /missing bundling v2 exports contract/i
48
+ );
49
+ }
50
+ } finally {
51
+ globalThis.window = originalWindow;
52
+ await rm(tempDir, { recursive: true, force: true });
53
+ }
54
+ });
55
+
56
+ test('loadBundle marks requested bundle key and metadata bundleKey as loaded', async () => {
57
+ const tempDir = await mkdtemp(path.join(tmpdir(), 'slice-controller-loader-'));
58
+ const loaderPath = path.join(tempDir, 'components-alias-loader.mjs');
59
+ await writeFile(
60
+ loaderPath,
61
+ `export async function resolve(specifier, context, nextResolve) {
62
+ if (specifier === '/Components/components.js') {
63
+ return {
64
+ shortCircuit: true,
65
+ url: 'data:text/javascript,export default {};',
66
+ };
67
+ }
68
+ return nextResolve(specifier, context);
69
+ }
70
+ `,
71
+ 'utf8'
72
+ );
73
+ register(pathToFileURL(loaderPath).href);
74
+
75
+ const controllerModuleUrl = new URL('../Components/Structural/Controller/Controller.js', import.meta.url).href;
76
+ const { default: Controller } = await import(controllerModuleUrl);
77
+ const controller = new Controller();
78
+ const originalSlice = globalThis.slice;
79
+
80
+ controller.bundleConfig = {
81
+ bundles: {
82
+ routes: {
83
+ dashboard: {
84
+ file: 'dashboard.js',
85
+ },
86
+ },
87
+ },
88
+ };
89
+
90
+ controller.importBundleOnce = async () => ({});
91
+ controller.validateBundleModule = async () => ({
92
+ metadata: {
93
+ bundleKey: 'routes.dashboard.v2',
94
+ type: 'route',
95
+ },
96
+ registerAll: async () => {},
97
+ });
98
+
99
+ try {
100
+ globalThis.slice = {
101
+ stylesManager: {},
102
+ };
103
+
104
+ await controller.loadBundle('dashboard');
105
+
106
+ assert.equal(controller.loadedBundles.has('dashboard'), true);
107
+ assert.equal(controller.loadedBundles.has('routes.dashboard.v2'), true);
108
+ assert.equal(controller.criticalBundleLoaded, false);
109
+ } finally {
110
+ globalThis.slice = originalSlice;
111
+ await rm(tempDir, { recursive: true, force: true });
112
+ }
113
+ });
114
+
115
+ test('Slice init fails fast with contextual error on invalid Bundling V2 contract path', async () => {
116
+ const tempDir = await mkdtemp(path.join(tmpdir(), 'slice-init-loader-'));
117
+ const loaderPath = path.join(tempDir, 'components-alias-loader.mjs');
118
+ await writeFile(
119
+ loaderPath,
120
+ `export async function resolve(specifier, context, nextResolve) {
121
+ if (specifier === '/Components/components.js') {
122
+ return {
123
+ shortCircuit: true,
124
+ url: 'data:text/javascript,export default {};',
125
+ };
126
+ }
127
+ return nextResolve(specifier, context);
128
+ }
129
+ `,
130
+ 'utf8'
131
+ );
132
+ register(pathToFileURL(loaderPath).href);
133
+
134
+ const originalWindow = globalThis.window;
135
+ const originalDocument = globalThis.document;
136
+ const originalFetch = globalThis.fetch;
137
+ const originalAlert = globalThis.alert;
138
+ const originalSliceDescriptor = Object.getOwnPropertyDescriptor(globalThis, 'slice');
139
+ const originalConsoleLog = console.log;
140
+ const originalConsoleWarn = console.warn;
141
+ const controllerModuleUrl = new URL('../Components/Structural/Controller/Controller.js', import.meta.url).href;
142
+ const { default: Controller } = await import(controllerModuleUrl);
143
+ const originalLoadBundle = Controller.prototype.loadBundle;
144
+
145
+ const loggedMessages = [];
146
+
147
+ try {
148
+ globalThis.window = {
149
+ location: {
150
+ pathname: '/dashboard',
151
+ origin: 'http://localhost',
152
+ },
153
+ };
154
+
155
+ Object.defineProperty(globalThis, 'slice', {
156
+ configurable: true,
157
+ get() {
158
+ return globalThis.window?.slice;
159
+ },
160
+ set(value) {
161
+ if (!globalThis.window) {
162
+ globalThis.window = {};
163
+ }
164
+ globalThis.window.slice = value;
165
+ },
166
+ });
167
+
168
+ Controller.prototype.loadBundle = async () => {
169
+ throw new Error(
170
+ 'Bundle "critical" missing Bundling V2 exports contract: requires SLICE_BUNDLE_META and registerAll'
171
+ );
172
+ };
173
+
174
+ globalThis.document = {
175
+ head: {
176
+ appendChild() {},
177
+ },
178
+ body: {
179
+ appendChild() {},
180
+ },
181
+ createElement() {
182
+ return {
183
+ appendChild() {},
184
+ innerHTML: '',
185
+ id: '',
186
+ };
187
+ },
188
+ createTextNode() {
189
+ return {};
190
+ },
191
+ addEventListener() {},
192
+ };
193
+
194
+ globalThis.alert = () => {};
195
+ console.log = (...args) => {
196
+ loggedMessages.push(args.map(String).join(' '));
197
+ };
198
+ console.warn = () => {};
199
+
200
+ globalThis.fetch = async (url) => {
201
+ if (url === '/sliceConfig.json') {
202
+ return {
203
+ ok: true,
204
+ json: async () => ({
205
+ paths: {
206
+ routesFile: '/routes.js',
207
+ components: {},
208
+ },
209
+ themeManager: { enabled: false },
210
+ stylesManager: { requestedStyles: [] },
211
+ logger: { enabled: false },
212
+ debugger: { enabled: false },
213
+ loading: { enabled: false },
214
+ events: { enabled: false },
215
+ context: { enabled: false },
216
+ }),
217
+ };
218
+ }
219
+
220
+ if (url === '/slice-env.json') {
221
+ return {
222
+ ok: true,
223
+ json: async () => ({ mode: 'production' }),
224
+ };
225
+ }
226
+
227
+ if (url === '/bundles/bundle.config.json') {
228
+ return {
229
+ ok: true,
230
+ json: async () => ({
231
+ production: true,
232
+ bundles: {
233
+ critical: { file: 'critical.js' },
234
+ routes: {},
235
+ },
236
+ routeBundles: {},
237
+ }),
238
+ };
239
+ }
240
+
241
+ throw new Error(`Unexpected fetch URL: ${url}`);
242
+ };
243
+
244
+ const sliceModuleUrl = new URL(`../Slice.js?fail-fast-test=${Date.now()}`, import.meta.url).href;
245
+
246
+ await assert.rejects(() => import(sliceModuleUrl), /Bundling V2 initialization failed/i);
247
+
248
+ assert.equal(
249
+ loggedMessages.some((message) => message.includes('Using individual component loading (no bundles found)')),
250
+ false,
251
+ 'init must not log fallback bundle message on Bundling V2 contract failure'
252
+ );
253
+ } finally {
254
+ Controller.prototype.loadBundle = originalLoadBundle;
255
+ globalThis.window = originalWindow;
256
+ globalThis.document = originalDocument;
257
+ globalThis.fetch = originalFetch;
258
+ globalThis.alert = originalAlert;
259
+ if (originalSliceDescriptor) {
260
+ Object.defineProperty(globalThis, 'slice', originalSliceDescriptor);
261
+ } else {
262
+ delete globalThis.slice;
263
+ }
264
+ console.log = originalConsoleLog;
265
+ console.warn = originalConsoleWarn;
266
+ await rm(tempDir, { recursive: true, force: true });
267
+ }
268
+ });
@@ -0,0 +1,44 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+
4
+ globalThis.alert = () => {};
5
+
6
+ const { default: Slice } = await import('../Slice.js');
7
+
8
+ function createSliceInstance() {
9
+ return new Slice({
10
+ paths: {},
11
+ themeManager: {},
12
+ stylesManager: {},
13
+ logger: {},
14
+ debugger: {},
15
+ loading: {},
16
+ events: {}
17
+ });
18
+ }
19
+
20
+ test('getEnv returns fallback for missing key and stored value for known key', () => {
21
+ const sliceInstance = createSliceInstance();
22
+
23
+ assert.equal(typeof sliceInstance.getEnv, 'function');
24
+ assert.equal(typeof sliceInstance.setPublicEnv, 'function');
25
+ assert.equal(sliceInstance.getEnv('SLICE_PUBLIC_MISSING', 'fallback'), 'fallback');
26
+
27
+ sliceInstance.setPublicEnv({ SLICE_PUBLIC_API_URL: 'https://api.example.com' });
28
+ assert.equal(sliceInstance.getEnv('SLICE_PUBLIC_API_URL'), 'https://api.example.com');
29
+ });
30
+
31
+ test('getPublicEnv returns a copy and only includes SLICE_PUBLIC_ keys', () => {
32
+ const sliceInstance = createSliceInstance();
33
+
34
+ sliceInstance.setPublicEnv({
35
+ SLICE_PUBLIC_FLAG: 'true',
36
+ INTERNAL_SECRET: 'hidden'
37
+ });
38
+
39
+ const snapshot = sliceInstance.getPublicEnv();
40
+ assert.deepEqual(snapshot, { SLICE_PUBLIC_FLAG: 'true' });
41
+
42
+ snapshot.SLICE_PUBLIC_FLAG = 'mutated';
43
+ assert.equal(sliceInstance.getEnv('SLICE_PUBLIC_FLAG'), 'true');
44
+ });