@supersoniks/concorde 5.1.2 → 5.1.3-immutable.1

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 (497) hide show
  1. package/.agents/skills/concorde-docs/SKILL.md +1 -1
  2. package/.claude/skills +1 -0
  3. package/.github/workflows/ci.yml +21 -0
  4. package/.github-export-ignore +30 -0
  5. package/CONTRIBUTING.md +59 -0
  6. package/DEV.md +54 -0
  7. package/LICENSE +21 -0
  8. package/OPEN_SOURCE_CHECKPOINT.md +133 -0
  9. package/README.md +1 -1
  10. package/ai/README.md +29 -41
  11. package/ai/skills/concorde/SKILL.md +54 -324
  12. package/ai/skills/concorde/rules/composition.md +32 -0
  13. package/ai/skills/concorde/rules/data.md +47 -0
  14. package/ai/skills/concorde/rules/http.md +25 -0
  15. package/ai/skills/concorde/rules/lists-forms.md +35 -0
  16. package/ai/skills/concorde/rules/styling.md +46 -0
  17. package/ai/skills/concorde/rules/troubleshooting.md +45 -0
  18. package/build-infos.json +1 -1
  19. package/concorde-core.bundle.js +177 -177
  20. package/concorde-core.es.js +4993 -4833
  21. package/custom-elements-manifest.public.config.mjs +8 -0
  22. package/{.tmp-cem/custom-elements.json → custom-elements.json} +11722 -8868
  23. package/dist/concorde-core.bundle.js +177 -177
  24. package/dist/concorde-core.es.js +4993 -4833
  25. package/dist/docs-mock-api-sw.js +58 -223
  26. package/dist/docs-mock-api-sw.js.map +4 -4
  27. package/dist/img/og-concorde.jpg +0 -0
  28. package/dist/robots.txt +11 -10
  29. package/docs/assets/index-CD4WyL6o.css +1 -0
  30. package/docs/assets/index-D_alEsng.js +12122 -0
  31. package/docs/crawl/core/components/functional/date/date.html +190 -0
  32. package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
  33. package/docs/crawl/core/components/functional/if/if.html +27 -0
  34. package/docs/crawl/core/components/functional/jsonata/jsonata.html +79 -0
  35. package/docs/crawl/core/components/functional/list/list.html +70 -0
  36. package/docs/crawl/core/components/functional/mix/mix.html +45 -0
  37. package/docs/crawl/core/components/functional/queue/queue.html +96 -0
  38. package/docs/crawl/core/components/functional/router/router.html +106 -0
  39. package/docs/{core → crawl/core}/components/functional/sdui/sdui-extension-points.html +8 -9
  40. package/docs/crawl/core/components/functional/sdui/sdui.html +368 -0
  41. package/docs/crawl/core/components/functional/states/states.html +66 -0
  42. package/docs/crawl/core/components/functional/submit/submit.html +160 -0
  43. package/docs/{core → crawl/core}/components/functional/subscriber/subscriber.html +5 -6
  44. package/docs/crawl/core/components/functional/value/value.html +51 -0
  45. package/docs/{core → crawl/core}/components/ui/alert/alert.html +63 -53
  46. package/docs/{core → crawl/core}/components/ui/alert-messages/alert-messages.html +5 -6
  47. package/docs/{core → crawl/core}/components/ui/badge/badge.html +33 -33
  48. package/docs/crawl/core/components/ui/button/button.html +150 -0
  49. package/docs/crawl/core/components/ui/captcha/captcha.html +112 -0
  50. package/docs/{core → crawl/core}/components/ui/card/card.html +11 -12
  51. package/docs/{core → crawl/core}/components/ui/divider/divider.html +14 -14
  52. package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
  53. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +266 -0
  54. package/docs/{core → crawl/core}/components/ui/form/form-actions/form-actions.html +23 -23
  55. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +121 -0
  56. package/docs/crawl/core/components/ui/form/input/input.html +109 -0
  57. package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +38 -0
  58. package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
  59. package/docs/crawl/core/components/ui/form/select/select.html +73 -0
  60. package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
  61. package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
  62. package/docs/crawl/core/components/ui/group/group.html +104 -0
  63. package/docs/{core → crawl/core}/components/ui/icon/icon.html +9 -10
  64. package/docs/crawl/core/components/ui/image/image.html +298 -0
  65. package/docs/{core → crawl/core}/components/ui/link/link.html +11 -12
  66. package/docs/crawl/core/components/ui/loader/loader.html +124 -0
  67. package/docs/{core → crawl/core}/components/ui/menu/menu.html +33 -34
  68. package/docs/crawl/core/components/ui/modal/modal.html +342 -0
  69. package/docs/crawl/core/components/ui/pop/pop.html +296 -0
  70. package/docs/{core → crawl/core}/components/ui/progress/progress.html +7 -8
  71. package/docs/crawl/core/components/ui/table/table.html +545 -0
  72. package/docs/crawl/core/components/ui/theme/theme.html +131 -0
  73. package/docs/crawl/core/components/ui/toast/toast.html +233 -0
  74. package/docs/crawl/core/components/ui/tooltip/tooltip.html +140 -0
  75. package/docs/{docs/getting-started → crawl/docs/_core-concept}/dataFlow.html +29 -26
  76. package/docs/crawl/docs/_core-concept/overview.html +66 -0
  77. package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
  78. package/docs/crawl/docs/_decorators/ancestor-attribute.html +117 -0
  79. package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
  80. package/docs/crawl/docs/_decorators/bind.html +141 -0
  81. package/docs/crawl/docs/_decorators/get.html +149 -0
  82. package/docs/crawl/docs/_decorators/handle.html +165 -0
  83. package/docs/crawl/docs/_decorators/on-assign.html +355 -0
  84. package/docs/crawl/docs/_decorators/patch.html +78 -0
  85. package/docs/crawl/docs/_decorators/post.html +139 -0
  86. package/docs/crawl/docs/_decorators/publish.html +61 -0
  87. package/docs/crawl/docs/_decorators/put.html +78 -0
  88. package/docs/crawl/docs/_decorators/subscribe.html +109 -0
  89. package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
  90. package/docs/crawl/docs/_directives/sub.html +93 -0
  91. package/docs/{docs/getting-started → crawl/docs/_getting-started}/ai-agents.html +11 -12
  92. package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
  93. package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
  94. package/docs/{docs/getting-started → crawl/docs/_getting-started}/create-a-component.html +14 -11
  95. package/docs/{docs/getting-started → crawl/docs/_getting-started}/my-first-component.html +22 -13
  96. package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
  97. package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
  98. package/docs/crawl/docs/_getting-started/start.html +76 -0
  99. package/docs/{docs/getting-started → crawl/docs/_getting-started}/theming.html +9 -10
  100. package/docs/{docs/misc → crawl/docs/_misc}/api-configuration.html +18 -18
  101. package/docs/{docs/misc → crawl/docs/_misc}/dataProviderKey.html +11 -12
  102. package/docs/{docs/misc → crawl/docs/_misc}/docs-mock-api.html +28 -25
  103. package/docs/{docs/misc → crawl/docs/_misc}/dynamic-path.html +15 -16
  104. package/docs/{docs/misc → crawl/docs/_misc}/endpoint.html +15 -16
  105. package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
  106. package/docs/{docs/misc → crawl/docs/_misc}/html-integration.html +15 -12
  107. package/docs/crawl/hubs/decorators.html +547 -0
  108. package/docs/crawl/hubs/form-components.html +381 -0
  109. package/docs/crawl/hubs/remote-data.html +452 -0
  110. package/docs/crawl/index.html +103 -0
  111. package/docs/docs-mock-api-sw.js +223 -58
  112. package/docs/docs-mock-api-sw.js.map +4 -4
  113. package/docs/index.html +68 -95
  114. package/docs/llms-full.txt +3610 -2231
  115. package/docs/llms.txt +86 -94
  116. package/docs/robots.txt +10 -11
  117. package/docs/sitemap.xml +84 -78
  118. package/docs/src/core/components/functional/date/date.md +231 -91
  119. package/docs/src/core/components/functional/fetch/fetch.md +83 -66
  120. package/docs/src/core/components/functional/if/if.md +3 -28
  121. package/docs/src/core/components/functional/jsonata/jsonata.md +37 -42
  122. package/docs/src/core/components/functional/list/list.md +43 -99
  123. package/docs/src/core/components/functional/mix/mix.md +26 -31
  124. package/docs/src/core/components/functional/queue/queue.md +61 -40
  125. package/docs/src/core/components/functional/router/router.md +65 -64
  126. package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  127. package/docs/src/core/components/functional/sdui/component-catalog.json +1 -1
  128. package/docs/src/core/components/functional/sdui/example.json +86 -19
  129. package/docs/src/core/components/functional/sdui/sdui-extension-points.md +1 -1
  130. package/docs/src/core/components/functional/sdui/sdui.md +358 -187
  131. package/docs/src/core/components/functional/states/states.md +61 -86
  132. package/docs/src/core/components/functional/submit/submit.md +72 -64
  133. package/docs/src/core/components/functional/value/value.md +22 -34
  134. package/docs/src/core/components/ui/alert/alert.md +58 -48
  135. package/docs/src/core/components/ui/badge/badge.md +34 -27
  136. package/docs/src/core/components/ui/button/button.md +106 -139
  137. package/docs/src/core/components/ui/captcha/captcha.md +32 -17
  138. package/docs/src/core/components/ui/card/card.md +6 -6
  139. package/docs/src/core/components/ui/divider/divider.md +11 -8
  140. package/docs/src/core/components/ui/form/checkbox/checkbox.md +42 -90
  141. package/docs/src/core/components/ui/form/fieldset/fieldset.md +75 -31
  142. package/docs/src/core/components/ui/form/form-actions/form-actions.md +16 -14
  143. package/docs/src/core/components/ui/form/form-layout/form-layout.md +29 -19
  144. package/docs/src/core/components/ui/form/input/input.md +95 -95
  145. package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +29 -0
  146. package/docs/src/core/components/ui/form/radio/radio.md +34 -55
  147. package/docs/src/core/components/ui/form/select/select.md +45 -60
  148. package/docs/src/core/components/ui/form/switch/switch.md +34 -57
  149. package/docs/src/core/components/ui/form/textarea/textarea.md +38 -55
  150. package/docs/src/core/components/ui/group/group.md +33 -35
  151. package/docs/src/core/components/ui/icon/icon.md +4 -4
  152. package/docs/src/core/components/ui/image/image.md +107 -41
  153. package/docs/src/core/components/ui/link/link.md +6 -6
  154. package/docs/src/core/components/ui/loader/loader.md +55 -30
  155. package/docs/src/core/components/ui/menu/menu.md +27 -27
  156. package/docs/src/core/components/ui/modal/modal.md +96 -72
  157. package/docs/src/core/components/ui/pop/pop.md +158 -80
  158. package/docs/src/core/components/ui/progress/progress.md +2 -2
  159. package/docs/src/core/components/ui/table/table.md +255 -91
  160. package/docs/src/core/components/ui/theme/theme.md +36 -11
  161. package/docs/src/core/components/ui/toast/toast.md +117 -48
  162. package/docs/src/core/components/ui/tooltip/tooltip.md +62 -27
  163. package/docs/{docs/getting-started → src/docs/_core-concept}/dataFlow.md +18 -17
  164. package/docs/src/docs/_core-concept/overview.md +57 -0
  165. package/docs/src/docs/_core-concept/subscriber.md +75 -0
  166. package/docs/src/docs/_decorators/ancestor-attribute.md +128 -0
  167. package/docs/src/docs/_decorators/auto-subscribe.md +202 -0
  168. package/docs/src/docs/_decorators/bind.md +167 -0
  169. package/docs/src/docs/_decorators/get.md +162 -0
  170. package/docs/src/docs/_decorators/handle.md +175 -0
  171. package/docs/src/docs/_decorators/on-assign.md +390 -0
  172. package/docs/src/docs/_decorators/patch.md +70 -0
  173. package/docs/src/docs/_decorators/post.md +146 -0
  174. package/docs/src/docs/_decorators/publish.md +55 -0
  175. package/docs/src/docs/_decorators/put.md +70 -0
  176. package/docs/src/docs/_decorators/subscribe.md +100 -0
  177. package/docs/src/docs/_decorators/wait-for-ancestors.md +163 -0
  178. package/docs/src/docs/_directives/sub.md +91 -0
  179. package/docs/src/docs/{getting-started → _getting-started}/ai-agents.md +3 -3
  180. package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
  181. package/docs/src/docs/_getting-started/concorde-outside.md +33 -0
  182. package/docs/{docs/getting-started → src/docs/_getting-started}/create-a-component.md +6 -3
  183. package/docs/src/docs/{getting-started → _getting-started}/my-first-component.md +14 -5
  184. package/docs/src/docs/_getting-started/my-first-subscriber.md +120 -0
  185. package/docs/src/docs/_getting-started/pubsub.md +37 -0
  186. package/docs/src/docs/{getting-started → _getting-started}/start.md +13 -1
  187. package/docs/src/docs/{getting-started → _getting-started}/theming.md +2 -2
  188. package/docs/src/docs/{misc → _misc}/api-configuration.md +12 -10
  189. package/docs/src/docs/{misc → _misc}/dataProviderKey.md +4 -4
  190. package/docs/{docs/misc → src/docs/_misc}/docs-mock-api.md +13 -12
  191. package/docs/{docs/misc → src/docs/_misc}/dynamic-path.md +8 -8
  192. package/docs/{docs/misc → src/docs/_misc}/endpoint.md +8 -8
  193. package/docs/src/docs/_misc/formelement-subscriber-removal.md +115 -0
  194. package/docs/{docs/misc → src/docs/_misc}/html-integration.md +5 -4
  195. package/docs/src/docs/search/docs-search.json +4375 -2420
  196. package/docs/src/tsconfig.declarations.json +22 -0
  197. package/docs/src/tsconfig.emit.json +23 -0
  198. package/docs/src/tsconfig.json +2 -23
  199. package/gitlab/job_github_mirror.sh +39 -0
  200. package/index.html +89 -0
  201. package/package.json +22 -4
  202. package/public/img/og-concorde.jpg +0 -0
  203. package/scripts/ai-init.mjs +104 -379
  204. package/scripts/ai-init.test.mjs +81 -239
  205. package/scripts/docs-markdown-vite-plugin.ts +11 -5
  206. package/scripts/docs-public-url.mjs +6 -0
  207. package/scripts/docs.htaccess +7 -0
  208. package/scripts/generate-cem.mjs +244 -0
  209. package/scripts/generate-cem.test.mjs +122 -0
  210. package/scripts/generate-crawl-docs.mjs +29 -5
  211. package/scripts/generate-sdui-catalog.mjs +11 -10
  212. package/scripts/github-export.mjs +150 -0
  213. package/scripts/post-build-docs.js +3 -0
  214. package/scripts/post-build.mjs +0 -0
  215. package/scripts/pre-publish.mjs +2 -1
  216. package/scripts/site-pages.mjs +212 -0
  217. package/scripts/site-pages.test.mjs +116 -0
  218. package/site-pages/about.md +22 -0
  219. package/site-pages/privacy.md +32 -0
  220. package/src/core/components/functional/date/date.md +1 -1
  221. package/src/core/components/functional/example/example.ts +3 -1
  222. package/src/core/components/functional/if/if.ts +0 -0
  223. package/src/core/components/functional/list/list.demo.ts +0 -0
  224. package/src/core/components/functional/list/list.md +6 -2
  225. package/src/core/components/functional/list/list.ts +17 -4
  226. package/src/core/components/functional/mix/mix.md +0 -0
  227. package/src/core/components/functional/router/router.demo.ts +0 -0
  228. package/src/core/components/functional/router/router.ts +0 -0
  229. package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +0 -0
  230. package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  231. package/src/core/components/functional/sdui/component-catalog.json +2 -2
  232. package/src/core/components/functional/sdui/example.json +0 -0
  233. package/src/core/components/functional/sdui/sdui-immutable.spec.ts +74 -0
  234. package/src/core/components/functional/sdui/sdui.ts +33 -8
  235. package/src/core/components/functional/sdui/types.ts +0 -0
  236. package/src/core/components/functional/states/states.ts +0 -0
  237. package/src/core/components/functional/submit/submit.spec.ts +60 -0
  238. package/src/core/components/functional/submit/submit.ts +6 -3
  239. package/src/core/components/functional/subscriber/subscriber.ts +0 -0
  240. package/src/core/components/functional/value/value.md +0 -0
  241. package/src/core/components/functional/value/value.ts +0 -0
  242. package/src/core/components/ui/_css/size.ts +0 -0
  243. package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
  244. package/src/core/components/ui/card/card.md +1 -1
  245. package/src/core/components/ui/form/input/input.md +19 -1
  246. package/src/core/components/ui/form/input/input.ts +8 -2
  247. package/src/core/components/ui/form/radio/radio.md +14 -0
  248. package/src/core/components/ui/image/image.md +17 -17
  249. package/src/core/components/ui/modal/modal.md +2 -2
  250. package/src/core/decorators/subscriber/bind.ts +9 -14
  251. package/src/core/decorators/subscriber/subscribe.ts +15 -9
  252. package/src/core/decorators/subscriber/subscribe.type-test.ts +14 -5
  253. package/src/core/mixins/Subscriber.ts +0 -0
  254. package/src/core/utils/DataBindObserver.ts +0 -0
  255. package/src/core/utils/Objects.ts +0 -0
  256. package/src/core/utils/PublisherProxy.ts +166 -125
  257. package/src/core/utils/deepReadonly.spec.ts +66 -0
  258. package/src/core/utils/deepReadonly.ts +71 -0
  259. package/src/core/utils/immutableValue.spec.ts +54 -0
  260. package/src/core/utils/immutableValue.ts +102 -0
  261. package/src/core/utils/nestedDotForm.spec.ts +88 -0
  262. package/src/core/utils/publisherImmutable.spec.ts +76 -0
  263. package/src/core/utils/route.ts +0 -0
  264. package/src/core/utils/strictGet.spec.ts +61 -0
  265. package/src/core/utils/strictGet.ts +102 -0
  266. package/src/css.d.ts +19 -0
  267. package/src/docs/components/docs-demo-sources.ts +3 -3
  268. package/src/docs/decorators/bind.md +23 -24
  269. package/src/docs/docs-location.spec.ts +10 -0
  270. package/src/docs/docs-location.ts +10 -0
  271. package/src/docs/example/decorators-demo-bind-demos.ts +11 -28
  272. package/src/docs/example/docs-toggle-demos.ts +1 -1
  273. package/src/docs/example/users.ts +0 -0
  274. package/src/docs/getting-started/ai-agents.md +29 -55
  275. package/src/docs/getting-started/dataFlow.md +2 -2
  276. package/src/docs/home/home.ts +3 -1
  277. package/src/docs/misc/publisher-get-immutability-docs-crawl.json +902 -0
  278. package/src/docs/misc/publisher-get-immutability-docs-recheck.json +13 -0
  279. package/src/docs/misc/publisher-get-immutability-study.md +229 -0
  280. package/src/docs/navigation/navigation.ts +5 -1
  281. package/src/docs/search/docs-search.json +358 -58
  282. package/src/docs/search/markdown-renderer.ts +6 -1
  283. package/src/docs/tailwind/css/docs/content.css +4 -5
  284. package/src/tsconfig.declarations.json +22 -0
  285. package/src/tsconfig.emit.json +23 -0
  286. package/src/tsconfig.json +53 -5
  287. package/src/tsconfig.tsbuildinfo +1 -1
  288. package/.taste-skill/after/desktop-fold.jpg +0 -0
  289. package/.taste-skill/after/desktop-page-01.jpg +0 -0
  290. package/.taste-skill/after/desktop-page-02.jpg +0 -0
  291. package/.taste-skill/after/desktop-page-03.jpg +0 -0
  292. package/.taste-skill/after/mobile-fold.jpg +0 -0
  293. package/.taste-skill/after/mobile-page-01.jpg +0 -0
  294. package/.taste-skill/after/report.json +0 -4103
  295. package/.taste-skill/after/tablet-fold.jpg +0 -0
  296. package/.taste-skill/after/tablet-page-01.jpg +0 -0
  297. package/.taste-skill/after/tablet-page-02.jpg +0 -0
  298. package/.taste-skill/before/desktop-fold.jpg +0 -0
  299. package/.taste-skill/before/desktop-page-01.jpg +0 -0
  300. package/.taste-skill/before/desktop-page-02.jpg +0 -0
  301. package/.taste-skill/before/mobile-fold.jpg +0 -0
  302. package/.taste-skill/before/mobile-page-01.jpg +0 -0
  303. package/.taste-skill/before/report.json +0 -2556
  304. package/.taste-skill/before/tablet-fold.jpg +0 -0
  305. package/.taste-skill/before/tablet-page-01.jpg +0 -0
  306. package/.taste-skill/direction.json +0 -510
  307. package/.taste-skill/notes.md +0 -84
  308. package/.taste-skill/prod/desktop-fold.jpg +0 -0
  309. package/.taste-skill/prod/desktop-page-01.jpg +0 -0
  310. package/.taste-skill/prod/desktop-page-02.jpg +0 -0
  311. package/.taste-skill/prod/desktop-page-03.jpg +0 -0
  312. package/.taste-skill/prod/mobile-fold.jpg +0 -0
  313. package/.taste-skill/prod/mobile-page-01.jpg +0 -0
  314. package/.taste-skill/prod/mobile-page-02.jpg +0 -0
  315. package/.taste-skill/prod/report.json +0 -1973
  316. package/.taste-skill/prod/tablet-fold.jpg +0 -0
  317. package/.taste-skill/prod/tablet-page-01.jpg +0 -0
  318. package/.taste-skill/prod/tablet-page-02.jpg +0 -0
  319. package/AUDIT.md +0 -228
  320. package/PLAN-AMELIORATION.md +0 -220
  321. package/PLAN-DOCS-AGENTS.md +0 -80
  322. package/ai/AGENTS.md +0 -56
  323. package/ai/cursor/rules/concorde-menu.mdc +0 -15
  324. package/ai/cursor/rules/concorde-scope.mdc +0 -14
  325. package/ai/cursor/rules/concorde-theme.mdc +0 -13
  326. package/ai/cursor/rules/concorde.mdc +0 -66
  327. package/ai/jetbrains/rules/concorde.md +0 -53
  328. package/ai/skills/concorde-get-set-dp/SKILL.md +0 -194
  329. package/ai/skills/concorde-imports/SKILL.md +0 -78
  330. package/ai/skills/concorde-menu/SKILL.md +0 -74
  331. package/ai/skills/concorde-scope/SKILL.md +0 -70
  332. package/ai/skills/concorde-theme/SKILL.md +0 -57
  333. package/docs/.htaccess +0 -75
  334. package/docs/404.html +0 -15
  335. package/docs/404.md +0 -5
  336. package/docs/assets/index-BgG6FFPt.js +0 -11765
  337. package/docs/assets/index-x89XINSG.css +0 -1
  338. package/docs/core/components/functional/date/date.html +0 -211
  339. package/docs/core/components/functional/date/date.md +0 -150
  340. package/docs/core/components/functional/fetch/fetch.html +0 -180
  341. package/docs/core/components/functional/fetch/fetch.md +0 -108
  342. package/docs/core/components/functional/if/if.html +0 -65
  343. package/docs/core/components/functional/if/if.md +0 -34
  344. package/docs/core/components/functional/jsonata/jsonata.html +0 -110
  345. package/docs/core/components/functional/jsonata/jsonata.md +0 -61
  346. package/docs/core/components/functional/list/list.html +0 -198
  347. package/docs/core/components/functional/list/list.md +0 -121
  348. package/docs/core/components/functional/mix/mix.html +0 -78
  349. package/docs/core/components/functional/mix/mix.md +0 -46
  350. package/docs/core/components/functional/queue/queue.html +0 -155
  351. package/docs/core/components/functional/queue/queue.md +0 -51
  352. package/docs/core/components/functional/router/router.html +0 -154
  353. package/docs/core/components/functional/router/router.md +0 -93
  354. package/docs/core/components/functional/sdui/sdui-extension-points.md +0 -94
  355. package/docs/core/components/functional/sdui/sdui.html +0 -397
  356. package/docs/core/components/functional/sdui/sdui.md +0 -307
  357. package/docs/core/components/functional/states/states.html +0 -141
  358. package/docs/core/components/functional/states/states.md +0 -112
  359. package/docs/core/components/functional/submit/submit.html +0 -178
  360. package/docs/core/components/functional/submit/submit.md +0 -106
  361. package/docs/core/components/functional/subscriber/subscriber.md +0 -91
  362. package/docs/core/components/functional/translation/translation.html +0 -60
  363. package/docs/core/components/functional/translation/translation.md +0 -38
  364. package/docs/core/components/functional/value/value.html +0 -81
  365. package/docs/core/components/functional/value/value.md +0 -47
  366. package/docs/core/components/ui/alert/alert.md +0 -186
  367. package/docs/core/components/ui/alert-messages/alert-messages.md +0 -85
  368. package/docs/core/components/ui/badge/badge.md +0 -181
  369. package/docs/core/components/ui/button/button.html +0 -309
  370. package/docs/core/components/ui/button/button.md +0 -216
  371. package/docs/core/components/ui/captcha/captcha.html +0 -80
  372. package/docs/core/components/ui/captcha/captcha.md +0 -56
  373. package/docs/core/components/ui/card/card.md +0 -215
  374. package/docs/core/components/ui/divider/divider.md +0 -126
  375. package/docs/core/components/ui/form/checkbox/checkbox.html +0 -200
  376. package/docs/core/components/ui/form/checkbox/checkbox.md +0 -125
  377. package/docs/core/components/ui/form/fieldset/fieldset.html +0 -238
  378. package/docs/core/components/ui/form/fieldset/fieldset.md +0 -161
  379. package/docs/core/components/ui/form/form-actions/form-actions.md +0 -98
  380. package/docs/core/components/ui/form/form-layout/form-layout.html +0 -115
  381. package/docs/core/components/ui/form/form-layout/form-layout.md +0 -109
  382. package/docs/core/components/ui/form/input/input.html +0 -235
  383. package/docs/core/components/ui/form/input/input.md +0 -142
  384. package/docs/core/components/ui/form/radio/radio.html +0 -144
  385. package/docs/core/components/ui/form/radio/radio.md +0 -78
  386. package/docs/core/components/ui/form/select/select.html +0 -178
  387. package/docs/core/components/ui/form/select/select.md +0 -86
  388. package/docs/core/components/ui/form/switch/switch.html +0 -146
  389. package/docs/core/components/ui/form/switch/switch.md +0 -80
  390. package/docs/core/components/ui/form/textarea/textarea.html +0 -162
  391. package/docs/core/components/ui/form/textarea/textarea.md +0 -82
  392. package/docs/core/components/ui/group/group.html +0 -113
  393. package/docs/core/components/ui/group/group.md +0 -77
  394. package/docs/core/components/ui/icon/icon.md +0 -214
  395. package/docs/core/components/ui/image/image.html +0 -194
  396. package/docs/core/components/ui/image/image.md +0 -167
  397. package/docs/core/components/ui/link/link.md +0 -81
  398. package/docs/core/components/ui/loader/loader.html +0 -114
  399. package/docs/core/components/ui/loader/loader.md +0 -87
  400. package/docs/core/components/ui/menu/menu.md +0 -370
  401. package/docs/core/components/ui/modal/modal.html +0 -324
  402. package/docs/core/components/ui/modal/modal.md +0 -211
  403. package/docs/core/components/ui/pop/pop.html +0 -250
  404. package/docs/core/components/ui/pop/pop.md +0 -216
  405. package/docs/core/components/ui/progress/progress.md +0 -109
  406. package/docs/core/components/ui/table/table.html +0 -333
  407. package/docs/core/components/ui/table/table.md +0 -267
  408. package/docs/core/components/ui/theme/theme.html +0 -116
  409. package/docs/core/components/ui/theme/theme.md +0 -97
  410. package/docs/core/components/ui/toast/toast.html +0 -185
  411. package/docs/core/components/ui/toast/toast.md +0 -147
  412. package/docs/core/components/ui/tooltip/tooltip.html +0 -112
  413. package/docs/core/components/ui/tooltip/tooltip.md +0 -89
  414. package/docs/docs/decorators/ancestor-attribute.html +0 -71
  415. package/docs/docs/decorators/ancestor-attribute.md +0 -59
  416. package/docs/docs/decorators/auto-subscribe.html +0 -61
  417. package/docs/docs/decorators/auto-subscribe.md +0 -40
  418. package/docs/docs/decorators/bind.html +0 -86
  419. package/docs/docs/decorators/bind.md +0 -77
  420. package/docs/docs/decorators/get.html +0 -166
  421. package/docs/docs/decorators/get.md +0 -160
  422. package/docs/docs/decorators/handle.html +0 -139
  423. package/docs/docs/decorators/handle.md +0 -119
  424. package/docs/docs/decorators/on-assign.html +0 -72
  425. package/docs/docs/decorators/on-assign.md +0 -63
  426. package/docs/docs/decorators/patch.html +0 -76
  427. package/docs/docs/decorators/patch.md +0 -44
  428. package/docs/docs/decorators/post.html +0 -150
  429. package/docs/docs/decorators/post.md +0 -134
  430. package/docs/docs/decorators/publish.html +0 -74
  431. package/docs/docs/decorators/publish.md +0 -56
  432. package/docs/docs/decorators/put.html +0 -83
  433. package/docs/docs/decorators/put.md +0 -51
  434. package/docs/docs/decorators/subscribe.html +0 -91
  435. package/docs/docs/decorators/subscribe.md +0 -87
  436. package/docs/docs/decorators/wait-for-ancestors.html +0 -82
  437. package/docs/docs/decorators/wait-for-ancestors.md +0 -76
  438. package/docs/docs/directives/sub.html +0 -79
  439. package/docs/docs/directives/sub.md +0 -75
  440. package/docs/docs/directives/t.html +0 -91
  441. package/docs/docs/directives/t.md +0 -73
  442. package/docs/docs/getting-started/ai-agents.md +0 -76
  443. package/docs/docs/getting-started/components.html +0 -27
  444. package/docs/docs/getting-started/components.md +0 -5
  445. package/docs/docs/getting-started/installation.html +0 -69
  446. package/docs/docs/getting-started/installation.md +0 -36
  447. package/docs/docs/getting-started/my-first-component.md +0 -227
  448. package/docs/docs/getting-started/start.html +0 -47
  449. package/docs/docs/getting-started/start.md +0 -35
  450. package/docs/docs/getting-started/theming.md +0 -253
  451. package/docs/docs/index.html +0 -99
  452. package/docs/docs/misc/api-configuration.md +0 -79
  453. package/docs/docs/misc/dataProviderKey.md +0 -168
  454. package/docs/hubs/decorators.html +0 -443
  455. package/docs/hubs/form-components.html +0 -404
  456. package/docs/hubs/remote-data.html +0 -371
  457. package/docs/img/archive/concorde-001-2cv.webp +0 -0
  458. package/docs/img/archive/concorde-red-arrows-2002-poster.jpg +0 -0
  459. package/docs/img/archive/concorde-red-arrows-2002.webm +0 -0
  460. package/docs/img/archive/credits.json +0 -28
  461. package/docs/index.md +0 -22
  462. package/docs/src/core/components/functional/translation/translation.md +0 -38
  463. package/docs/src/docs/decorators/ancestor-attribute.md +0 -59
  464. package/docs/src/docs/decorators/auto-subscribe.md +0 -40
  465. package/docs/src/docs/decorators/bind.md +0 -77
  466. package/docs/src/docs/decorators/get.md +0 -160
  467. package/docs/src/docs/decorators/handle.md +0 -119
  468. package/docs/src/docs/decorators/on-assign.md +0 -63
  469. package/docs/src/docs/decorators/patch.md +0 -44
  470. package/docs/src/docs/decorators/post.md +0 -134
  471. package/docs/src/docs/decorators/publish.md +0 -56
  472. package/docs/src/docs/decorators/put.md +0 -51
  473. package/docs/src/docs/decorators/subscribe.md +0 -87
  474. package/docs/src/docs/decorators/wait-for-ancestors.md +0 -76
  475. package/docs/src/docs/directives/sub.md +0 -75
  476. package/docs/src/docs/directives/t.md +0 -73
  477. package/docs/src/docs/getting-started/components.md +0 -5
  478. package/docs/src/docs/getting-started/create-a-component.md +0 -136
  479. package/docs/src/docs/getting-started/dataFlow.md +0 -87
  480. package/docs/src/docs/getting-started/installation.md +0 -36
  481. package/docs/src/docs/misc/docs-mock-api.md +0 -62
  482. package/docs/src/docs/misc/dynamic-path.md +0 -71
  483. package/docs/src/docs/misc/endpoint.md +0 -45
  484. package/docs/src/docs/misc/html-integration.md +0 -14
  485. /package/{docs → dist}/img/concorde/plane_01.jpg +0 -0
  486. /package/{docs → dist}/img/concorde/plane_02.jpg +0 -0
  487. /package/{docs → dist}/img/concorde/plane_03.jpg +0 -0
  488. /package/{docs → dist}/img/concorde/plane_04.jpg +0 -0
  489. /package/{docs → dist}/img/concorde/plane_05.jpg +0 -0
  490. /package/{docs → dist}/img/concorde/plane_06.jpg +0 -0
  491. /package/{docs → dist}/img/concorde/plane_07.jpg +0 -0
  492. /package/{docs → dist}/img/concorde/plane_08.jpg +0 -0
  493. /package/{docs → dist}/img/concorde/plane_09.jpg +0 -0
  494. /package/{docs → dist}/img/concorde/plane_10.jpg +0 -0
  495. /package/{docs → dist}/img/concorde/plane_11.jpg +0 -0
  496. /package/{docs → dist}/img/concorde/plane_12.jpg +0 -0
  497. /package/{docs → dist}/img/concorde/plane_13.jpg +0 -0
@@ -11,10 +11,39 @@ import type {
11
11
  } from "../_types/types";
12
12
  import type { DataProviderKey } from "./dataProviderKey";
13
13
  import { resolveStaticPublisherPath } from "./dataProviderKey";
14
+ import type { Frozen } from "./deepReadonly";
14
15
  import HTML from "./HTML";
16
+ import {
17
+ deepFreeze,
18
+ deleteAtKey,
19
+ setAtKey,
20
+ stripUndefinedKeys,
21
+ takeOwnership,
22
+ } from "./immutableValue";
15
23
  import Objects from "./Objects";
24
+ import {
25
+ getStrictGetMode,
26
+ setStrictGetMode,
27
+ wrapStrictGet,
28
+ type StrictGetMode,
29
+ } from "./strictGet";
16
30
  import { sonicClassPrefix } from "./Utils";
17
31
 
32
+ export type {
33
+ DeepReadonly,
34
+ Frozen,
35
+ FrozenArray,
36
+ FrozenObject,
37
+ } from "./deepReadonly";
38
+ /** @deprecated Prefer {@link Frozen}. */
39
+ export type ReadonlyDeep<T> = Frozen<T>;
40
+ export type { StrictGetMode } from "./strictGet";
41
+ export {
42
+ clearStrictGetWarnings,
43
+ getStrictGetMode,
44
+ setStrictGetMode,
45
+ } from "./strictGet";
46
+
18
47
  export type Observable = string;
19
48
 
20
49
  type DynamicFillingListener = any;
@@ -85,7 +114,7 @@ export class PublisherProxy<T = any> {
85
114
  _invalidate_on_page_show_ = false;
86
115
  _invalidateListeners_ = new Set<VoidFunction>();
87
116
  _formInvalidateListeners_ = new Set<VoidFunction>();
88
- _assignListeners_ = new Set<(value: T) => void>();
117
+ _assignListeners_ = new Set<(value: Frozen<T>) => void>();
89
118
  _mutationListeners_ = new Set<VoidFunction>();
90
119
  _fillListeners_ = new Set<Record<string, CoreJSType>>();
91
120
  _templateFillListeners_ = new Set<TemplateFillingListener>();
@@ -100,7 +129,8 @@ export class PublisherProxy<T = any> {
100
129
  parentProxPub: PublisherProxy | null,
101
130
  parentKey?: string,
102
131
  ) {
103
- this._value_ = target;
132
+ // Child publishers often receive an already-owned (frozen) subtree from the parent.
133
+ this._value_ = takeOwnership(target) as T;
104
134
  this.parent = parentProxPub || null;
105
135
  this._parentKey_ = parentKey;
106
136
  this.root = this;
@@ -165,7 +195,7 @@ export class PublisherProxy<T = any> {
165
195
  if (currentId !== this._assignmentId_) return;
166
196
  const newValue = this.get();
167
197
 
168
- this._assignListeners_.forEach((handler: (value: T) => void) => {
198
+ this._assignListeners_.forEach((handler) => {
169
199
  handler(newValue);
170
200
  });
171
201
  this._publishInternalMutation_(lockInternalMutationsTransmission);
@@ -206,7 +236,10 @@ export class PublisherProxy<T = any> {
206
236
  * Appel la fonction "handler" (passée en paramettre) lorsque la valeur gérée par le proxy change par assignation
207
237
  * hanlder reçois alors la nouvelle valeur interne du proxy en paramètre
208
238
  */
209
- onAssign(handler: (value: T) => void, directHandlerCall = true) {
239
+ onAssign(
240
+ handler: (value: Frozen<T>) => void,
241
+ directHandlerCall = true,
242
+ ) {
210
243
  if (typeof handler != "function") return;
211
244
  if (this._assignListeners_.has(handler)) return;
212
245
  this._assignListeners_.add(handler);
@@ -215,7 +248,7 @@ export class PublisherProxy<T = any> {
215
248
  /**
216
249
  * Stop les appels de la fonction "handler" (passée en paramettre) lorsque la valeur gérée par le proxy change par assignation
217
250
  */
218
- offAssign(handler: (value: T) => void) {
251
+ offAssign(handler: (value: Frozen<T>) => void) {
219
252
  this._assignListeners_.delete(handler);
220
253
  }
221
254
 
@@ -320,84 +353,54 @@ export class PublisherProxy<T = any> {
320
353
  this._fillListeners_.delete(handler);
321
354
  }
322
355
  /**
323
- * Assigne une nouvelle valeur au proxy ce qui déclenche la transmission de la donnée en fonction des "écouteurs" associés
356
+ * Assigne une nouvelle valeur : ownership (clone) + freeze, puis publication.
357
+ * @param alreadyOwned si true, `newValue` est déjà une valeur du store (frozen) — pas de re-clone.
324
358
  */
359
+ set(
360
+ newValue: T | Frozen<T>,
361
+ lockInternalMutationsTransmission = false,
362
+ alreadyOwned = false,
363
+ ) {
364
+ const normalized = (
365
+ isComplex(newValue) ? newValue : { __value: newValue }
366
+ ) as T;
367
+ const prepared = stripUndefinedKeys(normalized);
368
+ // alreadyOwned: freeze without re-clone (subtree from parent or fresh __value wrapper).
369
+ const owned = (
370
+ alreadyOwned ? deepFreeze(prepared) : takeOwnership(prepared)
371
+ ) as T;
325
372
 
326
- set(newValue: T, lockInternalMutationsTransmission = false) {
327
- /**
328
- * On retounre tout de suite si la valeur n'a pas changé
329
- */
330
-
331
- if (this._value_ === newValue) return true;
373
+ if (this._value_ === owned) return true;
332
374
 
333
- /**
334
- * On retounre tout de suite si la valeur n'a pas changé
335
- * et qu'elle est primitive
336
- */
337
375
  if (
338
376
  (isComplex(this._value_) &&
339
- isComplex(newValue) &&
340
- newValue &&
377
+ isComplex(owned) &&
378
+ owned &&
341
379
  isLeaf(this._value_) &&
342
- isLeaf(newValue) &&
343
- (this._value_ as any).__value === (newValue as any).__value) ||
380
+ isLeaf(owned) &&
381
+ (this._value_ as any).__value === (owned as any).__value) ||
344
382
  (!isComplex(newValue) && newValue === (this._value_ as any).__value)
345
383
  ) {
346
384
  return true;
347
385
  }
348
386
 
349
- /**
350
- * On assigne la nouvelle valeur
351
- */
352
-
353
- /** Si la valeur est complexe on assigne newValue directe sinon on le met dans une sous valeur __value */
354
- this._value_ = isComplex(newValue)
355
- ? newValue
356
- : ({ __value: newValue } as any);
387
+ this._value_ = owned;
357
388
  this._cachedGet_ = undefined;
358
389
 
359
- /**
360
- * Si il s'agit d'une valeur primitive (un entier, une chaine ) la valeure en renseignée par un objet contenant la vaeur {__value}
361
- * On publie juste et on sen va.
362
- */
363
390
  const isLeafNewValue = isLeaf(this._value_);
364
391
 
365
- if (this._parentKey_ && this.parent) {
366
- //si le parent n'a pas de valeur, on la crée en renseignant this.value et on retourne.
367
- const valueTosetInParent = isLeaf(this._value_)
368
- ? (this._value_ as any).__value
369
- : this._value_;
370
- if (this.parent?.get() == null && this.parent?.get() == undefined) {
371
- //if _parentKey_ is a number, we assume it's an array
372
- if (!isNaN(Number(this._parentKey_))) {
373
- const parent = [];
374
- parent[Number(this._parentKey_)] = valueTosetInParent;
375
- this.parent.set(parent);
376
- } else {
377
- this.parent.set({ [this._parentKey_]: valueTosetInParent });
378
- }
379
- // return;
380
- } else {
381
- //on mets à jour la valeur de la clef dans l'objet parnet pour refléter le changement au ca sou elle n'existait pas
382
- this.parent._value_[this._parentKey_] = valueTosetInParent;
383
- }
392
+ if (this._parentKey_ && this.parent && !lockInternalMutationsTransmission) {
393
+ this._syncOwnedValueIntoParent_(lockInternalMutationsTransmission);
384
394
  }
385
395
 
386
396
  if (isLeafNewValue) {
387
- // Si la valeur précédente était composite, on reset tous les sous-éléments à null
388
397
  this._proxies_.forEach((_subProxy, key) => {
389
- /**
390
- *
391
- * On reùmplace les undefined par des nuls pour eviter la suppression des clefs sauf pour les clef tableaux
392
- **/
393
-
394
398
  if (key != "_parent_") {
395
- _subProxy.set(null);
399
+ _subProxy.set(null, true, true);
396
400
  this._publishDynamicFilling_(key, null);
397
401
  }
398
402
  });
399
403
 
400
- //await //await here gives better performance but can cause issues with some listeners
401
404
  this._publishAssignement_(lockInternalMutationsTransmission);
402
405
  if (this.parent && this._parentKey_) {
403
406
  this.parent._publishDynamicFilling_(
@@ -408,23 +411,8 @@ export class PublisherProxy<T = any> {
408
411
 
409
412
  return true;
410
413
  }
411
- /**
412
- * On fait la diff sur l'existant.
413
- * On maintient les proxys à supprimer et ceux à ajouter.
414
- * On met à jour leur valeur interne
415
- * On publie les maj au fur et a mesure de modifications
416
- */
417
-
418
- for (const key in this._value_) {
419
- const currentValue = this._value_[key] as any;
420
- if (currentValue === undefined) delete this._value_[key];
421
- }
422
414
 
423
415
  this._proxies_.forEach((_subProxy, key) => {
424
- /**
425
- *
426
- * On reùmplace les undefined par des nuls pour eviter la suppression des clefs sauf pour les clef tableaux
427
- **/
428
416
  const currentValue: any = (this._value_ as any)[key];
429
417
 
430
418
  if (key != "_parent_") {
@@ -433,63 +421,99 @@ export class PublisherProxy<T = any> {
433
421
  currentValue !== null &&
434
422
  isNaN(Number(key))
435
423
  ) {
436
- _subProxy.set(null);
424
+ _subProxy.set(null, true, true);
437
425
  this._publishDynamicFilling_(key, null);
438
426
  }
439
427
  }
440
428
  });
441
429
 
442
- /**
443
- * On prévient les écouteurs que la valeur a changé
444
- */
445
- //await //await here gives better performance but can cause issues with some listeners
446
- this._publishAssignement_();
430
+ this._publishAssignement_(lockInternalMutationsTransmission);
447
431
  if (this.parent && this._parentKey_)
448
432
  this.parent._publishDynamicFilling_(
449
433
  this._parentKey_,
450
434
  this._value_ as any,
451
435
  );
452
- /**
453
- * Si la donnée est complexe (objet, tableau)
454
- * on crée les proxys pour les sous-éléments qui n'en on pas
455
- * On renseigne les nouvelles valeurs internes des proxies
456
- */
457
436
 
458
437
  if (isComplex(this._value_)) {
459
438
  for (const key in this._value_) {
460
- const v = newValue[key] as any;
439
+ const v = (this._value_ as any)[key];
461
440
  const isVComplex = isComplex(v);
462
441
  const valueV = isVComplex ? v : { __value: v };
463
442
  if (!this._proxies_.has(key)) {
464
- // A surveiller ancienne version
465
- // const newPublisher = new DataProvider({}, this);
466
- // this._proxies_.set(key, newPublisher);
467
- // newPublisher._proxies_.set("_parent_", this);
468
-
469
443
  this._publishDynamicFilling_(key, v);
470
444
  continue;
471
445
  }
472
- //await //await here gives better performance but can cause issues with some listeners
473
- this._proxies_.get(key)?.set(valueV, true);
446
+ // Child already holds an owned subtree — do not sync back to parent.
447
+ this._proxies_.get(key)?.set(valueV as any, true, true);
474
448
  this._publishDynamicFilling_(key, v);
475
449
  }
476
450
  }
477
451
  return true;
478
452
  }
453
+
454
+ /** Rebuild parent immutably so this node's owned value is reflected at `_parentKey_`. */
455
+ _syncOwnedValueIntoParent_(lockInternalMutationsTransmission = false) {
456
+ if (!this.parent || this._parentKey_ == null) return;
457
+ const valueTosetInParent = isLeaf(this._value_)
458
+ ? (this._value_ as any).__value
459
+ : this._value_;
460
+ const parentRaw = this.parent._value_;
461
+ const parentEmpty =
462
+ parentRaw == null ||
463
+ parentRaw === undefined ||
464
+ (isLeaf(parentRaw) && (parentRaw as any).__value == null);
465
+
466
+ if (parentEmpty) {
467
+ if (!isNaN(Number(this._parentKey_))) {
468
+ const parent: any[] = [];
469
+ parent[Number(this._parentKey_)] = valueTosetInParent;
470
+ this.parent.set(parent as any, lockInternalMutationsTransmission);
471
+ } else {
472
+ this.parent.set(
473
+ { [this._parentKey_]: valueTosetInParent } as any,
474
+ lockInternalMutationsTransmission,
475
+ );
476
+ }
477
+ return;
478
+ }
479
+
480
+ // Already reflected on parent (same ref) — skip rebuild/publish (avoids list render loops).
481
+ const currentAtKey = (parentRaw as any)[this._parentKey_];
482
+ if (currentAtKey === valueTosetInParent) return;
483
+
484
+ const nextParent = setAtKey(
485
+ parentRaw as object,
486
+ this._parentKey_,
487
+ valueTosetInParent,
488
+ );
489
+ this.parent.set(
490
+ nextParent as any,
491
+ lockInternalMutationsTransmission,
492
+ true,
493
+ );
494
+ }
479
495
  /**
480
496
  * Extraire la valeur actuelle du proxy
481
497
  */
482
498
  _cachedGet_?: T;
483
- get(): T {
499
+ /**
500
+ * Lecture typée {@link Frozen}. Runtime = valeur **owned / frozen** du store
501
+ * (même ref entre deux `set`). `strictGet` reste un radar optionnel sur le wrap.
502
+ */
503
+ get(): Frozen<T> {
484
504
  trackModifiedPublisher(this);
485
- if (this._cachedGet_ !== undefined) return this._cachedGet_;
486
- if (Object.prototype.hasOwnProperty.call(this._value_, "__value")) {
505
+ let raw: T;
506
+ if (this._cachedGet_ !== undefined) {
507
+ raw = this._cachedGet_;
508
+ } else if (Object.prototype.hasOwnProperty.call(this._value_, "__value")) {
487
509
  const v = (this._value_ as any).__value;
488
- return (this._cachedGet_ = (v != undefined ? v : null) as T);
510
+ raw = this._cachedGet_ = (v != undefined ? v : null) as T;
511
+ } else {
512
+ raw = this._cachedGet_ = (
513
+ this._value_ != undefined ? this._value_ : null
514
+ ) as T;
489
515
  }
490
- return (this._cachedGet_ = (
491
- this._value_ != undefined ? this._value_ : null
492
- ) as T);
516
+ return wrapStrictGet(raw) as Frozen<T>;
493
517
  }
494
518
  /**
495
519
  * retourner le webcomponent auquel le proxy est associé
@@ -539,6 +563,17 @@ export class PublisherManager {
539
563
  static saveId = 0;
540
564
  static instance: PublisherManager | null = null;
541
565
  static instances: Map<string, PublisherManager> = new Map();
566
+ /**
567
+ * Runtime guard on `get()` results: `off` | `warn` | `throw`.
568
+ * Default `off`. Enable in local/CI to detect in-place mutations after get().
569
+ * @see wrapStrictGet
570
+ */
571
+ static get strictGet(): StrictGetMode {
572
+ return getStrictGetMode();
573
+ }
574
+ static set strictGet(mode: StrictGetMode) {
575
+ setStrictGetMode(mode);
576
+ }
542
577
  enabledLocaStorageProxies: string[] = [];
543
578
  publishers = new Map<string, PublisherInterface>();
544
579
  localStorageData: Record<
@@ -825,6 +860,7 @@ const internalProps: Set<string> = new Set([
825
860
  "_publishFormInvalidation_",
826
861
  "_publishTemplateFilling_",
827
862
  "_publishAssignement_",
863
+ "_syncOwnedValueIntoParent_",
828
864
  "_proxies_",
829
865
  "parent",
830
866
  "_parentKey_",
@@ -943,19 +979,17 @@ function createPublisherHandler<T = any>(
943
979
  newPublisher._proxies_.set("_parent_", getProxy());
944
980
  publisherInstance._proxies_.set(sKey, newPublisher);
945
981
  }
946
- //mis à jour et publication de la donnée si elle a changé
947
982
 
948
- const prevValue = (publisherInstance._value_ as any)[sKey];
983
+ const prevValue = (publisherInstance._value_ as any)?.[sKey];
949
984
 
950
985
  if (prevValue !== vValue) {
951
- (publisherInstance._value_ as any)[sKey] = vValue;
952
- publisherInstance._publishDynamicFilling_(sKey, vValue);
953
- publisherInstance._proxies_
954
- .get(sKey)
955
- ?.set(isComplex(vValue) ? vValue : { __value: vValue });
986
+ const childStorage = isComplex(vValue)
987
+ ? vValue
988
+ : ({ __value: vValue } as any);
989
+ // Child commits owned value and syncs parent immutably (no in-place _value_ patch).
990
+ publisherInstance._proxies_.get(sKey)?.set(childStorage as any);
991
+ publisherInstance._publishDynamicFilling_(sKey, vValue as any);
956
992
  }
957
- //on retourne le proxy pour pouvoir chainer les assignements
958
- // return publisherInstance._proxies_.get(sKey);
959
993
  return true;
960
994
  },
961
995
  /**
@@ -963,12 +997,17 @@ function createPublisherHandler<T = any>(
963
997
  */
964
998
  deleteProperty: function (_publisherInstance, sKey: string) {
965
999
  publisherInstance._publishDynamicFilling_(sKey, null);
966
- // if (!publisherInstance._proxies_.get(sKey)?.hasListener()) {
967
- // publisherInstance._proxies_.delete(sKey);
968
- // } else {
969
- publisherInstance._proxies_.get(sKey)?.set(null);
970
- // }
971
- return delete (publisherInstance._value_ as any)[sKey];
1000
+ // Clear child without syncing; parent rebuild drops the key immutably.
1001
+ publisherInstance._proxies_.get(sKey)?.set(null, true, true);
1002
+ if (
1003
+ publisherInstance._value_ != null &&
1004
+ typeof publisherInstance._value_ === "object" &&
1005
+ !isLeaf(publisherInstance._value_)
1006
+ ) {
1007
+ const next = deleteAtKey(publisherInstance._value_ as object, sKey);
1008
+ publisherInstance.set(next as any, false, true);
1009
+ }
1010
+ return true;
972
1011
  },
973
1012
  // enumerate: function (publisherInstance, sKey): CoreJSType {
974
1013
  // return publisherInstance._value_.keys();
@@ -981,10 +1020,9 @@ function createPublisherHandler<T = any>(
981
1020
  },
982
1021
  defineProperty: function (_publisherInstance, sKey, oDesc) {
983
1022
  if (oDesc && "value" in oDesc) {
984
- (publisherInstance._value_ as any)[sKey] = oDesc.value;
1023
+ (getProxy() as any)[sKey] = oDesc.value;
985
1024
  }
986
1025
  return true;
987
- // return publisherInstance._value_;
988
1026
  },
989
1027
  getOwnPropertyDescriptor: function (_publisherInstance, sKey) {
990
1028
  sKey;
@@ -1076,12 +1114,12 @@ export const getObservables = <T = any>(
1076
1114
  return new Set<DataProvider<T>>([observable as DataProvider<T>]);
1077
1115
  };
1078
1116
 
1079
- // get value (snapshot at call time)
1080
- export function get<T>(id: DataProviderKey<T>): T;
1081
- export function get<T = any>(id: string): T;
1082
- export function get<T>(id: string | DataProviderKey<T>): T {
1117
+ // get value (typed Frozen — owned frozen store ref; see get() JSDoc)
1118
+ export function get<T>(id: DataProviderKey<T>): Frozen<T>;
1119
+ export function get<T = any>(id: string): Frozen<T>;
1120
+ export function get<T>(id: string | DataProviderKey<T>): Frozen<T> {
1083
1121
  const path = resolveStaticPublisherPath(id);
1084
- return getObservables<T>(path).values().next().value?.get() as T;
1122
+ return getObservables<T>(path).values().next().value?.get() as Frozen<T>;
1085
1123
  }
1086
1124
 
1087
1125
  function deepee<T>(
@@ -1177,9 +1215,12 @@ export function mirrorDp(
1177
1215
  );
1178
1216
  }
1179
1217
 
1180
- export function set<T>(id: DataProviderKey<T>, value: T): void;
1181
- export function set<T = any>(id: string, value: T): void;
1182
- export function set<T>(id: string | DataProviderKey<T>, value: T): void {
1218
+ export function set<T>(id: DataProviderKey<T>, value: T | Frozen<T>): void;
1219
+ export function set<T = any>(id: string, value: T | Frozen<T>): void;
1220
+ export function set<T>(
1221
+ id: string | DataProviderKey<T>,
1222
+ value: T | Frozen<T>,
1223
+ ): void {
1183
1224
  const path = resolveStaticPublisherPath(id);
1184
1225
  getObservables(path).values().next().value?.set(value);
1185
1226
  }
@@ -0,0 +1,66 @@
1
+ import { describe, it, expect, expectTypeOf } from "vitest";
2
+ import { DataProviderKey } from "./dataProviderKey";
3
+ import type { Frozen, FrozenArray } from "./deepReadonly";
4
+ import { dp, get, set } from "./PublisherProxy";
5
+
6
+ type Cart = { items: { id: number; qty: number }[]; total: number };
7
+ type City = { nom: string; code: string };
8
+
9
+ describe("Frozen get() (79567)", () => {
10
+ const cartKey = new DataProviderKey<Cart>("deepReadonlySpecCart");
11
+
12
+ it("runtime: get() returns the owned frozen store ref", () => {
13
+ const initial: Cart = { items: [{ id: 1, qty: 1 }], total: 1 };
14
+ set(cartKey, initial);
15
+ const snapshot = get(cartKey);
16
+ expect(snapshot).toBe(dp(cartKey).get());
17
+ expect(Object.isFrozen(snapshot)).toBe(true);
18
+ expect(() => {
19
+ (snapshot as Cart).total = 99;
20
+ }).toThrow();
21
+ expect(get(cartKey).total).toBe(1);
22
+ });
23
+
24
+ it("types: array is FrozenArray and index is Frozen element", () => {
25
+ type Arr = Frozen<City[]>;
26
+ expectTypeOf<Arr>().toMatchTypeOf<FrozenArray<City>>();
27
+ type Elem = Arr[0];
28
+ expectTypeOf<Elem>().toEqualTypeOf<Frozen<City>>();
29
+ });
30
+
31
+ it("types: get() is Frozen when the key is typed", () => {
32
+ set(cartKey, { items: [{ id: 1, qty: 1 }], total: 1 });
33
+ const cart = get(cartKey);
34
+ expectTypeOf(cart).toEqualTypeOf<Frozen<Cart>>();
35
+ expectTypeOf(cart.items).toMatchTypeOf<FrozenArray<{ id: number; qty: number }>>();
36
+ expect(cart.total).toBeTypeOf("number");
37
+ });
38
+
39
+ it("types: keyof FrozenObject keeps domain keys (IDE completions)", () => {
40
+ type Payload = { request: Request; response?: Response; result: City[] };
41
+ type Keys = keyof Frozen<Payload>;
42
+ expectTypeOf<Keys>().toEqualTypeOf<"request" | "response" | "result">();
43
+ type R = Frozen<Payload>["result"];
44
+ expectTypeOf<R>().toEqualTypeOf<FrozenArray<City>>();
45
+ });
46
+
47
+ it("types: nested mutation is rejected", () => {
48
+ set(cartKey, { items: [{ id: 1, qty: 1 }], total: 1 });
49
+ const cart = get(cartKey);
50
+ if (false as boolean) {
51
+ // @ts-expect-error Frozen blocks push on items
52
+ cart.items.push({ id: 2, qty: 1 });
53
+ // @ts-expect-error Frozen blocks property write
54
+ cart.total = 0;
55
+ // @ts-expect-error Frozen blocks nested write
56
+ cart.items[0].qty = 3;
57
+ }
58
+ expect(cart.items).toHaveLength(1);
59
+ });
60
+
61
+ it("set accepts get() snapshot without cast", () => {
62
+ set(cartKey, { items: [], total: 0 });
63
+ set(cartKey, get(cartKey));
64
+ expect(get(cartKey).total).toBe(0);
65
+ });
66
+ });
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Valeur du DataProvider en lecture seule (runtime = frozen).
3
+ *
4
+ * Nom public : `Frozen<T>`.
5
+ * - Tableaux → interface `FrozenArray<V>` (hover nommé + autocomplétion OK).
6
+ * - Objets → alias mappé `FrozenObject<T>` (l’interface `extends` un mapped
7
+ * générique est illégale / TS2312 → props perdues, `test.` vide).
8
+ * - Built-ins DOM/host (`Request`, `Response`, `Date`, …) : opaque, non retraversés
9
+ * (sinon language service noyé, ex. `ApiResult`).
10
+ */
11
+
12
+ /** Types host / builtin : shallow (pas de deep Frozen). */
13
+ type FrozenLeaf =
14
+ | Date
15
+ | RegExp
16
+ | Error
17
+ | ArrayBuffer
18
+ | SharedArrayBuffer
19
+ | DataView
20
+ | Promise<unknown>
21
+ | WeakMap<object, unknown>
22
+ | WeakSet<object>
23
+ | Request
24
+ | Response
25
+ | Headers
26
+ | FormData
27
+ | Blob
28
+ | File
29
+ | URL
30
+ | URLSearchParams
31
+ | AbortSignal
32
+ | AbortController
33
+ | ReadableStream<unknown>
34
+ | WritableStream<unknown>
35
+ | TransformStream<unknown, unknown>;
36
+
37
+ /**
38
+ * Objet frozen — mapped alias (seul pattern compatible autocomplétion).
39
+ * Hover peut déplier les champs ; le paramètre `T` reste le type maître.
40
+ */
41
+ export type FrozenObject<T> = {
42
+ readonly [K in keyof T]: Frozen<T[K]>;
43
+ };
44
+
45
+ /**
46
+ * Tableau frozen nommé — hover = `FrozenArray<V>` ; `arr[0]` = `Frozen<V>`.
47
+ */
48
+ export interface FrozenArray<T> extends ReadonlyArray<Frozen<T>> {}
49
+
50
+ export type Frozen<T> = 0 extends 1 & T
51
+ ? T
52
+ : unknown extends T
53
+ ? T
54
+ : T extends string | number | boolean | bigint | symbol | null | undefined
55
+ ? T
56
+ : T extends (...args: never[]) => unknown
57
+ ? T
58
+ : T extends FrozenLeaf
59
+ ? T
60
+ : T extends ReadonlyMap<infer K, infer V>
61
+ ? ReadonlyMap<Frozen<K>, Frozen<V>>
62
+ : T extends ReadonlySet<infer V>
63
+ ? ReadonlySet<Frozen<V>>
64
+ : T extends readonly (infer V)[]
65
+ ? FrozenArray<V>
66
+ : T extends object
67
+ ? FrozenObject<T>
68
+ : T;
69
+
70
+ /** @deprecated Prefer {@link Frozen} — même type, nom plus long. */
71
+ export type DeepReadonly<T> = Frozen<T>;
@@ -0,0 +1,54 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import {
3
+ deepFreeze,
4
+ deleteAtKey,
5
+ setAtKey,
6
+ takeOwnership,
7
+ } from "./immutableValue";
8
+
9
+ describe("immutableValue helpers", () => {
10
+ it("takeOwnership clones so external mutation does not affect owned value", () => {
11
+ const external = { a: 1, nested: { b: 2 } };
12
+ const owned = takeOwnership(external);
13
+ external.a = 9;
14
+ external.nested.b = 9;
15
+ expect(owned.a).toBe(1);
16
+ expect(owned.nested.b).toBe(2);
17
+ expect(Object.isFrozen(owned)).toBe(true);
18
+ expect(Object.isFrozen(owned.nested)).toBe(true);
19
+ });
20
+
21
+ it("takeOwnership is idempotent on frozen values", () => {
22
+ const once = takeOwnership({ x: 1 });
23
+ expect(takeOwnership(once)).toBe(once);
24
+ });
25
+
26
+ it("deepFreeze blocks assignment", () => {
27
+ const v = deepFreeze({ n: 1 });
28
+ expect(() => {
29
+ (v as { n: number }).n = 2;
30
+ }).toThrow();
31
+ });
32
+
33
+ it("setAtKey / deleteAtKey rebuild without mutating root", () => {
34
+ const root = takeOwnership({ a: 1, b: 2 });
35
+ const next = setAtKey(root, "b", 3);
36
+ expect(root.b).toBe(2);
37
+ expect(next.b).toBe(3);
38
+ expect(Object.isFrozen(next)).toBe(true);
39
+ const dropped = deleteAtKey(next, "a");
40
+ expect("a" in dropped).toBe(false);
41
+ expect(next.a).toBe(1);
42
+ });
43
+
44
+ it("unclonable values warn and pass through", () => {
45
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
46
+ const fn = () => 1;
47
+ const obj = { fn };
48
+ // functions inside plain objects: structuredClone throws in many engines
49
+ const owned = takeOwnership(obj);
50
+ expect(owned).toBe(obj);
51
+ expect(warn).toHaveBeenCalled();
52
+ warn.mockRestore();
53
+ });
54
+ });