@shapio/cms 0.5.8 → 0.5.10

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 (343) hide show
  1. package/dist/admin/assets/{AssetTile-BrMzsUZD.js → AssetTile-DecaDqjj.js} +2 -2
  2. package/dist/admin/assets/{AssetTile-BrMzsUZD.js.map → AssetTile-DecaDqjj.js.map} +1 -1
  3. package/dist/admin/assets/AssistError-rslPtgWB.js +2 -0
  4. package/dist/admin/assets/{AssistError-Cs-r9Ssc.js.map → AssistError-rslPtgWB.js.map} +1 -1
  5. package/dist/admin/assets/{BlockMenuItems-DsccXMc_.js → BlockMenuItems-JHFue7Qt.js} +2 -2
  6. package/dist/admin/assets/{BlockMenuItems-DsccXMc_.js.map → BlockMenuItems-JHFue7Qt.js.map} +1 -1
  7. package/dist/admin/assets/Body-7NgJl9Pi.js +2 -0
  8. package/dist/admin/assets/Body-7NgJl9Pi.js.map +1 -0
  9. package/dist/admin/assets/Builder-DmlYcgiP.js +2 -0
  10. package/dist/admin/assets/Builder-DmlYcgiP.js.map +1 -0
  11. package/dist/admin/assets/{CodeEditor-CBCR73Wd.js → CodeEditor-Dv1FtkvI.js} +2 -2
  12. package/dist/admin/assets/{CodeEditor-CBCR73Wd.js.map → CodeEditor-Dv1FtkvI.js.map} +1 -1
  13. package/dist/admin/assets/{CopyButton-CxFsBHfF.js → CopyButton-Brnpfqe0.js} +2 -2
  14. package/dist/admin/assets/{CopyButton-CxFsBHfF.js.map → CopyButton-Brnpfqe0.js.map} +1 -1
  15. package/dist/admin/assets/{CursorPager-BW2U3v6l.js → CursorPager-C7cAK5Qe.js} +2 -2
  16. package/dist/admin/assets/{CursorPager-BW2U3v6l.js.map → CursorPager-C7cAK5Qe.js.map} +1 -1
  17. package/dist/admin/assets/{ExternalLink-BITMgS1K.js → ExternalLink-D80sb5Jj.js} +2 -2
  18. package/dist/admin/assets/{ExternalLink-BITMgS1K.js.map → ExternalLink-D80sb5Jj.js.map} +1 -1
  19. package/dist/admin/assets/{FocalPoint-CpZTve1E.js → FocalPoint-Bhtb1gUa.js} +2 -2
  20. package/dist/admin/assets/{FocalPoint-CpZTve1E.js.map → FocalPoint-Bhtb1gUa.js.map} +1 -1
  21. package/dist/admin/assets/Form-Cf1ephPH.js +2 -0
  22. package/dist/admin/assets/Form-Cf1ephPH.js.map +1 -0
  23. package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js +2 -0
  24. package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js.map +1 -0
  25. package/dist/admin/assets/{FormRadioGroup-Cfx5pvzU.js → FormRadioGroup-BzmLzRnI.js} +2 -2
  26. package/dist/admin/assets/{FormRadioGroup-Cfx5pvzU.js.map → FormRadioGroup-BzmLzRnI.js.map} +1 -1
  27. package/dist/admin/assets/FormSelectField-Cl7EjXc3.js +2 -0
  28. package/dist/admin/assets/FormSelectField-Cl7EjXc3.js.map +1 -0
  29. package/dist/admin/assets/FormSheet-CLZpd_7B.js +2 -0
  30. package/dist/admin/assets/FormSheet-CLZpd_7B.js.map +1 -0
  31. package/dist/admin/assets/{FormSwitchField-BLOh7qei.js → FormSwitchField-BbqQ3tx_.js} +2 -2
  32. package/dist/admin/assets/{FormSwitchField-BLOh7qei.js.map → FormSwitchField-BbqQ3tx_.js.map} +1 -1
  33. package/dist/admin/assets/{FormTextareaField-CO115n_u.js → FormTextareaField-9RN5Pt3B.js} +2 -2
  34. package/dist/admin/assets/{FormTextareaField-CO115n_u.js.map → FormTextareaField-9RN5Pt3B.js.map} +1 -1
  35. package/dist/admin/assets/{HintedLabel-DzHnEdIK.js → HintedLabel-D9IVF0EE.js} +2 -2
  36. package/dist/admin/assets/{HintedLabel-DzHnEdIK.js.map → HintedLabel-D9IVF0EE.js.map} +1 -1
  37. package/dist/admin/assets/{InfoHint-CSEtcHjL.js → InfoHint-tlSeZB9U.js} +2 -2
  38. package/dist/admin/assets/{InfoHint-CSEtcHjL.js.map → InfoHint-tlSeZB9U.js.map} +1 -1
  39. package/dist/admin/assets/{InlineConfirm-yW-iUKFC.js → InlineConfirm-Kj9AOIFO.js} +2 -2
  40. package/dist/admin/assets/{InlineConfirm-yW-iUKFC.js.map → InlineConfirm-Kj9AOIFO.js.map} +1 -1
  41. package/dist/admin/assets/{InsertMenuItem-CCr9e0qY.js → InsertMenuItem-CHAp2tH7.js} +2 -2
  42. package/dist/admin/assets/{InsertMenuItem-CCr9e0qY.js.map → InsertMenuItem-CHAp2tH7.js.map} +1 -1
  43. package/dist/admin/assets/{LinkTabs-8SmS1vCd.js → LinkTabs-oQXsy1I3.js} +2 -2
  44. package/dist/admin/assets/{LinkTabs-8SmS1vCd.js.map → LinkTabs-oQXsy1I3.js.map} +1 -1
  45. package/dist/admin/assets/{Match-CcD9KxHH.js → Match-BfNRwPfR.js} +2 -2
  46. package/dist/admin/assets/{Match-CcD9KxHH.js.map → Match-BfNRwPfR.js.map} +1 -1
  47. package/dist/admin/assets/{NoAccess-C8RLPN0I.js → NoAccess-DnEpYj9l.js} +2 -2
  48. package/dist/admin/assets/{NoAccess-C8RLPN0I.js.map → NoAccess-DnEpYj9l.js.map} +1 -1
  49. package/dist/admin/assets/Panel-Bcl09TtM.js.map +1 -1
  50. package/dist/admin/assets/{QueryView-xMP_uJ_t.js → QueryView-B86NcRt5.js} +2 -2
  51. package/dist/admin/assets/{QueryView-xMP_uJ_t.js.map → QueryView-B86NcRt5.js.map} +1 -1
  52. package/dist/admin/assets/{RadioTile-DQFmni5A.js → RadioTile-Bwd2Pmlk.js} +2 -2
  53. package/dist/admin/assets/RadioTile-Bwd2Pmlk.js.map +1 -0
  54. package/dist/admin/assets/{RichTextField-CVHRIbnu.js → RichTextField-Dou79MHF.js} +4 -4
  55. package/dist/admin/assets/RichTextField-Dou79MHF.js.map +1 -0
  56. package/dist/admin/assets/{RowTitle-Bqt6evG9.js → RowTitle-DH9OZs3g.js} +2 -2
  57. package/dist/admin/assets/{RowTitle-Bqt6evG9.js.map → RowTitle-DH9OZs3g.js.map} +1 -1
  58. package/dist/admin/assets/{SecretReveal-Bm6nYg5J.js → SecretReveal-D95oACLj.js} +2 -2
  59. package/dist/admin/assets/{SecretReveal-Bm6nYg5J.js.map → SecretReveal-D95oACLj.js.map} +1 -1
  60. package/dist/admin/assets/{SharedGlyph-cUmTh0_C.js → SharedGlyph-Chwb1EIS.js} +2 -2
  61. package/dist/admin/assets/{SharedGlyph-cUmTh0_C.js.map → SharedGlyph-Chwb1EIS.js.map} +1 -1
  62. package/dist/admin/assets/StepList-D9iHsUZJ.js +2 -0
  63. package/dist/admin/assets/StepList-D9iHsUZJ.js.map +1 -0
  64. package/dist/admin/assets/Structure-CewJL1b3.js +2 -0
  65. package/dist/admin/assets/{Structure-D8csgrIt.js.map → Structure-CewJL1b3.js.map} +1 -1
  66. package/dist/admin/assets/{SubNavLink-CiCaVV8U.js → SubNavLink-7Cs1LqMv.js} +2 -2
  67. package/dist/admin/assets/SubNavLink-7Cs1LqMv.js.map +1 -0
  68. package/dist/admin/assets/{SuggestAltButton-CvIoirnz.js → SuggestAltButton-BK1uo4yC.js} +2 -2
  69. package/dist/admin/assets/{SuggestAltButton-CvIoirnz.js.map → SuggestAltButton-BK1uo4yC.js.map} +1 -1
  70. package/dist/admin/assets/{TextLink-HRn66VL1.js → TextLink-Dfs5wsc5.js} +2 -2
  71. package/dist/admin/assets/{TextLink-HRn66VL1.js.map → TextLink-Dfs5wsc5.js.map} +1 -1
  72. package/dist/admin/assets/{Thumbnail-DNj5TRBI.js → Thumbnail-C2A_Ub77.js} +2 -2
  73. package/dist/admin/assets/{Thumbnail-DNj5TRBI.js.map → Thumbnail-C2A_Ub77.js.map} +1 -1
  74. package/dist/admin/assets/Trans-CPoNNUK1.js +2 -0
  75. package/dist/admin/assets/Trans-CPoNNUK1.js.map +1 -0
  76. package/dist/admin/assets/{UnsavedChangesGuard-CUiuMklN.js → UnsavedChangesGuard-BsEyn9oH.js} +2 -2
  77. package/dist/admin/assets/{UnsavedChangesGuard-CUiuMklN.js.map → UnsavedChangesGuard-BsEyn9oH.js.map} +1 -1
  78. package/dist/admin/assets/{UserAvatar-p-jV-LoD.js → UserAvatar-CgGKOFfP.js} +2 -2
  79. package/dist/admin/assets/{UserAvatar-p-jV-LoD.js.map → UserAvatar-CgGKOFfP.js.map} +1 -1
  80. package/dist/admin/assets/auth-BFSvtV59.js +2 -0
  81. package/dist/admin/assets/{auth-CQO4MBUj.js.map → auth-BFSvtV59.js.map} +1 -1
  82. package/dist/admin/assets/{badge-CqKF1pwz.js → badge-DGqA_yr_.js} +2 -2
  83. package/dist/admin/assets/{badge-CqKF1pwz.js.map → badge-DGqA_yr_.js.map} +1 -1
  84. package/dist/admin/assets/baseExtensions-TVKN1UwW.js.map +1 -1
  85. package/dist/admin/assets/{boxes-CAygw8zF.js → boxes-_5klpWNM.js} +2 -2
  86. package/dist/admin/assets/{boxes-CAygw8zF.js.map → boxes-_5klpWNM.js.map} +1 -1
  87. package/dist/admin/assets/{calendar-clock-BZGtAvWR.js → calendar-clock-VXok22Xj.js} +2 -2
  88. package/dist/admin/assets/{calendar-clock-BZGtAvWR.js.map → calendar-clock-VXok22Xj.js.map} +1 -1
  89. package/dist/admin/assets/changeSets-B6HxCJ4A.js +2 -0
  90. package/dist/admin/assets/{changeSets-8EburmT0.js.map → changeSets-B6HxCJ4A.js.map} +1 -1
  91. package/dist/admin/assets/chevron-left-CkRxDtvO.js +2 -0
  92. package/dist/admin/assets/{chevron-left-DGU3HGYG.js.map → chevron-left-CkRxDtvO.js.map} +1 -1
  93. package/dist/admin/assets/{circle-check-C37MSJqX.js → circle-check-DtDq7QMo.js} +2 -2
  94. package/dist/admin/assets/{circle-check-C37MSJqX.js.map → circle-check-DtDq7QMo.js.map} +1 -1
  95. package/dist/admin/assets/{clock-2arjsgZ4.js → clock-BtvZR9KD.js} +2 -2
  96. package/dist/admin/assets/{clock-2arjsgZ4.js.map → clock-BtvZR9KD.js.map} +1 -1
  97. package/dist/admin/assets/cn-DVhJ55Mo.js.map +1 -1
  98. package/dist/admin/assets/{constants-a_15vqOh.js → constants-DY3YJAKH.js} +2 -2
  99. package/dist/admin/assets/{constants-a_15vqOh.js.map → constants-DY3YJAKH.js.map} +1 -1
  100. package/dist/admin/assets/content-BNZF26Ve.js +3 -0
  101. package/dist/admin/assets/content-BNZF26Ve.js.map +1 -0
  102. package/dist/admin/assets/{contentCounts-DP7YYeZZ.js → contentCounts-BzC7IQqP.js} +2 -2
  103. package/dist/admin/assets/{contentCounts-DP7YYeZZ.js.map → contentCounts-BzC7IQqP.js.map} +1 -1
  104. package/dist/admin/assets/{contentTypes-84uc0bjR.js → contentTypes-Bz2xpqGf.js} +2 -2
  105. package/dist/admin/assets/{contentTypes-84uc0bjR.js.map → contentTypes-Bz2xpqGf.js.map} +1 -1
  106. package/dist/admin/assets/{context-IKYdzQJ-.js → context-CEVKblBl.js} +2 -2
  107. package/dist/admin/assets/{context-IKYdzQJ-.js.map → context-CEVKblBl.js.map} +1 -1
  108. package/dist/admin/assets/{copy-CsSRHgKZ.js → copy-B7vIq8DS.js} +2 -2
  109. package/dist/admin/assets/{copy-CsSRHgKZ.js.map → copy-B7vIq8DS.js.map} +1 -1
  110. package/dist/admin/assets/createLucideIcon-BOsNKleB.js +2 -0
  111. package/dist/admin/assets/createLucideIcon-BOsNKleB.js.map +1 -0
  112. package/dist/admin/assets/develop-D6CtwuYj.js +11 -0
  113. package/dist/admin/assets/develop-D6CtwuYj.js.map +1 -0
  114. package/dist/admin/assets/{dropdown-menu-_xfaEp5C.js → dropdown-menu-Bz7CLcRK.js} +2 -2
  115. package/dist/admin/assets/{dropdown-menu-_xfaEp5C.js.map → dropdown-menu-Bz7CLcRK.js.map} +1 -1
  116. package/dist/admin/assets/{ellipsis-F91991on.js → ellipsis-Ci0rsbCJ.js} +2 -2
  117. package/dist/admin/assets/{ellipsis-F91991on.js.map → ellipsis-Ci0rsbCJ.js.map} +1 -1
  118. package/dist/admin/assets/{entryLink-CVB-TdIn.js → entryLink-B0hSb_dN.js} +2 -2
  119. package/dist/admin/assets/{entryLink-CVB-TdIn.js.map → entryLink-B0hSb_dN.js.map} +1 -1
  120. package/dist/admin/assets/es2015-Cv57ynE1.js +42 -0
  121. package/dist/admin/assets/es2015-Cv57ynE1.js.map +1 -0
  122. package/dist/admin/assets/{external-link-CdG6kHfA.js → external-link-Bs9YRzvY.js} +2 -2
  123. package/dist/admin/assets/{external-link-CdG6kHfA.js.map → external-link-Bs9YRzvY.js.map} +1 -1
  124. package/dist/admin/assets/{field-COOzRptX.js → field-D-xWW2E7.js} +2 -2
  125. package/dist/admin/assets/{field-COOzRptX.js.map → field-D-xWW2E7.js.map} +1 -1
  126. package/dist/admin/assets/{file-stack-28ZtO1xW.js → file-stack-X4OGmkLA.js} +2 -2
  127. package/dist/admin/assets/{file-stack-28ZtO1xW.js.map → file-stack-X4OGmkLA.js.map} +1 -1
  128. package/dist/admin/assets/{fileRoute-s7mCMYUJ.js → fileRoute-DMal-zYL.js} +2 -2
  129. package/dist/admin/assets/{fileRoute-s7mCMYUJ.js.map → fileRoute-DMal-zYL.js.map} +1 -1
  130. package/dist/admin/assets/{folder-plus-DIk0pWkP.js → folder-plus-De2GNvry.js} +2 -2
  131. package/dist/admin/assets/{folder-plus-DIk0pWkP.js.map → folder-plus-De2GNvry.js.map} +1 -1
  132. package/dist/admin/assets/followPlural-CsgeALTW.js +2 -0
  133. package/dist/admin/assets/followPlural-CsgeALTW.js.map +1 -0
  134. package/dist/admin/assets/{globe-DFr3Gd2w.js → globe-DBw84s8Z.js} +2 -2
  135. package/dist/admin/assets/{globe-DFr3Gd2w.js.map → globe-DBw84s8Z.js.map} +1 -1
  136. package/dist/admin/assets/{image-DT79QFa_.js → image-CX4mT-_R.js} +2 -2
  137. package/dist/admin/assets/{image-DT79QFa_.js.map → image-CX4mT-_R.js.map} +1 -1
  138. package/dist/admin/assets/{image-off-DFs5upyX.js → image-off-CVaH_qKf.js} +2 -2
  139. package/dist/admin/assets/{image-off-DFs5upyX.js.map → image-off-CVaH_qKf.js.map} +1 -1
  140. package/dist/admin/assets/inbox-C0PVc6UI.js +2 -0
  141. package/dist/admin/assets/inbox-C0PVc6UI.js.map +1 -0
  142. package/dist/admin/assets/{inbox-CySnQydm.js → inbox-D9SmWt5L.js} +2 -2
  143. package/dist/admin/assets/{inbox-CySnQydm.js.map → inbox-D9SmWt5L.js.map} +1 -1
  144. package/dist/admin/assets/index-BqtCXB0u.js +4 -0
  145. package/dist/admin/assets/index-BqtCXB0u.js.map +1 -0
  146. package/dist/admin/assets/index-DZsQq6fY.css +2 -0
  147. package/dist/admin/assets/{key-round-D36CePnN.js → key-round-C8sd9CLN.js} +2 -2
  148. package/dist/admin/assets/{key-round-D36CePnN.js.map → key-round-C8sd9CLN.js.map} +1 -1
  149. package/dist/admin/assets/{labels-DQckbLGW.js → labels-BtktCNGw.js} +2 -2
  150. package/dist/admin/assets/{labels-DQckbLGW.js.map → labels-BtktCNGw.js.map} +1 -1
  151. package/dist/admin/assets/{languages-CzbTaQv9.js → languages-DLjdz6gb.js} +2 -2
  152. package/dist/admin/assets/{languages-CzbTaQv9.js.map → languages-DLjdz6gb.js.map} +1 -1
  153. package/dist/admin/assets/{layers-BmcodiaH.js → layers-swLuw-3a.js} +2 -2
  154. package/dist/admin/assets/{layers-BmcodiaH.js.map → layers-swLuw-3a.js.map} +1 -1
  155. package/dist/admin/assets/{link-2-off-CoJNwrxm.js → link-2-off-CEsI5T8h.js} +2 -2
  156. package/dist/admin/assets/{link-2-off-CoJNwrxm.js.map → link-2-off-CEsI5T8h.js.map} +1 -1
  157. package/dist/admin/assets/{link-Pyr2Y35S.js → link-C98FG_p5.js} +2 -2
  158. package/dist/admin/assets/{link-Pyr2Y35S.js.map → link-C98FG_p5.js.map} +1 -1
  159. package/dist/admin/assets/locales-CkuC7TJ1.js +2 -0
  160. package/dist/admin/assets/{locales-Bg3htKo8.js.map → locales-CkuC7TJ1.js.map} +1 -1
  161. package/dist/admin/assets/media-CbGSd_Mw.js +2 -0
  162. package/dist/admin/assets/{media-BCnVhaDH.js.map → media-CbGSd_Mw.js.map} +1 -1
  163. package/dist/admin/assets/{media-CURizGns.js → media-CeZGDGh7.js} +2 -2
  164. package/dist/admin/assets/{media-CURizGns.js.map → media-CeZGDGh7.js.map} +1 -1
  165. package/dist/admin/assets/network-BflLSKFO.js +2 -0
  166. package/dist/admin/assets/network-BflLSKFO.js.map +1 -0
  167. package/dist/admin/assets/{plus-BoDtdLCo.js → plus-cr9ZfO6j.js} +2 -2
  168. package/dist/admin/assets/{plus-BoDtdLCo.js.map → plus-cr9ZfO6j.js.map} +1 -1
  169. package/dist/admin/assets/publishing-BkxBplUZ.js +2 -0
  170. package/dist/admin/assets/publishing-BkxBplUZ.js.map +1 -0
  171. package/dist/admin/assets/{radio-group-4ok5evXq.js → radio-group-CRuWQnuV.js} +2 -2
  172. package/dist/admin/assets/{radio-group-4ok5evXq.js.map → radio-group-CRuWQnuV.js.map} +1 -1
  173. package/dist/admin/assets/{rotate-ccw-DL6TzcZh.js → rotate-ccw-BP8Ba-mY.js} +2 -2
  174. package/dist/admin/assets/{rotate-ccw-DL6TzcZh.js.map → rotate-ccw-BP8Ba-mY.js.map} +1 -1
  175. package/dist/admin/assets/schedules-BIyBlsYZ.js +2 -0
  176. package/dist/admin/assets/{schedules-BmB9Y73z.js.map → schedules-BIyBlsYZ.js.map} +1 -1
  177. package/dist/admin/assets/schema-6eUoC8fJ.js +2 -0
  178. package/dist/admin/assets/schema-6eUoC8fJ.js.map +1 -0
  179. package/dist/admin/assets/{scroll-text-PqeZm472.js → scroll-text-B5vfi9fD.js} +2 -2
  180. package/dist/admin/assets/{scroll-text-PqeZm472.js.map → scroll-text-B5vfi9fD.js.map} +1 -1
  181. package/dist/admin/assets/{search-BdwIwOzC.js → search-wj7zbkx1.js} +2 -2
  182. package/dist/admin/assets/{search-BdwIwOzC.js.map → search-wj7zbkx1.js.map} +1 -1
  183. package/dist/admin/assets/{searchSchemas-CSScloG8.js → searchSchemas-DAnwh3I3.js} +2 -2
  184. package/dist/admin/assets/{searchSchemas-CSScloG8.js.map → searchSchemas-DAnwh3I3.js.map} +1 -1
  185. package/dist/admin/assets/{sections-DqBzSKMP.js → sections-CWL-XD6m.js} +2 -2
  186. package/dist/admin/assets/sections-CWL-XD6m.js.map +1 -0
  187. package/dist/admin/assets/{sections-BTS683ur.js → sections-DBQpB0uv.js} +2 -2
  188. package/dist/admin/assets/{sections-BTS683ur.js.map → sections-DBQpB0uv.js.map} +1 -1
  189. package/dist/admin/assets/{select-C0USI-Ox.js → select-DVrPV1b3.js} +2 -2
  190. package/dist/admin/assets/{select-C0USI-Ox.js.map → select-DVrPV1b3.js.map} +1 -1
  191. package/dist/admin/assets/{send-XPWo3m4u.js → send-CzFdgUc_.js} +2 -2
  192. package/dist/admin/assets/{send-XPWo3m4u.js.map → send-CzFdgUc_.js.map} +1 -1
  193. package/dist/admin/assets/seo-Bd0sWQMo.js +2 -0
  194. package/dist/admin/assets/{seo-CceGYTIX.js.map → seo-Bd0sWQMo.js.map} +1 -1
  195. package/dist/admin/assets/settings-CqnrPmzR.js +2 -0
  196. package/dist/admin/assets/{settings-B60vHpZd.js.map → settings-CqnrPmzR.js.map} +1 -1
  197. package/dist/admin/assets/shapes-ZAkMBB-Z.js +6 -0
  198. package/dist/admin/assets/shapes-ZAkMBB-Z.js.map +1 -0
  199. package/dist/admin/assets/{skeleton-B5MP72Kw.js → skeleton-CiX26LnL.js} +2 -2
  200. package/dist/admin/assets/{skeleton-B5MP72Kw.js.map → skeleton-CiX26LnL.js.map} +1 -1
  201. package/dist/admin/assets/{snapshots-DUI2t-qF.js → snapshots-DbFQNJgN.js} +2 -2
  202. package/dist/admin/assets/{snapshots-DUI2t-qF.js.map → snapshots-DbFQNJgN.js.map} +1 -1
  203. package/dist/admin/assets/{sparkles-CvT-jxrW.js → sparkles-D_kmZJVd.js} +2 -2
  204. package/dist/admin/assets/{sparkles-CvT-jxrW.js.map → sparkles-D_kmZJVd.js.map} +1 -1
  205. package/dist/admin/assets/src-CMor9izq.js +7 -0
  206. package/dist/admin/assets/src-CMor9izq.js.map +1 -0
  207. package/dist/admin/assets/{stableId-BrtQedPy.js → stableId-g1uxJGSz.js} +2 -2
  208. package/dist/admin/assets/{stableId-BrtQedPy.js.map → stableId-g1uxJGSz.js.map} +1 -1
  209. package/dist/admin/assets/{store-CdIFG90N.js → store-CznhNKEi.js} +2 -2
  210. package/dist/admin/assets/{store-CdIFG90N.js.map → store-CznhNKEi.js.map} +1 -1
  211. package/dist/admin/assets/{switch-Dp6WYNam.js → switch-CiVf05NF.js} +2 -2
  212. package/dist/admin/assets/{switch-Dp6WYNam.js.map → switch-CiVf05NF.js.map} +1 -1
  213. package/dist/admin/assets/{theme-65PB8uAu.js → theme-Cv-MfOv8.js} +2 -2
  214. package/dist/admin/assets/theme-Cv-MfOv8.js.map +1 -0
  215. package/dist/admin/assets/titles-DrQhW8z3.js +2 -0
  216. package/dist/admin/assets/titles-DrQhW8z3.js.map +1 -0
  217. package/dist/admin/assets/tokens-B1S81Epe.js +2 -0
  218. package/dist/admin/assets/{tokens-ixHjAkDK.js.map → tokens-B1S81Epe.js.map} +1 -1
  219. package/dist/admin/assets/{tooltip-BGP1DVBt.js → tooltip-Bqf3oyqC.js} +2 -2
  220. package/dist/admin/assets/{tooltip-BGP1DVBt.js.map → tooltip-Bqf3oyqC.js.map} +1 -1
  221. package/dist/admin/assets/{undo-2-BiTANHFz.js → undo-2-DpwwRQTf.js} +2 -2
  222. package/dist/admin/assets/{undo-2-BiTANHFz.js.map → undo-2-DpwwRQTf.js.map} +1 -1
  223. package/dist/admin/assets/useContentSchema-B_q1rMrG.js +2 -0
  224. package/dist/admin/assets/useContentSchema-B_q1rMrG.js.map +1 -0
  225. package/dist/admin/assets/useCursorPager-BHYqHb3M.js +2 -0
  226. package/dist/admin/assets/{useCursorPager-0zHjlm-7.js.map → useCursorPager-BHYqHb3M.js.map} +1 -1
  227. package/dist/admin/assets/{useDiscardGuard-BskWSlbT.js → useDiscardGuard-C4QTfiU4.js} +2 -2
  228. package/dist/admin/assets/{useDiscardGuard-BskWSlbT.js.map → useDiscardGuard-C4QTfiU4.js.map} +1 -1
  229. package/dist/admin/assets/{useMediaPickerDialog-CU-ekPqX.js → useMediaPickerDialog-BLrVV1Kn.js} +2 -2
  230. package/dist/admin/assets/{useMediaPickerDialog-CU-ekPqX.js.map → useMediaPickerDialog-BLrVV1Kn.js.map} +1 -1
  231. package/dist/admin/assets/{useMediaUploader-CBcq1ICg.js → useMediaUploader-CFy6lasO.js} +2 -2
  232. package/dist/admin/assets/useMediaUploader-CFy6lasO.js.map +1 -0
  233. package/dist/admin/assets/useModelIndex-NU-WlHQY.js +2 -0
  234. package/dist/admin/assets/useModelIndex-NU-WlHQY.js.map +1 -0
  235. package/dist/admin/assets/useNetworkPermission-DehDln-U.js +2 -0
  236. package/dist/admin/assets/{useNetworkPermission-Cts98h9d.js.map → useNetworkPermission-DehDln-U.js.map} +1 -1
  237. package/dist/admin/assets/{usePaletteItems-DtReWmkd.js → usePaletteItems-CFpNlSOs.js} +2 -2
  238. package/dist/admin/assets/{usePaletteItems-DtReWmkd.js.map → usePaletteItems-CFpNlSOs.js.map} +1 -1
  239. package/dist/admin/assets/usePlaces-BA4x6503.js +2 -0
  240. package/dist/admin/assets/usePlaces-BA4x6503.js.map +1 -0
  241. package/dist/admin/assets/useResolvedDefinitions-30lnwFQ1.js +2 -0
  242. package/dist/admin/assets/useResolvedDefinitions-30lnwFQ1.js.map +1 -0
  243. package/dist/admin/assets/{useResolvedScheme-C8vcQVko.js → useResolvedScheme-BVM4qLct.js} +2 -2
  244. package/dist/admin/assets/{useResolvedScheme-C8vcQVko.js.map → useResolvedScheme-BVM4qLct.js.map} +1 -1
  245. package/dist/admin/assets/useSaveShortcut-DQuNL1uJ.js +2 -0
  246. package/dist/admin/assets/useSaveShortcut-DQuNL1uJ.js.map +1 -0
  247. package/dist/admin/assets/{useSchemaScopeAccess-ByrxIdKM.js → useSchemaScopeAccess-JXOMx51q.js} +2 -2
  248. package/dist/admin/assets/{useSchemaScopeAccess-ByrxIdKM.js.map → useSchemaScopeAccess-JXOMx51q.js.map} +1 -1
  249. package/dist/admin/assets/users-38jLQ7zr.js +2 -0
  250. package/dist/admin/assets/users-38jLQ7zr.js.map +1 -0
  251. package/dist/admin/assets/{users-DM7CXUBJ.js → users-DYwcVDqp.js} +2 -2
  252. package/dist/admin/assets/{users-DM7CXUBJ.js.map → users-DYwcVDqp.js.map} +1 -1
  253. package/dist/admin/assets/{zod-Cry7YvLY.js → zod-ZaQjjiAq.js} +2 -2
  254. package/dist/admin/assets/{zod-Cry7YvLY.js.map → zod-ZaQjjiAq.js.map} +1 -1
  255. package/dist/admin/index.html +60 -58
  256. package/dist/cli.js +1 -1
  257. package/dist/{cliMain-papyXJDd.js → cliMain-CTntiVc2.js} +107 -30
  258. package/dist/cliMain-CTntiVc2.js.map +1 -0
  259. package/dist/config.d.ts +2 -2
  260. package/dist/config.js +1 -1
  261. package/dist/{contentDisposition-DOL2Xt0l.js → contentDisposition-DzhPhncr.js} +2 -2
  262. package/dist/{contentDisposition-DOL2Xt0l.js.map → contentDisposition-DzhPhncr.js.map} +1 -1
  263. package/dist/index.d.ts +43 -6
  264. package/dist/index.js +2 -2
  265. package/dist/{public-COKbHR-N.d.ts → public-CMFaGDyf.d.ts} +50 -8
  266. package/dist/{public-B57h4F7Y.js → public-sJCQaNaP.js} +2 -2
  267. package/dist/public-sJCQaNaP.js.map +1 -0
  268. package/dist/{s3Adapter-U01iEAcK.js → s3Adapter-CZcCl0sy.js} +2 -2
  269. package/dist/{s3Adapter-U01iEAcK.js.map → s3Adapter-CZcCl0sy.js.map} +1 -1
  270. package/dist/{worker-B-sC-eY2.js → worker-DHm2JwMZ.js} +3140 -1292
  271. package/dist/worker-DHm2JwMZ.js.map +1 -0
  272. package/package.json +5 -5
  273. package/dist/admin/assets/AssistError-Cs-r9Ssc.js +0 -2
  274. package/dist/admin/assets/Body-BzZD-TZT.js +0 -2
  275. package/dist/admin/assets/Body-BzZD-TZT.js.map +0 -1
  276. package/dist/admin/assets/Builder-DW-GJA_q.js +0 -2
  277. package/dist/admin/assets/Builder-DW-GJA_q.js.map +0 -1
  278. package/dist/admin/assets/Form-lNrRHc0I.js +0 -2
  279. package/dist/admin/assets/Form-lNrRHc0I.js.map +0 -1
  280. package/dist/admin/assets/FormCheckboxGroup-DeeaYnzB.js +0 -2
  281. package/dist/admin/assets/FormCheckboxGroup-DeeaYnzB.js.map +0 -1
  282. package/dist/admin/assets/FormSelectField-BzE9Lq9i.js +0 -2
  283. package/dist/admin/assets/FormSelectField-BzE9Lq9i.js.map +0 -1
  284. package/dist/admin/assets/RadioTile-DQFmni5A.js.map +0 -1
  285. package/dist/admin/assets/RichTextField-CVHRIbnu.js.map +0 -1
  286. package/dist/admin/assets/StepList-BXGYD9eJ.js +0 -2
  287. package/dist/admin/assets/StepList-BXGYD9eJ.js.map +0 -1
  288. package/dist/admin/assets/Structure-D8csgrIt.js +0 -2
  289. package/dist/admin/assets/SubNavLink-CiCaVV8U.js.map +0 -1
  290. package/dist/admin/assets/auth-CQO4MBUj.js +0 -2
  291. package/dist/admin/assets/changeSets-8EburmT0.js +0 -2
  292. package/dist/admin/assets/chevron-left-DGU3HGYG.js +0 -2
  293. package/dist/admin/assets/content-CAjkbZEY.js +0 -3
  294. package/dist/admin/assets/content-CAjkbZEY.js.map +0 -1
  295. package/dist/admin/assets/createLucideIcon-CLmh7Go-.js +0 -2
  296. package/dist/admin/assets/createLucideIcon-CLmh7Go-.js.map +0 -1
  297. package/dist/admin/assets/develop-BOqvnlgt.js +0 -11
  298. package/dist/admin/assets/develop-BOqvnlgt.js.map +0 -1
  299. package/dist/admin/assets/es2015-BHmI7wjK.js +0 -42
  300. package/dist/admin/assets/es2015-BHmI7wjK.js.map +0 -1
  301. package/dist/admin/assets/followPlural-Cm7v_Udv.js +0 -2
  302. package/dist/admin/assets/followPlural-Cm7v_Udv.js.map +0 -1
  303. package/dist/admin/assets/inbox-DGO2D8fa.js +0 -2
  304. package/dist/admin/assets/inbox-DGO2D8fa.js.map +0 -1
  305. package/dist/admin/assets/index-BIIU9ZI6.js +0 -4
  306. package/dist/admin/assets/index-BIIU9ZI6.js.map +0 -1
  307. package/dist/admin/assets/index-lxe7WimO.css +0 -2
  308. package/dist/admin/assets/locales-Bg3htKo8.js +0 -2
  309. package/dist/admin/assets/media-BCnVhaDH.js +0 -2
  310. package/dist/admin/assets/network-BixABr0o.js +0 -2
  311. package/dist/admin/assets/network-BixABr0o.js.map +0 -1
  312. package/dist/admin/assets/publishing-Dke9bSKp.js +0 -2
  313. package/dist/admin/assets/publishing-Dke9bSKp.js.map +0 -1
  314. package/dist/admin/assets/schedules-BmB9Y73z.js +0 -2
  315. package/dist/admin/assets/schema-D-qo7XSF.js +0 -2
  316. package/dist/admin/assets/schema-D-qo7XSF.js.map +0 -1
  317. package/dist/admin/assets/sections-DqBzSKMP.js.map +0 -1
  318. package/dist/admin/assets/seo-CceGYTIX.js +0 -2
  319. package/dist/admin/assets/settings-B60vHpZd.js +0 -2
  320. package/dist/admin/assets/shapes-B5twqZcp.js +0 -6
  321. package/dist/admin/assets/shapes-B5twqZcp.js.map +0 -1
  322. package/dist/admin/assets/src-ndgTSYLX.js +0 -7
  323. package/dist/admin/assets/src-ndgTSYLX.js.map +0 -1
  324. package/dist/admin/assets/theme-65PB8uAu.js.map +0 -1
  325. package/dist/admin/assets/titles-CQiqqDw-.js +0 -2
  326. package/dist/admin/assets/titles-CQiqqDw-.js.map +0 -1
  327. package/dist/admin/assets/tokens-ixHjAkDK.js +0 -2
  328. package/dist/admin/assets/useContentSchema-DtYfhsd2.js +0 -2
  329. package/dist/admin/assets/useContentSchema-DtYfhsd2.js.map +0 -1
  330. package/dist/admin/assets/useCursorPager-0zHjlm-7.js +0 -2
  331. package/dist/admin/assets/useMediaUploader-CBcq1ICg.js.map +0 -1
  332. package/dist/admin/assets/useNetworkPermission-Cts98h9d.js +0 -2
  333. package/dist/admin/assets/usePlaces-DC47wVeU.js +0 -2
  334. package/dist/admin/assets/usePlaces-DC47wVeU.js.map +0 -1
  335. package/dist/admin/assets/useQueries-CirW3Mvp.js +0 -2
  336. package/dist/admin/assets/useQueries-CirW3Mvp.js.map +0 -1
  337. package/dist/admin/assets/useSaveShortcut-rKtp1qK7.js +0 -2
  338. package/dist/admin/assets/useSaveShortcut-rKtp1qK7.js.map +0 -1
  339. package/dist/admin/assets/users-2iJYwlJb.js +0 -2
  340. package/dist/admin/assets/users-2iJYwlJb.js.map +0 -1
  341. package/dist/cliMain-papyXJDd.js.map +0 -1
  342. package/dist/public-B57h4F7Y.js.map +0 -1
  343. package/dist/worker-B-sC-eY2.js.map +0 -1
package/dist/config.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as ServiceFactoryContext, C as HookEvent, D as MediaUsage, E as MediaReferenceService, F as defineConfig, I as isHookError, M as ShapioServices, N as ThemeDefinition, O as ModelHooks, P as ThemeTokens, S as HookError, T as JobHandlerContext, _ as ExtensionRoute, a as BeforeHookContext, b as ExtensionSite, c as ContentReadOptions, d as EXTENSION_CONTRACT_VERSION, f as EnqueueOptions, g as ExtensionJobService, h as ExtensionJobHandler, i as BeforeHook, j as ShapioConfig, k as ServiceFactory, l as ContentReadService, m as ExtensionHostConfig, n as AfterHookContext, o as BeforeHookEvent, p as EntryData, r as AfterHookEvent, s as ContentReadEntry, t as AfterHook, u as CustomServices, v as ExtensionRouteOptions, w as HookModel, x as HookEntry, y as ExtensionServices } from "./public-COKbHR-N.js";
2
- export { AfterHook, AfterHookContext, AfterHookEvent, BeforeHook, BeforeHookContext, BeforeHookEvent, ContentReadEntry, ContentReadOptions, ContentReadService, CustomServices, EXTENSION_CONTRACT_VERSION, EnqueueOptions, EntryData, ExtensionHostConfig, ExtensionJobHandler, ExtensionJobService, ExtensionRoute, ExtensionRouteOptions, ExtensionServices, ExtensionSite, HookEntry, HookError, HookEvent, HookModel, JobHandlerContext, MediaReferenceService, MediaUsage, ModelHooks, ServiceFactory, ServiceFactoryContext, ShapioConfig, ShapioServices, ThemeDefinition, ThemeTokens, defineConfig, isHookError };
1
+ import { A as ServiceFactoryContext, C as HookEvent, D as MediaUsage, E as MediaReferenceService, F as ThemeDefinition, I as ThemeTokens, L as defineConfig, M as ServiceModel, N as ShapioConfig, O as ModelHooks, P as ShapioServices, R as isHookError, S as HookError, T as JobHandlerContext, _ as ExtensionRoute, a as BeforeHookContext, b as ExtensionSite, c as ContentReadOptions, d as EXTENSION_CONTRACT_VERSION, f as EnqueueOptions, g as ExtensionJobService, h as ExtensionJobHandler, i as BeforeHook, j as ServiceField, k as ServiceFactory, l as ContentReadService, m as ExtensionHostConfig, n as AfterHookContext, o as BeforeHookEvent, p as EntryData, r as AfterHookEvent, s as ContentReadEntry, t as AfterHook, u as CustomServices, v as ExtensionRouteOptions, w as HookModel, x as HookEntry, y as ExtensionServices } from "./public-CMFaGDyf.js";
2
+ export { AfterHook, AfterHookContext, AfterHookEvent, BeforeHook, BeforeHookContext, BeforeHookEvent, ContentReadEntry, ContentReadOptions, ContentReadService, CustomServices, EXTENSION_CONTRACT_VERSION, EnqueueOptions, EntryData, ExtensionHostConfig, ExtensionJobHandler, ExtensionJobService, ExtensionRoute, ExtensionRouteOptions, ExtensionServices, ExtensionSite, HookEntry, HookError, HookEvent, HookModel, JobHandlerContext, MediaReferenceService, MediaUsage, ModelHooks, ServiceFactory, ServiceFactoryContext, ServiceField, ServiceModel, ShapioConfig, ShapioServices, ThemeDefinition, ThemeTokens, defineConfig, isHookError };
package/dist/config.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as isHookError, n as HookError, r as defineConfig, t as EXTENSION_CONTRACT_VERSION } from "./public-B57h4F7Y.js";
1
+ import { i as isHookError, n as HookError, r as defineConfig, t as EXTENSION_CONTRACT_VERSION } from "./public-sJCQaNaP.js";
2
2
  export { EXTENSION_CONTRACT_VERSION, HookError, defineConfig, isHookError };
@@ -16,7 +16,7 @@ const splitExtension = (name) => {
16
16
  };
17
17
  };
18
18
  /**
19
- * The display name kept for an upload: the last path segment, NFC-normalised, without control or
19
+ * The display name kept for an upload: the last path segment, NFC-normalized, without control or
20
20
  * path characters, at most 200 characters with the extension preserved. Never used as a storage path.
21
21
  */
22
22
  const sanitizeFilename = (input) => {
@@ -87,4 +87,4 @@ const bucketContentDisposition = (contentType) => PASSIVE_INLINE_TYPE.test(conte
87
87
  //#endregion
88
88
  export { buildAssetKey as a, isValidStorageKey as c, withVisibility as d, ObjectNotFoundError as i, sanitizeFilename as l, contentDisposition as n, buildVariantKey as o, InvalidStorageKeyError as r, encodeKeyPath as s, bucketContentDisposition as t, visibilityOfKey as u };
89
89
 
90
- //# sourceMappingURL=contentDisposition-DOL2Xt0l.js.map
90
+ //# sourceMappingURL=contentDisposition-DzhPhncr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contentDisposition-DOL2Xt0l.js","names":[],"sources":["../src/media/keys.ts","../src/media/errors.ts","../src/media/contentDisposition.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\n\nexport type MediaVisibility = 'public' | 'private';\n\nconst MAX_FILENAME_LENGTH = 200;\nconst MAX_SLUG_LENGTH = 80;\n/** Characters Windows, macOS or shells treat specially, plus every control character. */\n// eslint-disable-next-line no-control-regex\nconst UNSAFE_FILENAME_CHARACTERS = /[\\u0000-\\u001f\\u007f<>:\"/\\\\|?*]+/g;\nconst SEGMENT = '[A-Za-z0-9][A-Za-z0-9._-]{0,127}';\nconst STORAGE_KEY_PATTERN = new RegExp(`^(public|private)(/${SEGMENT}){2,5}$`);\n\nconst splitExtension = (name: string): { stem: string; extension: string } => {\n const dot = name.lastIndexOf('.');\n return dot > 0 && name.length - dot <= 16\n ? { stem: name.slice(0, dot), extension: name.slice(dot) }\n : { stem: name, extension: '' };\n};\n\n/**\n * The display name kept for an upload: the last path segment, NFC-normalised, without control or\n * path characters, at most 200 characters with the extension preserved. Never used as a storage path.\n */\nexport const sanitizeFilename = (input: string): string => {\n const base = input.split(/[/\\\\]/).pop() ?? '';\n const cleaned = base\n .normalize('NFC')\n .replace(UNSAFE_FILENAME_CHARACTERS, '-')\n .replace(/\\s+/g, ' ')\n .replace(/^[\\s.-]+|[\\s.]+$/g, '');\n if (cleaned === '') {\n return 'file';\n }\n if (cleaned.length <= MAX_FILENAME_LENGTH) {\n return cleaned;\n }\n const { stem, extension } = splitExtension(cleaned);\n return `${stem.slice(0, MAX_FILENAME_LENGTH - extension.length)}${extension}`;\n};\n\n/** An ASCII, lower-case, URL-safe version of a file name for storage keys: `Été 2026.JPG` → `ete-2026.jpg`. */\nexport const toStorageSlug = (filename: string): string => {\n const { stem, extension } = splitExtension(filename);\n const slugify = (value: string) =>\n value\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n const slugStem = slugify(stem).slice(0, MAX_SLUG_LENGTH) || 'file';\n const slugExtension = slugify(extension).slice(0, 15);\n return slugExtension ? `${slugStem}.${slugExtension}` : slugStem;\n};\n\n/** Relative keys only, made of safe segments under a visibility prefix: no `..`, no absolute paths. */\nexport const isValidStorageKey = (key: string): boolean => STORAGE_KEY_PATTERN.test(key);\n\n/**\n * `public/<assetId>/<token>/<slug>`. The visibility prefix lets an operator expose only `public/` through a\n * CDN or bucket policy; the random token gives every upload (and replacement) a new, cacheable URL.\n */\nexport const buildAssetKey = (visibility: MediaVisibility, assetId: string, filename: string): string =>\n `${visibility}/${assetId}/${randomBytes(12).toString('hex')}/${toStorageSlug(filename)}`;\n\n/** Variants sit beside their original: `public/<assetId>/<token>/v/<name>.<extension>`. */\nexport const buildVariantKey = (assetKey: string, name: string, extension: string): string =>\n `${assetKey.slice(0, assetKey.lastIndexOf('/'))}/v/${name}.${extension}`;\n\n/** The same key under the other visibility prefix (visibility changes move objects). */\nexport const withVisibility = (key: string, visibility: MediaVisibility): string =>\n `${visibility}${key.slice(key.indexOf('/'))}`;\n\nexport const visibilityOfKey = (key: string): MediaVisibility | undefined => {\n const prefix = key.slice(0, key.indexOf('/'));\n return prefix === 'public' || prefix === 'private' ? prefix : undefined;\n};\n\n/** Percent-encodes each segment for use in a URL path. */\nexport const encodeKeyPath = (key: string): string => key.split('/').map(encodeURIComponent).join('/');\n","/** Thrown by adapters when a key has no object, so callers can tell \"missing\" from \"storage is down\". */\nexport class ObjectNotFoundError extends Error {\n constructor(key: string, options?: ErrorOptions) {\n super(`No stored object at ${key}`, options);\n this.name = 'ObjectNotFoundError';\n }\n}\n\nexport class InvalidStorageKeyError extends Error {\n constructor(key: string) {\n super(`Not a valid media storage key: ${JSON.stringify(key)}`);\n this.name = 'InvalidStorageKeyError';\n }\n}\n","/**\n * A Content-Disposition value that names the file safely: an ASCII fallback plus the RFC 5987 UTF-8 form,\n * so quotes, semicolons or line breaks in a filename can never inject header parameters.\n */\nexport const contentDisposition = (filename: string, type: 'inline' | 'attachment' = 'inline'): string => {\n const ascii = filename.replace(/[^\\x20-\\x7e]/g, '_').replace(/[\"\\\\]/g, '_');\n return `${type}; filename=\"${ascii}\"; filename*=UTF-8''${encodeURIComponent(filename)}`;\n};\n\n/** Types a browser only ever displays passively: opening one directly cannot run script. */\nconst PASSIVE_INLINE_TYPE =\n /^(image\\/(png|jpeg|gif|webp|avif|bmp|tiff|x-icon|vnd\\.microsoft\\.icon)|video\\/.+|audio\\/.+)$/;\n\n/**\n * Content-Disposition to store on an object in a bucket. Public objects can be served straight from the\n * bucket or a CDN, where Shapio's sandboxing headers are absent; anything that could run as a page there\n * (SVG, HTML, XML, PDF...) is stored as an attachment, so opening it downloads it. `<img>` tags still show\n * an SVG, since embedding ignores Content-Disposition.\n */\nexport const bucketContentDisposition = (contentType: string): string | undefined =>\n PASSIVE_INLINE_TYPE.test(contentType.toLowerCase()) ? undefined : 'attachment';\n"],"mappings":";;AAIA,MAAM,sBAAsB;AAC5B,MAAM,kBAAkB;;AAGxB,MAAM,6BAA6B;AAEnC,MAAM,sBAAsB,IAAI,OAAO,4DAAsC;AAE7E,MAAM,kBAAkB,SAAsD;CAC5E,MAAM,MAAM,KAAK,YAAY,GAAG;CAChC,OAAO,MAAM,KAAK,KAAK,SAAS,OAAO,KACnC;EAAE,MAAM,KAAK,MAAM,GAAG,GAAG;EAAG,WAAW,KAAK,MAAM,GAAG;CAAE,IACvD;EAAE,MAAM;EAAM,WAAW;CAAG;AAClC;;;;;AAMA,MAAa,oBAAoB,UAA0B;CAEzD,MAAM,WADO,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,KAAK,GAAA,CAExC,UAAU,KAAK,CAAC,CAChB,QAAQ,4BAA4B,GAAG,CAAC,CACxC,QAAQ,QAAQ,GAAG,CAAC,CACpB,QAAQ,qBAAqB,EAAE;CAClC,IAAI,YAAY,IACd,OAAO;CAET,IAAI,QAAQ,UAAU,qBACpB,OAAO;CAET,MAAM,EAAE,MAAM,cAAc,eAAe,OAAO;CAClD,OAAO,GAAG,KAAK,MAAM,GAAG,sBAAsB,UAAU,MAAM,IAAI;AACpE;;AAGA,MAAa,iBAAiB,aAA6B;CACzD,MAAM,EAAE,MAAM,cAAc,eAAe,QAAQ;CACnD,MAAM,WAAW,UACf,MACG,UAAU,MAAM,CAAC,CACjB,QAAQ,UAAU,EAAE,CAAC,CACrB,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EAAE;CAC3B,MAAM,WAAW,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,eAAe,KAAK;CAC5D,MAAM,gBAAgB,QAAQ,SAAS,CAAC,CAAC,MAAM,GAAG,EAAE;CACpD,OAAO,gBAAgB,GAAG,SAAS,GAAG,kBAAkB;AAC1D;;AAGA,MAAa,qBAAqB,QAAyB,oBAAoB,KAAK,GAAG;;;;;AAMvF,MAAa,iBAAiB,YAA6B,SAAiB,aAC1E,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,EAAE,CAAC,CAAC,SAAS,KAAK,EAAE,GAAG,cAAc,QAAQ;;AAGvF,MAAa,mBAAmB,UAAkB,MAAc,cAC9D,GAAG,SAAS,MAAM,GAAG,SAAS,YAAY,GAAG,CAAC,EAAE,KAAK,KAAK,GAAG;;AAG/D,MAAa,kBAAkB,KAAa,eAC1C,GAAG,aAAa,IAAI,MAAM,IAAI,QAAQ,GAAG,CAAC;AAE5C,MAAa,mBAAmB,QAA6C;CAC3E,MAAM,SAAS,IAAI,MAAM,GAAG,IAAI,QAAQ,GAAG,CAAC;CAC5C,OAAO,WAAW,YAAY,WAAW,YAAY,SAAS,KAAA;AAChE;;AAGA,MAAa,iBAAiB,QAAwB,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,KAAK,GAAG;;;;AC9ErG,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YAAY,KAAa,SAAwB;EAC/C,MAAM,uBAAuB,OAAO,OAAO;EAC3C,KAAK,OAAO;CACd;AACF;AAEA,IAAa,yBAAb,cAA4C,MAAM;CAChD,YAAY,KAAa;EACvB,MAAM,kCAAkC,KAAK,UAAU,GAAG,GAAG;EAC7D,KAAK,OAAO;CACd;AACF;;;;;;;ACTA,MAAa,sBAAsB,UAAkB,OAAgC,aAAqB;CAExG,OAAO,GAAG,KAAK,cADD,SAAS,QAAQ,iBAAiB,GAAG,CAAC,CAAC,QAAQ,UAAU,GACtC,EAAE,sBAAsB,mBAAmB,QAAQ;AACtF;;AAGA,MAAM,sBACJ;;;;;;;AAQF,MAAa,4BAA4B,gBACvC,oBAAoB,KAAK,YAAY,YAAY,CAAC,IAAI,KAAA,IAAY"}
1
+ {"version":3,"file":"contentDisposition-DzhPhncr.js","names":[],"sources":["../src/media/keys.ts","../src/media/errors.ts","../src/media/contentDisposition.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\n\nexport type MediaVisibility = 'public' | 'private';\n\nconst MAX_FILENAME_LENGTH = 200;\nconst MAX_SLUG_LENGTH = 80;\n/** Characters Windows, macOS or shells treat specially, plus every control character. */\n// eslint-disable-next-line no-control-regex\nconst UNSAFE_FILENAME_CHARACTERS = /[\\u0000-\\u001f\\u007f<>:\"/\\\\|?*]+/g;\nconst SEGMENT = '[A-Za-z0-9][A-Za-z0-9._-]{0,127}';\nconst STORAGE_KEY_PATTERN = new RegExp(`^(public|private)(/${SEGMENT}){2,5}$`);\n\nconst splitExtension = (name: string): { stem: string; extension: string } => {\n const dot = name.lastIndexOf('.');\n return dot > 0 && name.length - dot <= 16\n ? { stem: name.slice(0, dot), extension: name.slice(dot) }\n : { stem: name, extension: '' };\n};\n\n/**\n * The display name kept for an upload: the last path segment, NFC-normalized, without control or\n * path characters, at most 200 characters with the extension preserved. Never used as a storage path.\n */\nexport const sanitizeFilename = (input: string): string => {\n const base = input.split(/[/\\\\]/).pop() ?? '';\n const cleaned = base\n .normalize('NFC')\n .replace(UNSAFE_FILENAME_CHARACTERS, '-')\n .replace(/\\s+/g, ' ')\n .replace(/^[\\s.-]+|[\\s.]+$/g, '');\n if (cleaned === '') {\n return 'file';\n }\n if (cleaned.length <= MAX_FILENAME_LENGTH) {\n return cleaned;\n }\n const { stem, extension } = splitExtension(cleaned);\n return `${stem.slice(0, MAX_FILENAME_LENGTH - extension.length)}${extension}`;\n};\n\n/** An ASCII, lower-case, URL-safe version of a file name for storage keys: `Été 2026.JPG` → `ete-2026.jpg`. */\nexport const toStorageSlug = (filename: string): string => {\n const { stem, extension } = splitExtension(filename);\n const slugify = (value: string) =>\n value\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n const slugStem = slugify(stem).slice(0, MAX_SLUG_LENGTH) || 'file';\n const slugExtension = slugify(extension).slice(0, 15);\n return slugExtension ? `${slugStem}.${slugExtension}` : slugStem;\n};\n\n/** Relative keys only, made of safe segments under a visibility prefix: no `..`, no absolute paths. */\nexport const isValidStorageKey = (key: string): boolean => STORAGE_KEY_PATTERN.test(key);\n\n/**\n * `public/<assetId>/<token>/<slug>`. The visibility prefix lets an operator expose only `public/` through a\n * CDN or bucket policy; the random token gives every upload (and replacement) a new, cacheable URL.\n */\nexport const buildAssetKey = (visibility: MediaVisibility, assetId: string, filename: string): string =>\n `${visibility}/${assetId}/${randomBytes(12).toString('hex')}/${toStorageSlug(filename)}`;\n\n/** Variants sit beside their original: `public/<assetId>/<token>/v/<name>.<extension>`. */\nexport const buildVariantKey = (assetKey: string, name: string, extension: string): string =>\n `${assetKey.slice(0, assetKey.lastIndexOf('/'))}/v/${name}.${extension}`;\n\n/** The same key under the other visibility prefix (visibility changes move objects). */\nexport const withVisibility = (key: string, visibility: MediaVisibility): string =>\n `${visibility}${key.slice(key.indexOf('/'))}`;\n\nexport const visibilityOfKey = (key: string): MediaVisibility | undefined => {\n const prefix = key.slice(0, key.indexOf('/'));\n return prefix === 'public' || prefix === 'private' ? prefix : undefined;\n};\n\n/** Percent-encodes each segment for use in a URL path. */\nexport const encodeKeyPath = (key: string): string => key.split('/').map(encodeURIComponent).join('/');\n","/** Thrown by adapters when a key has no object, so callers can tell \"missing\" from \"storage is down\". */\nexport class ObjectNotFoundError extends Error {\n constructor(key: string, options?: ErrorOptions) {\n super(`No stored object at ${key}`, options);\n this.name = 'ObjectNotFoundError';\n }\n}\n\nexport class InvalidStorageKeyError extends Error {\n constructor(key: string) {\n super(`Not a valid media storage key: ${JSON.stringify(key)}`);\n this.name = 'InvalidStorageKeyError';\n }\n}\n","/**\n * A Content-Disposition value that names the file safely: an ASCII fallback plus the RFC 5987 UTF-8 form,\n * so quotes, semicolons or line breaks in a filename can never inject header parameters.\n */\nexport const contentDisposition = (filename: string, type: 'inline' | 'attachment' = 'inline'): string => {\n const ascii = filename.replace(/[^\\x20-\\x7e]/g, '_').replace(/[\"\\\\]/g, '_');\n return `${type}; filename=\"${ascii}\"; filename*=UTF-8''${encodeURIComponent(filename)}`;\n};\n\n/** Types a browser only ever displays passively: opening one directly cannot run script. */\nconst PASSIVE_INLINE_TYPE =\n /^(image\\/(png|jpeg|gif|webp|avif|bmp|tiff|x-icon|vnd\\.microsoft\\.icon)|video\\/.+|audio\\/.+)$/;\n\n/**\n * Content-Disposition to store on an object in a bucket. Public objects can be served straight from the\n * bucket or a CDN, where Shapio's sandboxing headers are absent; anything that could run as a page there\n * (SVG, HTML, XML, PDF...) is stored as an attachment, so opening it downloads it. `<img>` tags still show\n * an SVG, since embedding ignores Content-Disposition.\n */\nexport const bucketContentDisposition = (contentType: string): string | undefined =>\n PASSIVE_INLINE_TYPE.test(contentType.toLowerCase()) ? undefined : 'attachment';\n"],"mappings":";;AAIA,MAAM,sBAAsB;AAC5B,MAAM,kBAAkB;;AAGxB,MAAM,6BAA6B;AAEnC,MAAM,sBAAsB,IAAI,OAAO,4DAAsC;AAE7E,MAAM,kBAAkB,SAAsD;CAC5E,MAAM,MAAM,KAAK,YAAY,GAAG;CAChC,OAAO,MAAM,KAAK,KAAK,SAAS,OAAO,KACnC;EAAE,MAAM,KAAK,MAAM,GAAG,GAAG;EAAG,WAAW,KAAK,MAAM,GAAG;CAAE,IACvD;EAAE,MAAM;EAAM,WAAW;CAAG;AAClC;;;;;AAMA,MAAa,oBAAoB,UAA0B;CAEzD,MAAM,WADO,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,KAAK,GAAA,CAExC,UAAU,KAAK,CAAC,CAChB,QAAQ,4BAA4B,GAAG,CAAC,CACxC,QAAQ,QAAQ,GAAG,CAAC,CACpB,QAAQ,qBAAqB,EAAE;CAClC,IAAI,YAAY,IACd,OAAO;CAET,IAAI,QAAQ,UAAU,qBACpB,OAAO;CAET,MAAM,EAAE,MAAM,cAAc,eAAe,OAAO;CAClD,OAAO,GAAG,KAAK,MAAM,GAAG,sBAAsB,UAAU,MAAM,IAAI;AACpE;;AAGA,MAAa,iBAAiB,aAA6B;CACzD,MAAM,EAAE,MAAM,cAAc,eAAe,QAAQ;CACnD,MAAM,WAAW,UACf,MACG,UAAU,MAAM,CAAC,CACjB,QAAQ,UAAU,EAAE,CAAC,CACrB,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EAAE;CAC3B,MAAM,WAAW,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,eAAe,KAAK;CAC5D,MAAM,gBAAgB,QAAQ,SAAS,CAAC,CAAC,MAAM,GAAG,EAAE;CACpD,OAAO,gBAAgB,GAAG,SAAS,GAAG,kBAAkB;AAC1D;;AAGA,MAAa,qBAAqB,QAAyB,oBAAoB,KAAK,GAAG;;;;;AAMvF,MAAa,iBAAiB,YAA6B,SAAiB,aAC1E,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,EAAE,CAAC,CAAC,SAAS,KAAK,EAAE,GAAG,cAAc,QAAQ;;AAGvF,MAAa,mBAAmB,UAAkB,MAAc,cAC9D,GAAG,SAAS,MAAM,GAAG,SAAS,YAAY,GAAG,CAAC,EAAE,KAAK,KAAK,GAAG;;AAG/D,MAAa,kBAAkB,KAAa,eAC1C,GAAG,aAAa,IAAI,MAAM,IAAI,QAAQ,GAAG,CAAC;AAE5C,MAAa,mBAAmB,QAA6C;CAC3E,MAAM,SAAS,IAAI,MAAM,GAAG,IAAI,QAAQ,GAAG,CAAC;CAC5C,OAAO,WAAW,YAAY,WAAW,YAAY,SAAS,KAAA;AAChE;;AAGA,MAAa,iBAAiB,QAAwB,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,KAAK,GAAG;;;;AC9ErG,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YAAY,KAAa,SAAwB;EAC/C,MAAM,uBAAuB,OAAO,OAAO;EAC3C,KAAK,OAAO;CACd;AACF;AAEA,IAAa,yBAAb,cAA4C,MAAM;CAChD,YAAY,KAAa;EACvB,MAAM,kCAAkC,KAAK,UAAU,GAAG,GAAG;EAC7D,KAAK,OAAO;CACd;AACF;;;;;;;ACTA,MAAa,sBAAsB,UAAkB,OAAgC,aAAqB;CAExG,OAAO,GAAG,KAAK,cADD,SAAS,QAAQ,iBAAiB,GAAG,CAAC,CAAC,QAAQ,UAAU,GACtC,EAAE,sBAAsB,mBAAmB,QAAQ;AACtF;;AAGA,MAAM,sBACJ;;;;;;;AAQF,MAAa,4BAA4B,gBACvC,oBAAoB,KAAK,YAAY,YAAY,CAAC,IAAI,KAAA,IAAY"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as ServiceFactoryContext, B as Principal, C as HookEvent, D as MediaUsage, E as MediaReferenceService, F as defineConfig, G as ComponentDefinition, H as DB, I as isHookError, J as ModelDefinition, K as DataType, L as KnownVersions, M as ShapioServices, N as ThemeDefinition, O as ModelHooks, P as ThemeTokens, R as PermissionEvaluator, S as HookError, T as JobHandlerContext, U as OutboxEvents, V as Database, W as ContentData, Y as PlannedChange, _ as ExtensionRoute, a as BeforeHookContext, b as ExtensionSite, c as ContentReadOptions, d as EXTENSION_CONTRACT_VERSION, f as EnqueueOptions, g as ExtensionJobService, h as ExtensionJobHandler, i as BeforeHook, j as ShapioConfig, k as ServiceFactory, l as ContentReadService, m as ExtensionHostConfig, n as AfterHookContext, o as BeforeHookEvent, p as EntryData, q as JsonValue, r as AfterHookEvent, s as ContentReadEntry, t as AfterHook, u as CustomServices, v as ExtensionRouteOptions, w as HookModel, x as HookEntry, y as ExtensionServices, z as PermissionExecutor } from "./public-COKbHR-N.js";
1
+ import { A as ServiceFactoryContext, B as PermissionEvaluator, C as HookEvent, D as MediaUsage, E as MediaReferenceService, F as ThemeDefinition, G as OutboxEvents, H as Principal, I as ThemeTokens, J as DataType, K as ContentData, L as defineConfig, M as ServiceModel, N as ShapioConfig, O as ModelHooks, P as ShapioServices, R as isHookError, S as HookError, T as JobHandlerContext, U as Database, V as PermissionExecutor, W as DB, X as PlannedChange, Y as JsonValue, Z as ResolvedModelDefinition, _ as ExtensionRoute, a as BeforeHookContext, b as ExtensionSite, c as ContentReadOptions, d as EXTENSION_CONTRACT_VERSION, f as EnqueueOptions, g as ExtensionJobService, h as ExtensionJobHandler, i as BeforeHook, j as ServiceField, k as ServiceFactory, l as ContentReadService, m as ExtensionHostConfig, n as AfterHookContext, o as BeforeHookEvent, p as EntryData, q as ComponentDefinition, r as AfterHookEvent, s as ContentReadEntry, t as AfterHook, u as CustomServices, v as ExtensionRouteOptions, w as HookModel, x as HookEntry, y as ExtensionServices, z as KnownVersions } from "./public-CMFaGDyf.js";
2
2
  import { FastifyBaseLogger, FastifyInstance } from "fastify";
3
3
  import { Kysely, Selectable, Transaction } from "kysely";
4
4
  import { Static, Type } from "typebox";
@@ -432,15 +432,33 @@ type SiteRef = {
432
432
  //#region src/content/model.d.ts
433
433
  /** A collection or singleton resolved from a pinned snapshot, with what writes need to know about it. */
434
434
  type ContentModel = {
435
- definition: ModelDefinition;
435
+ /** The effective definition: inherited fields first (`inheritedFrom` set), then the model's own. */
436
+ definition: ResolvedModelDefinition;
436
437
  /** Per-model version at the pinned snapshot (re-checked at commit). */
437
438
  version: number;
438
439
  revisionId: string;
439
- /** Components reachable from the model (directly or through other components), with their versions. */
440
+ /**
441
+ * The models this one extends, by ID, at the pinned snapshot: a parent change changes this model's shape
442
+ * without changing its own version, so writes re-check these too and validators are cached by them.
443
+ */
444
+ ancestors: ReadonlyMap<string, {
445
+ version: number;
446
+ revisionId: string;
447
+ }>;
448
+ /** Components reachable from the model's effective fields (directly or through other components). */
440
449
  components: ReadonlyMap<string, {
441
450
  definition: ComponentDefinition;
442
451
  version: number;
443
452
  }>;
453
+ /**
454
+ * Where the model is served (plan polymorphic-types): its route key (`products/digital`) and its ancestors'
455
+ * API IDs, root first. Set by the resolvers here; absent on models built by hand.
456
+ */
457
+ route?: ModelRoute;
458
+ };
459
+ type ModelRoute = {
460
+ key: string;
461
+ ancestors: readonly string[];
444
462
  };
445
463
  //#endregion
446
464
  //#region src/content/hooks.d.ts
@@ -519,7 +537,7 @@ type JobContext = {
519
537
  signal: AbortSignal;
520
538
  log: JobLogger;
521
539
  };
522
- /** Returns an optional JSON-serialisable result. Throw to fail the attempt; the queue retries with backoff. */
540
+ /** Returns an optional JSON-serializable result. Throw to fail the attempt; the queue retries with backoff. */
523
541
  type JobHandler = (context: JobContext) => Promise<unknown>;
524
542
  /**
525
543
  * Turns an outbox event into follow-up work (usually by enqueueing jobs) inside the relay's transaction.
@@ -575,6 +593,11 @@ type FieldVisibilityLookup = {
575
593
  * definition is granted by roles held on that site (plan site-schema, rule 4).
576
594
  */
577
595
  getModelSite: (modelId: string, executor?: PermissionExecutor, versions?: KnownVersions) => Promise<string | null>;
596
+ /**
597
+ * The models a model extends, root first ([] for a root or an unknown model), at the request's schema
598
+ * version: a grant on an ancestor applies to its descendants (plan polymorphic-types D8).
599
+ */
600
+ getAncestors: (modelId: string, executor?: PermissionExecutor, versions?: KnownVersions) => Promise<readonly string[]>;
578
601
  };
579
602
  //#endregion
580
603
  //#region src/publishing/outbound/ssrf.d.ts
@@ -611,7 +634,8 @@ type SeqAllocator = {
611
634
  /**
612
635
  * Where a definition's values live inside entries: for a model, its own heads at the root; for a
613
636
  * component, every model that embeds it, with the field-ID path from the entry root down to the component
614
- * or dynamic-zone field that holds it.
637
+ * or dynamic-zone field that holds it. A change to a model that others extend has one location per family
638
+ * member holding the field (plan polymorphic-types), all at the root.
615
639
  */
616
640
  type ValueLocation = {
617
641
  modelId: string;
@@ -623,6 +647,8 @@ type ContentStep = {
623
647
  ownerId: string;
624
648
  fieldId: string;
625
649
  locations: ValueLocation[];
650
+ /** The field's API ID, to name it when the check fails. Absent in older plans. */
651
+ fieldApiKey?: string;
626
652
  } | {
627
653
  kind: 'backfill';
628
654
  ownerId: string;
@@ -637,8 +663,14 @@ type ContentStep = {
637
663
  locations: ValueLocation[];
638
664
  } | {
639
665
  kind: 'checkUnique';
666
+ /** The model whose entries are checked: one step per family member holding the field. */
640
667
  modelId: string;
641
668
  fieldId: string;
669
+ /**
670
+ * The definition the change is for (the model a family's steps come from), when it is not `modelId`;
671
+ * the content ports load the proposed schema through it. Absent in plans made before inheritance.
672
+ */
673
+ ownerId?: string;
642
674
  /**
643
675
  * The field is already unique under the active schema (its type changes): its live registry rows stay in
644
676
  * force until activation, so the dry run stages its claims under a separate registry key and the
@@ -667,6 +699,11 @@ type FollowUpStep = IndexStep | {
667
699
  } | {
668
700
  kind: 'releaseUnique';
669
701
  fieldId: string;
702
+ /**
703
+ * The models whose registry rows go: the family members that lose the field (a parent keeps its own
704
+ * when a child moves away). Absent in plans made before inheritance: every model's.
705
+ */
706
+ modelIds?: string[];
670
707
  } |
671
708
  /**
672
709
  * Deletes a removed locale's heads, revisions and unique-registry rows, and moves non-localized entries stored
@@ -861,5 +898,5 @@ export declare const startDedicatedWorker: (config: AppConfig) => Promise<Worker
861
898
  //#region src/constants/version.d.ts
862
899
  export declare const SHAPIO_VERSION: string;
863
900
  //#endregion
864
- export { AfterHook, AfterHookContext, AfterHookEvent, type AppConfig, type AppDependencies, BeforeHook, BeforeHookContext, BeforeHookEvent, ContentReadEntry, ContentReadOptions, ContentReadService, CustomServices, EXTENSION_CONTRACT_VERSION, EnqueueOptions, EntryData, ExtensionHostConfig, ExtensionJobHandler, ExtensionJobService, ExtensionRoute, ExtensionRouteOptions, ExtensionServices, ExtensionSite, HookEntry, HookError, HookEvent, HookModel, JobHandlerContext, MediaReferenceService, MediaUsage, ModelHooks, type RunningServer, ServiceFactory, ServiceFactoryContext, ShapioConfig, ShapioServices, ThemeDefinition, ThemeTokens, defineConfig, isHookError };
901
+ export { AfterHook, AfterHookContext, AfterHookEvent, type AppConfig, type AppDependencies, BeforeHook, BeforeHookContext, BeforeHookEvent, ContentReadEntry, ContentReadOptions, ContentReadService, CustomServices, EXTENSION_CONTRACT_VERSION, EnqueueOptions, EntryData, ExtensionHostConfig, ExtensionJobHandler, ExtensionJobService, ExtensionRoute, ExtensionRouteOptions, ExtensionServices, ExtensionSite, HookEntry, HookError, HookEvent, HookModel, JobHandlerContext, MediaReferenceService, MediaUsage, ModelHooks, type RunningServer, ServiceFactory, ServiceFactoryContext, ServiceField, ServiceModel, ShapioConfig, ShapioServices, ThemeDefinition, ThemeTokens, defineConfig, isHookError };
865
902
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { a as loadConfig, n as startServer, s as buildApp, t as startDedicatedWorker, u as SHAPIO_VERSION } from "./worker-B-sC-eY2.js";
2
- import { i as isHookError, n as HookError, r as defineConfig, t as EXTENSION_CONTRACT_VERSION } from "./public-B57h4F7Y.js";
1
+ import { a as loadConfig, n as startServer, s as buildApp, t as startDedicatedWorker, u as SHAPIO_VERSION } from "./worker-DHm2JwMZ.js";
2
+ import { i as isHookError, n as HookError, r as defineConfig, t as EXTENSION_CONTRACT_VERSION } from "./public-sJCQaNaP.js";
3
3
  export { EXTENSION_CONTRACT_VERSION, HookError, SHAPIO_VERSION, buildApp, defineConfig, isHookError, loadConfig, startDedicatedWorker, startServer };
@@ -215,9 +215,28 @@ type ModelDefinition = {
215
215
  description?: string;
216
216
  localized: boolean;
217
217
  draftAndPublish: boolean;
218
+ /**
219
+ * The stable ID of the collection this one extends. The stored definition holds its own fields only;
220
+ * `resolveModelDefinition` adds the inherited ones (ancestors' first).
221
+ */
222
+ extends?: string;
218
223
  fields: FieldDefinition[];
219
224
  display: ModelDisplay;
220
225
  };
226
+ /** A field as a model sees it after inheritance: `inheritedFrom` names the declaring ancestor's ID. */
227
+ type ResolvedField = FieldDefinition & {
228
+ inheritedFrom?: string;
229
+ };
230
+ /**
231
+ * A model with its effective fields: every ancestor's fields (root first), then its own, and its display
232
+ * merged with its ancestors' (`resolveModelDefinition`). `ancestorIds` is required so code that needs
233
+ * effective fields can demand this type; a stored definition does not satisfy it.
234
+ */
235
+ type ResolvedModelDefinition = Omit<ModelDefinition, 'fields'> & {
236
+ fields: ResolvedField[];
237
+ /** Ancestors' stable IDs, root first; empty for a model that extends nothing. */
238
+ ancestorIds: readonly string[];
239
+ };
221
240
  type ComponentDefinition = {
222
241
  id: string;
223
242
  kind: 'component';
@@ -231,7 +250,7 @@ type ComponentDefinition = {
231
250
  };
232
251
  //#endregion
233
252
  //#region src/diff/types.d.ts
234
- declare const CHANGE_KINDS: readonly ["definition.added", "definition.removed", "definition.apiKey", "definition.pluralApiKey", "definition.metadata", "model.kind", "model.localized", "model.draftAndPublish", "field.added", "field.removed", "field.order", "field.apiKey", "field.metadata", "field.editor", "field.type", "field.required", "field.localized", "field.public", "field.deprecated", "field.unique", "field.filterable", "field.sortable", "field.settings"];
253
+ declare const CHANGE_KINDS: readonly ["definition.added", "definition.removed", "definition.apiKey", "definition.pluralApiKey", "definition.metadata", "model.kind", "model.localized", "model.draftAndPublish", "model.extends", "field.added", "field.removed", "field.order", "field.apiKey", "field.metadata", "field.editor", "field.type", "field.required", "field.localized", "field.public", "field.deprecated", "field.unique", "field.filterable", "field.sortable", "field.settings"];
235
254
  type ChangeKind = (typeof CHANGE_KINDS)[number];
236
255
  /**
237
256
  * One difference between two versions of a definition. `property` names the changed property for
@@ -1312,6 +1331,26 @@ type HookModel = {
1312
1331
  kind: 'collection' | 'singleton';
1313
1332
  localized: boolean;
1314
1333
  draftAndPublish: boolean;
1334
+ /** The API ID of the model this one extends; absent for a model that extends nothing. */
1335
+ extends?: string;
1336
+ };
1337
+ /** A field of a model as `content.models()` describes it (its effective fields, inherited ones first). */
1338
+ type ServiceField = {
1339
+ /** Stable field ID (never changes; an inherited field keeps the declaring model's ID). */
1340
+ id: string;
1341
+ apiKey: string;
1342
+ label: string;
1343
+ type: string;
1344
+ required: boolean;
1345
+ localized: boolean;
1346
+ /** The API ID of the model that declares the field, when it is inherited; absent for the model's own. */
1347
+ inheritedFrom?: string;
1348
+ };
1349
+ /** A content model with its effective fields and where the delivery API serves it. */
1350
+ type ServiceModel = HookModel & {
1351
+ /** The delivery route key: the plural API ID, nested under the models it extends (`posts/guides`). */
1352
+ routeKey: string;
1353
+ fields: ServiceField[];
1315
1354
  };
1316
1355
  type HookEntry = {
1317
1356
  id: string;
@@ -1340,8 +1379,11 @@ type ContentReadService = {
1340
1379
  }>;
1341
1380
  /** Number of (non-deleted) entries of a model. */
1342
1381
  count: (modelKey: string) => Promise<number>;
1343
- /** The active content models (collections and singletons) of this site: shared ones and its own. */
1344
- models: () => Promise<HookModel[]>;
1382
+ /**
1383
+ * The active content models (collections and singletons) of this site: shared ones and its own, each with
1384
+ * its effective fields (a model that extends another lists the inherited fields first) and route key.
1385
+ */
1386
+ models: () => Promise<ServiceModel[]>;
1345
1387
  };
1346
1388
  type MediaUsage = {
1347
1389
  entryId: string;
@@ -1486,7 +1528,7 @@ type JobHandlerContext = {
1486
1528
  /** Throw to retry with backoff; the return value (JSON) is stored as the job result. */
1487
1529
  type ExtensionJobHandler = (context: JobHandlerContext) => Promise<unknown>;
1488
1530
  /**
1489
- * A colour theme for the admin: token values for a light variant, a dark variant, or both. Every UI token is
1531
+ * A color theme for the admin: token values for a light variant, a dark variant, or both. Every UI token is
1490
1532
  * required in a variant; the `brand-*` tokens may be left out (Shapio's are used). Values are `#rrggbb`
1491
1533
  * (contrast is checked by `shapio extensions check`), `#rgb`, `#rrggbbaa`, or `rgb()`, `hsl()`, `oklch()`,
1492
1534
  * `oklab()` with plain arguments.
@@ -1511,7 +1553,7 @@ type ShapioConfig = {
1511
1553
  editors?: string[];
1512
1554
  /** Job handlers by name; registered as `ext.<name>`. */
1513
1555
  jobs?: Record<string, ExtensionJobHandler>;
1514
- /** Admin colour themes, listed after the built-in ones in the theme menu. */
1556
+ /** Admin color themes, listed after the built-in ones in the theme menu. */
1515
1557
  themes?: ThemeDefinition[];
1516
1558
  };
1517
1559
  /** Identity helper for completion and type checking in `shapio.config.ts`. */
@@ -1519,7 +1561,7 @@ declare const defineConfig: (config: ShapioConfig) => ShapioConfig;
1519
1561
  declare const HOOK_ERROR_BRAND: unique symbol;
1520
1562
  /**
1521
1563
  * Thrown by a `before*` hook to reject a write: the API answers 422 with code `HOOK_REJECTED`, this message
1522
- * and the details. Recognised by a brand, not `instanceof`, so a copy of this class loaded from another
1564
+ * and the details. Recognized by a brand, not `instanceof`, so a copy of this class loaded from another
1523
1565
  * path (a project's own `node_modules`) works the same.
1524
1566
  */
1525
1567
  declare class HookError extends Error {
@@ -1529,5 +1571,5 @@ declare class HookError extends Error {
1529
1571
  }
1530
1572
  declare const isHookError: (error: unknown) => error is HookError;
1531
1573
  //#endregion
1532
- export { ServiceFactoryContext as A, Principal as B, HookEvent as C, MediaUsage as D, MediaReferenceService as E, defineConfig as F, ComponentDefinition as G, DB as H, isHookError as I, ModelDefinition as J, DataType as K, KnownVersions as L, ShapioServices as M, ThemeDefinition as N, ModelHooks as O, ThemeTokens as P, PermissionEvaluator as R, HookError as S, JobHandlerContext as T, OutboxEvents as U, Database as V, ContentData as W, PlannedChange as Y, ExtensionRoute as _, BeforeHookContext as a, ExtensionSite as b, ContentReadOptions as c, EXTENSION_CONTRACT_VERSION as d, EnqueueOptions as f, ExtensionJobService as g, ExtensionJobHandler as h, BeforeHook as i, ShapioConfig as j, ServiceFactory as k, ContentReadService as l, ExtensionHostConfig as m, AfterHookContext as n, BeforeHookEvent as o, EntryData as p, JsonValue$1 as q, AfterHookEvent as r, ContentReadEntry as s, AfterHook as t, CustomServices as u, ExtensionRouteOptions as v, HookModel as w, HookEntry as x, ExtensionServices as y, PermissionExecutor as z };
1533
- //# sourceMappingURL=public-COKbHR-N.d.ts.map
1574
+ export { ServiceFactoryContext as A, PermissionEvaluator as B, HookEvent as C, MediaUsage as D, MediaReferenceService as E, ThemeDefinition as F, OutboxEvents as G, Principal as H, ThemeTokens as I, DataType as J, ContentData as K, defineConfig as L, ServiceModel as M, ShapioConfig as N, ModelHooks as O, ShapioServices as P, isHookError as R, HookError as S, JobHandlerContext as T, Database as U, PermissionExecutor as V, DB as W, PlannedChange as X, JsonValue$1 as Y, ResolvedModelDefinition as Z, ExtensionRoute as _, BeforeHookContext as a, ExtensionSite as b, ContentReadOptions as c, EXTENSION_CONTRACT_VERSION as d, EnqueueOptions as f, ExtensionJobService as g, ExtensionJobHandler as h, BeforeHook as i, ServiceField as j, ServiceFactory as k, ContentReadService as l, ExtensionHostConfig as m, AfterHookContext as n, BeforeHookEvent as o, EntryData as p, ComponentDefinition as q, AfterHookEvent as r, ContentReadEntry as s, AfterHook as t, CustomServices as u, ExtensionRouteOptions as v, HookModel as w, HookEntry as x, ExtensionServices as y, KnownVersions as z };
1575
+ //# sourceMappingURL=public-CMFaGDyf.d.ts.map
@@ -20,7 +20,7 @@ const defineConfig = (config) => config;
20
20
  const HOOK_ERROR_BRAND = Symbol.for("shapio.HookError");
21
21
  /**
22
22
  * Thrown by a `before*` hook to reject a write: the API answers 422 with code `HOOK_REJECTED`, this message
23
- * and the details. Recognised by a brand, not `instanceof`, so a copy of this class loaded from another
23
+ * and the details. Recognized by a brand, not `instanceof`, so a copy of this class loaded from another
24
24
  * path (a project's own `node_modules`) works the same.
25
25
  */
26
26
  var HookError = class extends Error {
@@ -36,4 +36,4 @@ const isHookError = (error) => typeof error === "object" && error !== null && er
36
36
  //#endregion
37
37
  export { isHookError as i, HookError as n, defineConfig as r, EXTENSION_CONTRACT_VERSION as t };
38
38
 
39
- //# sourceMappingURL=public-B57h4F7Y.js.map
39
+ //# sourceMappingURL=public-sJCQaNaP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-sJCQaNaP.js","names":[],"sources":["../src/extensions/public.ts"],"sourcesContent":["import type { ThemeToken } from '@shapio/schema';\nimport type { FastifyBaseLogger, FastifyPluginAsync, preHandlerAsyncHookHandler } from 'fastify';\nimport type { Kysely, Transaction } from 'kysely';\nimport type { DB } from '../db/types.js';\nimport type { PermissionEvaluator, Principal } from '../permissions/types.js';\nimport type { RouteAuditConfig } from '../plugins/auditDeclaration.js';\n\n// What Shapio adds to Fastify, repeated here so custom route code is typed without the server's internals.\ndeclare module 'fastify' {\n interface FastifyRequest {\n /** Who is calling. Anonymous unless a session cookie or API token resolved. Never null after onRequest. */\n principal: Principal;\n /**\n * The request's site on a site route (custom routes are site routes): the credential's site, else the\n * `Shapio-Site` header or `?site=`, else the primary site. Undefined on a route declaring\n * `config.site = 'network'`.\n */\n site: { id: string; key: string } | undefined;\n }\n interface FastifyContextConfig {\n /** Required on every mutating route: the audit action recorded on success, or `{ exempt: '<why>' }`. */\n audit?: RouteAuditConfig;\n /** `'network'` for a custom route that is about the whole instance rather than one site. */\n site?: 'site' | 'network';\n }\n}\n\n/**\n * The project extension contract (ADR 0009), imported by project authors from `@shapio/cms/config`:\n *\n * ```ts\n * import { defineConfig } from '@shapio/cms/config';\n * export const config = defineConfig({ hooks: { article: { beforePublish: (ctx) => { ... } } } });\n * ```\n *\n * Extensions are code: changing them needs a restart of Shapio (never a rebuild). Content models are never\n * configured here; they change live in the admin. This file has no runtime imports from the server, so a\n * config that imports it stays cheap to load.\n *\n * Stability: everything exported here follows semver with `EXTENSION_CONTRACT_VERSION`; Shapio's database\n * tables (reachable through `trx`) are internal and may change in any release.\n */\nexport const EXTENSION_CONTRACT_VERSION = 1;\n\nexport type BeforeHookEvent = 'beforeCreate' | 'beforeUpdate' | 'beforePublish' | 'beforeDelete';\nexport type AfterHookEvent = 'afterCreate' | 'afterUpdate' | 'afterPublish' | 'afterDelete';\nexport type HookEvent = BeforeHookEvent | AfterHookEvent;\n\n/** A site of a multi-site instance: its stable ID and its key (sites share the schema, not content). */\nexport type ExtensionSite = { id: string; key: string };\n\n/** Entry data keyed by field API key (the admin API's shape; media and relations are IDs). */\nexport type EntryData = Readonly<Record<string, unknown>>;\n\nexport type HookModel = {\n /** Stable model ID (never changes). */\n id: string;\n apiKey: string;\n label: string;\n kind: 'collection' | 'singleton';\n localized: boolean;\n draftAndPublish: boolean;\n /** The API ID of the model this one extends; absent for a model that extends nothing. */\n extends?: string;\n};\n\n/** A field of a model as `content.models()` describes it (its effective fields, inherited ones first). */\nexport type ServiceField = {\n /** Stable field ID (never changes; an inherited field keeps the declaring model's ID). */\n id: string;\n apiKey: string;\n label: string;\n type: string;\n required: boolean;\n localized: boolean;\n /** The API ID of the model that declares the field, when it is inherited; absent for the model's own. */\n inheritedFrom?: string;\n};\n\n/** A content model with its effective fields and where the delivery API serves it. */\nexport type ServiceModel = HookModel & {\n /** The delivery route key: the plural API ID, nested under the models it extends (`posts/guides`). */\n routeKey: string;\n fields: ServiceField[];\n};\n\nexport type HookEntry = {\n id: string;\n locale: string | null;\n /** Which head the change is about: the draft (create/update), the live version (publish), or a delete. */\n state: 'draft' | 'published' | 'deleted';\n};\n\nexport type ContentReadOptions = {\n locale?: string;\n /** Read as this principal (its permissions apply). Default: Shapio itself (everything). */\n principal?: Principal;\n};\n\nexport type ContentReadEntry = {\n id: string;\n locale: string;\n status: string;\n data: Record<string, unknown>;\n};\n\n/** Read-only access to content (drafts, as the admin API shows them). Reads committed data. */\nexport type ContentReadService = {\n get: (modelKey: string, id: string, options?: ContentReadOptions) => Promise<ContentReadEntry>;\n /** `query` is a delivery-style querystring, e.g. `filters[title][$contains]=a&pageSize=10`. */\n list: (\n modelKey: string,\n query?: string,\n options?: Omit<ContentReadOptions, 'locale'>,\n ) => Promise<{ items: ContentReadEntry[]; total: number }>;\n /** Number of (non-deleted) entries of a model. */\n count: (modelKey: string) => Promise<number>;\n /**\n * The active content models (collections and singletons) of this site: shared ones and its own, each with\n * its effective fields (a model that extends another lists the inherited fields first) and route key.\n */\n models: () => Promise<ServiceModel[]>;\n};\n\nexport type MediaUsage = {\n entryId: string;\n modelId: string;\n fieldId: string;\n locale: string;\n state: string;\n};\n\nexport type MediaReferenceService = {\n /** Where an asset is used (up to 100 references, plus the total). */\n usages: (assetId: string) => Promise<{ items: MediaUsage[]; total: number }>;\n};\n\nexport type EnqueueOptions = {\n runAt?: Date;\n /** Enqueueing the same key twice creates one job. */\n idempotencyKey?: string;\n maxAttempts?: number;\n};\n\nexport type ExtensionJobService = {\n /** Enqueues one of the project's own jobs (`jobs` in the config), by its name without the `ext.` prefix. */\n enqueue: (\n name: string,\n payload?: Record<string, unknown>,\n options?: EnqueueOptions,\n ) => Promise<{ id: string; created: boolean }>;\n};\n\n/**\n * What Shapio offers extensions. Deliberately small; everything else goes through `trx` or HTTP.\n *\n * Content and media are per site. The services handed to a hook read the hook's site; the services given to\n * routes, jobs and service factories read the primary site. Use `forSite` for another one (in a custom\n * route: `services.forSite(request.site)`).\n */\nexport type ShapioServices = {\n /** The site `content` and `media` read. */\n site: ExtensionSite;\n /** The same services reading another site. */\n forSite: (site: ExtensionSite) => ShapioServices;\n content: ContentReadService;\n media: MediaReferenceService;\n jobs: ExtensionJobService;\n logger: FastifyBaseLogger;\n};\n\n/**\n * Your own services, by name. Augment it for typed access everywhere services appear:\n *\n * ```ts\n * declare module '@shapio/cms/config' {\n * interface CustomServices { stats: StatsService }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- augmented by projects\nexport interface CustomServices {}\n\nexport type ExtensionServices = ShapioServices & CustomServices;\n\ntype HookContextBase = {\n /** The site the entry belongs to; `services` read this site. */\n site: ExtensionSite;\n model: HookModel;\n entry: HookEntry;\n locale: string | null;\n /** The document after the change (absent for deletes). */\n data: EntryData | undefined;\n /** The document before the change: the previous draft (update) or the live version (publish). */\n before: EntryData | undefined;\n /** Who made the change (an admin, an API token, an app user, or Shapio itself for scheduled work). */\n principal: Principal;\n services: ExtensionServices;\n logger: FastifyBaseLogger;\n /** Aborted when Shapio shuts down. */\n signal: AbortSignal;\n};\n\n/**\n * `before*` hooks run INSIDE the write's transaction, before it commits. Throw `HookError` (or call\n * `reject`) to abort the write with 422 `HOOK_REJECTED`; nothing of the write is kept. Other errors abort it\n * too, as a 500. Database work through `trx` commits or rolls back with the write.\n */\nexport type BeforeHookContext = HookContextBase & {\n event: BeforeHookEvent;\n trx: Transaction<DB>;\n reject: (message: string, details?: Record<string, unknown>) => never;\n};\n\n/**\n * `after*` hooks run AFTER the write committed, as a job (retried with backoff on error, never rolling the\n * write back). Database work through `trx` is exactly once: it commits together with the record that the\n * hook ran. Other side effects (HTTP calls) are at least once: make them idempotent with `idempotencyKey`.\n */\nexport type AfterHookContext = HookContextBase & {\n event: AfterHookEvent;\n trx: Transaction<DB>;\n /** The outbox event the hook runs for. */\n eventId: string;\n /** `<eventId>:<hook name>`: stable across retries. */\n idempotencyKey: string;\n attempt: number;\n};\n\nexport type BeforeHook = (context: BeforeHookContext) => Promise<void> | void;\nexport type AfterHook = (context: AfterHookContext) => Promise<void> | void;\n\nexport type ModelHooks = { [E in BeforeHookEvent]?: BeforeHook } & { [E in AfterHookEvent]?: AfterHook };\n\nexport type ServiceFactoryContext = {\n /** Kysely on Shapio's database. Shapio's own tables are internal and may change between releases. */\n db: Kysely<DB>;\n config: ExtensionHostConfig;\n logger: FastifyBaseLogger;\n /** Shapio's services plus the custom services declared before this one. */\n services: ExtensionServices;\n};\n\nexport type ExtensionHostConfig = {\n nodeEnv: 'development' | 'production' | 'test';\n /** PUBLIC_URL origin, without a trailing slash. */\n publicUrl: string;\n basePath: string;\n /** The directory holding shapio.config and extensions/. */\n projectDir: string;\n};\n\nexport type ServiceFactory = (context: ServiceFactoryContext) => unknown;\n\n/** Options every custom route plugin receives (also available as `app.ext`). */\nexport type ExtensionRouteOptions = {\n services: ExtensionServices;\n /** Shapio's permission evaluator: `permissions.evaluate(request.principal, { action, modelId })`. */\n permissions: PermissionEvaluator;\n logger: FastifyBaseLogger;\n /** preHandler: 401/403 unless the caller is an admin user or an admin API token. */\n requireAdmin: preHandlerAsyncHookHandler;\n};\n\nexport type ExtensionRoute = {\n /** Mounted at `/api/ext/<prefix>` (under BASE_PATH). Lower-case letters, digits and dashes. */\n prefix: string;\n plugin: FastifyPluginAsync<ExtensionRouteOptions>;\n};\n\nexport type JobHandlerContext = {\n jobId: string;\n payload: Record<string, unknown>;\n attempt: number;\n maxAttempts: number;\n idempotencyKey: string | null;\n services: ExtensionServices;\n logger: FastifyBaseLogger;\n signal: AbortSignal;\n};\n\n/** Throw to retry with backoff; the return value (JSON) is stored as the job result. */\nexport type ExtensionJobHandler = (context: JobHandlerContext) => Promise<unknown>;\n\n/**\n * A color theme for the admin: token values for a light variant, a dark variant, or both. Every UI token is\n * required in a variant; the `brand-*` tokens may be left out (Shapio's are used). Values are `#rrggbb`\n * (contrast is checked by `shapio extensions check`), `#rgb`, `#rrggbbaa`, or `rgb()`, `hsl()`, `oklch()`,\n * `oklab()` with plain arguments.\n */\nexport type ThemeTokens = Partial<Record<ThemeToken, string>>;\n\nexport type ThemeDefinition = {\n /** Lower-case letters, digits and dashes; not a built-in theme's key. Saved in each browser's setting. */\n key: string;\n /** Shown in the theme menu (not translated). */\n name: string;\n description?: string;\n light?: ThemeTokens;\n dark?: ThemeTokens;\n};\n\nexport type ShapioConfig = {\n /** Lifecycle hooks by model API ID (or stable model UUID); `*` runs for every model. */\n hooks?: Record<string, ModelHooks>;\n routes?: ExtensionRoute[];\n /** Constructed once at startup, in order, and shared by hooks, routes and jobs. */\n services?: Record<string, ServiceFactory>;\n /** Custom field editor modules: file names inside `extensions/editors/` (built ES modules). */\n editors?: string[];\n /** Job handlers by name; registered as `ext.<name>`. */\n jobs?: Record<string, ExtensionJobHandler>;\n /** Admin color themes, listed after the built-in ones in the theme menu. */\n themes?: ThemeDefinition[];\n};\n\n/** Identity helper for completion and type checking in `shapio.config.ts`. */\nexport const defineConfig = (config: ShapioConfig): ShapioConfig => config;\n\nconst HOOK_ERROR_BRAND = Symbol.for('shapio.HookError');\n\n/**\n * Thrown by a `before*` hook to reject a write: the API answers 422 with code `HOOK_REJECTED`, this message\n * and the details. Recognized by a brand, not `instanceof`, so a copy of this class loaded from another\n * path (a project's own `node_modules`) works the same.\n */\nexport class HookError extends Error {\n readonly details: Record<string, unknown> | undefined;\n readonly [HOOK_ERROR_BRAND] = true;\n\n constructor(message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'HookError';\n this.details = details;\n }\n}\n\nexport const isHookError = (error: unknown): error is HookError =>\n typeof error === 'object' &&\n error !== null &&\n (error as Record<symbol, unknown>)[HOOK_ERROR_BRAND] === true;\n"],"mappings":";;;;;;;;;;;;;;;;AA0CA,MAAa,6BAA6B;;AAmR1C,MAAa,gBAAgB,WAAuC;AAEpE,MAAM,mBAAmB,OAAO,IAAI,kBAAkB;;;;;;AAOtD,IAAa,YAAb,cAA+B,MAAM;CACnC;CACA,CAAU,oBAAoB;CAE9B,YAAY,SAAiB,SAAmC;EAC9D,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,UAAU;CACjB;AACF;AAEA,MAAa,eAAe,UAC1B,OAAO,UAAU,YACjB,UAAU,QACT,MAAkC,sBAAsB"}
@@ -1,4 +1,4 @@
1
- import { c as isValidStorageKey, i as ObjectNotFoundError, n as contentDisposition, r as InvalidStorageKeyError, s as encodeKeyPath, t as bucketContentDisposition } from "./contentDisposition-DOL2Xt0l.js";
1
+ import { c as isValidStorageKey, i as ObjectNotFoundError, n as contentDisposition, r as InvalidStorageKeyError, s as encodeKeyPath, t as bucketContentDisposition } from "./contentDisposition-DzhPhncr.js";
2
2
  import { DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, PutObjectCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
3
3
  import { createPresignedPost } from "@aws-sdk/s3-presigned-post";
4
4
  import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
@@ -122,4 +122,4 @@ const createS3Adapter = ({ config, publicBaseUrl, client }) => {
122
122
  //#endregion
123
123
  export { createS3Adapter };
124
124
 
125
- //# sourceMappingURL=s3Adapter-U01iEAcK.js.map
125
+ //# sourceMappingURL=s3Adapter-CZcCl0sy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"s3Adapter-U01iEAcK.js","names":[],"sources":["../src/media/s3Adapter.ts"],"sourcesContent":["import type { Readable } from 'node:stream';\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n PutObjectCommand,\n S3Client,\n S3ServiceException,\n} from '@aws-sdk/client-s3';\nimport { createPresignedPost } from '@aws-sdk/s3-presigned-post';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport type { S3StorageConfig } from '../config/index.js';\nimport { bucketContentDisposition, contentDisposition } from './contentDisposition.js';\nimport { InvalidStorageKeyError, ObjectNotFoundError } from './errors.js';\nimport { encodeKeyPath, isValidStorageKey } from './keys.js';\nimport type { StorageAdapter } from './types.js';\n\n/** R2 accepts any region name (\"auto\" by convention); AWS needs the bucket's real region. */\nconst DEFAULT_REGION = 'us-east-1';\n\nconst isNotFound = (error: unknown): boolean =>\n error instanceof S3ServiceException &&\n (error.$metadata.httpStatusCode === 404 || error.name === 'NotFound' || error.name === 'NoSuchKey');\n\nexport const createS3Client = (config: S3StorageConfig): S3Client =>\n new S3Client({\n region: config.region ?? DEFAULT_REGION,\n ...(config.endpoint ? { endpoint: config.endpoint } : {}),\n forcePathStyle: config.forcePathStyle,\n ...(config.accessKeyId && config.secretAccessKey\n ? { credentials: { accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey } }\n : {}),\n // Only send/validate checksums when an operation requires them: several S3-compatible services\n // (R2, B2 and other gateways) reject the SDK's default streaming CRC32 trailers.\n requestChecksumCalculation: 'WHEN_REQUIRED',\n responseChecksumValidation: 'WHEN_REQUIRED',\n });\n\nexport type S3AdapterOptions = {\n config: S3StorageConfig;\n publicBaseUrl: string | undefined;\n /** Injected in tests; created from `config` otherwise. */\n client?: S3Client;\n};\n\n/**\n * Any S3-compatible service (AWS S3, Cloudflare R2, B2, Spaces, Wasabi, versitygw). Private objects are read\n * through presigned GET URLs; browsers upload straight to the bucket with a presigned POST whose policy\n * limits size and content type, so Shapio never streams upload bytes.\n */\nexport const createS3Adapter = ({ config, publicBaseUrl, client }: S3AdapterOptions): StorageAdapter => {\n const s3 = client ?? createS3Client(config);\n const Bucket = config.bucket;\n const checkKey = (key: string) => {\n if (!isValidStorageKey(key)) {\n throw new InvalidStorageKeyError(key);\n }\n return key;\n };\n\n const head = async (key: string) => {\n try {\n const result = await s3.send(new HeadObjectCommand({ Bucket, Key: checkKey(key) }));\n return { size: result.ContentLength ?? 0, contentType: result.ContentType };\n } catch (error) {\n if (isNotFound(error)) {\n return undefined;\n }\n throw error;\n }\n };\n\n return {\n driver: 's3',\n put: async (key, body, { contentType, contentLength }) => {\n await s3.send(\n new PutObjectCommand({\n Bucket,\n Key: checkKey(key),\n Body: body,\n ContentType: contentType,\n ContentLength: Buffer.isBuffer(body) ? body.length : contentLength,\n ContentDisposition: bucketContentDisposition(contentType),\n }),\n );\n },\n getStream: async (key, range) => {\n try {\n const result = await s3.send(\n new GetObjectCommand({\n Bucket,\n Key: checkKey(key),\n ...(range ? { Range: `bytes=${range.start}-${range.end}` } : {}),\n }),\n );\n if (!result.Body) {\n throw new ObjectNotFoundError(key);\n }\n return result.Body as Readable;\n } catch (error) {\n throw isNotFound(error) ? new ObjectNotFoundError(key, { cause: error }) : error;\n }\n },\n head,\n exists: async (key) => (await head(key)) !== undefined,\n delete: async (key) => {\n await s3.send(new DeleteObjectCommand({ Bucket, Key: checkKey(key) }));\n },\n signedGetUrl: async (key, { expiresInSeconds, filename, contentType }) =>\n getSignedUrl(\n s3,\n new GetObjectCommand({\n Bucket,\n Key: checkKey(key),\n ResponseContentType: contentType,\n ResponseContentDisposition: contentDisposition(filename),\n }),\n { expiresIn: expiresInSeconds },\n ),\n publicUrl: (key) => (publicBaseUrl ? `${publicBaseUrl}/${encodeKeyPath(checkKey(key))}` : undefined),\n presignedUpload: async ({ key, contentType, maxSizeBytes, expiresInSeconds }) => {\n const disposition = bucketContentDisposition(contentType);\n const { url, fields } = await createPresignedPost(s3, {\n Bucket,\n Key: checkKey(key),\n Conditions: [\n ['content-length-range', 1, maxSizeBytes],\n ['eq', '$Content-Type', contentType],\n ...(disposition ? [['eq', '$Content-Disposition', disposition] as ['eq', string, string]] : []),\n ],\n Fields: {\n 'Content-Type': contentType,\n ...(disposition ? { 'Content-Disposition': disposition } : {}),\n },\n Expires: expiresInSeconds,\n });\n return { url, fields };\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"s3Adapter-CZcCl0sy.js","names":[],"sources":["../src/media/s3Adapter.ts"],"sourcesContent":["import type { Readable } from 'node:stream';\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n PutObjectCommand,\n S3Client,\n S3ServiceException,\n} from '@aws-sdk/client-s3';\nimport { createPresignedPost } from '@aws-sdk/s3-presigned-post';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\nimport type { S3StorageConfig } from '../config/index.js';\nimport { bucketContentDisposition, contentDisposition } from './contentDisposition.js';\nimport { InvalidStorageKeyError, ObjectNotFoundError } from './errors.js';\nimport { encodeKeyPath, isValidStorageKey } from './keys.js';\nimport type { StorageAdapter } from './types.js';\n\n/** R2 accepts any region name (\"auto\" by convention); AWS needs the bucket's real region. */\nconst DEFAULT_REGION = 'us-east-1';\n\nconst isNotFound = (error: unknown): boolean =>\n error instanceof S3ServiceException &&\n (error.$metadata.httpStatusCode === 404 || error.name === 'NotFound' || error.name === 'NoSuchKey');\n\nexport const createS3Client = (config: S3StorageConfig): S3Client =>\n new S3Client({\n region: config.region ?? DEFAULT_REGION,\n ...(config.endpoint ? { endpoint: config.endpoint } : {}),\n forcePathStyle: config.forcePathStyle,\n ...(config.accessKeyId && config.secretAccessKey\n ? { credentials: { accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey } }\n : {}),\n // Only send/validate checksums when an operation requires them: several S3-compatible services\n // (R2, B2 and other gateways) reject the SDK's default streaming CRC32 trailers.\n requestChecksumCalculation: 'WHEN_REQUIRED',\n responseChecksumValidation: 'WHEN_REQUIRED',\n });\n\nexport type S3AdapterOptions = {\n config: S3StorageConfig;\n publicBaseUrl: string | undefined;\n /** Injected in tests; created from `config` otherwise. */\n client?: S3Client;\n};\n\n/**\n * Any S3-compatible service (AWS S3, Cloudflare R2, B2, Spaces, Wasabi, versitygw). Private objects are read\n * through presigned GET URLs; browsers upload straight to the bucket with a presigned POST whose policy\n * limits size and content type, so Shapio never streams upload bytes.\n */\nexport const createS3Adapter = ({ config, publicBaseUrl, client }: S3AdapterOptions): StorageAdapter => {\n const s3 = client ?? createS3Client(config);\n const Bucket = config.bucket;\n const checkKey = (key: string) => {\n if (!isValidStorageKey(key)) {\n throw new InvalidStorageKeyError(key);\n }\n return key;\n };\n\n const head = async (key: string) => {\n try {\n const result = await s3.send(new HeadObjectCommand({ Bucket, Key: checkKey(key) }));\n return { size: result.ContentLength ?? 0, contentType: result.ContentType };\n } catch (error) {\n if (isNotFound(error)) {\n return undefined;\n }\n throw error;\n }\n };\n\n return {\n driver: 's3',\n put: async (key, body, { contentType, contentLength }) => {\n await s3.send(\n new PutObjectCommand({\n Bucket,\n Key: checkKey(key),\n Body: body,\n ContentType: contentType,\n ContentLength: Buffer.isBuffer(body) ? body.length : contentLength,\n ContentDisposition: bucketContentDisposition(contentType),\n }),\n );\n },\n getStream: async (key, range) => {\n try {\n const result = await s3.send(\n new GetObjectCommand({\n Bucket,\n Key: checkKey(key),\n ...(range ? { Range: `bytes=${range.start}-${range.end}` } : {}),\n }),\n );\n if (!result.Body) {\n throw new ObjectNotFoundError(key);\n }\n return result.Body as Readable;\n } catch (error) {\n throw isNotFound(error) ? new ObjectNotFoundError(key, { cause: error }) : error;\n }\n },\n head,\n exists: async (key) => (await head(key)) !== undefined,\n delete: async (key) => {\n await s3.send(new DeleteObjectCommand({ Bucket, Key: checkKey(key) }));\n },\n signedGetUrl: async (key, { expiresInSeconds, filename, contentType }) =>\n getSignedUrl(\n s3,\n new GetObjectCommand({\n Bucket,\n Key: checkKey(key),\n ResponseContentType: contentType,\n ResponseContentDisposition: contentDisposition(filename),\n }),\n { expiresIn: expiresInSeconds },\n ),\n publicUrl: (key) => (publicBaseUrl ? `${publicBaseUrl}/${encodeKeyPath(checkKey(key))}` : undefined),\n presignedUpload: async ({ key, contentType, maxSizeBytes, expiresInSeconds }) => {\n const disposition = bucketContentDisposition(contentType);\n const { url, fields } = await createPresignedPost(s3, {\n Bucket,\n Key: checkKey(key),\n Conditions: [\n ['content-length-range', 1, maxSizeBytes],\n ['eq', '$Content-Type', contentType],\n ...(disposition ? [['eq', '$Content-Disposition', disposition] as ['eq', string, string]] : []),\n ],\n Fields: {\n 'Content-Type': contentType,\n ...(disposition ? { 'Content-Disposition': disposition } : {}),\n },\n Expires: expiresInSeconds,\n });\n return { url, fields };\n },\n };\n};\n"],"mappings":"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"}