@ryuzaki13/react-foundation-ui 1.8.11 → 1.8.13

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 (281) hide show
  1. package/dist/chunks/defaultRenderers-u_Vep6Pj.js.map +1 -1
  2. package/dist/chunks/multi-select-DtmRtX6v.js.map +1 -1
  3. package/dist/chunks/select-MN6zDPKM.js.map +1 -1
  4. package/dist/chunks/useODataSelectBase-DR4PrY1j.js.map +1 -1
  5. package/dist/multi-select/model/useODataMultiSelect.d.ts +1 -1
  6. package/dist/multi-select/model/useODataMultiSelect.d.ts.map +1 -1
  7. package/dist/multi-select/ui/MultiSelect.d.ts +1 -1
  8. package/dist/multi-select/ui/MultiSelect.d.ts.map +1 -1
  9. package/dist/multi-select/ui/SerializableMultiSelect.d.ts.map +1 -1
  10. package/dist/multi-select/ui/defaultRenderers.d.ts +1 -1
  11. package/dist/multi-select/ui/defaultRenderers.d.ts.map +1 -1
  12. package/dist/select/model/useODataSelect.d.ts +1 -1
  13. package/dist/select/model/useODataSelect.d.ts.map +1 -1
  14. package/dist/select/model/useODataSelectBase.d.ts +1 -1
  15. package/dist/select/model/useODataSelectBase.d.ts.map +1 -1
  16. package/dist/tree-select/index.js.map +1 -1
  17. package/dist/tree-select/model/buildODataTreeNodes.d.ts +1 -1
  18. package/dist/tree-select/model/buildODataTreeNodes.d.ts.map +1 -1
  19. package/package.json +3 -3
  20. package/storybook-static/assets/{Badge-BojMuOws.js → Badge-BFhBl7yM.js} +1 -1
  21. package/storybook-static/assets/{Badge.stories-C9gJRuIO.js → Badge.stories-BEu55X4s.js} +1 -1
  22. package/storybook-static/assets/{BadgeList-dNEWI7-O.js → BadgeList-mqmnGtRR.js} +1 -1
  23. package/storybook-static/assets/{Button-Bbt3JzIY.js → Button-CESdnWrO.js} +1 -1
  24. package/storybook-static/assets/{Button-CrTHXWYk.js → Button-_YPAu9sd.js} +1 -1
  25. package/storybook-static/assets/{Button.stories-BaYXOBeF.js → Button.stories-B0Y_T17B.js} +1 -1
  26. package/storybook-static/assets/{CalendarView-Dp0zus1o.js → CalendarView-DLuO2Ywz.js} +1 -1
  27. package/storybook-static/assets/{CheckBox-BiK9yWNt.js → CheckBox-CGiNmAPT.js} +1 -1
  28. package/storybook-static/assets/{CheckBox-UzYHaD6S.js → CheckBox-l0pbBm9z.js} +1 -1
  29. package/storybook-static/assets/{CheckBox.stories-C2BOiWZj.js → CheckBox.stories-ROPAnqh8.js} +1 -1
  30. package/storybook-static/assets/{Color-6AOWCN3U-C5S4wUlD.js → Color-6AOWCN3U-kPaRN0HS.js} +1 -1
  31. package/storybook-static/assets/{ContextMenu-D9EZxb7d.js → ContextMenu-Bob4DtRn.js} +1 -1
  32. package/storybook-static/assets/{ContextMenu-BWQln_tb.js → ContextMenu-DxfUAeJS.js} +1 -1
  33. package/storybook-static/assets/{ContextMenu.stories-U38zPh9_.js → ContextMenu.stories-DCJmWy5n.js} +1 -1
  34. package/storybook-static/assets/{CustomOptionButton-COIOrxQn.js → CustomOptionButton-DuEz9CXt.js} +1 -1
  35. package/storybook-static/assets/DateInput-BQ8SoeLE.js +1 -0
  36. package/storybook-static/assets/{DateInput-C-entb-r.js → DateInput-DmNLD4Dz.js} +1 -1
  37. package/storybook-static/assets/{DateInput.stories-NmUXQLDU.js → DateInput.stories-sTpYf7Ob.js} +1 -1
  38. package/storybook-static/assets/{DateRangePresetSelect-BM1L1KOo.js → DateRangePresetSelect-DRq4eJ2n.js} +1 -1
  39. package/storybook-static/assets/{DateRangePresetSelect-CAJzxaq0.js → DateRangePresetSelect-fgJfLaLO.js} +1 -1
  40. package/storybook-static/assets/{DateRangePresetSelect.stories-CC47XLnD.js → DateRangePresetSelect.stories-ib7Qh_BB.js} +1 -1
  41. package/storybook-static/assets/{Detail-CDluXtts.js → Detail-CJniLn1R.js} +1 -1
  42. package/storybook-static/assets/{Detail.stories-DjniLC4n.js → Detail.stories-BXjdNaL-.js} +1 -1
  43. package/storybook-static/assets/{Dialog-bzRSgGU7.js → Dialog-D6a_qzr3.js} +1 -1
  44. package/storybook-static/assets/{Dialog-bw6cHUsz.js → Dialog-DOYnnXlU.js} +1 -1
  45. package/storybook-static/assets/{Dialog.stories-C6Rs6s_p.js → Dialog.stories-B1cZLRK3.js} +1 -1
  46. package/storybook-static/assets/{Disclosure-DelA6FsQ.js → Disclosure-Chh5o_0s.js} +1 -1
  47. package/storybook-static/assets/{Disclosure.stories-D7yUinyb.js → Disclosure.stories-Cvdvf7V8.js} +1 -1
  48. package/storybook-static/assets/{DisclosureGroup-DbK7mU_Q.js → DisclosureGroup-CRnQOgVj.js} +1 -1
  49. package/storybook-static/assets/{DocsRenderer-JROSPFPF-v3z0zVN1.js → DocsRenderer-JROSPFPF-BBiErkeC.js} +1 -1
  50. package/storybook-static/assets/{DropZone-CI3NW4AC.js → DropZone-Bm5gqdi9.js} +1 -1
  51. package/storybook-static/assets/{DropZone-Cyy-ttEO.js → DropZone-C4L7JAlq.js} +1 -1
  52. package/storybook-static/assets/{DropZone.stories-S0HSpGTB.js → DropZone.stories-BhA9q8Qv.js} +1 -1
  53. package/storybook-static/assets/{DropdownMenu-Ct1bSZsE.js → DropdownMenu-DtZNSUHF.js} +1 -1
  54. package/storybook-static/assets/{ExpandableActionPanel-Oj3xlasj.js → ExpandableActionPanel-0ugXlJy_.js} +1 -1
  55. package/storybook-static/assets/{ExpandableActionPanel.stories-Ch7CLkpR.js → ExpandableActionPanel.stories-CLgMlA9k.js} +1 -1
  56. package/storybook-static/assets/{Flex-UiFm8Tkc.js → Flex-CJlia-8f.js} +1 -1
  57. package/storybook-static/assets/{Flex.stories-CaDiVlBD.js → Flex.stories-DCvfi1EY.js} +1 -1
  58. package/storybook-static/assets/{FloatingPopover-CTYV9W7T.js → FloatingPopover-CsnfPiwV.js} +1 -1
  59. package/storybook-static/assets/{FormattedTableCell-D-ysSR3p.js → FormattedTableCell-Dz5xWVYO.js} +1 -1
  60. package/storybook-static/assets/{Grid-CigBXPe2.js → Grid-C-KwTRAM.js} +1 -1
  61. package/storybook-static/assets/{Grid.stories-ay3z9DQZ.js → Grid.stories-CzbqknNR.js} +1 -1
  62. package/storybook-static/assets/{ImageCropper.stories-Dkce_ugb.js → ImageCropper.stories-DaE-gm-b.js} +1 -1
  63. package/storybook-static/assets/{ImageRenderer-C9_EmGBW.js → ImageRenderer-IsNCXCrZ.js} +1 -1
  64. package/storybook-static/assets/{ImageRenderer.stories-C7bXaNBI.js → ImageRenderer.stories-BbsjUEfJ.js} +1 -1
  65. package/storybook-static/assets/{ImageView.stories-D-ZzGlk8.js → ImageView.stories-DY0UITYz.js} +1 -1
  66. package/storybook-static/assets/{ImageViewer.stories-ItcRfxyy.js → ImageViewer.stories--9q9b9nv.js} +2 -2
  67. package/storybook-static/assets/{ImageViewerRuntime-eaupID36.js → ImageViewerRuntime-CNEH3XGN.js} +1 -1
  68. package/storybook-static/assets/{Input-op4j7Beh.js → Input-DLubbE7P.js} +1 -1
  69. package/storybook-static/assets/{Input-BUDNR96c.js → Input-Dw2JblYt.js} +1 -1
  70. package/storybook-static/assets/{Input.stories-DwulvJIg.js → Input.stories-DQeyDULG.js} +1 -1
  71. package/storybook-static/assets/{InputDateTime-B_cxOp6k.js → InputDateTime-BRzl8Vrt.js} +1 -1
  72. package/storybook-static/assets/{InputDateTime.stories-BueLF4HC.js → InputDateTime.stories-BJTj5v8J.js} +1 -1
  73. package/storybook-static/assets/{InputFile-DSg7sugm.js → InputFile-B8UroZji.js} +1 -1
  74. package/storybook-static/assets/{InputFile-C8z6TPc1.js → InputFile-DPftxjGw.js} +1 -1
  75. package/storybook-static/assets/{InputFile.stories-C6XSbIua.js → InputFile.stories-C7yyqHqc.js} +1 -1
  76. package/storybook-static/assets/{InputFiles-DoatLq3q.js → InputFiles-BQVXHVLy.js} +1 -1
  77. package/storybook-static/assets/{InputFiles-DeZ84Uu_.js → InputFiles-UD_9S7-N.js} +1 -1
  78. package/storybook-static/assets/{InputFiles.stories-BMbE8SJU.js → InputFiles.stories-DjjJS5pZ.js} +1 -1
  79. package/storybook-static/assets/{InputFilesList-CsfDDqaJ.js → InputFilesList-BNjijD3Y.js} +1 -1
  80. package/storybook-static/assets/{InputImage-yJSq98EH.js → InputImage-C-pHr-Sx.js} +1 -1
  81. package/storybook-static/assets/{InputImage-D_YnB2Tw.js → InputImage-DbcbqIhY.js} +1 -1
  82. package/storybook-static/assets/{InputImage.stories-nivUG307.js → InputImage.stories-D-TC9r9t.js} +1 -1
  83. package/storybook-static/assets/{InteractiveComponents-IPkC_Rkg.js → InteractiveComponents-DbhWgM9y.js} +1 -1
  84. package/storybook-static/assets/{InteractiveComponents.stories-D4VzVKZJ.js → InteractiveComponents.stories-B4mkVSea.js} +1 -1
  85. package/storybook-static/assets/{LayoutPicker-ZHkMi-LM.js → LayoutPicker-BoV_E3qt.js} +1 -1
  86. package/storybook-static/assets/{LayoutPicker-aMzPN5Do.js → LayoutPicker-w1EsRpYP.js} +1 -1
  87. package/storybook-static/assets/{LayoutPicker.stories-DAzpzxn5.js → LayoutPicker.stories--ChGnGxf.js} +1 -1
  88. package/storybook-static/assets/{Listbox-CR5nXC9J.js → Listbox-CzZRsr6a.js} +1 -1
  89. package/storybook-static/assets/{Listbox-BmfQOnrb.js → Listbox-qZdTi11b.js} +1 -1
  90. package/storybook-static/assets/{Listbox.stories-CeOpsKxB.js → Listbox.stories-C9k_1850.js} +1 -1
  91. package/storybook-static/assets/{Modal-BStp52Zo.js → Modal-DCpul8QM.js} +1 -1
  92. package/storybook-static/assets/{Modal.stories-CwGm5GYE.js → Modal.stories-Cy0Xd4LF.js} +1 -1
  93. package/storybook-static/assets/{ModalManagerProvider-B5uUXWF9.js → ModalManagerProvider-BrPVMcHV.js} +1 -1
  94. package/storybook-static/assets/{MultiSelect-308npb27.js → MultiSelect-BEQdl-F4.js} +1 -1
  95. package/storybook-static/assets/{MultiSelect-BDs02MZh.js → MultiSelect-Dy4X94E2.js} +1 -1
  96. package/storybook-static/assets/{MultiSelect.stories-DRi_iTp4.js → MultiSelect.stories-FuzejJmz.js} +1 -1
  97. package/storybook-static/assets/{NoData-ovaQEE9W.js → NoData-BsQ9EfkA.js} +1 -1
  98. package/storybook-static/assets/{NotificationsHost-BpeMWhLY.js → NotificationsHost-BSrODvw7.js} +1 -1
  99. package/storybook-static/assets/NotificationsHost.stories-DeiWspcY.js +29 -0
  100. package/storybook-static/assets/{ODataMultiSelect-qlft9L9L.js → ODataMultiSelect-BEz9gcd2.js} +1 -1
  101. package/storybook-static/assets/{ODataMultiSelect.stories-CMPIoPiy.js → ODataMultiSelect.stories-BwMgAkbE.js} +2 -2
  102. package/storybook-static/assets/{ODataSelect-DKBQArAK.js → ODataSelect-BgC7GHOv.js} +1 -1
  103. package/storybook-static/assets/{ODataSelect.stories-DxYIhtwe.js → ODataSelect.stories-DEIRAB-s.js} +2 -2
  104. package/storybook-static/assets/{ODataTreeMultiSelect-DAt6THP3.js → ODataTreeMultiSelect-WyZZuX0_.js} +1 -1
  105. package/storybook-static/assets/{ODataTreeMultiSelect.stories-CBNJP0mP.js → ODataTreeMultiSelect.stories-B6cxuagy.js} +1 -1
  106. package/storybook-static/assets/{ODataTreeSelect-Bzzt4CQC.js → ODataTreeSelect-OJGi3-S7.js} +1 -1
  107. package/storybook-static/assets/{ODataTreeSelect.stories-CWVvuqOt.js → ODataTreeSelect.stories-wGRGErCH.js} +1 -1
  108. package/storybook-static/assets/{OneStepScroller-BY5lz8qi.js → OneStepScroller-DycQ3RuL.js} +1 -1
  109. package/storybook-static/assets/{Option-Rw8xwrPg.js → Option-taxbFfjo.js} +1 -1
  110. package/storybook-static/assets/{OptionButton-Br48w_Zg.js → OptionButton-Q0QaPCII.js} +1 -1
  111. package/storybook-static/assets/{PeriodSelect-8-wpXz6w.js → PeriodSelect-DUJ2nF3F.js} +1 -1
  112. package/storybook-static/assets/{PeriodSelect-DxSRwKw-.js → PeriodSelect-DnM7x-uC.js} +1 -1
  113. package/storybook-static/assets/{PeriodSelect.stories-B-qgUzlS.js → PeriodSelect.stories-Db0bqe3J.js} +1 -1
  114. package/storybook-static/assets/{PickerTriggerActions-C5xmysFh.js → PickerTriggerActions-CGJd7xmR.js} +1 -1
  115. package/storybook-static/assets/{Popover-NJwt_vZZ.js → Popover-B6oidz5p.js} +1 -1
  116. package/storybook-static/assets/{Popover-Ds8PUigp.js → Popover-Tbhf8T81.js} +1 -1
  117. package/storybook-static/assets/{Popover.stories-CUOFA_Xf.js → Popover.stories-DE1LxZvv.js} +1 -1
  118. package/storybook-static/assets/{PresetRangeDateInput-DyOpbkON.js → PresetRangeDateInput-CQ5FfmrL.js} +1 -1
  119. package/storybook-static/assets/{PresetRangeDateInput-Xk0bOy3S.js → PresetRangeDateInput-DfgoR0My.js} +1 -1
  120. package/storybook-static/assets/{PresetRangeDateInput.stories-CwjUlXj0.js → PresetRangeDateInput.stories-CgoYAYBG.js} +1 -1
  121. package/storybook-static/assets/{PresetSelect-Ddmr0niY.js → PresetSelect-BPtAknAr.js} +1 -1
  122. package/storybook-static/assets/README--TpGcM95.js +110 -0
  123. package/storybook-static/assets/{README-MzcO5Z_P.js → README-4iBHWAP5.js} +1 -1
  124. package/storybook-static/assets/README-98KIgy5G.js +75 -0
  125. package/storybook-static/assets/README-B6II8p0W.js +154 -0
  126. package/storybook-static/assets/{README-CkWglKbS.js → README-B6vU5_7I.js} +1 -1
  127. package/storybook-static/assets/README-BFJVjjZR.js +325 -0
  128. package/storybook-static/assets/README-BIT4HlFP.js +441 -0
  129. package/storybook-static/assets/{README-DqQDgJN-.js → README-BK6Epio1.js} +1 -1
  130. package/storybook-static/assets/{README-DRnlD7y8.js → README-BRlPB5_k.js} +1 -1
  131. package/storybook-static/assets/README-BTFpEaXG.js +64 -0
  132. package/storybook-static/assets/README-BWhXgC_o.js +226 -0
  133. package/storybook-static/assets/README-BbNHvOoR.js +101 -0
  134. package/storybook-static/assets/README-BbunUo8b.js +118 -0
  135. package/storybook-static/assets/README-BmYpfZKr.js +1844 -0
  136. package/storybook-static/assets/README-Bu5uvhAT.js +230 -0
  137. package/storybook-static/assets/README-Bx6fvSBE.js +1282 -0
  138. package/storybook-static/assets/README-Bx6gIGiA.js +69 -0
  139. package/storybook-static/assets/README-ByhxsX44.js +324 -0
  140. package/storybook-static/assets/README-Byi1FFpw.js +98 -0
  141. package/storybook-static/assets/README-C3Is3a3B.js +208 -0
  142. package/storybook-static/assets/{README-C0BwTe5N.js → README-C6prwAXw.js} +1 -1
  143. package/storybook-static/assets/{README-BzVni2ve.js → README-C9S83J_G.js} +1 -1
  144. package/storybook-static/assets/{README-BHw6MVjD.js → README-CGgxP5Zo.js} +1 -1
  145. package/storybook-static/assets/README-CJ2ZVG2U.js +2124 -0
  146. package/storybook-static/assets/README-CNGCAm5d.js +95 -0
  147. package/storybook-static/assets/README-Cb_q420B.js +90 -0
  148. package/storybook-static/assets/README-CtIDPNJ3.js +186 -0
  149. package/storybook-static/assets/README-CzO3Dchr.js +64 -0
  150. package/storybook-static/assets/README-D0rzQthv.js +264 -0
  151. package/storybook-static/assets/README-DEQu7djz.js +1704 -0
  152. package/storybook-static/assets/README-DFihT_sm.js +296 -0
  153. package/storybook-static/assets/{README-CTIBG4zH.js → README-DMiWsyv_.js} +1 -1
  154. package/storybook-static/assets/README-DOx8lXXk.js +82 -0
  155. package/storybook-static/assets/{README-DzTc6XmY.js → README-DPhDjr43.js} +1 -1
  156. package/storybook-static/assets/{README-Dki94Nf2.js → README-D_NqWPa9.js} +1 -1
  157. package/storybook-static/assets/README-DhJ5Rb1w.js +355 -0
  158. package/storybook-static/assets/README-DlwhWCvQ.js +1146 -0
  159. package/storybook-static/assets/README-Dxi73a2Q.js +740 -0
  160. package/storybook-static/assets/README-Dycov6NP.js +583 -0
  161. package/storybook-static/assets/README-GTBkSG4_.js +3591 -0
  162. package/storybook-static/assets/README-Gfd9tLTw.js +672 -0
  163. package/storybook-static/assets/{README-B4zYJg6u.js → README-Kfawetke.js} +1 -1
  164. package/storybook-static/assets/{README-BzVHwvgo.js → README-UDBM7ZMT.js} +1 -1
  165. package/storybook-static/assets/{README-D-XjRtAE.js → README-VTWQxLm_.js} +1 -1
  166. package/storybook-static/assets/README-YHNWrTZv.js +400 -0
  167. package/storybook-static/assets/README-_0Otw0eD.js +448 -0
  168. package/storybook-static/assets/README-aw2Xu9xu.js +158 -0
  169. package/storybook-static/assets/README-eg1emlll.js +192 -0
  170. package/storybook-static/assets/README-iqQHdhZ4.js +416 -0
  171. package/storybook-static/assets/{README-BdPlV5nA.js → README-llxZAtCj.js} +1 -1
  172. package/storybook-static/assets/README-wFnEIGl4.js +95 -0
  173. package/storybook-static/assets/{README-Dx3cpFMr.js → README-webB1yH0.js} +1 -1
  174. package/storybook-static/assets/README-wtreGRCe.js +208 -0
  175. package/storybook-static/assets/{RadioButton-DWbkCY8u.js → RadioButton-CNOLDk_o.js} +1 -1
  176. package/storybook-static/assets/{RadioButton-oSvQ-gQh.js → RadioButton-Ce05_q7s.js} +1 -1
  177. package/storybook-static/assets/{RadioButton.stories-GNQ9XJZT.js → RadioButton.stories-CPd4lTl0.js} +1 -1
  178. package/storybook-static/assets/{RadioGroup-CvXjGXcV.js → RadioGroup-BtfD5Szd.js} +1 -1
  179. package/storybook-static/assets/{RadioGroup-eBYggurL.js → RadioGroup-Ccm7G-dv.js} +1 -1
  180. package/storybook-static/assets/{RadioGroup.stories-C77j_cPv.js → RadioGroup.stories-D-RRPHwi.js} +1 -1
  181. package/storybook-static/assets/{Scrollable-De6SdhI3.js → Scrollable-DvdBIeig.js} +1 -1
  182. package/storybook-static/assets/{Select-DQMoVjn4.js → Select-8PV9PBKF.js} +1 -1
  183. package/storybook-static/assets/{Select-Bwc0bEpt.js → Select-G04B41FM.js} +1 -1
  184. package/storybook-static/assets/{Select.stories-BSIJKJnM.js → Select.stories-Cf6CBhV8.js} +1 -1
  185. package/storybook-static/assets/{SerializableSelect-B73irNFR.js → SerializableSelect-CdQdHIVp.js} +1 -1
  186. package/storybook-static/assets/{SerializableSelect.stories-Z9q6g5v2.js → SerializableSelect.stories-0AKUGpbS.js} +1 -1
  187. package/storybook-static/assets/{SingleDateTimeInput-Dq9LcjnS.js → SingleDateTimeInput-DWT1ORhL.js} +1 -1
  188. package/storybook-static/assets/{SingleDateTimeInput-BHl6srqA.js → SingleDateTimeInput-DattLt6w.js} +1 -1
  189. package/storybook-static/assets/SingleDateTimeInput.stories-BLJV3jzV.js +48 -0
  190. package/storybook-static/assets/{Slider-CvM0N_kc.js → Slider-DKEI4cDd.js} +1 -1
  191. package/storybook-static/assets/{Slider-BiyKexKa.js → Slider-Dci-mJt_.js} +1 -1
  192. package/storybook-static/assets/{Slider.stories-CdHAMDmY.js → Slider.stories-Dp7oQueF.js} +1 -1
  193. package/storybook-static/assets/{SliderInput-DqHotbhB.js → SliderInput-BGPQmlgY.js} +1 -1
  194. package/storybook-static/assets/{SliderInput-Bx_oHUCV.js → SliderInput-BhjqGOKt.js} +1 -1
  195. package/storybook-static/assets/{SliderInput.stories-R5yDhghM.js → SliderInput.stories-DXNhRU3X.js} +1 -1
  196. package/storybook-static/assets/{Sortable-D7pjTHO0.js → Sortable-CMd9l1Gd.js} +1 -1
  197. package/storybook-static/assets/{Sortable.stories-CVLG6pSH.js → Sortable.stories-BN1cFEFJ.js} +1 -1
  198. package/storybook-static/assets/{Splitter-B1Du6XI2.js → Splitter-GL65TlI9.js} +1 -1
  199. package/storybook-static/assets/{Splitter.stories-D-FRLMCc.js → Splitter.stories-q5PlI6rB.js} +1 -1
  200. package/storybook-static/assets/{StateSelect-zl-yZibY.js → StateSelect-Byik5-iZ.js} +1 -1
  201. package/storybook-static/assets/{StateSelect-BJdUEUBc.js → StateSelect-CT0JF2V6.js} +1 -1
  202. package/storybook-static/assets/{StateSelect.stories-DgidR5zR.js → StateSelect.stories-pPEPmgnN.js} +1 -1
  203. package/storybook-static/assets/{StringToggle.stories-IucGrtIi.js → StringToggle.stories-BQlFmCE7.js} +1 -1
  204. package/storybook-static/assets/{Switch-BJrn2lIN.js → Switch--xGPiYk-.js} +1 -1
  205. package/storybook-static/assets/{Switch-5dCshvVo.js → Switch-DhaLI9CG.js} +1 -1
  206. package/storybook-static/assets/{Switch.stories-Dp_l3_JL.js → Switch.stories-5DisgIyj.js} +1 -1
  207. package/storybook-static/assets/{Table-BFAEcUde.js → Table-Bf6MicdG.js} +1 -1
  208. package/storybook-static/assets/{Table.stories-CohejRQv.js → Table.stories-CS7rQgj9.js} +2 -2
  209. package/storybook-static/assets/{Tabs-CI32QiHf.js → Tabs-B4y4y8Ap.js} +1 -1
  210. package/storybook-static/assets/{Tabs.stories-Cr9d9ipA.js → Tabs.stories-C0SpdGkh.js} +1 -1
  211. package/storybook-static/assets/{TabsBox-BlDOUDMF.js → TabsBox-C5LLLhnj.js} +1 -1
  212. package/storybook-static/assets/{TagInput-YZ7eSv8W.js → TagInput-D4BpuCoH.js} +1 -1
  213. package/storybook-static/assets/{TagInput.stories-DrOvsiI5.js → TagInput.stories-rn2wtZP_.js} +1 -1
  214. package/storybook-static/assets/{Text-DK4jN26J.js → Text-BhBt9e7C.js} +1 -1
  215. package/storybook-static/assets/{Textarea-CFh5f_lC.js → Textarea-B-Hz7ujq.js} +1 -1
  216. package/storybook-static/assets/{Textarea-DxPuWBZj.js → Textarea-BHHxY5sd.js} +1 -1
  217. package/storybook-static/assets/{Textarea.stories-CUeOGKYc.js → Textarea.stories-CZ2kWz20.js} +1 -1
  218. package/storybook-static/assets/{TimePanel-BUhFtwlb.js → TimePanel-Cg8fgFsn.js} +1 -1
  219. package/storybook-static/assets/{TimePanel.stories-CpXpMBDN.js → TimePanel.stories-BxdwtK2e.js} +1 -1
  220. package/storybook-static/assets/{Toggle-l2AvDbRn.js → Toggle-BWwfk9fi.js} +1 -1
  221. package/storybook-static/assets/{Toggle-BtApzBNH.js → Toggle-Ce9rbjBc.js} +1 -1
  222. package/storybook-static/assets/{Toggle.stories-Ca8otmAa.js → Toggle.stories-0fzcmzKy.js} +1 -1
  223. package/storybook-static/assets/{TreeMultiSelect-C9QDV63L.js → TreeMultiSelect-B06Y0lIc.js} +1 -1
  224. package/storybook-static/assets/{TreeMultiSelect-nXC4ZB5b.js → TreeMultiSelect-CrAdR_jM.js} +1 -1
  225. package/storybook-static/assets/{TreeMultiSelect.stories-6STRGJbF.js → TreeMultiSelect.stories-CAVoj56E.js} +1 -1
  226. package/storybook-static/assets/{TreePickerBase-Cq7fSw3x.js → TreePickerBase-qU2xPlar.js} +1 -1
  227. package/storybook-static/assets/{TreeSelect-CITef9rp.js → TreeSelect-BIHydJFy.js} +1 -1
  228. package/storybook-static/assets/{TreeSelect-rMNyu_KT.js → TreeSelect-BKnWu0C7.js} +1 -1
  229. package/storybook-static/assets/{TreeSelect.stories-B-Emz9yW.js → TreeSelect.stories-Dp_8ybAf.js} +1 -1
  230. package/storybook-static/assets/{TreeTable-CLiP0td3.js → TreeTable-pVXjU9dG.js} +1 -1
  231. package/storybook-static/assets/{TreeTable.stories-DJb9qt8k.js → TreeTable.stories-CV_8Ui6R.js} +2 -2
  232. package/storybook-static/assets/{blocks-DndFRxxW.js → blocks-BY40djCc.js} +3 -3
  233. package/storybook-static/assets/{check-CLkTJVXe.js → check-CVkPTDzp.js} +1 -1
  234. package/storybook-static/assets/{chevron-down-miCejSEn.js → chevron-down-BtNO4Vhe.js} +1 -1
  235. package/storybook-static/assets/{chevron-left-DhQIPej2.js → chevron-left-kceSK3sZ.js} +1 -1
  236. package/storybook-static/assets/{chevron-right-DfBBx-fr.js → chevron-right-BA_LO2El.js} +1 -1
  237. package/storybook-static/assets/{chunk-W22LQPXL-IdwKKJUw.js → chunk-W22LQPXL-yJiFPv6e.js} +1 -1
  238. package/storybook-static/assets/{circle-alert-DOmVf8am.js → circle-alert-B2m4a1zz.js} +1 -1
  239. package/storybook-static/assets/{circle-check-e7eSQ2VD.js → circle-check-Cfjhotlm.js} +1 -1
  240. package/storybook-static/assets/{components-Bm4Cw8Ap.js → components-D6yV8PLX.js} +3 -3
  241. package/storybook-static/assets/{contextMenu-DpIKeJju.js → contextMenu-B0pQBIW0.js} +1 -1
  242. package/storybook-static/assets/{defaultRenderers-m21aWJXz.js → defaultRenderers-DfmnIuod.js} +1 -1
  243. package/storybook-static/assets/{download-eAKjms6q.js → download-Lba8elK9.js} +1 -1
  244. package/storybook-static/assets/{floating-ui.react-DmilONq6.js → floating-ui.react-BFNvfMpU.js} +1 -1
  245. package/storybook-static/assets/formatters-D33Uh3si-CxrG0jsB.js +1 -0
  246. package/storybook-static/assets/foundationApi-DZhnQ2cC.js +59 -0
  247. package/storybook-static/assets/foundationLib-CoVTo22U.js +30 -0
  248. package/storybook-static/assets/{hooks-RI5_2AXI.js → hooks-Cc6eXN6U.js} +1 -1
  249. package/storybook-static/assets/iframe-BXM-JBuH.js +1 -0
  250. package/storybook-static/assets/{iframe-Sr0umHM6.js → iframe-o7sH2IXC.js} +4 -4
  251. package/storybook-static/assets/{info-DhJTzwcL.js → info-BpsVP_dM.js} +1 -1
  252. package/storybook-static/assets/odata-CXsbxsRY.js +1 -0
  253. package/storybook-static/assets/odata-service-CWkHASdw-DlmSiioz.js +3 -0
  254. package/storybook-static/assets/{odataStoryFixtures-lgnWIUp7.js → odataStoryFixtures-Dj_bzRqh.js} +1 -1
  255. package/storybook-static/assets/{react-YFbUKK0m.js → react-DeJ0JTHb.js} +1 -1
  256. package/storybook-static/assets/{refresh-cw-C7WnxX9M.js → refresh-cw-BvGyjEXe.js} +1 -1
  257. package/storybook-static/assets/{settings-2-0NVvyKQl.js → settings-2-BdXxnHos.js} +1 -1
  258. package/storybook-static/assets/{sortable-DDGG-Zfs.js → sortable-XkyN-9r5.js} +1 -1
  259. package/storybook-static/assets/{syntaxhighlighter-QEQV7K2Y-CxWm8nc8.js → syntaxhighlighter-QEQV7K2Y-Cafn3LV1.js} +1 -1
  260. package/storybook-static/assets/{trash-2-BnceCuhg.js → trash-2-uPH9-fND.js} +1 -1
  261. package/storybook-static/assets/{triangle-alert-MPi3GVgt.js → triangle-alert-tT01vSMw.js} +1 -1
  262. package/storybook-static/assets/{useODataSelectBase-hmjK6chS.js → useODataSelectBase-B2LlOwPZ.js} +1 -1
  263. package/storybook-static/assets/useODataTreeData-CU7Rqcb9.js +1 -0
  264. package/storybook-static/assets/{usePickerQuery-CtsGhieD.js → usePickerQuery-D8GHQ6KR.js} +1 -1
  265. package/storybook-static/assets/{usePickerTriggerController-EaI8W2G0.js → usePickerTriggerController-CcK1jmDy.js} +1 -1
  266. package/storybook-static/assets/{x-CqPSvWfo.js → x-BlAURbAH.js} +1 -1
  267. package/storybook-static/iframe.html +2 -2
  268. package/storybook-static/index.json +1 -1
  269. package/storybook-static/project.json +1 -1
  270. package/storybook-static/assets/DateInput-05Iy69_a.js +0 -1
  271. package/storybook-static/assets/NotificationsHost.stories-CgbFboVD.js +0 -29
  272. package/storybook-static/assets/SingleDateTimeInput.stories-C2RuBRAF.js +0 -48
  273. package/storybook-static/assets/async-SjiCjIjO.js +0 -625
  274. package/storybook-static/assets/formatters-CBgrBeSA-CqB1pZxS.js +0 -1
  275. package/storybook-static/assets/foundationLib-DRrox3tN.js +0 -25
  276. package/storybook-static/assets/iframe-DQo-3eW2.js +0 -1
  277. package/storybook-static/assets/odata-DhISMZkE.js +0 -1
  278. package/storybook-static/assets/odata-service-B6TxBSLm-Bq8Ya67E.js +0 -3
  279. package/storybook-static/assets/odataFetchFn-Dv6Xi5CI.js +0 -763
  280. package/storybook-static/assets/persisted-CUFiw53N.js +0 -600
  281. package/storybook-static/assets/useODataTreeData-CKuavbWc.js +0 -1
@@ -0,0 +1,740 @@
1
+ import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-o7sH2IXC.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-BY40djCc.js";function o(e){let t={a:`a`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,strong:`strong`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation API/Query/Persisted Records`}),`
2
+ `,(0,c.jsxs)(t.h1,{id:`сохранённые-записи-через-ryuzaki13react-foundation-apipersisted`,children:[`Сохранённые записи через `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-api/persisted`})]}),`
3
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`persisted`}),` — специализированный слой поверх TanStack Query для данных, которые пользователь сохраняет и позднее восстанавливает: presets, variants, view configs и другие versioned records.`]}),`
4
+ `,(0,c.jsxs)(t.p,{children:[`Слово `,(0,c.jsx)(t.code,{children:`persisted`}),` здесь означает backend-сущности «сохранённая запись». Это не то же самое, что persistence TanStack Query cache в IndexedDB.`]}),`
5
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`Persisted record
6
+ пользователь нажал «Сохранить» → backend хранит вариант/конфигурацию
7
+
8
+ Persisted Query cache
9
+ infrastructure сохраняет временный server snapshot между reload
10
+ `})}),`
11
+ `,(0,c.jsx)(t.p,{children:`Backend record остаётся source of truth. Query persistence, если настроена проектом, лишь ускоряет восстановление snapshot.`}),`
12
+ `,(0,c.jsx)(t.h2,{id:`ментальная-модель`,children:`Ментальная модель`}),`
13
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`PersistedResourceDescriptor
14
+ ├─ identity: namespace + resource + normalized scope
15
+ ├─ read capability: list | latest | history
16
+ ├─ write capability: save | create | delete
17
+ ├─ transport operation: REST | OData | server-fn | custom
18
+ └─ cache strategy после успешной mutation
19
+ `})}),`
20
+ `,(0,c.jsx)(t.p,{children:`Capability optional: resource не обязан поддерживать все шесть операций. TypeScript разрешит соответствующий hook только когда operation присутствует в descriptor; runtime также выдаёт понятную ошибку при неправильном объекте.`}),`
21
+ `,(0,c.jsx)(t.h3,{id:`термины-для-начинающих`,children:`Термины для начинающих`}),`
22
+ `,(0,c.jsxs)(t.ul,{children:[`
23
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`record`}),` — сохранённая запись на backend;`]}),`
24
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`payload`}),` — полезная конфигурация внутри record, часто JSON string;`]}),`
25
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`scope`}),` — кому или чему принадлежат records: user, app, table, entity;`]}),`
26
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`latest`}),` — последний актуальный snapshot;`]}),`
27
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`history`}),` — версии/события с аргументами paging;`]}),`
28
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`capability`}),` — реально поддерживаемая operation;`]}),`
29
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`transport adapter`}),` — как capability выполняет REST/OData/serverFn request;`]}),`
30
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.strong,{children:`descriptor`}),` — единая карта resource, keys, scope policy и capabilities.`]}),`
31
+ `]}),`
32
+ `,(0,c.jsx)(t.h3,{id:`почему-это-не-crud`,children:`Почему это не CRUD`}),`
33
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`save`}),` и `,(0,c.jsx)(t.code,{children:`create`}),` могут иметь разную бизнес-семантику, `,(0,c.jsx)(t.code,{children:`latest`}),` не равен generic `,(0,c.jsx)(t.code,{children:`read(id)`}),`, а `,(0,c.jsx)(t.code,{children:`history`}),` требует paging/filter args. Фиксированные имена отражают распространённую модель versioned user records, но не пытаются описать любую entity.`]}),`
34
+ `,(0,c.jsxs)(t.h2,{id:`persisted-или-resource`,children:[(0,c.jsx)(t.code,{children:`persisted`}),` или `,(0,c.jsx)(t.code,{children:`resource`})]}),`
35
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Нужна модель`}),(0,c.jsx)(t.th,{children:`Использовать`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Фиксированные сохранённые records: list/latest/history/save/create/delete`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`/persisted`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Произвольные названия и semantics операций`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.a,{href:`../resource/README.mdx`,children:(0,c.jsx)(t.code,{children:`/resource`})})})]})]})]}),`
36
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`persisted`}),` построен на тех же принципах keys/cache, но намеренно не является универсальным CRUD.`]}),`
37
+ `,(0,c.jsxs)(t.p,{children:[`Не используйте `,(0,c.jsx)(t.code,{children:`/persisted`}),` для обычного server list, который пользователь никогда не сохраняет и не восстанавливает. Для него достаточно entity query или `,(0,c.jsx)(t.code,{children:`/resource`}),`.`]}),`
38
+ `,(0,c.jsx)(t.h2,{id:`установка-и-provider`,children:`Установка и provider`}),`
39
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-bash`,children:`npm install @ryuzaki13/react-foundation-api @ryuzaki13/react-foundation-lib @tanstack/react-query react
40
+ `})}),`
41
+ `,(0,c.jsxs)(t.p,{children:[`Hooks требуют `,(0,c.jsx)(t.code,{children:`QueryClientProvider`}),`. Descriptor и operations создавайте на module level, чтобы ссылки были стабильными.`]}),`
42
+ `,(0,c.jsx)(t.h2,{id:`импорт`,children:`Импорт`}),`
43
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
44
+ applyPersistedCacheStrategy,
45
+ composePersistedCacheStrategies,
46
+ createInvalidatePersistedScopeCacheStrategy,
47
+ createPersistedJsonCodec,
48
+ createPersistedODataMutationOperation,
49
+ createPersistedODataQueryOperation,
50
+ createPersistedODataReadOperation,
51
+ createPersistedRecordKeys,
52
+ createPersistedResourceDescriptor,
53
+ createPersistedRestMutationOperation,
54
+ createPersistedRestQueryOperation,
55
+ createSetPersistedQueryDataCacheStrategy,
56
+ getPersistedHistoryData,
57
+ getPersistedLatestData,
58
+ getPersistedListData,
59
+ parsePersistedJson,
60
+ stringifyPersistedJson,
61
+ usePersistedCreateMutation,
62
+ usePersistedDeleteMutation,
63
+ usePersistedHistoryQuery,
64
+ usePersistedLatestQuery,
65
+ usePersistedListQuery,
66
+ usePersistedSaveMutation
67
+ } from "@ryuzaki13/react-foundation-api/persisted";
68
+ `})}),`
69
+ `,(0,c.jsx)(t.h2,{id:`пошаговый-rest-пример`,children:`Пошаговый REST пример`}),`
70
+ `,(0,c.jsx)(t.h3,{id:`1-контракты`,children:`1. Контракты`}),`
71
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`type ViewScope = {
72
+ userId: string;
73
+ viewId: string;
74
+ };
75
+
76
+ type ViewConfig = {
77
+ columns: string[];
78
+ compact: boolean;
79
+ };
80
+
81
+ type SavedViewRecord = {
82
+ id: string;
83
+ createdUtc: string;
84
+ payload: string;
85
+ };
86
+
87
+ type SaveViewInput = {
88
+ payload: ViewConfig;
89
+ };
90
+ `})}),`
91
+ `,(0,c.jsx)(t.p,{children:`Внешний record и распарсенный config — разные типы. TypeScript не проверяет network payload автоматически.`}),`
92
+ `,(0,c.jsx)(t.h3,{id:`2-runtime-parsers`,children:`2. Runtime parsers`}),`
93
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function parseRecord(value: unknown): SavedViewRecord {
94
+ if (!isSavedViewRecord(value)) {
95
+ throw new Error("Некорректный SavedViewRecord payload");
96
+ }
97
+
98
+ return value;
99
+ }
100
+
101
+ function parseRecordList(value: unknown): SavedViewRecord[] {
102
+ if (!Array.isArray(value)) throw new Error("Ожидался массив records");
103
+ return value.map(parseRecord);
104
+ }
105
+ `})}),`
106
+ `,(0,c.jsx)(t.h3,{id:`3-operations`,children:`3. Operations`}),`
107
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const listOperation = createPersistedRestQueryOperation<
108
+ ViewScope,
109
+ void,
110
+ SavedViewRecord[]
111
+ >({
112
+ buildUrl: (scope) =>
113
+ \`/api/users/\${encodeURIComponent(scope.userId)}/views/\${encodeURIComponent(scope.viewId)}\`,
114
+ parseResponse: parseRecordList,
115
+ staleTime: 60_000
116
+ });
117
+
118
+ const latestOperation = createPersistedRestQueryOperation<
119
+ ViewScope,
120
+ void,
121
+ SavedViewRecord,
122
+ ViewConfig | null
123
+ >({
124
+ buildUrl: (scope) =>
125
+ \`/api/users/\${encodeURIComponent(scope.userId)}/views/\${encodeURIComponent(scope.viewId)}/latest\`,
126
+ parseResponse: parseRecord,
127
+ transform: (record) => parsePersistedJson<ViewConfig>(record.payload)
128
+ });
129
+
130
+ const saveOperation = createPersistedRestMutationOperation<
131
+ ViewScope,
132
+ SaveViewInput,
133
+ SavedViewRecord
134
+ >({
135
+ buildUrl: (scope) =>
136
+ \`/api/users/\${encodeURIComponent(scope.userId)}/views/\${encodeURIComponent(scope.viewId)}\`,
137
+ method: "PUT",
138
+ bodyMapper: (_scope, input) => ({
139
+ payload: stringifyPersistedJson(input.payload)
140
+ }),
141
+ parseResponse: parseRecord,
142
+ cacheStrategy: createInvalidatePersistedScopeCacheStrategy()
143
+ });
144
+ `})}),`
145
+ `,(0,c.jsx)(t.h3,{id:`4-descriptor`,children:`4. Descriptor`}),`
146
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const viewResource = createPersistedResourceDescriptor({
147
+ namespace: "view-config",
148
+ resource: "view",
149
+ normalizeScope: (scope: ViewScope | null | undefined) => ({
150
+ userId: scope?.userId.trim() ?? "",
151
+ viewId: scope?.viewId.trim() ?? ""
152
+ }),
153
+ isEnabled: (scope) => Boolean(scope?.userId && scope?.viewId),
154
+ getScopeError: () => "Не определён пользователь или представление",
155
+ transport: {
156
+ list: listOperation,
157
+ latest: latestOperation,
158
+ save: saveOperation
159
+ }
160
+ });
161
+ `})}),`
162
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`normalizeScope`}),` изменяет только cache identity. В `,(0,c.jsx)(t.code,{children:`buildUrl`}),`/`,(0,c.jsx)(t.code,{children:`execute`}),` передаётся исходный scope.`]}),`
163
+ `,(0,c.jsx)(t.h3,{id:`5-hooks`,children:`5. Hooks`}),`
164
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const scope = { userId, viewId };
165
+ const latestQuery = usePersistedLatestQuery(viewResource, scope);
166
+ const listQuery = usePersistedListQuery(viewResource, scope);
167
+ const saveMutation = usePersistedSaveMutation(viewResource, scope);
168
+
169
+ saveMutation.mutate({
170
+ payload: { columns: ["name", "status"], compact: true }
171
+ });
172
+ `})}),`
173
+ `,(0,c.jsxs)(t.p,{children:[`Нельзя вызвать `,(0,c.jsx)(t.code,{children:`usePersistedHistoryQuery`}),` для этого descriptor, пока capability `,(0,c.jsx)(t.code,{children:`history`}),` не добавлена.`]}),`
174
+ `,(0,c.jsx)(t.h2,{id:`descriptor-подробно`,children:`Descriptor подробно`}),`
175
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`interface PersistedResourceDescriptor<TScope, TTransport> {
176
+ namespace: string;
177
+ resource: string;
178
+ keys: PersistedRecordKeys<TScope>;
179
+ transport: TTransport;
180
+ isEnabled?: (scope: TScope | null | undefined) => boolean;
181
+ getScopeError?: (scope: TScope | null | undefined) => string | null;
182
+ }
183
+ `})}),`
184
+ `,(0,c.jsxs)(t.h3,{id:`namespace-и-resource`,children:[(0,c.jsx)(t.code,{children:`namespace`}),` и `,(0,c.jsx)(t.code,{children:`resource`})]}),`
185
+ `,(0,c.jsx)(t.p,{children:`Это техническая стабильная identity:`}),`
186
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`namespace: "view-config",
187
+ resource: "table-view"
188
+ `})}),`
189
+ `,(0,c.jsx)(t.p,{children:`Не используйте локализованные labels, route title, случайный UUID при каждом start или URL endpoint. User id принадлежит scope, а не namespace.`}),`
190
+ `,(0,c.jsx)(t.h3,{id:`transport`,children:(0,c.jsx)(t.code,{children:`transport`})}),`
191
+ `,(0,c.jsx)(t.p,{children:`Это object capabilities:`}),`
192
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`transport: {
193
+ list,
194
+ latest,
195
+ history,
196
+ save,
197
+ create,
198
+ delete: deleteOperation
199
+ }
200
+ `})}),`
201
+ `,(0,c.jsx)(t.p,{children:`Подключайте только реально существующие operations. Empty placeholder создаёт ложный public contract.`}),`
202
+ `,(0,c.jsx)(t.h3,{id:`normalizescope`,children:(0,c.jsx)(t.code,{children:`normalizeScope`})}),`
203
+ `,(0,c.jsxs)(t.p,{children:[`Normalizer используется при создании `,(0,c.jsx)(t.code,{children:`keys`}),` и меняет только cache identity:`]}),`
204
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const scope = { userId: " ivanov ", viewId: " main " };
205
+
206
+ // Key может содержать trimmed values,
207
+ // но execute/buildUrl получает literal scope с пробелами.
208
+ `})}),`
209
+ `,(0,c.jsx)(t.p,{children:`Если transport требует canonical values, нормализуйте их на request boundary или создавайте canonical scope до вызова descriptor-а.`}),`
210
+ `,(0,c.jsxs)(t.h3,{id:`nullable-scope-требует-isenabled`,children:[`Nullable scope требует `,(0,c.jsx)(t.code,{children:`isEnabled`})]}),`
211
+ `,(0,c.jsx)(t.p,{children:`Критическое правило:`}),`
212
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`isEnabled: (scope) => Boolean(scope?.userId && scope?.viewId)
213
+ `})}),`
214
+ `,(0,c.jsxs)(t.p,{children:[`Если callback отсутствует, default query enabled равен `,(0,c.jsx)(t.code,{children:`true`}),`, даже при `,(0,c.jsx)(t.code,{children:`scope === undefined`}),`. TanStack Query запустит queryFn, а scope assertion выбросит error.`]}),`
215
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`getScopeError`}),` не отключает query. Он только формирует сообщение при actual invalid execution.`]}),`
216
+ `,(0,c.jsx)(t.p,{children:`Standard error:`}),`
217
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`Недостаточно данных scope для persisted-record ресурса.
218
+ `})}),`
219
+ `,(0,c.jsx)(t.h3,{id:`descriptor-создаётся-на-module-boundary`,children:`Descriptor создаётся на module boundary`}),`
220
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`export const viewResource = createPersistedResourceDescriptor(...);
221
+ `})}),`
222
+ `,(0,c.jsx)(t.p,{children:`Не создавайте descriptor внутри React render. Stable module object упрощает inference, keys, testing и reuse.`}),`
223
+ `,(0,c.jsx)(t.h2,{id:`read-capabilities`,children:`Read capabilities`}),`
224
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Capability`}),(0,c.jsx)(t.th,{children:`Hook`}),(0,c.jsx)(t.th,{children:`Imperative helper`}),(0,c.jsx)(t.th,{children:`Args`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`list`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedListQuery`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getPersistedListData`})}),(0,c.jsxs)(t.td,{children:[`нет (`,(0,c.jsx)(t.code,{children:`void`}),`)`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`latest`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedLatestQuery`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getPersistedLatestData`})}),(0,c.jsxs)(t.td,{children:[`нет (`,(0,c.jsx)(t.code,{children:`void`}),`)`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`history`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedHistoryQuery`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`getPersistedHistoryData`})}),(0,c.jsx)(t.td,{children:`обязательный generic args`})]})]})]}),`
225
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const page = await getPersistedHistoryData(
226
+ resourceWithHistory,
227
+ scope,
228
+ { cursor: "next", limit: 20 },
229
+ queryClient
230
+ );
231
+ `})}),`
232
+ `,(0,c.jsxs)(t.p,{children:[`Query operation получает `,(0,c.jsx)(t.code,{children:`{ scope, args, client, signal }`}),`. `,(0,c.jsx)(t.code,{children:`isEnabled`}),` operation и descriptor определяют автоматический запуск React observer; `,(0,c.jsx)(t.code,{children:`staleTime`}),`, `,(0,c.jsx)(t.code,{children:`gcTime`}),`, `,(0,c.jsx)(t.code,{children:`meta`}),` переходят в TanStack Query options.`]}),`
233
+ `,(0,c.jsx)(t.h3,{id:`read-lifecycle`,children:`Read lifecycle`}),`
234
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`hook/get helper
235
+
236
+
237
+ найти capability в descriptor.transport
238
+ │ missing
239
+ ├────────────────► runtime error
240
+ │ exists
241
+
242
+ построить key + enabled + lifetime + meta
243
+
244
+
245
+ TanStack Query запускает queryFn
246
+
247
+
248
+ assert scope
249
+
250
+
251
+ operation.execute({ scope, args, client, signal })
252
+ `})}),`
253
+ `,(0,c.jsx)(t.p,{children:`Missing capability error содержит resource и operation:`}),`
254
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`Persisted-record ресурс 'view' не поддерживает операцию 'history'.
255
+ `})}),`
256
+ `,(0,c.jsxs)(t.h3,{id:`list-и-latest-получают-args-undefined`,children:[(0,c.jsx)(t.code,{children:`list`}),` и `,(0,c.jsx)(t.code,{children:`latest`}),` получают `,(0,c.jsx)(t.code,{children:`args: undefined`})]}),`
257
+ `,(0,c.jsxs)(t.p,{children:[`Их operation type — `,(0,c.jsx)(t.code,{children:`PersistedQueryOperation<TScope, void, TResult>`}),`. В query key optional args не добавляется:`]}),`
258
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`descriptor.keys.list(scope);
259
+ // [...scopeKey, "list"]
260
+ `})}),`
261
+ `,(0,c.jsxs)(t.h3,{id:`history-identity`,children:[(0,c.jsx)(t.code,{children:`history`}),` identity`]}),`
262
+ `,(0,c.jsx)(t.p,{children:`Все args, меняющие page/result, должны попасть в call:`}),`
263
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`usePersistedHistoryQuery(resource, scope, {
264
+ cursor: "next-42",
265
+ limit: 20,
266
+ includeDeleted: false
267
+ });
268
+ `})}),`
269
+ `,(0,c.jsx)(t.p,{children:`Они нормализуются и добавляются в key. Не прячьте paging/filter во внешнем closure operation-а.`}),`
270
+ `,(0,c.jsx)(t.h3,{id:`disabled-query-и-imperative-fetch`,children:`Disabled query и imperative fetch`}),`
271
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`enabled: false`}),` управляет automatic observer start. При `,(0,c.jsx)(t.code,{children:`queryClient.fetchQuery`}),` query function всё равно защищает scope. Передавайте валидный scope imperative helpers.`]}),`
272
+ `,(0,c.jsxs)(t.h3,{id:`query-meta`,children:[`Query `,(0,c.jsx)(t.code,{children:`meta`})]}),`
273
+ `,(0,c.jsxs)(t.p,{children:[`Operation может передать `,(0,c.jsx)(t.code,{children:`QueryMeta`}),`, например marker persistence/diagnostics. Generic layer не интерпретирует meta, только переносит в TanStack options.`]}),`
274
+ `,(0,c.jsxs)(t.p,{children:[`Imperative helpers используют `,(0,c.jsx)(t.code,{children:`queryClient.fetchQuery`}),`. Передавайте валидный scope; disabled policy в первую очередь управляет observer, а фактическая query function всё равно проверяет scope.`]}),`
275
+ `,(0,c.jsx)(t.h2,{id:`write-capabilities`,children:`Write capabilities`}),`
276
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Capability`}),(0,c.jsx)(t.th,{children:`Hook`}),(0,c.jsx)(t.th,{children:`Типичный смысл`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`save`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedSaveMutation`})}),(0,c.jsx)(t.td,{children:`Сохранить/обновить snapshot`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`create`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedCreateMutation`})}),(0,c.jsx)(t.td,{children:`Создать новую именованную запись`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`delete`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`usePersistedDeleteMutation`})}),(0,c.jsx)(t.td,{children:`Удалить запись`})]})]})]}),`
277
+ `,(0,c.jsxs)(t.p,{children:[`Mutation operation получает `,(0,c.jsx)(t.code,{children:`{ scope, input, client }`}),`. Generic persisted contract не передаёт `,(0,c.jsx)(t.code,{children:`AbortSignal`}),` для mutation.`]}),`
278
+ `,(0,c.jsx)(t.h3,{id:`write-lifecycle`,children:`Write lifecycle`}),`
279
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`usePersistedSave/Create/DeleteMutation
280
+
281
+
282
+ assert capability существует
283
+
284
+
285
+ mutate(input)
286
+
287
+
288
+ assert scope
289
+
290
+
291
+ operation.execute({ scope, input, client })
292
+ │ success
293
+
294
+ cache strategy
295
+ │ await
296
+
297
+ hook onSuccess(result, input)
298
+ `})}),`
299
+ `,(0,c.jsx)(t.p,{children:`Mutation key включает operation/scope, но не input. Две save mutations одного scope могут иметь разные inputs, оставаясь одним operation family.`}),`
300
+ `,(0,c.jsxs)(t.p,{children:[`При сохранённом inferred descriptor TypeScript не даст передать resource без `,(0,c.jsx)(t.code,{children:`delete`}),` в delete hook. Runtime всё равно проверяет capability для JS, `,(0,c.jsx)(t.code,{children:`any`}),`, cast и dynamic object.`]}),`
301
+ `,(0,c.jsx)(t.p,{children:`Scope повторно проверяется перед cache strategy. Не мутируйте captured scope object на месте во время request.`}),`
302
+ `,(0,c.jsx)(t.p,{children:`После успешного transport:`}),`
303
+ `,(0,c.jsxs)(t.ol,{children:[`
304
+ `,(0,c.jsx)(t.li,{children:`выбирается cache strategy;`}),`
305
+ `,(0,c.jsx)(t.li,{children:`strategy выполняется и awaited;`}),`
306
+ `,(0,c.jsxs)(t.li,{children:[`вызывается optional hook `,(0,c.jsx)(t.code,{children:`onSuccess(result, input)`}),`.`]}),`
307
+ `]}),`
308
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`usePersistedSaveMutation(resource, scope, {
309
+ cacheStrategy: null, // Отключить operation strategy.
310
+ onSuccess(result) {
311
+ showSuccess(\`Сохранено \${result.id}\`);
312
+ }
313
+ });
314
+ `})}),`
315
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`cacheStrategy: undefined`}),` использует strategy операции; `,(0,c.jsx)(t.code,{children:`null`}),` отключает; объект заменяет исходную strategy. Для дополнения применяйте композицию.`]}),`
316
+ `,(0,c.jsx)(t.p,{children:`Если cache strategy бросила error, server write уже мог завершиться. Не повторяйте write автоматически только ради исправления cache: это может создать duplicate.`}),`
317
+ `,(0,c.jsx)(t.h2,{id:`query-keys`,children:`Query keys`}),`
318
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const keys = createPersistedRecordKeys<ViewScope>({
319
+ namespace: "view-config",
320
+ resource: "view",
321
+ normalizeScope: (scope) => ({
322
+ userId: scope?.userId ?? "",
323
+ viewId: scope?.viewId ?? ""
324
+ })
325
+ });
326
+
327
+ keys.all;
328
+ keys.scope(scope);
329
+ keys.list(scope);
330
+ keys.latest(scope);
331
+ keys.history(scope, { limit: 20 });
332
+ keys.save(scope);
333
+ keys.create(scope);
334
+ keys.delete(scope);
335
+ `})}),`
336
+ `,(0,c.jsx)(t.p,{children:`Форма:`}),`
337
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`[namespace, resource, normalizedScope, operation, optionalArgs]
338
+ `})}),`
339
+ `,(0,c.jsxs)(t.p,{children:[`Используется нормализация `,(0,c.jsx)(t.code,{children:`/resource`}),`: strings trim, object keys сортируются, `,(0,c.jsx)(t.code,{children:`undefined`}),` становится `,(0,c.jsx)(t.code,{children:`null`}),`. Date/Map/cyclic object требуют явного нормализатора.`]}),`
340
+ `,(0,c.jsx)(t.h3,{id:`точные-key-forms`,children:`Точные key forms`}),`
341
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`keys.all;
342
+ // [namespace, resource]
343
+
344
+ keys.scope(scope);
345
+ // [namespace, resource, normalizedScope]
346
+
347
+ keys.list(scope);
348
+ // [namespace, resource, normalizedScope, "list"]
349
+
350
+ keys.latest(scope);
351
+ // [namespace, resource, normalizedScope, "latest"]
352
+
353
+ keys.history(scope, args);
354
+ // [namespace, resource, normalizedScope, "history", normalizedArgs]
355
+
356
+ keys.save(scope);
357
+ // [namespace, resource, normalizedScope, "save"]
358
+ `})}),`
359
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`history(scope, undefined)`}),` не добавляет последний item, а `,(0,c.jsx)(t.code,{children:`history(scope, null)`}),` добавляет `,(0,c.jsx)(t.code,{children:`null`}),`.`]}),`
360
+ `,(0,c.jsx)(t.h3,{id:`prefix-invalidation`,children:`Prefix invalidation`}),`
361
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`await queryClient.invalidateQueries({
362
+ queryKey: descriptor.keys.scope(scope)
363
+ });
364
+ `})}),`
365
+ `,(0,c.jsx)(t.p,{children:`Затрагивает list/latest/history этого scope. Точечный вариант:`}),`
366
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`await queryClient.invalidateQueries({
367
+ queryKey: descriptor.keys.latest(scope)
368
+ });
369
+ `})}),`
370
+ `,(0,c.jsx)(t.h3,{id:`специальные-значения-scope`,children:`Специальные значения scope`}),`
371
+ `,(0,c.jsx)(t.p,{children:`Default normalizer не умеет Date/Map/Set. Используйте ISO string:`}),`
372
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`normalizeScope: (scope) => ({
373
+ userId: scope?.userId ?? "",
374
+ periodStart: scope?.periodStart.toISOString() ?? null
375
+ })
376
+ `})}),`
377
+ `,(0,c.jsx)(t.p,{children:`Query keys нельзя использовать для secrets, SAML/CSRF tokens или полного payload config.`}),`
378
+ `,(0,c.jsx)(t.h2,{id:`json-payload-codec`,children:`JSON payload codec`}),`
379
+ `,(0,c.jsx)(t.h3,{id:`parse`,children:`Parse`}),`
380
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`parsePersistedJson<ViewConfig>(null); // null.
381
+ parsePersistedJson<ViewConfig>(""); // null.
382
+ parsePersistedJson<ViewConfig>("broken"); // null.
383
+ parsePersistedJson<ViewConfig>('{"compact":true,"columns":[]}');
384
+ // Object, но без runtime validation.
385
+ `})}),`
386
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`parsePersistedJson<T>`}),` только вызывает `,(0,c.jsx)(t.code,{children:`JSON.parse`}),` и делает TypeScript cast. Он не проверяет schema. После parse примените domain validator/normalizer на явной restore boundary.`]}),`
387
+ `,(0,c.jsx)(t.h3,{id:`stringify`,children:`Stringify`}),`
388
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const payload = stringifyPersistedJson({ compact: false, columns: [] });
389
+ `})}),`
390
+ `,(0,c.jsxs)(t.p,{children:[`Ошибки `,(0,c.jsx)(t.code,{children:`JSON.stringify`}),` пробрасываются. Передавайте только JSON-compatible данные. В частности:`]}),`
391
+ `,(0,c.jsxs)(t.ul,{children:[`
392
+ `,(0,c.jsxs)(t.li,{children:[`cyclic object и `,(0,c.jsx)(t.code,{children:`BigInt`}),` приводят к ошибке;`]}),`
393
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`Date`}),` превращается в ISO string;`]}),`
394
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`undefined`}),` в object-поле удаляется;`]}),`
395
+ `,(0,c.jsxs)(t.li,{children:[`вызов с корневым `,(0,c.jsx)(t.code,{children:`undefined`}),` фактически может вернуть `,(0,c.jsx)(t.code,{children:`undefined`}),`, несмотря на заявленный string contract — не передавайте его.`]}),`
396
+ `]}),`
397
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedJsonCodec<T>()`}),` возвращает `,(0,c.jsx)(t.code,{children:`{ parse, stringify }`}),` для передачи единым контрактом.`]}),`
398
+ `,(0,c.jsx)(t.h3,{id:`restore-boundary`,children:`Restore boundary`}),`
399
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`backend payload string
400
+ │ parsePersistedJson
401
+
402
+ JS value с compile-time T
403
+ │ runtime validation
404
+
405
+ valid saved model
406
+ │ explicit normalize/migrate restore boundary
407
+
408
+ application state
409
+ `})}),`
410
+ `,(0,c.jsx)(t.p,{children:`Не нормализуйте пользовательский draft при каждом keystroke. Serialization/normalization должны происходить на явно названной save/restore boundary.`}),`
411
+ `,(0,c.jsx)(t.h3,{id:`повреждённый-json-и-отсутствие-payload-неразличимы`,children:`Повреждённый JSON и отсутствие payload неразличимы`}),`
412
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`parsePersistedJson(null); // null
413
+ parsePersistedJson(""); // null
414
+ parsePersistedJson("broken"); // null
415
+ parsePersistedJson("null"); // null
416
+ `})}),`
417
+ `,(0,c.jsx)(t.p,{children:`Если product должен различать «не сохранено» и «данные повреждены», используйте strict custom codec/parser с discriminated result или typed error.`}),`
418
+ `,(0,c.jsx)(t.h3,{id:`codec-не-делает-migration`,children:`Codec не делает migration`}),`
419
+ `,(0,c.jsx)(t.p,{children:`Generic type не добавляет version/schema check. Для versioned payload храните version в data и обрабатывайте старые versions в domain restore mapper.`}),`
420
+ `,(0,c.jsx)(t.h2,{id:`rest-adapters`,children:`REST adapters`}),`
421
+ `,(0,c.jsx)(t.h3,{id:`query`,children:`Query`}),`
422
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedRestQueryOperation`}),` принимает:`]}),`
423
+ `,(0,c.jsxs)(t.ul,{children:[`
424
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`buildUrl(scope, args)`}),` — относительный или абсолютный URL;`]}),`
425
+ `,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`baseUrl`}),`;`]}),`
426
+ `,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`buildInit(scope, args)`}),`;`]}),`
427
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`parseResponse(unknown)`}),` или custom `,(0,c.jsx)(t.code,{children:`executor`}),`;`]}),`
428
+ `,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`transform`}),`;`]}),`
429
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`staleTime`}),`, `,(0,c.jsx)(t.code,{children:`gcTime`}),`, `,(0,c.jsx)(t.code,{children:`isEnabled`}),`.`]}),`
430
+ `]}),`
431
+ `,(0,c.jsxs)(t.p,{children:[`Если нет ни `,(0,c.jsx)(t.code,{children:`executor`}),`, ни `,(0,c.jsx)(t.code,{children:`parseResponse`}),`, operation бросит `,(0,c.jsx)(t.code,{children:`REST persisted operation requires executor or parseResponse.`})]}),`
432
+ `,(0,c.jsxs)(t.p,{children:[`Read signal всегда записывается поверх `,(0,c.jsx)(t.code,{children:`buildInit.signal`}),`, чтобы текущая TanStack Query отменяла именно свой запрос.`]}),`
433
+ `,(0,c.jsx)(t.h3,{id:`rest-read-точная-сборка-request`,children:`REST read: точная сборка request`}),`
434
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
435
+ url: buildUrl(scope, args),
436
+ baseUrl,
437
+ init: {
438
+ ...buildInit?.(scope, args),
439
+ signal
440
+ }
441
+ }
442
+ `})}),`
443
+ `,(0,c.jsxs)(t.p,{children:[`Query signal перезаписывает signal, который мог вернуть `,(0,c.jsx)(t.code,{children:`buildInit`}),`.`]}),`
444
+ `,(0,c.jsxs)(t.p,{children:[`Если custom `,(0,c.jsx)(t.code,{children:`executor`}),` задан, он получает весь request `,(0,c.jsx)(t.code,{children:`{ url, baseUrl, init }`}),`, а `,(0,c.jsx)(t.code,{children:`parseResponse`}),` не вызывается. Executor обязан вернуть `,(0,c.jsx)(t.code,{children:`TResponse`}),`.`]}),`
445
+ `,(0,c.jsxs)(t.p,{children:[`Без executor используется `,(0,c.jsx)(t.code,{children:`/http`}),` → `,(0,c.jsx)(t.code,{children:`httpFetchPayload`}),` → обязательный `,(0,c.jsx)(t.code,{children:`parseResponse(unknown)`}),`.`]}),`
446
+ `,(0,c.jsx)(t.h3,{id:`rest-read-transform`,children:`REST read transform`}),`
447
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`transform: (record, { scope, args }) => ({
448
+ id: record.id,
449
+ config: parseAndValidateConfig(record.payload),
450
+ owner: scope.userId
451
+ })
452
+ `})}),`
453
+ `,(0,c.jsx)(t.p,{children:`Ошибка parser/transform становится query error. Не заменяйте invalid payload пустым config без product decision.`}),`
454
+ `,(0,c.jsx)(t.h3,{id:`mutation`,children:`Mutation`}),`
455
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedRestMutationOperation`}),` поддерживает method `,(0,c.jsx)(t.code,{children:`POST`}),`, `,(0,c.jsx)(t.code,{children:`PUT`}),`, `,(0,c.jsx)(t.code,{children:`DELETE`}),`.`]}),`
456
+ `,(0,c.jsxs)(t.ul,{children:[`
457
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`bodyMapper(scope, input)`}),` создаёт JSON body;`]}),`
458
+ `,(0,c.jsxs)(t.li,{children:[`если mapper отсутствует/вернул `,(0,c.jsx)(t.code,{children:`undefined`}),`, body и default Content-Type не задаются;`]}),`
459
+ `,(0,c.jsxs)(t.li,{children:[`иначе body сериализуется и default header равен `,(0,c.jsx)(t.code,{children:`application/json`}),`;`]}),`
460
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`buildInit`}),` применяется после default headers и может полностью заменить headers;`]}),`
461
+ `,(0,c.jsxs)(t.li,{children:[`response обязательно проходит `,(0,c.jsx)(t.code,{children:`parseResponse`}),` или custom executor;`]}),`
462
+ `,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`transform`}),` строит domain result;`]}),`
463
+ `,(0,c.jsxs)(t.li,{children:[`optional `,(0,c.jsx)(t.code,{children:`cacheStrategy`}),` прикрепляется к operation.`]}),`
464
+ `]}),`
465
+ `,(0,c.jsxs)(t.p,{children:[`REST adapter использует нейтральный `,(0,c.jsx)(t.code,{children:`/http`}),`: SAP SSO/X-CSRF policy здесь нет.`]}),`
466
+ `,(0,c.jsx)(t.h3,{id:`rest-mutation-точная-сборка-init`,children:`REST mutation: точная сборка init`}),`
467
+ `,(0,c.jsxs)(t.p,{children:[`Default fields строятся до `,(0,c.jsx)(t.code,{children:`buildInit`}),`, а body — после:`]}),`
468
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
469
+ method,
470
+ headers: payload === undefined
471
+ ? undefined
472
+ : { "Content-Type": "application/json" },
473
+ ...buildInit(scope, input),
474
+ body: payload === undefined
475
+ ? undefined
476
+ : JSON.stringify(payload)
477
+ }
478
+ `})}),`
479
+ `,(0,c.jsx)(t.p,{children:`Следствия:`}),`
480
+ `,(0,c.jsxs)(t.ul,{children:[`
481
+ `,(0,c.jsxs)(t.li,{children:[`custom `,(0,c.jsx)(t.code,{children:`buildInit.headers`}),` полностью заменяет default Headers object;`]}),`
482
+ `,(0,c.jsx)(t.li,{children:`если нужны custom headers вместе с JSON, добавьте Content-Type сами;`}),`
483
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`buildInit`}),` по type не может менять `,(0,c.jsx)(t.code,{children:`method`}),`/`,(0,c.jsx)(t.code,{children:`body`}),`;`]}),`
484
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`bodyMapper`}),` может вернуть `,(0,c.jsx)(t.code,{children:`null`}),`: body станет string `,(0,c.jsx)(t.code,{children:`"null"`}),`;`]}),`
485
+ `,(0,c.jsxs)(t.li,{children:[`только `,(0,c.jsx)(t.code,{children:`undefined`}),` означает отсутствие body;`]}),`
486
+ `,(0,c.jsx)(t.li,{children:`mutation AbortSignal generic contract не передаёт.`}),`
487
+ `]}),`
488
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`buildInit: () => ({
489
+ headers: {
490
+ "Content-Type": "application/json",
491
+ "If-Match": "*"
492
+ }
493
+ })
494
+ `})}),`
495
+ `,(0,c.jsxs)(t.p,{children:[`Для DELETE body появится только при `,(0,c.jsx)(t.code,{children:`bodyMapper`}),`. Проверьте contract endpoint-а; многие DELETE используют только URL.`]}),`
496
+ `,(0,c.jsx)(t.h3,{id:`custom-rest-executor`,children:`Custom REST executor`}),`
497
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const executor = vi.fn(async (request) => {
498
+ expect(request.url).toBe("/api/views/latest");
499
+ return savedRecordFixture;
500
+ });
501
+
502
+ const operation = createPersistedRestQueryOperation({
503
+ buildUrl: () => "/api/views/latest",
504
+ executor,
505
+ transform: (record) => record.payload
506
+ });
507
+ `})}),`
508
+ `,(0,c.jsx)(t.p,{children:`Custom executor полезен для tests/tracing, но не должен содержать business mapping конкретной config.`}),`
509
+ `,(0,c.jsx)(t.h2,{id:`odata-adapters`,children:`OData adapters`}),`
510
+ `,(0,c.jsxs)(t.p,{children:[`OData operations используют metadata-aware transport из `,(0,c.jsx)(t.a,{href:`../odata/README.mdx`,children:(0,c.jsx)(t.code,{children:`/odata`})}),`.`]}),`
511
+ `,(0,c.jsx)(t.h3,{id:`query-collection`,children:`Query collection`}),`
512
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const list = createPersistedODataQueryOperation<
513
+ ViewScope,
514
+ void,
515
+ SavedViewRecord[]
516
+ >({
517
+ odata: { service: "Z_VIEW_CONFIG_SRV", target: "ViewSet" },
518
+ buildOptions: (scope) => ({
519
+ expression: createFilterEqual("UserId", scope.userId)
520
+ }),
521
+ transform: (rows) => rows
522
+ });
523
+ `})}),`
524
+ `,(0,c.jsxs)(t.p,{children:[`Доступные options factory: `,(0,c.jsx)(t.code,{children:`odata`}),`, optional `,(0,c.jsx)(t.code,{children:`baseUrl`}),`, `,(0,c.jsx)(t.code,{children:`buildParams`}),`, `,(0,c.jsx)(t.code,{children:`buildOptions`}),`, `,(0,c.jsx)(t.code,{children:`buildInit`}),`, `,(0,c.jsx)(t.code,{children:`transform`}),`, `,(0,c.jsx)(t.code,{children:`executor`}),`, `,(0,c.jsx)(t.code,{children:`staleTime`}),`, `,(0,c.jsx)(t.code,{children:`gcTime`}),`, `,(0,c.jsx)(t.code,{children:`meta`}),`, `,(0,c.jsx)(t.code,{children:`isEnabled`}),`.`]}),`
525
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`createPersistedODataQueryOperation`}),` использует semantic method `,(0,c.jsx)(t.code,{children:`query`}),` и возвращает collection response data. `,(0,c.jsx)(t.code,{children:`createPersistedODataReadOperation`}),` использует `,(0,c.jsx)(t.code,{children:`read`}),` для одной entity по key parameters:`]}),`
526
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const latest = createPersistedODataReadOperation({
527
+ odata: { service: "Z_VIEW_CONFIG_SRV", target: "ViewSet" },
528
+ buildParams: (scope: ViewScope) => wrapODataParams({
529
+ UserId: scope.userId,
530
+ ViewId: scope.viewId
531
+ }),
532
+ transform: (record: SavedViewRecord) =>
533
+ parsePersistedJson<ViewConfig>(record.payload)
534
+ });
535
+ `})}),`
536
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`buildParams`}),` должен возвращать wrapped OData parameters из `,(0,c.jsx)(t.code,{children:`foundation-lib/odata-service`}),`.`]}),`
537
+ `,(0,c.jsxs)(t.h3,{id:`query-или-read`,children:[(0,c.jsx)(t.code,{children:`query`}),` или `,(0,c.jsx)(t.code,{children:`read`})]}),`
538
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Factory`}),(0,c.jsx)(t.th,{children:`Semantic operation`}),(0,c.jsx)(t.th,{children:`Target`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`createPersistedODataQueryOperation`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`query`})}),(0,c.jsx)(t.td,{children:`collection/plain или parameterized Entity`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`createPersistedODataReadOperation`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`read`})}),(0,c.jsx)(t.td,{children:`одна Entity по keys`})]})]})]}),`
539
+ `,(0,c.jsxs)(t.p,{children:[`Выбор определяется metadata target. Если query возвращает array и transform берёт первый элемент, semantic operation всё равно `,(0,c.jsx)(t.code,{children:`query`}),`.`]}),`
540
+ `,(0,c.jsxs)(t.p,{children:[`Для keyed read `,(0,c.jsx)(t.code,{children:`buildParams`}),` фактически обязателен, даже если structural options допускают отсутствие. Metadata-aware OData layer проверит keys/path.`]}),`
541
+ `,(0,c.jsx)(t.h3,{id:`odata-query-request-assembly`,children:`OData query request assembly`}),`
542
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
543
+ odata,
544
+ params: buildParams?.(scope, args),
545
+ options: {
546
+ baseUrl,
547
+ ...buildOptions?.(scope, args)
548
+ },
549
+ init: buildInit?.(scope, args)
550
+ }
551
+ `})}),`
552
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`buildOptions.baseUrl`}),`, если возвращён, перезапишет adapter `,(0,c.jsx)(t.code,{children:`baseUrl`}),`, потому что spread идёт позже. Для ясности задавайте base URL одним способом.`]}),`
553
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`buildInit`}),` не может задавать signal/method/body по type. Query signal приходит из generic operation context.`]}),`
554
+ `,(0,c.jsxs)(t.h3,{id:`autoparse-не-включён-adapter-ом`,children:[(0,c.jsx)(t.code,{children:`autoParse`}),` не включён adapter-ом`]}),`
555
+ `,(0,c.jsxs)(t.p,{children:[`Persisted OData factories не имеют option `,(0,c.jsx)(t.code,{children:`autoParse`}),` и не добавляют его во request. Response values остаются transport values.`]}),`
556
+ `,(0,c.jsxs)(t.p,{children:[`Если нужны Date/number/boolean domain values, выполните явный transform/validator. Type с `,(0,c.jsx)(t.code,{children:`Date`}),` сам Date не создаёт.`]}),`
557
+ `,(0,c.jsx)(t.h3,{id:`mutation-1`,children:`Mutation`}),`
558
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const save = createPersistedODataMutationOperation({
559
+ odata: { service: "Z_VIEW_CONFIG_SRV", target: "ViewSet" },
560
+ method: "update",
561
+ buildParams: (scope: ViewScope) => wrapODataParams({
562
+ UserId: scope.userId,
563
+ ViewId: scope.viewId
564
+ }),
565
+ bodyMapper: (_scope, input: SaveViewInput) => ({
566
+ Payload: stringifyPersistedJson(input.payload)
567
+ }),
568
+ cacheStrategy: createInvalidatePersistedScopeCacheStrategy()
569
+ });
570
+ `})}),`
571
+ `,(0,c.jsx)(t.p,{children:`Semantic methods:`}),`
572
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Method`}),(0,c.jsx)(t.th,{children:`Params`}),(0,c.jsx)(t.th,{children:`Body`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`create`})}),(0,c.jsx)(t.td,{children:`запрещены`}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`bodyMapper`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`update`})}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`buildParams`})]}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`bodyMapper`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`delete`})}),(0,c.jsxs)(t.td,{children:[`обязательный `,(0,c.jsx)(t.code,{children:`buildParams`})]}),(0,c.jsx)(t.td,{children:`запрещён`})]})]})]}),`
573
+ `,(0,c.jsxs)(t.p,{children:[`Это OData operation names, а не raw HTTP strings. Не передавайте `,(0,c.jsx)(t.code,{children:`"PUT"`}),`/`,(0,c.jsx)(t.code,{children:`"POST"`}),`.`]}),`
574
+ `,(0,c.jsx)(t.p,{children:`OData adapter наследует metadata validation, SAP cookies, SSO recovery и X-CSRF lifecycle. Query/read получают AbortSignal; mutations — нет в generic contract.`}),`
575
+ `,(0,c.jsx)(t.h3,{id:`odata-mutation-assembly`,children:`OData mutation assembly`}),`
576
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`create`}),`:`]}),`
577
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`body = bodyMapper(scope, input)
578
+ params отсутствуют
579
+ `})}),`
580
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`update`}),`:`]}),`
581
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`params = buildParams(scope, input)
582
+ body = bodyMapper(scope, input)
583
+ `})}),`
584
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`delete`}),`:`]}),`
585
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`params = buildParams(scope, input)
586
+ body отсутствует
587
+ `})}),`
588
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`buildOptions`}),` и `,(0,c.jsx)(t.code,{children:`buildInit`}),` доступны всем трём. Cache strategy получает уже transformed result.`]}),`
589
+ `,(0,c.jsx)(t.h3,{id:`functionimport`,children:`FunctionImport`}),`
590
+ `,(0,c.jsxs)(t.p,{children:[`Persisted OData mutation factory поддерживает только `,(0,c.jsx)(t.code,{children:`create`}),`, `,(0,c.jsx)(t.code,{children:`update`}),`, `,(0,c.jsx)(t.code,{children:`delete`}),`. FunctionImport capability собирайте custom persisted operation/совместимым adapter-ом. Не выдавайте FI за create из-за business verb.`]}),`
591
+ `,(0,c.jsx)(t.h3,{id:`custom-odata-executor`,children:`Custom OData executor`}),`
592
+ `,(0,c.jsxs)(t.p,{children:[`Executor получает semantic method, metadata-aware request и `,(0,c.jsx)(t.code,{children:`{ client, signal? }`}),`. Query/read context содержит signal, mutation context — только client.`]}),`
593
+ `,(0,c.jsx)(t.h2,{id:`custom-и-server-function-operations`,children:`Custom и server-function operations`}),`
594
+ `,(0,c.jsxs)(t.p,{children:[`Descriptor принимает любой object, соответствующий `,(0,c.jsx)(t.code,{children:`PersistedQueryOperation`}),`/`,(0,c.jsx)(t.code,{children:`PersistedMutationOperation`}),`. Server-function factories из `,(0,c.jsx)(t.a,{href:`../server-fn/README.mdx`,children:(0,c.jsx)(t.code,{children:`/server-fn`})}),` возвращают совместимые resource operations и могут быть использованы как capabilities, если их generic contract совпадает.`]}),`
595
+ `,(0,c.jsx)(t.p,{children:`Пример custom operation:`}),`
596
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const latest: PersistedQueryOperation<ViewScope, void, ViewConfig | null> = {
597
+ staleTime: 60_000,
598
+ async execute({ scope, client, signal }) {
599
+ const record = await customTransport(scope, { client, signal });
600
+ return restoreViewConfig(record.payload);
601
+ }
602
+ };
603
+ `})}),`
604
+ `,(0,c.jsx)(t.p,{children:`Business mapper остаётся у владельца ViewConfig, generic package содержит infrastructure contract.`}),`
605
+ `,(0,c.jsx)(t.h2,{id:`cache-strategies`,children:`Cache strategies`}),`
606
+ `,(0,c.jsx)(t.h3,{id:`инвалидация-всего-scope`,children:`Инвалидация всего scope`}),`
607
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const invalidate = createInvalidatePersistedScopeCacheStrategy();
608
+ `})}),`
609
+ `,(0,c.jsxs)(t.p,{children:[`Инвалидирует prefix `,(0,c.jsx)(t.code,{children:`descriptor.keys.scope(scope)`}),`, поэтому затрагивает list/latest/history данного scope.`]}),`
610
+ `,(0,c.jsx)(t.h3,{id:`точечное-обновление`,children:`Точечное обновление`}),`
611
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const setLatest = createSetPersistedQueryDataCacheStrategy({
612
+ getQueryKey: ({ descriptor, scope }) => descriptor.keys.latest(scope),
613
+ update: (_current, { result }) => result
614
+ });
615
+ `})}),`
616
+ `,(0,c.jsx)(t.h3,{id:`композиция`,children:`Композиция`}),`
617
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const combined = composePersistedCacheStrategies(setLatest, invalidate);
618
+ `})}),`
619
+ `,(0,c.jsxs)(t.p,{children:[`Порядок последовательный. Если strategy бросила ошибку, следующие steps и hook `,(0,c.jsx)(t.code,{children:`onSuccess`}),` не выполняются, хотя backend mutation уже могла завершиться.`]}),`
620
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`applyPersistedCacheStrategy`}),` — низкоуровневый helper для ручного вызова optional strategy.`]}),`
621
+ `,(0,c.jsx)(t.h3,{id:`cache-strategy-context`,children:`Cache strategy context`}),`
622
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`{
623
+ client,
624
+ descriptor,
625
+ scope,
626
+ input,
627
+ result
628
+ }
629
+ `})}),`
630
+ `,(0,c.jsx)(t.p,{children:`Точечный update latest:`}),`
631
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const updateLatest = createSetPersistedQueryDataCacheStrategy<
632
+ ViewScope,
633
+ SaveViewInput,
634
+ ViewConfig,
635
+ ViewConfig | null
636
+ >({
637
+ getQueryKey: ({ descriptor, scope }) => descriptor.keys.latest(scope),
638
+ update: (_current, { result }) => result
639
+ });
640
+ `})}),`
641
+ `,(0,c.jsx)(t.h3,{id:`почему-invalidation--безопасный-default`,children:`Почему invalidation — безопасный default`}),`
642
+ `,(0,c.jsx)(t.p,{children:`Save может изменить latest, list labels/timestamps, history и server-computed revision. Если result не содержит authoritative формы всех projections, инвалидируйте scope.`}),`
643
+ `,(0,c.jsx)(t.h3,{id:`strategy-order`,children:`Strategy order`}),`
644
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`composePersistedCacheStrategies(updateLatest, invalidateHistory)
645
+ `})}),`
646
+ `,(0,c.jsxs)(t.p,{children:[`выполняется слева направо и await-ит каждую strategy. `,(0,c.jsx)(t.code,{children:`null`}),`/`,(0,c.jsx)(t.code,{children:`undefined`}),` entries пропускаются.`]}),`
647
+ `,(0,c.jsx)(t.p,{children:`Updater не должен мутировать current snapshot. Возвращайте новое значение.`}),`
648
+ `,(0,c.jsx)(t.h3,{id:`cache-error-после-write`,children:`Cache error после write`}),`
649
+ `,(0,c.jsx)(t.p,{children:`Server уже мог сохранить record. Cache failure — не доказательство write failure. Восстановите cache/refetch отдельно вместо слепого повторения create/save.`}),`
650
+ `,(0,c.jsx)(t.h2,{id:`полный-end-to-end-сценарий-restoreeditsave`,children:`Полный end-to-end сценарий restore/edit/save`}),`
651
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`1. usePersistedLatestQuery(scope)
652
+ 2. transport получает backend record
653
+ 3. transform разбирает и валидирует payload
654
+ 4. component создаёт независимый draft clone
655
+ 5. пользователь меняет literal draft
656
+ 6. save mutation сериализует snapshot на save boundary
657
+ 7. backend сохраняет record
658
+ 8. cache strategy invalidates/updates snapshots
659
+ 9. draft отдельно принимает product-specific saved state
660
+ `})}),`
661
+ `,(0,c.jsx)(t.p,{children:`Не записывайте normalized saved snapshot обратно в draft автоматически, если продукт должен сохранять literal ввод до explicit save.`}),`
662
+ `,(0,c.jsx)(t.h2,{id:`тестирование`,children:`Тестирование`}),`
663
+ `,(0,c.jsx)(t.h3,{id:`keys-и-scope`,children:`Keys и scope`}),`
664
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`it("строит одинаковый key для эквивалентного scope", () => {
665
+ const first = viewResource.keys.latest({
666
+ userId: " ivanov ",
667
+ viewId: "main"
668
+ });
669
+ const second = viewResource.keys.latest({
670
+ viewId: "main",
671
+ userId: "ivanov"
672
+ });
673
+
674
+ expect(first).toEqual(second);
675
+ });
676
+ `})}),`
677
+ `,(0,c.jsx)(t.h3,{id:`codec`,children:`Codec`}),`
678
+ `,(0,c.jsxs)(t.p,{children:[`Проверяйте valid object, `,(0,c.jsx)(t.code,{children:`null`}),`, empty string, malformed JSON, version migration и non-serializable value.`]}),`
679
+ `,(0,c.jsx)(t.h3,{id:`rest-request`,children:`REST request`}),`
680
+ `,(0,c.jsx)(t.p,{children:`С custom executor проверяйте URL/base URL, read signal, method, body serialization, headers replacement, parser bypass и transform context.`}),`
681
+ `,(0,c.jsx)(t.h3,{id:`odata-request`,children:`OData request`}),`
682
+ `,(0,c.jsx)(t.p,{children:`С custom executor проверяйте semantic method, wrapped params, body presence/absence, options/baseUrl и context client/signal.`}),`
683
+ `,(0,c.jsx)(t.h3,{id:`descriptor-lifecycle`,children:`Descriptor lifecycle`}),`
684
+ `,(0,c.jsx)(t.p,{children:`Покройте:`}),`
685
+ `,(0,c.jsxs)(t.ul,{children:[`
686
+ `,(0,c.jsx)(t.li,{children:`отсутствующую capability;`}),`
687
+ `,(0,c.jsxs)(t.li,{children:[`nullable scope с `,(0,c.jsx)(t.code,{children:`isEnabled`}),`;`]}),`
688
+ `,(0,c.jsx)(t.li,{children:`imperative invalid scope error;`}),`
689
+ `,(0,c.jsx)(t.li,{children:`list/latest keys без args;`}),`
690
+ `,(0,c.jsx)(t.li,{children:`history keys с args;`}),`
691
+ `,(0,c.jsxs)(t.li,{children:[`mutation cache override `,(0,c.jsx)(t.code,{children:`undefined`}),`/`,(0,c.jsx)(t.code,{children:`null`}),`/object;`]}),`
692
+ `,(0,c.jsx)(t.li,{children:`порядок strategy → hook onSuccess;`}),`
693
+ `,(0,c.jsx)(t.li,{children:`strategy error не запускает следующие callbacks;`}),`
694
+ `,(0,c.jsx)(t.li,{children:`transport error не применяет strategy.`}),`
695
+ `]}),`
696
+ `,(0,c.jsx)(t.h2,{id:`частые-ошибки`,children:`Частые ошибки`}),`
697
+ `,(0,c.jsx)(t.h3,{id:`путать-persisted-record-и-persisted-query-cache`,children:`Путать persisted record и persisted Query cache`}),`
698
+ `,(0,c.jsx)(t.p,{children:`Это разные lifecycle и sources of truth.`}),`
699
+ `,(0,c.jsxs)(t.h3,{id:`descriptor-без-isenabled-при-nullable-scope`,children:[`Descriptor без `,(0,c.jsx)(t.code,{children:`isEnabled`}),` при nullable scope`]}),`
700
+ `,(0,c.jsx)(t.p,{children:`Query будет автоматически запущен и упадёт на scope assertion.`}),`
701
+ `,(0,c.jsx)(t.h3,{id:`использовать-json-codec-как-validator`,children:`Использовать JSON codec как validator`}),`
702
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`JSON.parse`}),` проверяет syntax, но не domain schema.`]}),`
703
+ `,(0,c.jsx)(t.h3,{id:`нормализовать-key-и-ожидать-нормализованный-request-scope`,children:`Нормализовать key и ожидать нормализованный request scope`}),`
704
+ `,(0,c.jsx)(t.p,{children:`Key normalizer не переписывает execute input.`}),`
705
+ `,(0,c.jsx)(t.h3,{id:`скрыть-history-args-во-внешнем-closure`,children:`Скрыть history args во внешнем closure`}),`
706
+ `,(0,c.jsx)(t.p,{children:`Args должны входить в hook/helper call и query key.`}),`
707
+ `,(0,c.jsxs)(t.h3,{id:`потерять-content-type-в-rest-buildinitheaders`,children:[`Потерять Content-Type в REST `,(0,c.jsx)(t.code,{children:`buildInit.headers`})]}),`
708
+ `,(0,c.jsx)(t.p,{children:`Custom headers заменяют default object — добавьте JSON header явно.`}),`
709
+ `,(0,c.jsx)(t.h3,{id:`передать-http-method-в-odata-adapter`,children:`Передать HTTP method в OData adapter`}),`
710
+ `,(0,c.jsxs)(t.p,{children:[`Нужны semantic `,(0,c.jsx)(t.code,{children:`create`}),`/`,(0,c.jsx)(t.code,{children:`update`}),`/`,(0,c.jsx)(t.code,{children:`delete`}),`.`]}),`
711
+ `,(0,c.jsxs)(t.h3,{id:`ожидать-autoparse-odata-values`,children:[`Ожидать `,(0,c.jsx)(t.code,{children:`autoParse`}),` OData values`]}),`
712
+ `,(0,c.jsx)(t.p,{children:`Persisted adapter его не включает. Парсите/валидируйте в transform.`}),`
713
+ `,(0,c.jsx)(t.h3,{id:`retry-create-после-cache-error`,children:`Retry create после cache error`}),`
714
+ `,(0,c.jsx)(t.p,{children:`Backend мог уже создать record. Используйте idempotency и отдельное cache recovery.`}),`
715
+ `,(0,c.jsx)(t.h2,{id:`ошибки-и-безопасность`,children:`Ошибки и безопасность`}),`
716
+ `,(0,c.jsxs)(t.ul,{children:[`
717
+ `,(0,c.jsxs)(t.li,{children:[`Scope `,(0,c.jsx)(t.code,{children:`null`}),`/`,(0,c.jsx)(t.code,{children:`undefined`}),` или rejected `,(0,c.jsx)(t.code,{children:`isEnabled`}),` блокирует query и вызывает ошибку при фактическом execution.`]}),`
718
+ `,(0,c.jsxs)(t.li,{children:[`Network payload валидируйте в `,(0,c.jsx)(t.code,{children:`parseResponse`}),`/`,(0,c.jsx)(t.code,{children:`transform`}),`; TypeScript generic не является validator-ом.`]}),`
719
+ `,(0,c.jsx)(t.li,{children:`Не храните secrets в payload/query keys/client persistence.`}),`
720
+ `,(0,c.jsx)(t.li,{children:`Save/create должны быть идемпотентны настолько, насколько это возможно для retry policy.`}),`
721
+ `,(0,c.jsx)(t.li,{children:`Cache update — локальная проекция, backend остаётся source of truth.`}),`
722
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`parsePersistedJson`}),` подавляет syntax error и возвращает `,(0,c.jsx)(t.code,{children:`null`}),`; различайте «нет payload» и «повреждён payload» на уровне продукта, если это важно.`]}),`
723
+ `]}),`
724
+ `,(0,c.jsx)(t.h2,{id:`faq`,children:`FAQ`}),`
725
+ `,(0,c.jsx)(t.h3,{id:`обязан-ли-resource-поддерживать-все-capabilities`,children:`Обязан ли resource поддерживать все capabilities?`}),`
726
+ `,(0,c.jsx)(t.p,{children:`Нет. Подключайте только существующие backend operations.`}),`
727
+ `,(0,c.jsxs)(t.h3,{id:`чем-save-отличается-от-create`,children:[`Чем `,(0,c.jsx)(t.code,{children:`save`}),` отличается от `,(0,c.jsx)(t.code,{children:`create`}),`?`]}),`
728
+ `,(0,c.jsx)(t.p,{children:`Generic layer не навязывает точную semantics. Обычно save обновляет текущий snapshot, create создаёт новую named/versioned запись; contract определяет owner resource.`}),`
729
+ `,(0,c.jsx)(t.h3,{id:`можно-ли-использовать-другой-payload-format`,children:`Можно ли использовать другой payload format?`}),`
730
+ `,(0,c.jsxs)(t.p,{children:[`Да. `,(0,c.jsx)(t.code,{children:`PersistedPayloadCodec`}),` — interface; JSON helpers лишь convenience.`]}),`
731
+ `,(0,c.jsx)(t.h3,{id:`как-получить-data-вне-react-component`,children:`Как получить data вне React component?`}),`
732
+ `,(0,c.jsxs)(t.p,{children:[`Через `,(0,c.jsx)(t.code,{children:`getPersistedListData`}),`, `,(0,c.jsx)(t.code,{children:`getPersistedLatestData`}),`, `,(0,c.jsx)(t.code,{children:`getPersistedHistoryData`}),` с общим QueryClient.`]}),`
733
+ `,(0,c.jsx)(t.h3,{id:`есть-ли-imperative-mutation-helper`,children:`Есть ли imperative mutation helper?`}),`
734
+ `,(0,c.jsx)(t.p,{children:`Public convenience API mutation сейчас hook-oriented. Custom orchestration должна работать через корректную operation/resource boundary и не обходить cache strategy случайно.`}),`
735
+ `,(0,c.jsx)(t.h3,{id:`кто-мигрирует-старую-version-payload`,children:`Кто мигрирует старую version payload?`}),`
736
+ `,(0,c.jsx)(t.p,{children:`Domain restore mapper владельца конфигурации.`}),`
737
+ `,(0,c.jsx)(t.h3,{id:`можно-ли-хранить-draft-прямо-в-query-cache`,children:`Можно ли хранить draft прямо в Query cache?`}),`
738
+ `,(0,c.jsx)(t.p,{children:`Нет. Query cache хранит backend snapshot; editable draft должен быть независимым.`}),`
739
+ `,(0,c.jsx)(t.h2,{id:`полный-api`,children:`Полный API`}),`
740
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Группа`}),(0,c.jsx)(t.th,{children:`Exports`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Descriptor/keys`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`createPersistedResourceDescriptor`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedRecordKeys`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`React reads`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`usePersistedListQuery`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedLatestQuery`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedHistoryQuery`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Imperative reads`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`getPersistedListData`}),`, `,(0,c.jsx)(t.code,{children:`getPersistedLatestData`}),`, `,(0,c.jsx)(t.code,{children:`getPersistedHistoryData`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Mutations`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`usePersistedSaveMutation`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedCreateMutation`}),`, `,(0,c.jsx)(t.code,{children:`usePersistedDeleteMutation`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Payload`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`parsePersistedJson`}),`, `,(0,c.jsx)(t.code,{children:`stringifyPersistedJson`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedJsonCodec`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`REST adapters`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`createPersistedRestQueryOperation`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedRestMutationOperation`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`OData adapters`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`createPersistedODataQueryOperation`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedODataReadOperation`}),`, `,(0,c.jsx)(t.code,{children:`createPersistedODataMutationOperation`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Cache`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`applyPersistedCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`createInvalidatePersistedScopeCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`createSetPersistedQueryDataCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`composePersistedCacheStrategies`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Names/types`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`PersistedReadOperationName`}),`, `,(0,c.jsx)(t.code,{children:`PersistedWriteOperationName`}),`, `,(0,c.jsx)(t.code,{children:`PersistedOperationName`}),`, `,(0,c.jsx)(t.code,{children:`PersistedPayloadCodec`}),`, `,(0,c.jsx)(t.code,{children:`PersistedRecordKeys`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Operation contracts`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`PersistedQueryOperationContext`}),`, `,(0,c.jsx)(t.code,{children:`PersistedMutationOperationContext`}),`, `,(0,c.jsx)(t.code,{children:`PersistedQueryOperation`}),`, `,(0,c.jsx)(t.code,{children:`PersistedMutationOperation`}),`, `,(0,c.jsx)(t.code,{children:`PersistedOperationCapabilities`}),`, `,(0,c.jsx)(t.code,{children:`PersistedTransportAdapter`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Descriptor/cache contracts`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`PersistedResourceDescriptor`}),`, `,(0,c.jsx)(t.code,{children:`CreatePersistedResourceDescriptorOptions`}),`, `,(0,c.jsx)(t.code,{children:`PersistedCacheStrategyContext`}),`, `,(0,c.jsx)(t.code,{children:`PersistedCacheStrategy`}),`, `,(0,c.jsx)(t.code,{children:`PersistedSetQueryDataStrategyOptions`})]})]})]})]})]})}function s(e={}){let{wrapper:t}={...n(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(o,{...e})}):o(e)}var c;function l(){return(l=e((()=>{c=t(),r(),a()})))()}l();export{s as default};