@anzusystems/common-admin 2.0.0-rc.5 → 2.0.0-rc.7

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 (690) hide show
  1. package/README.md +4 -0
  2. package/dist/AnzuSystemsCommonAdmin.d.ts +42 -32
  3. package/dist/AnzuSystemsCommonAdmin.js.map +1 -1
  4. package/dist/common-admin.css +1 -1
  5. package/dist/common-admin.js +282 -282
  6. package/dist/domains/anzuUser/api/anzuUserApi.d.ts +9 -12
  7. package/dist/domains/anzuUser/api/anzuUserApi.js.map +1 -1
  8. package/dist/domains/anzuUser/components/AAnzuUserDatatable.js.map +1 -1
  9. package/dist/domains/anzuUser/components/AAnzuUserDatatable.vue.d.ts +38 -44
  10. package/dist/domains/anzuUser/components/AAnzuUserDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/domains/anzuUser/components/AAnzuUserFilter.js.map +1 -1
  12. package/dist/domains/anzuUser/components/AAnzuUserFilter.vue.d.ts +12 -13
  13. package/dist/domains/anzuUser/components/AAnzuUserFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/domains/anzuUser/components/AAnzuUserForm.js.map +1 -1
  15. package/dist/domains/anzuUser/components/AAnzuUserForm.vue.d.ts +18 -20
  16. package/dist/domains/anzuUser/components/AAnzuUserForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/domains/anzuUser/components/AAnzuUserRoleAutocomplete.js.map +1 -1
  18. package/dist/domains/anzuUser/components/AAnzuUserRoleAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/domains/anzuUser/components/AUserBulkActionDialog.js.map +1 -1
  20. package/dist/domains/anzuUser/components/AUserBulkActionDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/domains/anzuUser/components/AUserCopyPermissionsDialog.js.map +1 -1
  22. package/dist/domains/anzuUser/components/AUserCopyPermissionsDialog.vue.d.ts +2 -3
  23. package/dist/domains/anzuUser/components/AUserCopyPermissionsDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/domains/anzuUser/components/AUserCreateInSystemButton.js.map +1 -1
  25. package/dist/domains/anzuUser/components/AUserCreateInSystemButton.vue.d.ts +9 -15
  26. package/dist/domains/anzuUser/components/AUserCreateInSystemButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/domains/anzuUser/components/AUserEnabledSwitch.js.map +1 -1
  28. package/dist/domains/anzuUser/components/AUserEnabledSwitch.vue.d.ts +8 -7
  29. package/dist/domains/anzuUser/components/AUserEnabledSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/domains/anzuUser/components/AUserManageButton.js.map +1 -1
  31. package/dist/domains/anzuUser/components/AUserManageButton.vue.d.ts +0 -1
  32. package/dist/domains/anzuUser/components/AUserManageButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/domains/anzuUser/components/AUserMetadataForm.js.map +1 -1
  34. package/dist/domains/anzuUser/components/AUserMetadataForm.vue.d.ts +8 -9
  35. package/dist/domains/anzuUser/components/AUserMetadataForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/domains/anzuUser/components/AUserMetadataRepairDialog.js.map +1 -1
  37. package/dist/domains/anzuUser/components/AUserMetadataRepairDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  38. package/dist/domains/anzuUser/components/AUserOtherSystemsTable.js.map +1 -1
  39. package/dist/domains/anzuUser/components/AUserOtherSystemsTable.vue.d.ts +1 -2
  40. package/dist/domains/anzuUser/components/AUserOtherSystemsTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/domains/anzuUser/components/AUserSystemOverview.js.map +1 -1
  42. package/dist/domains/anzuUser/components/AUserSystemOverview.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/domains/anzuUser/components/AUserSystemPanel.js.map +1 -1
  44. package/dist/domains/anzuUser/components/AUserSystemPanel.vue.d.ts +2 -2
  45. package/dist/domains/anzuUser/components/AUserSystemPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  46. package/dist/domains/anzuUser/components/AUserSystemStatusChip.js.map +1 -1
  47. package/dist/domains/anzuUser/components/AUserSystemStatusChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/domains/anzuUser/components/AUserTabsShell.js.map +1 -1
  49. package/dist/domains/anzuUser/components/AUserTabsShell.vue.d.ts +17 -22
  50. package/dist/domains/anzuUser/components/AUserTabsShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/domains/anzuUser/composables/anzuUserActions.d.ts +5 -9
  52. package/dist/domains/anzuUser/composables/anzuUserActions.js.map +1 -1
  53. package/dist/domains/anzuUser/composables/anzuUserValidations.d.ts +4 -6
  54. package/dist/domains/anzuUser/composables/anzuUserValidations.js.map +1 -1
  55. package/dist/domains/anzuUser/composables/cachedAnzuUsers.d.ts +3 -3
  56. package/dist/domains/anzuUser/composables/cachedAnzuUsers.js.map +1 -1
  57. package/dist/domains/anzuUser/composables/userCrossSystemSearch.d.ts +2 -4
  58. package/dist/domains/anzuUser/composables/userCrossSystemSearch.js.map +1 -1
  59. package/dist/domains/anzuUser/composables/userCrossSystemWrites.d.ts +5 -11
  60. package/dist/domains/anzuUser/composables/userCrossSystemWrites.js.map +1 -1
  61. package/dist/domains/anzuUser/composables/userSystemDescriptor.d.ts +33 -57
  62. package/dist/domains/anzuUser/composables/userSystemDescriptor.js.map +1 -1
  63. package/dist/domains/anzuUser/composables/userSystemProbe.d.ts +7 -27
  64. package/dist/domains/anzuUser/composables/userSystemProbe.js.map +1 -1
  65. package/dist/domains/anzuUser/filter/anzuUserFilter.d.ts +6 -16
  66. package/dist/domains/anzuUser/filter/anzuUserFilter.js.map +1 -1
  67. package/dist/domains/anzuUser/store/anzuUserStore.d.ts +1 -5
  68. package/dist/domains/anzuUser/store/anzuUserStore.js.map +1 -1
  69. package/dist/domains/anzuUser/store/userCrossSystemStore.d.ts +3 -14
  70. package/dist/domains/anzuUser/store/userCrossSystemStore.js.map +1 -1
  71. package/dist/domains/anzuUser/utils/userMetadataDiff.d.ts +7 -19
  72. package/dist/domains/anzuUser/utils/userMetadataDiff.js.map +1 -1
  73. package/dist/domains/anzuUser/utils/userSystemState.d.ts +12 -30
  74. package/dist/domains/anzuUser/utils/userSystemState.js.map +1 -1
  75. package/dist/domains/anzuUser/utils/userTabs.d.ts +1 -3
  76. package/dist/domains/anzuUser/utils/userTabs.js.map +1 -1
  77. package/dist/domains/api/composables/defineApiClient.d.ts +4 -8
  78. package/dist/domains/api/composables/defineApiClient.js.map +1 -1
  79. package/dist/domains/api/composables/request.d.ts +18 -48
  80. package/dist/domains/api/composables/request.js.map +1 -1
  81. package/dist/domains/api/composables/useApiFetchByIds.d.ts +7 -21
  82. package/dist/domains/api/composables/useApiFetchByIds.js.map +1 -1
  83. package/dist/domains/api/composables/useApiFetchItems.d.ts +18 -57
  84. package/dist/domains/api/composables/useApiFetchItems.js.map +1 -1
  85. package/dist/domains/api/composables/useApiFetchList.d.ts +7 -23
  86. package/dist/domains/api/composables/useApiFetchList.js.map +1 -1
  87. package/dist/domains/api/composables/useApiFetchListBatch.d.ts +5 -22
  88. package/dist/domains/api/composables/useApiFetchListBatch.js.map +1 -1
  89. package/dist/domains/api/composables/useApiQueryBuilder.js.map +1 -1
  90. package/dist/domains/api/composables/useApiRequest.d.ts +16 -39
  91. package/dist/domains/api/composables/useApiRequest.js.map +1 -1
  92. package/dist/domains/api/utils/apiErrors.d.ts +28 -55
  93. package/dist/domains/api/utils/apiErrors.js.map +1 -1
  94. package/dist/domains/api/utils/listBody.d.ts +22 -43
  95. package/dist/domains/api/utils/listBody.js.map +1 -1
  96. package/dist/domains/auth/components/Acl.js.map +1 -1
  97. package/dist/domains/auth/components/Acl.vue_vue_type_script_setup_true_lang.js.map +1 -1
  98. package/dist/domains/auth/composables/aclAllowed.d.ts +2 -3
  99. package/dist/domains/auth/composables/aclAllowed.js.map +1 -1
  100. package/dist/domains/auth/composables/defineAuth.js.map +1 -1
  101. package/dist/domains/auth/composables/refreshSession.d.ts +10 -13
  102. package/dist/domains/auth/composables/refreshSession.js.map +1 -1
  103. package/dist/domains/cached/components/ACachedChip.js.map +1 -1
  104. package/dist/domains/cached/components/ACachedChip.vue.d.ts +13 -11
  105. package/dist/domains/cached/components/ACachedChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  106. package/dist/domains/cached/components/ACachedUserChip.js +1 -1
  107. package/dist/domains/cached/components/ACachedUserChip.js.map +1 -1
  108. package/dist/domains/cached/components/ACachedUserChip.vue.d.ts +3 -3
  109. package/dist/domains/cached/components/ACachedUserChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  110. package/dist/domains/cached/composables/createUserAndTimeTrackingFields.d.ts +9 -9
  111. package/dist/domains/cached/composables/createUserAndTimeTrackingFields.js.map +1 -1
  112. package/dist/domains/cached/composables/defineCached.d.ts +13 -11
  113. package/dist/domains/cached/composables/defineCached.js.map +1 -1
  114. package/dist/domains/cached/composables/useCachedItem.d.ts +7 -8
  115. package/dist/domains/cached/composables/useCachedItem.js.map +1 -1
  116. package/dist/domains/collab/components/ACollabLockedByUser.js.map +1 -1
  117. package/dist/domains/collab/components/ACollabLockedByUser.vue_vue_type_script_setup_true_lang.js.map +1 -1
  118. package/dist/domains/collab/composables/collabAnyDataChange.js.map +1 -1
  119. package/dist/domains/collab/composables/collabField.d.ts +5 -3
  120. package/dist/domains/collab/composables/collabField.js.map +1 -1
  121. package/dist/domains/collab/composables/collabInit.js +58 -54
  122. package/dist/domains/collab/composables/collabInit.js.map +1 -1
  123. package/dist/domains/collab/composables/collabRecovery.d.ts +49 -0
  124. package/dist/domains/collab/composables/collabRecovery.js +99 -0
  125. package/dist/domains/collab/composables/collabRecovery.js.map +1 -0
  126. package/dist/domains/collab/composables/collabRoom.js +106 -106
  127. package/dist/domains/collab/composables/collabRoom.js.map +1 -1
  128. package/dist/domains/collab/composables/collabState.d.ts +11 -4
  129. package/dist/domains/collab/composables/collabState.js +34 -25
  130. package/dist/domains/collab/composables/collabState.js.map +1 -1
  131. package/dist/domains/collab/composables/commonAdminCollabOptions.d.ts +4 -2
  132. package/dist/domains/collab/types/Collab.d.ts +31 -5
  133. package/dist/domains/collab/types/Collab.js +23 -11
  134. package/dist/domains/collab/types/Collab.js.map +1 -1
  135. package/dist/domains/customDataForm/components/ACustomDataForm.js.map +1 -1
  136. package/dist/domains/customDataForm/components/ACustomDataForm.vue.d.ts +7 -5
  137. package/dist/domains/customDataForm/components/ACustomDataForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  138. package/dist/domains/customDataForm/components/ACustomDataFormElement.js.map +1 -1
  139. package/dist/domains/customDataForm/components/ACustomDataFormElement.vue_vue_type_script_setup_true_lang.js.map +1 -1
  140. package/dist/domains/customDataForm/components/ACustomDataFormHiddenPart.js.map +1 -1
  141. package/dist/domains/customDataForm/components/ACustomDataFormHiddenPart.vue.d.ts +5 -3
  142. package/dist/domains/customDataForm/components/ACustomDataFormHiddenPart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/domains/customDataForm/composables/useCustomDataForm.js.map +1 -1
  144. package/dist/domains/customDataForm/types/CustomDataForm.d.ts +4 -1
  145. package/dist/domains/dam/api/damAssetApi.d.ts +7 -7
  146. package/dist/domains/dam/api/damAssetApi.js.map +1 -1
  147. package/dist/domains/dam/api/damAssetLicenceApi.d.ts +1 -1
  148. package/dist/domains/dam/api/damAssetLicenceApi.js.map +1 -1
  149. package/dist/domains/dam/api/damConstants.js.map +1 -1
  150. package/dist/domains/dam/api/damEndPoints.js.map +1 -1
  151. package/dist/domains/dam/api/damImageApi.js.map +1 -1
  152. package/dist/domains/dam/api/uploadApi.js.map +1 -1
  153. package/dist/domains/dam/assetDetail/components/AssetCustomMetadataForm.js.map +1 -1
  154. package/dist/domains/dam/assetDetail/components/AssetCustomMetadataForm.vue.d.ts +7 -5
  155. package/dist/domains/dam/assetDetail/components/AssetCustomMetadataForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  156. package/dist/domains/dam/assetDetail/components/AssetDetailDialog.js.map +1 -1
  157. package/dist/domains/dam/assetDetail/components/AssetDetailDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  158. package/dist/domains/dam/assetDetail/components/AssetDetailDialogFrame.js.map +1 -1
  159. package/dist/domains/dam/assetDetail/components/AssetDetailDialogFrame.vue.d.ts +1 -1
  160. package/dist/domains/dam/assetDetail/components/AssetDetailDialogFrame.vue_vue_type_script_setup_true_lang.js.map +1 -1
  161. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarActionsWrapper.vue.d.ts +5 -3
  162. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarFrame.js.map +1 -1
  163. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarFrame.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarMetadata.js.map +1 -1
  165. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  166. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarROI.js.map +1 -1
  167. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarROI.vue_vue_type_script_setup_true_lang.js.map +1 -1
  168. package/dist/domains/dam/assetDetail/components/AssetFileInfoPanel.js.map +1 -1
  169. package/dist/domains/dam/assetDetail/components/AssetFileInfoPanel.vue.d.ts +1 -1
  170. package/dist/domains/dam/assetDetail/components/AssetFileInfoPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  171. package/dist/domains/dam/assetDetail/components/AssetImage.js.map +1 -1
  172. package/dist/domains/dam/assetDetail/components/AssetImage.vue.d.ts +1 -1
  173. package/dist/domains/dam/assetDetail/components/AssetImage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  174. package/dist/domains/dam/assetDetail/components/AssetImageMetaIcons.js.map +1 -1
  175. package/dist/domains/dam/assetDetail/components/AssetImageMetaIcons.vue.d.ts +2 -2
  176. package/dist/domains/dam/assetDetail/components/AssetImageMetaIcons.vue_vue_type_script_setup_true_lang.js.map +1 -1
  177. package/dist/domains/dam/assetDetail/components/AssetInfobox.js.map +1 -1
  178. package/dist/domains/dam/assetDetail/components/AssetInfobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/domains/dam/assetDetail/components/AssetMetadata.js.map +1 -1
  180. package/dist/domains/dam/assetDetail/components/AssetMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  181. package/dist/domains/dam/assetDetail/composables/assetDetailExtSystem.d.ts +5 -6
  182. package/dist/domains/dam/assetDetail/composables/assetDetailExtSystem.js.map +1 -1
  183. package/dist/domains/dam/assetDetail/composables/assetDetailView.d.ts +10 -10
  184. package/dist/domains/dam/assetDetail/composables/assetDetailView.js.map +1 -1
  185. package/dist/domains/dam/assetDetail/store/assetDetailStore.js.map +1 -1
  186. package/dist/domains/dam/assetDetail/utils/assetMetadataMayStillChange.d.ts +4 -3
  187. package/dist/domains/dam/assetDetail/utils/assetMetadataMayStillChange.js.map +1 -1
  188. package/dist/domains/dam/assetSelect/api/damPodcastApi.js.map +1 -1
  189. package/dist/domains/dam/assetSelect/components/AAssetListInner.js.map +1 -1
  190. package/dist/domains/dam/assetSelect/components/AAssetListInner.vue.d.ts +789 -787
  191. package/dist/domains/dam/assetSelect/components/AAssetListInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  192. package/dist/domains/dam/assetSelect/components/AAssetSelect.js.map +1 -1
  193. package/dist/domains/dam/assetSelect/components/AAssetSelect.vue.d.ts +395 -393
  194. package/dist/domains/dam/assetSelect/components/AAssetSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  195. package/dist/domains/dam/assetSelect/components/AAssetSelectMedia.js.map +1 -1
  196. package/dist/domains/dam/assetSelect/components/AAssetSelectMedia.vue.d.ts +14 -12
  197. package/dist/domains/dam/assetSelect/components/AAssetSelectMedia.vue_vue_type_script_setup_true_lang.js.map +1 -1
  198. package/dist/domains/dam/assetSelect/components/AssetDistributionServiceNameFilter.js.map +1 -1
  199. package/dist/domains/dam/assetSelect/components/AssetDistributionServiceNameFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/domains/dam/assetSelect/components/AssetSelectListBar.js.map +1 -1
  201. package/dist/domains/dam/assetSelect/components/AssetSelectListBar.vue.d.ts +9 -7
  202. package/dist/domains/dam/assetSelect/components/AssetSelectListBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/domains/dam/assetSelect/components/AssetSelectTableRowItem.js.map +1 -1
  204. package/dist/domains/dam/assetSelect/components/AssetSelectTableRowItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  205. package/dist/domains/dam/assetSelect/composables/assetSelectListActions.js.map +1 -1
  206. package/dist/domains/dam/assetSelect/store/assetSelectStore.js.map +1 -1
  207. package/dist/domains/dam/author/api/authorApi.js.map +1 -1
  208. package/dist/domains/dam/author/components/AuthorCreateButton.js.map +1 -1
  209. package/dist/domains/dam/author/components/AuthorCreateButton.vue.d.ts +1 -1
  210. package/dist/domains/dam/author/components/AuthorCreateButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  211. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChip.js.map +1 -1
  212. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChip.vue.d.ts +9 -6
  213. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  214. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChipConflicts.js.map +1 -1
  215. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChipConflicts.vue_vue_type_script_setup_true_lang.js.map +1 -1
  216. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.js +1 -1
  217. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.js.map +1 -1
  218. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.vue.d.ts +2 -2
  219. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.vue_vue_type_script_setup_true_lang.js.map +1 -1
  220. package/dist/domains/dam/author/components/DamAuthorFilterRemoteAutocomplete.js.map +1 -1
  221. package/dist/domains/dam/author/components/DamAuthorFilterRemoteAutocomplete.vue.d.ts +1 -1
  222. package/dist/domains/dam/author/components/DamAuthorFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  223. package/dist/domains/dam/author/composables/cachedAuthors.d.ts +5 -4
  224. package/dist/domains/dam/author/composables/cachedAuthors.js.map +1 -1
  225. package/dist/domains/dam/author/composables/cachedUsers.d.ts +5 -4
  226. package/dist/domains/dam/author/composables/cachedUsers.js.map +1 -1
  227. package/dist/domains/dam/author/composables/damAuthorConfig.d.ts +2 -2
  228. package/dist/domains/dam/author/composables/damAuthorConfig.js.map +1 -1
  229. package/dist/domains/dam/components/DamAdminAssetLink.js.map +1 -1
  230. package/dist/domains/dam/components/DamAdminAssetLink.vue_vue_type_script_setup_true_lang.js.map +1 -1
  231. package/dist/domains/dam/composables/commonAdminCoreDamOptions.d.ts +10 -8
  232. package/dist/domains/dam/composables/commonAdminCoreDamOptions.js.map +1 -1
  233. package/dist/domains/dam/composables/damConfigName.d.ts +8 -9
  234. package/dist/domains/dam/composables/damConfigName.js.map +1 -1
  235. package/dist/domains/dam/composables/damNotifications.d.ts +9 -9
  236. package/dist/domains/dam/composables/damNotifications.js.map +1 -1
  237. package/dist/domains/dam/composables/damNotificationsConnection.d.ts +4 -4
  238. package/dist/domains/dam/composables/damNotificationsConnection.js.map +1 -1
  239. package/dist/domains/dam/composables/damNotificationsEventBus.d.ts +2 -2
  240. package/dist/domains/dam/composables/damNotificationsEventBus.js.map +1 -1
  241. package/dist/domains/dam/composables/extSystemIdForCached.d.ts +5 -4
  242. package/dist/domains/dam/composables/extSystemIdForCached.js.map +1 -1
  243. package/dist/domains/dam/config/api/damAssetCustomFormApi.js.map +1 -1
  244. package/dist/domains/dam/config/api/damConfigApi.js.map +1 -1
  245. package/dist/domains/dam/config/composables/damConfigState.d.ts +5 -5
  246. package/dist/domains/dam/config/composables/damConfigState.js.map +1 -1
  247. package/dist/domains/dam/config/store/damConfigStore.d.ts +5 -4
  248. package/dist/domains/dam/config/store/damConfigStore.js.map +1 -1
  249. package/dist/domains/dam/config/utils/damFilterUserAllowedUploadConfigs.d.ts +3 -1
  250. package/dist/domains/dam/config/utils/damFilterUserAllowedUploadConfigs.js.map +1 -1
  251. package/dist/domains/dam/cropper/components/ACropper.js.map +1 -1
  252. package/dist/domains/dam/cropper/components/ACropper.vue.d.ts +8 -16
  253. package/dist/domains/dam/cropper/components/ACropper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  254. package/dist/domains/dam/cropper/components/DamAssetImageRoiSelect.js.map +1 -1
  255. package/dist/domains/dam/cropper/components/DamAssetImageRoiSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  256. package/dist/domains/dam/cropper/store/imageRoiStore.d.ts +9 -12
  257. package/dist/domains/dam/cropper/store/imageRoiStore.js.map +1 -1
  258. package/dist/domains/dam/cropper/utils/cropperGeometry.d.ts +24 -38
  259. package/dist/domains/dam/cropper/utils/cropperGeometry.js.map +1 -1
  260. package/dist/domains/dam/cropper/utils/cropperJsService.d.ts +3 -7
  261. package/dist/domains/dam/cropper/utils/cropperJsService.js +10 -3
  262. package/dist/domains/dam/cropper/utils/cropperJsService.js.map +1 -1
  263. package/dist/domains/dam/cropper/utils/cropperTypes.d.ts +3 -6
  264. package/dist/domains/dam/cropper/utils/damAssetImageRoiSelectLoader.d.ts +5 -5
  265. package/dist/domains/dam/cropper/utils/damAssetImageRoiSelectLoader.js.map +1 -1
  266. package/dist/domains/dam/imageWidget/components/AImageMediaWidget.js.map +1 -1
  267. package/dist/domains/dam/imageWidget/components/AImageMediaWidget.vue_vue_type_script_setup_true_lang.js.map +1 -1
  268. package/dist/domains/dam/imageWidget/components/AImagePublicInput.js.map +1 -1
  269. package/dist/domains/dam/imageWidget/components/AImagePublicInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  270. package/dist/domains/dam/imageWidget/components/AImageWidget.js.map +1 -1
  271. package/dist/domains/dam/imageWidget/components/AImageWidget.vue_vue_type_script_setup_true_lang.js.map +1 -1
  272. package/dist/domains/dam/imageWidget/components/AImageWidgetMultiple.js.map +1 -1
  273. package/dist/domains/dam/imageWidget/components/AImageWidgetMultiple.vue_vue_type_script_setup_true_lang.js.map +1 -1
  274. package/dist/domains/dam/imageWidget/components/AImageWidgetSimple.vue.d.ts +43 -41
  275. package/dist/domains/dam/imageWidget/components/AMediaWidgetSimple.vue.d.ts +31 -29
  276. package/dist/domains/dam/imageWidget/components/ImageDetailDialogMetadata.js.map +1 -1
  277. package/dist/domains/dam/imageWidget/components/ImageDetailDialogMetadata.vue.d.ts +29 -27
  278. package/dist/domains/dam/imageWidget/components/ImageDetailDialogMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  279. package/dist/domains/dam/imageWidget/components/ImageMassOperations.js.map +1 -1
  280. package/dist/domains/dam/imageWidget/components/ImageMassOperations.vue.d.ts +1 -1
  281. package/dist/domains/dam/imageWidget/components/ImageMassOperations.vue_vue_type_script_setup_true_lang.js.map +1 -1
  282. package/dist/domains/dam/imageWidget/components/ImageMediaWidgetInner.js.map +1 -1
  283. package/dist/domains/dam/imageWidget/components/ImageMediaWidgetInner.vue.d.ts +68 -66
  284. package/dist/domains/dam/imageWidget/components/ImageMediaWidgetInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  285. package/dist/domains/dam/imageWidget/components/ImageWidgetInner.js.map +1 -1
  286. package/dist/domains/dam/imageWidget/components/ImageWidgetInner.vue.d.ts +402 -400
  287. package/dist/domains/dam/imageWidget/components/ImageWidgetInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  288. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleInner.js.map +1 -1
  289. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleInner.vue.d.ts +384 -382
  290. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  291. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleItem.js.map +1 -1
  292. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  293. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleLimitDialog.js.map +1 -1
  294. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleLimitDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  295. package/dist/domains/dam/imageWidget/components/MediaWidgetSimpleDialog.vue.d.ts +7 -5
  296. package/dist/domains/dam/imageWidget/composables/commonAdminImageOptions.js.map +1 -1
  297. package/dist/domains/dam/imageWidget/composables/imageApiCms.js.map +1 -1
  298. package/dist/domains/dam/imageWidget/composables/imageDialogDamAuthors.d.ts +11 -13
  299. package/dist/domains/dam/imageWidget/composables/imageDialogDamAuthors.js.map +1 -1
  300. package/dist/domains/dam/imageWidget/composables/useImageMassOperations.js.map +1 -1
  301. package/dist/domains/dam/imageWidget/store/imageMediaWidgetStore.js.map +1 -1
  302. package/dist/domains/dam/imageWidget/store/imageStore.js.map +1 -1
  303. package/dist/domains/dam/imageWidget/utils/damImage.d.ts +5 -6
  304. package/dist/domains/dam/imageWidget/utils/damImage.js.map +1 -1
  305. package/dist/domains/dam/imageWidget/utils/fieldLockTurns.d.ts +1 -2
  306. package/dist/domains/dam/imageWidget/utils/fieldLockTurns.js.map +1 -1
  307. package/dist/domains/dam/imageWidget/utils/imageSaves.d.ts +10 -14
  308. package/dist/domains/dam/imageWidget/utils/imageSaves.js.map +1 -1
  309. package/dist/domains/dam/imageWidget/utils/metadataToImageMap.js.map +1 -1
  310. package/dist/domains/dam/imageWidget/utils/waitLimit.d.ts +4 -6
  311. package/dist/domains/dam/imageWidget/utils/waitLimit.js.map +1 -1
  312. package/dist/domains/dam/keyword/api/keywordApi.js.map +1 -1
  313. package/dist/domains/dam/keyword/components/DamKeywordFilterRemoteAutocomplete.js.map +1 -1
  314. package/dist/domains/dam/keyword/components/DamKeywordFilterRemoteAutocomplete.vue.d.ts +1 -1
  315. package/dist/domains/dam/keyword/components/DamKeywordFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  316. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteCachedKeywordChip.js.map +1 -1
  317. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteCachedKeywordChip.vue.d.ts +8 -5
  318. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteCachedKeywordChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  319. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.js +1 -1
  320. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.js.map +1 -1
  321. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.vue.d.ts +2 -2
  322. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.vue_vue_type_script_setup_true_lang.js.map +1 -1
  323. package/dist/domains/dam/keyword/composables/cachedKeywords.d.ts +5 -4
  324. package/dist/domains/dam/keyword/composables/cachedKeywords.js.map +1 -1
  325. package/dist/domains/dam/keyword/composables/damKeywordConfig.d.ts +2 -2
  326. package/dist/domains/dam/keyword/composables/damKeywordConfig.js.map +1 -1
  327. package/dist/domains/dam/types/Asset.d.ts +1 -1
  328. package/dist/domains/dam/types/Asset.js.map +1 -1
  329. package/dist/domains/dam/types/UploadQueue.d.ts +5 -4
  330. package/dist/domains/dam/types/UploadQueue.js.map +1 -1
  331. package/dist/domains/dam/uploadQueue/components/AssetCustomMetadataFormMassOperations.js.map +1 -1
  332. package/dist/domains/dam/uploadQueue/components/AssetCustomMetadataFormMassOperations.vue_vue_type_script_setup_true_lang.js.map +1 -1
  333. package/dist/domains/dam/uploadQueue/components/AssetQueueSelectedSidebar.js.map +1 -1
  334. package/dist/domains/dam/uploadQueue/components/AssetQueueSelectedSidebar.vue.d.ts +2 -2
  335. package/dist/domains/dam/uploadQueue/components/AssetQueueSelectedSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  336. package/dist/domains/dam/uploadQueue/components/UploadQueueDialog.js.map +1 -1
  337. package/dist/domains/dam/uploadQueue/components/UploadQueueDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  338. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingle.js.map +1 -1
  339. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  340. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebar.js.map +1 -1
  341. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebar.vue.d.ts +6 -4
  342. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  343. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadata.js.map +1 -1
  344. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadata.vue.d.ts +1 -1
  345. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  346. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadataContent.js.map +1 -1
  347. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadataContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  348. package/dist/domains/dam/uploadQueue/components/UploadQueueEditable.js.map +1 -1
  349. package/dist/domains/dam/uploadQueue/components/UploadQueueEditable.vue.d.ts +6 -6
  350. package/dist/domains/dam/uploadQueue/components/UploadQueueEditable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  351. package/dist/domains/dam/uploadQueue/components/UploadQueueItemEditable.js.map +1 -1
  352. package/dist/domains/dam/uploadQueue/components/UploadQueueItemEditable.vue.d.ts +13 -13
  353. package/dist/domains/dam/uploadQueue/components/UploadQueueItemEditable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  354. package/dist/domains/dam/uploadQueue/components/uploadQueueBindings.d.ts +13 -13
  355. package/dist/domains/dam/uploadQueue/components/uploadQueueBindings.js.map +1 -1
  356. package/dist/domains/dam/uploadQueue/composables/damUploadChunkSize.d.ts +2 -2
  357. package/dist/domains/dam/uploadQueue/composables/damUploadChunkSize.js.map +1 -1
  358. package/dist/domains/dam/uploadQueue/composables/uploadMeter.d.ts +12 -12
  359. package/dist/domains/dam/uploadQueue/composables/uploadMeter.js.map +1 -1
  360. package/dist/domains/dam/uploadQueue/composables/uploadQueueItemRefresh.d.ts +5 -5
  361. package/dist/domains/dam/uploadQueue/composables/uploadQueueItemRefresh.js.map +1 -1
  362. package/dist/domains/dam/uploadQueue/composables/uploadService.d.ts +2 -3
  363. package/dist/domains/dam/uploadQueue/composables/uploadService.js.map +1 -1
  364. package/dist/domains/dam/uploadQueue/composables/useUploadQueueDialog.d.ts +5 -4
  365. package/dist/domains/dam/uploadQueue/composables/useUploadQueueDialog.js.map +1 -1
  366. package/dist/domains/dam/uploadQueue/core/uploadQueueCore.d.ts +3 -2
  367. package/dist/domains/dam/uploadQueue/core/uploadQueueCore.js.map +1 -1
  368. package/dist/domains/dam/uploadQueue/core/uploadQueueCoreTypes.d.ts +8 -5
  369. package/dist/domains/dam/uploadQueue/core/uploadQueueCoreTypes.js.map +1 -1
  370. package/dist/domains/dam/uploadQueue/core/uploadQueueFill.d.ts +3 -3
  371. package/dist/domains/dam/uploadQueue/core/uploadQueueFill.js.map +1 -1
  372. package/dist/domains/dam/uploadQueue/presets/queuePresets.d.ts +8 -5
  373. package/dist/domains/dam/uploadQueue/presets/queuePresets.js.map +1 -1
  374. package/dist/domains/dam/uploadQueue/presets/uploadPresets.d.ts +15 -13
  375. package/dist/domains/dam/uploadQueue/presets/uploadPresets.js.map +1 -1
  376. package/dist/domains/dam/uploadQueue/settlement/uploadPollSchedule.d.ts +7 -7
  377. package/dist/domains/dam/uploadQueue/settlement/uploadPollSchedule.js.map +1 -1
  378. package/dist/domains/dam/uploadQueue/settlement/uploadPoller.d.ts +4 -4
  379. package/dist/domains/dam/uploadQueue/settlement/uploadPoller.js.map +1 -1
  380. package/dist/domains/dam/uploadQueue/settlement/uploadSettle.d.ts +28 -30
  381. package/dist/domains/dam/uploadQueue/settlement/uploadSettle.js.map +1 -1
  382. package/dist/domains/dam/uploadQueue/settlement/uploadSettlement.d.ts +2 -2
  383. package/dist/domains/dam/uploadQueue/settlement/uploadSettlement.js.map +1 -1
  384. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementRuntime.d.ts +2 -2
  385. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementRuntime.js.map +1 -1
  386. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementTypes.d.ts +63 -73
  387. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementTypes.js.map +1 -1
  388. package/dist/domains/dam/uploadQueue/store/uploadQueuesStore.d.ts +8 -9
  389. package/dist/domains/dam/uploadQueue/store/uploadQueuesStore.js.map +1 -1
  390. package/dist/domains/dam/user/api/userApi.d.ts +2 -2
  391. package/dist/domains/dam/user/api/userApi.js.map +1 -1
  392. package/dist/domains/dam/user/components/DamDistributionServiceSelect.js.map +1 -1
  393. package/dist/domains/dam/user/components/DamDistributionServiceSelect.vue.d.ts +1 -1
  394. package/dist/domains/dam/user/components/DamDistributionServiceSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  395. package/dist/domains/dam/user/components/DamExternalProviderAssetSelect.js.map +1 -1
  396. package/dist/domains/dam/user/components/DamExternalProviderAssetSelect.vue.d.ts +1 -1
  397. package/dist/domains/dam/user/components/DamExternalProviderAssetSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  398. package/dist/domains/dam/user/components/DamUserRemoteAutocomplete.js.map +1 -1
  399. package/dist/domains/dam/user/components/DamUserRemoteAutocomplete.vue.d.ts +1 -1
  400. package/dist/domains/dam/user/components/DamUserRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  401. package/dist/domains/dam/user/composables/damUserSelectActions.d.ts +1 -1
  402. package/dist/domains/dam/user/composables/damUserSelectActions.js.map +1 -1
  403. package/dist/domains/dam/user/types/DamDistributionServiceType.d.ts +2 -2
  404. package/dist/domains/dam/user/types/DamDistributionServiceType.js.map +1 -1
  405. package/dist/domains/dam/user/types/DamExternalProviderAssetType.d.ts +1 -1
  406. package/dist/domains/dam/user/types/DamExternalProviderAssetType.js.map +1 -1
  407. package/dist/domains/filters/bookmarks/components/FilterBookmarkDialog.js.map +1 -1
  408. package/dist/domains/filters/bookmarks/components/FilterBookmarkDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  409. package/dist/domains/filters/bookmarks/store/bookmarksStore.d.ts +3 -3
  410. package/dist/domains/filters/bookmarks/store/bookmarksStore.js.map +1 -1
  411. package/dist/domains/filters/components/AFilterDatetimePicker.js.map +1 -1
  412. package/dist/domains/filters/components/AFilterDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  413. package/dist/domains/filters/components/AFilterInteger.js.map +1 -1
  414. package/dist/domains/filters/components/AFilterInteger.vue_vue_type_script_setup_true_lang.js.map +1 -1
  415. package/dist/domains/filters/components/AFilterString.js.map +1 -1
  416. package/dist/domains/filters/components/AFilterString.vue_vue_type_script_setup_true_lang.js.map +1 -1
  417. package/dist/domains/filters/components/AFilterTimeInterval.js +1 -1
  418. package/dist/domains/filters/components/AFilterTimeInterval.js.map +1 -1
  419. package/dist/domains/filters/components/AFilterTimeInterval.vue.d.ts +5 -3
  420. package/dist/domains/filters/components/AFilterTimeInterval.vue_vue_type_script_setup_true_lang.js.map +1 -1
  421. package/dist/domains/filters/components/AFilterValueObjectOptionsSelect.js.map +1 -1
  422. package/dist/domains/filters/components/AFilterValueObjectOptionsSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  423. package/dist/domains/filters/components/AFilterWrapper.js.map +1 -1
  424. package/dist/domains/filters/components/AFilterWrapper.vue.d.ts +17 -15
  425. package/dist/domains/filters/components/AFilterWrapper.vue_vue_type_script_setup_true_lang.js +63 -62
  426. package/dist/domains/filters/components/AFilterWrapper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  427. package/dist/domains/filters/components/AFilterWrapperSidebar.vue.d.ts +5 -3
  428. package/dist/domains/filters/components/FiltersSelected.js.map +1 -1
  429. package/dist/domains/filters/components/FiltersSelected.vue_vue_type_script_setup_true_lang.js.map +1 -1
  430. package/dist/domains/filters/composables/filterFactory.d.ts +16 -26
  431. package/dist/domains/filters/composables/filterFactory.js +38 -31
  432. package/dist/domains/filters/composables/filterFactory.js.map +1 -1
  433. package/dist/domains/filters/datatable/components/ADatatableOrdering.js.map +1 -1
  434. package/dist/domains/filters/datatable/components/ADatatableOrdering.vue_vue_type_script_setup_true_lang.js +3 -1
  435. package/dist/domains/filters/datatable/components/ADatatableOrdering.vue_vue_type_script_setup_true_lang.js.map +1 -1
  436. package/dist/domains/filters/datatable/components/ADatatablePagination.js.map +1 -1
  437. package/dist/domains/filters/datatable/components/ADatatablePagination.vue_vue_type_script_setup_true_lang.js +2 -4
  438. package/dist/domains/filters/datatable/components/ADatatablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  439. package/dist/domains/filters/utils/filterInjectionKeys.js.map +1 -1
  440. package/dist/domains/form/components/AFormDatetimePicker.js.map +1 -1
  441. package/dist/domains/form/components/AFormDatetimePicker.vue.d.ts +7 -5
  442. package/dist/domains/form/components/AFormDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  443. package/dist/domains/form/components/AFormFlagDatetimePicker.js.map +1 -1
  444. package/dist/domains/form/components/AFormFlagDatetimePicker.vue.d.ts +7 -5
  445. package/dist/domains/form/components/AFormFlagDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  446. package/dist/domains/form/components/AFormSwitch.vue.d.ts +7 -5
  447. package/dist/domains/form/components/AFormTextField.js.map +1 -1
  448. package/dist/domains/form/components/AFormTextField.vue.d.ts +9 -7
  449. package/dist/domains/form/components/AFormTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  450. package/dist/domains/form/components/AFormTextarea.vue.d.ts +13 -11
  451. package/dist/domains/form/components/AFormValueObjectOptionsSelect.vue.d.ts +7 -5
  452. package/dist/domains/form/components/ASystemEntityScope.vue.d.ts +5 -3
  453. package/dist/domains/job/api/jobApi.js.map +1 -1
  454. package/dist/domains/job/components/AJobDetailCommon.vue.d.ts +5 -3
  455. package/dist/domains/listEditor/components/AListEditor.js.map +1 -1
  456. package/dist/domains/listEditor/components/AListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  457. package/dist/domains/listEditor/components/ANestedSortableListEditor.js.map +1 -1
  458. package/dist/domains/listEditor/components/ANestedSortableListEditor.vue.d.ts +2 -3
  459. package/dist/domains/listEditor/components/ANestedSortableListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  460. package/dist/domains/listEditor/components/ASortableListEditor.js.map +1 -1
  461. package/dist/domains/listEditor/components/ASortableListEditor.vue.d.ts +2 -3
  462. package/dist/domains/listEditor/components/ASortableListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  463. package/dist/domains/listEditor/composables/useListEditorController.d.ts +4 -5
  464. package/dist/domains/listEditor/composables/useListEditorController.js.map +1 -1
  465. package/dist/domains/listEditor/composables/useNestedListEditor.d.ts +3 -4
  466. package/dist/domains/listEditor/composables/useNestedListEditor.js.map +1 -1
  467. package/dist/domains/listEditor/composables/useNestedListEditorController.d.ts +5 -4
  468. package/dist/domains/listEditor/composables/useNestedListEditorController.js.map +1 -1
  469. package/dist/domains/listEditor/composables/useReorderMode.js.map +1 -1
  470. package/dist/domains/listEditor/types/listEditorTypes.d.ts +2 -2
  471. package/dist/domains/listEditor/utils/listEditorLoader.d.ts +5 -5
  472. package/dist/domains/listEditor/utils/listEditorLoader.js.map +1 -1
  473. package/dist/domains/listEditor/utils/resolveCompactText.js.map +1 -1
  474. package/dist/domains/log/api/logApi.d.ts +2 -3
  475. package/dist/domains/log/api/logApi.js.map +1 -1
  476. package/dist/domains/log/components/ALogDatatable.js.map +1 -1
  477. package/dist/domains/log/components/ALogDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  478. package/dist/domains/log/components/ALogDetailView.js.map +1 -1
  479. package/dist/domains/log/components/ALogDetailView.vue.d.ts +1 -1
  480. package/dist/domains/log/components/ALogDetailView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  481. package/dist/domains/log/components/ALogFilter.js.map +1 -1
  482. package/dist/domains/log/components/ALogFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  483. package/dist/domains/log/components/ALogListView.js.map +1 -1
  484. package/dist/domains/log/components/ALogListView.vue.d.ts +1 -1
  485. package/dist/domains/log/components/ALogListView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  486. package/dist/domains/log/composables/logActions.d.ts +4 -5
  487. package/dist/domains/log/composables/logActions.js.map +1 -1
  488. package/dist/domains/log/composables/logType.d.ts +6 -7
  489. package/dist/domains/log/composables/logType.js.map +1 -1
  490. package/dist/domains/log/filter/logFilter.d.ts +8 -11
  491. package/dist/domains/log/filter/logFilter.js.map +1 -1
  492. package/dist/domains/permission/components/APermissionEditor.js.map +1 -1
  493. package/dist/domains/permission/components/APermissionEditor.vue.d.ts +4 -4
  494. package/dist/domains/permission/components/APermissionEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  495. package/dist/domains/permission/composables/permissionActions.d.ts +3 -6
  496. package/dist/domains/permission/composables/permissionActions.js.map +1 -1
  497. package/dist/domains/permission/config/api/permissionConfigApi.d.ts +2 -2
  498. package/dist/domains/permission/config/api/permissionConfigApi.js.map +1 -1
  499. package/dist/domains/permission/config/composables/permissionConfigActions.d.ts +3 -7
  500. package/dist/domains/permission/config/composables/permissionConfigActions.js.map +1 -1
  501. package/dist/domains/permission/config/store/permissionConfigStore.d.ts +2 -4
  502. package/dist/domains/permission/config/store/permissionConfigStore.js.map +1 -1
  503. package/dist/domains/permission/group/api/permissionGroupApi.d.ts +8 -10
  504. package/dist/domains/permission/group/api/permissionGroupApi.js.map +1 -1
  505. package/dist/domains/permission/group/components/APermissionGroupDatatable.js.map +1 -1
  506. package/dist/domains/permission/group/components/APermissionGroupDatatable.vue.d.ts +12 -10
  507. package/dist/domains/permission/group/components/APermissionGroupDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  508. package/dist/domains/permission/group/components/APermissionGroupDetail.js.map +1 -1
  509. package/dist/domains/permission/group/components/APermissionGroupDetail.vue.d.ts +21 -22
  510. package/dist/domains/permission/group/components/APermissionGroupDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  511. package/dist/domains/permission/group/components/APermissionGroupManage.js.map +1 -1
  512. package/dist/domains/permission/group/components/APermissionGroupManage.vue.d.ts +21 -22
  513. package/dist/domains/permission/group/components/APermissionGroupManage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  514. package/dist/domains/permission/group/composables/cachedPermissionGroups.js.map +1 -1
  515. package/dist/domains/permission/group/composables/permissionGroupActions.d.ts +6 -8
  516. package/dist/domains/permission/group/composables/permissionGroupActions.js.map +1 -1
  517. package/dist/domains/permission/group/composables/permissionGroupValidations.d.ts +2 -3
  518. package/dist/domains/permission/group/composables/permissionGroupValidations.js.map +1 -1
  519. package/dist/domains/permission/group/filter/permissionGroupFilter.d.ts +2 -3
  520. package/dist/domains/permission/group/filter/permissionGroupFilter.js.map +1 -1
  521. package/dist/domains/permission/group/store/permissionGroupStore.d.ts +3 -6
  522. package/dist/domains/permission/group/store/permissionGroupStore.js.map +1 -1
  523. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocomplete.js.map +1 -1
  524. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  525. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocompleteWithMinimal.js.map +1 -1
  526. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocompleteWithMinimal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  527. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocomplete.js.map +1 -1
  528. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  529. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocompleteWithCached.vue.d.ts +5 -3
  530. package/dist/domains/remoteAutocomplete/composables/createRemoteAutocomplete.d.ts +11 -13
  531. package/dist/domains/remoteAutocomplete/composables/createRemoteAutocomplete.js.map +1 -1
  532. package/dist/domains/subjectSelect/components/AFilterWrapperSubjectSelect.vue.d.ts +13 -11
  533. package/dist/domains/subjectSelect/components/ASubjectSelect.js.map +1 -1
  534. package/dist/domains/subjectSelect/components/ASubjectSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  535. package/dist/domains/subjectSelect/composables/useSubjectSelect.js +53 -51
  536. package/dist/domains/subjectSelect/composables/useSubjectSelect.js.map +1 -1
  537. package/dist/domains/system/appShell/components/AActionbar.vue.d.ts +7 -5
  538. package/dist/domains/system/appShell/components/ALayoutSwitch.js.map +1 -1
  539. package/dist/domains/system/appShell/components/ALayoutSwitch.vue.d.ts +7 -5
  540. package/dist/domains/system/appShell/components/ALayoutSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  541. package/dist/domains/system/appShell/composables/teleportSlot.d.ts +0 -1
  542. package/dist/domains/system/appShell/composables/teleportSlot.js.map +1 -1
  543. package/dist/domains/system/components/AAlerts.js.map +1 -1
  544. package/dist/domains/system/components/AAlerts.vue_vue_type_script_setup_true_lang.js.map +1 -1
  545. package/dist/domains/system/composables/alerts.js.map +1 -1
  546. package/dist/domains/system/composables/breadcrumbs.d.ts +3 -3
  547. package/dist/domains/system/composables/breadcrumbs.js.map +1 -1
  548. package/dist/domains/system/composables/languageSettings.js.map +1 -1
  549. package/dist/domains/system/composables/loginStatus.js.map +1 -1
  550. package/dist/domains/system/composables/navigationError.d.ts +6 -8
  551. package/dist/domains/system/composables/navigationError.js.map +1 -1
  552. package/dist/domains/system/composables/pageNavigation.d.ts +9 -10
  553. package/dist/domains/system/composables/pageNavigation.js.map +1 -1
  554. package/dist/domains/system/composables/recordActions.d.ts +14 -22
  555. package/dist/domains/system/composables/recordActions.js.map +1 -1
  556. package/dist/domains/system/composables/recordPage.d.ts +23 -38
  557. package/dist/domains/system/composables/recordPage.js.map +1 -1
  558. package/dist/domains/system/composables/routeHistory.d.ts +4 -5
  559. package/dist/domains/system/composables/routeHistory.js.map +1 -1
  560. package/dist/domains/system/composables/sentry.js.map +1 -1
  561. package/dist/domains/system/composables/useDebugFeatures.d.ts +3 -6
  562. package/dist/domains/system/composables/useDebugFeatures.js.map +1 -1
  563. package/dist/domains/system/store/datatablePageStore.d.ts +8 -1
  564. package/dist/domains/system/store/datatablePageStore.js +10 -3
  565. package/dist/domains/system/store/datatablePageStore.js.map +1 -1
  566. package/dist/domains/system/systemBar/components/ASystemBar.js.map +1 -1
  567. package/dist/domains/system/systemBar/components/ASystemBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  568. package/dist/domains/system/systemBar/utils/appReload.d.ts +5 -5
  569. package/dist/domains/system/systemBar/utils/appReload.js.map +1 -1
  570. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.js.map +1 -1
  571. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.vue.d.ts +2 -3
  572. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.vue_vue_type_script_setup_true_lang.js.map +1 -1
  573. package/dist/domains/ui/buttons/action/components/AActionDeleteButton.js.map +1 -1
  574. package/dist/domains/ui/buttons/action/components/AActionDeleteButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  575. package/dist/domains/ui/buttons/components/ABtnSplit.vue.d.ts +9 -7
  576. package/dist/domains/ui/components/AAvatarColorPicker.js.map +1 -1
  577. package/dist/domains/ui/components/AAvatarColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  578. package/dist/domains/ui/components/ACard.js.map +1 -1
  579. package/dist/domains/ui/components/ACard.vue.d.ts +7 -3
  580. package/dist/domains/ui/components/ACard.vue_vue_type_script_setup_true_lang.js +6 -2
  581. package/dist/domains/ui/components/ACard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  582. package/dist/domains/ui/components/ACardLoader.js.map +1 -1
  583. package/dist/domains/ui/components/ACardLoader.vue.d.ts +1 -0
  584. package/dist/domains/ui/components/ACardLoader.vue_vue_type_script_setup_true_lang.js +13 -7
  585. package/dist/domains/ui/components/ACardLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  586. package/dist/domains/ui/components/AChipNoLink.vue.d.ts +5 -3
  587. package/dist/domains/ui/components/ACopyText.vue.d.ts +9 -7
  588. package/dist/domains/ui/components/ACreateDialog.js.map +1 -1
  589. package/dist/domains/ui/components/ACreateDialog.vue.d.ts +11 -9
  590. package/dist/domains/ui/components/ACreateDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  591. package/dist/domains/ui/components/ADialogToolbar.vue.d.ts +5 -3
  592. package/dist/domains/ui/components/ARow.vue.d.ts +5 -3
  593. package/dist/domains/ui/components/ATimeTrackingFields.js.map +1 -1
  594. package/dist/domains/ui/components/ATimeTrackingFields.vue_vue_type_script_setup_true_lang.js.map +1 -1
  595. package/dist/domains/ui/components/AUserAndTimeTrackingFields.js.map +1 -1
  596. package/dist/domains/ui/components/AUserAndTimeTrackingFields.vue.d.ts +3 -5
  597. package/dist/domains/ui/components/AUserAndTimeTrackingFields.vue_vue_type_script_setup_true_lang.js.map +1 -1
  598. package/dist/domains/ui/datetime/components/ADatetimePicker.js +1 -1
  599. package/dist/domains/ui/datetime/components/ADatetimePicker.js.map +1 -1
  600. package/dist/domains/ui/datetime/components/ADatetimePicker.vue.d.ts +5 -3
  601. package/dist/domains/ui/datetime/components/ADatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  602. package/dist/domains/ui/file/components/AFileDropzone.js.map +1 -1
  603. package/dist/domains/ui/file/components/AFileDropzone.vue.d.ts +1 -1
  604. package/dist/domains/ui/file/components/AFileDropzone.vue_vue_type_script_setup_true_lang.js.map +1 -1
  605. package/dist/domains/ui/file/components/AFileInput.js.map +1 -1
  606. package/dist/domains/ui/file/components/AFileInput.vue.d.ts +9 -7
  607. package/dist/domains/ui/file/components/AFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  608. package/dist/domains/ui/file/components/AFileInputDialog.js.map +1 -1
  609. package/dist/domains/ui/file/components/AFileInputDialog.vue.d.ts +9 -7
  610. package/dist/domains/ui/file/components/AFileInputDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  611. package/dist/domains/ui/file/composables/dropzone.js.map +1 -1
  612. package/dist/domains/ui/file/composables/formatAndSizeCheck.js.map +1 -1
  613. package/dist/domains/ui/view/components/AGenericView.vue.d.ts +7 -5
  614. package/dist/domains/ui/view/components/ALoginView.js +1 -1
  615. package/dist/domains/ui/view/components/ALoginView.js.map +1 -1
  616. package/dist/domains/ui/view/components/ALoginView.vue.d.ts +5 -3
  617. package/dist/domains/ui/view/components/ALoginView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  618. package/dist/domains/ui/view/components/ALogoutView.js.map +1 -1
  619. package/dist/domains/ui/view/components/ALogoutView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  620. package/dist/domains/ui/view/components/ANotFoundView.js.map +1 -1
  621. package/dist/domains/ui/view/components/ANotFoundView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  622. package/dist/domains/unsavedGuard/composables/useUnsavedChangesGuard.d.ts +6 -7
  623. package/dist/domains/unsavedGuard/composables/useUnsavedChangesGuard.js.map +1 -1
  624. package/dist/lib.d.ts +2 -2
  625. package/dist/plugins/commonVuetifyConfig.d.ts +3 -3
  626. package/dist/plugins/commonVuetifyConfig.js.map +1 -1
  627. package/dist/plugins/i18n.d.ts +4 -5
  628. package/dist/plugins/i18n.js.map +1 -1
  629. package/dist/plugins/pluginOptions.d.ts +4 -2
  630. package/dist/plugins/pluginOptions.js.map +1 -1
  631. package/dist/plugins/webfontloader.js.map +1 -1
  632. package/dist/shared/error/AnzuApiCancelledError.d.ts +5 -8
  633. package/dist/shared/error/AnzuApiCancelledError.js.map +1 -1
  634. package/dist/shared/error/AnzuError.d.ts +3 -5
  635. package/dist/shared/error/AnzuError.js.map +1 -1
  636. package/dist/shared/error/AuthUnavailableError.d.ts +3 -3
  637. package/dist/shared/error/AuthUnavailableError.js.map +1 -1
  638. package/dist/shared/error/isInCauseChain.d.ts +2 -2
  639. package/dist/shared/error/isInCauseChain.js.map +1 -1
  640. package/dist/shared/types/UserAndTimeTracking.d.ts +5 -5
  641. package/dist/shared/types/Validation.d.ts +4 -5
  642. package/dist/shared/types/common.d.ts +1 -3
  643. package/dist/shared/types/globalComponents.d.ts +5 -6
  644. package/dist/shared/utils/common.js.map +1 -1
  645. package/dist/shared/utils/datetime.d.ts +0 -1
  646. package/dist/shared/utils/datetime.js.map +1 -1
  647. package/dist/shared/utils/datetimePickerValue.d.ts +4 -7
  648. package/dist/shared/utils/datetimePickerValue.js.map +1 -1
  649. package/dist/shared/utils/development.d.ts +3 -3
  650. package/dist/shared/utils/development.js.map +1 -1
  651. package/dist/shared/utils/envConfig.d.ts +4 -4
  652. package/dist/shared/utils/envConfig.js.map +1 -1
  653. package/dist/shared/utils/json.d.ts +1 -1
  654. package/dist/shared/utils/json.js.map +1 -1
  655. package/dist/shared/utils/userAndTimeTracking.d.ts +5 -7
  656. package/dist/shared/utils/userAndTimeTracking.js.map +1 -1
  657. package/dist/shared/validators/vuelidate/common/useValidateHexColor.d.ts +3 -5
  658. package/dist/shared/validators/vuelidate/common/useValidateHexColor.js.map +1 -1
  659. package/dist/testing/appShell.d.ts +11 -11
  660. package/dist/testing/appShell.js.map +1 -1
  661. package/dist/testing/closeButtons.d.ts +9 -11
  662. package/dist/testing/closeButtons.js.map +1 -1
  663. package/dist/testing/declaredDependencies.d.ts +7 -7
  664. package/dist/testing/declaredDependencies.js.map +1 -1
  665. package/dist/testing/generatedRoutes.d.ts +6 -11
  666. package/dist/testing/generatedRoutes.js.map +1 -1
  667. package/dist/testing/routeHistory.d.ts +5 -12
  668. package/dist/testing/routeHistory.js.map +1 -1
  669. package/dist/testing/sortableLists.d.ts +16 -21
  670. package/dist/testing/sortableLists.js.map +1 -1
  671. package/dist/testing/typedRouter.d.ts +0 -1
  672. package/dist/testing/typedRouter.js.map +1 -1
  673. package/package.json +39 -29
  674. package/src/e2e/conventions.d.mts +4 -0
  675. package/src/e2e/conventions.mjs +15 -0
  676. package/src/e2e/index.d.mts +8 -0
  677. package/src/e2e/index.mjs +1 -0
  678. package/src/e2e/routeWalk.d.mts +43 -0
  679. package/src/e2e/routeWalk.mjs +606 -0
  680. package/src/e2e/types.d.mts +161 -0
  681. package/src/eslint/adminConfig.mjs +19 -27
  682. package/src/eslint/globalComponentNames.mjs +3 -4
  683. package/src/eslint/oxlint.mjs +7 -20
  684. package/src/eslint/plugin.d.mts +2 -4
  685. package/src/eslint/plugin.mjs +18 -34
  686. package/src/eslint/validRouteName.mjs +6 -7
  687. package/src/vite/devWatch.mjs +30 -43
  688. package/src/vite/index.d.mts +5 -5
  689. package/src/vite/sentry.mjs +7 -12
  690. package/src/vite/sourcemaps.mjs +4 -8
@@ -2,87 +2,60 @@ import { AnzuError } from '../../../shared/error/AnzuError';
2
2
  export type ApiErrorContext = {
3
3
  system: string;
4
4
  entity: string;
5
- /** The url actually requested, parameters substituted and query included -- not the template. */
5
+ /** The url actually requested, with parameters substituted and query included. Not the template. */
6
6
  url?: string;
7
7
  /**
8
- * The status the backend answered with, when it answered at all. Absent for a transport failure,
9
- * where there is no response.
10
- *
11
- * It is here so an application can decide what is worth writing down without the call sites having
12
- * to: a 404 that a caller probes for, for instance. Those used to be silenced per call, which made
13
- * whether a failure was recorded depend on which call made it. The switch is the application's now,
14
- * and this is what it needs to use it.
15
- *
16
- * Two statuses are not the application's to decide, and the library keeps them: 401 and 403. They
17
- * are not an endpoint failing its contract, they are the session -- nobody is logged in, or this
18
- * user may not -- and every admin in the fleet already branches on them and acts. Everything else
19
- * reaches the logger and is filtered here, on this field.
8
+ * The status the backend answered with. Absent for a transport failure.
9
+ * The application's logger uses it to decide what to record, for example a 404 that a caller probes for.
10
+ * The library itself handles 401 and 403, because they concern the
11
+ * session and not the endpoint. Every other status reaches the logger.
20
12
  */
21
13
  status?: number;
22
14
  /**
23
- * The i18n scope a field-level validation failure is reported under, when it is not the same as
24
- * the backend above.
25
- *
26
- * `AnzuApiValidationError` turns the server's field names into `<system>.<entity>.model.<field>`
27
- * translation keys. For a component shared by nine backends those two are different questions:
28
- * *which* backend failed -- which is what the report needs -- and *whose labels* name its fields,
29
- * which for a shared form is always the library's own `common.*`. Left unset, the two stay one
30
- * value, exactly as before.
15
+ * The i18n scope for field-level validation errors, when it differs from the backend above.
16
+ * `AnzuApiValidationError` builds `<system>.<entity>.model.<field>` translation keys. A component
17
+ * shared by several backends reports which backend failed but uses the library's `common.*` labels.
18
+ * If unset, the backend value is used.
31
19
  */
32
20
  validationSystem?: string;
33
21
  validationEntity?: string;
34
22
  };
35
23
  export type ApiErrorLogger = (error: Error, context: ApiErrorContext) => void;
36
24
  /**
37
- * What the user probe calls itself in the error context.
38
- *
39
- * A 404 here is an answer, not a failure -- it is how a system says "no account of yours". The
40
- * default logger skips it; an app's own logger still receives it, so it filters on this together
41
- * with the status rather than on the url, which would also silence a real detail read of the same
42
- * path. The validation scope stays the user's, so a field error would still name a real label.
43
- * Defined here, not beside the probe, so the default logger can know it without an import cycle.
25
+ * Entity name of the user probe in the error context.
26
+ * A 404 from the probe means the user has no account, so the default logger skips it. App loggers
27
+ * should filter on this and the status, not the url, which would also silence a real detail read.
28
+ * The validation scope stays the user's, so field errors still resolve real labels.
29
+ * Defined here to avoid an import cycle with the default logger.
44
30
  */
45
31
  export declare const USER_PROBE_ENTITY = "anzuUserProbe";
46
- /** What reporting does until an application says otherwise; exported so a test can put it back. */
32
+ /** Default error reporting. Exported so tests can restore it. */
47
33
  export declare const defaultApiErrorLogger: ApiErrorLogger;
48
34
  /**
49
- * Replaces the logger the api helpers report unexpected failures through, or turns reporting off
50
- * with `null`.
51
- *
52
- * It is one switch for the whole family rather than a flag on each instance, which is what it
53
- * replaces: whether a failure was written down used to depend on which helper made the call and how
54
- * that instance happened to be constructed.
55
- *
56
- * An application that wants these where it can see them passes its own:
57
- * `setApiErrorLogger((e, ctx) => Sentry.captureException(e, { extra: ctx }))`.
35
+ * Replaces the logger the api helpers report unexpected failures through. `null` turns reporting off.
36
+ * One global switch for all helpers, so reporting does not depend on which helper made the call.
37
+ * @example setApiErrorLogger((e, ctx) => Sentry.captureException(e, { extra: ctx }))
58
38
  */
59
39
  export declare const setApiErrorLogger: (fn: ApiErrorLogger | null) => void;
60
40
  /**
61
- * The HTTP status the backend answered with, read off whichever class carries it: the axios response
62
- * of an `AnzuApiAxiosError`, or the `code` of an `AnzuApiResponseCodeError` (a response axios let
63
- * through). `undefined` when nothing answered -- a timeout, a network failure, a cancel.
41
+ * HTTP status from the axios response of `AnzuApiAxiosError` or the `code` of `AnzuApiResponseCodeError`.
42
+ * `undefined` when nothing answered: timeout, network failure, cancel.
64
43
  */
65
44
  export declare const apiErrorStatus: (error: unknown) => number | undefined;
66
45
  /**
67
- * Whether `report` hands this error, once mapped, to the logger: not a timeout, a 401 or a 403, nor
68
- * anything while reporting is off. For a caller that reports only the first failure of a series: a
69
- * failure dropped here has told nobody, and the series begins with the first one that was written.
70
- * What the application's own logger does with it is the application's.
46
+ * Whether `report` passes this error to the logger. False for a timeout, 401, 403, or while reporting is off.
47
+ * Lets a caller that reports only the first failure of a series start the series at the first logged one.
71
48
  */
72
49
  export declare const apiErrorIsReported: (error: unknown) => boolean;
73
50
  /**
74
- * Reports an error once, after it has been mapped, and hands it back so the caller can throw it.
75
- *
76
- * After, not during: an error the helper raised itself -- a body that never arrived, a status it
77
- * refuses -- is already an `Anzu*` class by the time it reaches the mapping, so a logger placed
78
- * inside the mapping would never see the two cases it exists for.
51
+ * Reports a mapped error once and returns it so the caller can throw it.
52
+ * Runs after mapping because errors the helper raises itself are
53
+ * already `Anzu*` classes and would bypass a logger inside the mapping.
79
54
  */
80
55
  export declare const report: <E>(error: E, context: ApiErrorContext) => E;
81
56
  /**
82
- * Turns whatever axios rejected with into one of the Anzu error classes.
83
- *
84
- * There used to be a copy of this inside each helper. The order of the checks is what decides which
85
- * class a failure becomes, so four copies were four chances for the same failure to arrive under
86
- * different names depending on which helper made the call.
57
+ * Turns whatever axios rejected with into an Anzu error class.
58
+ * Shared by all helpers. The order of checks decides the class,
59
+ * so separate copies would map the same failure differently.
87
60
  */
88
61
  export declare const mapApiError: (err: unknown, context: ApiErrorContext) => AnzuError;
@@ -1 +1 @@
1
- {"version":3,"file":"apiErrors.js","names":["axios","USER_PROBE_ENTITY","defaultApiErrorLogger","context","error","logger","setApiErrorLogger","fn","LOGGED","AnzuApiAxiosError","AnzuFatalError","AnzuApiResponseCodeError","apiErrorStatus","apiErrorIsReported","status","isInCauseChain","cause","SessionExpiredError","cls","report","mapApiError","labelSystem","system","labelEntity","entity","err","axiosError","isAnzuError","axiosErrorIsCancelled","AnzuApiCancelledError","axiosErrorResponseIsForbidden","AnzuApiForbiddenError","axiosErrorResponseHasValidationData","AnzuApiValidationError","axiosErrorResponseHasDependencyExistsData","AnzuApiDependencyExistsError","axiosErrorResponseHasForbiddenOperationData","AnzuApiForbiddenOperationError","axiosErrorIsTimeout","AnzuApiTimeoutError"],"sources":["../../../../src/domains/api/utils/apiErrors.ts"],"sourcesContent":["import axios, { type AxiosError } from 'axios'\nimport { AnzuApiAxiosError } from '@/shared/error/AnzuApiAxiosError'\nimport { AnzuApiCancelledError, axiosErrorIsCancelled } from '@/shared/error/AnzuApiCancelledError'\nimport {\n AnzuApiDependencyExistsError,\n axiosErrorResponseHasDependencyExistsData,\n} from '@/shared/error/AnzuApiDependencyExistsError'\nimport { AnzuApiForbiddenError, axiosErrorResponseIsForbidden } from '@/shared/error/AnzuApiForbiddenError'\nimport {\n AnzuApiForbiddenOperationError,\n axiosErrorResponseHasForbiddenOperationData,\n} from '@/shared/error/AnzuApiForbiddenOperationError'\nimport { AnzuApiResponseCodeError } from '@/shared/error/AnzuApiResponseCodeError'\nimport { AnzuApiTimeoutError, axiosErrorIsTimeout } from '@/shared/error/AnzuApiTimeoutError'\nimport { AnzuApiValidationError, axiosErrorResponseHasValidationData } from '@/shared/error/AnzuApiValidationError'\nimport { AnzuError, isAnzuError } from '@/shared/error/AnzuError'\nimport { AnzuFatalError } from '@/shared/error/AnzuFatalError'\nimport { HTTP_STATUS_FORBIDDEN, HTTP_STATUS_UNAUTHORIZED } from '@/shared/statusCodes'\nimport { SessionExpiredError } from '@/shared/error/SessionExpiredError'\nimport { isInCauseChain } from '@/shared/error/isInCauseChain'\n\nexport type ApiErrorContext = {\n system: string\n entity: string\n /** The url actually requested, parameters substituted and query included -- not the template. */\n url?: string\n /**\n * The status the backend answered with, when it answered at all. Absent for a transport failure,\n * where there is no response.\n *\n * It is here so an application can decide what is worth writing down without the call sites having\n * to: a 404 that a caller probes for, for instance. Those used to be silenced per call, which made\n * whether a failure was recorded depend on which call made it. The switch is the application's now,\n * and this is what it needs to use it.\n *\n * Two statuses are not the application's to decide, and the library keeps them: 401 and 403. They\n * are not an endpoint failing its contract, they are the session -- nobody is logged in, or this\n * user may not -- and every admin in the fleet already branches on them and acts. Everything else\n * reaches the logger and is filtered here, on this field.\n */\n status?: number\n /**\n * The i18n scope a field-level validation failure is reported under, when it is not the same as\n * the backend above.\n *\n * `AnzuApiValidationError` turns the server's field names into `<system>.<entity>.model.<field>`\n * translation keys. For a component shared by nine backends those two are different questions:\n * *which* backend failed -- which is what the report needs -- and *whose labels* name its fields,\n * which for a shared form is always the library's own `common.*`. Left unset, the two stay one\n * value, exactly as before.\n */\n validationSystem?: string\n validationEntity?: string\n}\n\nexport type ApiErrorLogger = (error: Error, context: ApiErrorContext) => void\n\n/**\n * What the user probe calls itself in the error context.\n *\n * A 404 here is an answer, not a failure -- it is how a system says \"no account of yours\". The\n * default logger skips it; an app's own logger still receives it, so it filters on this together\n * with the status rather than on the url, which would also silence a real detail read of the same\n * path. The validation scope stays the user's, so a field error would still name a real label.\n * Defined here, not beside the probe, so the default logger can know it without an import cycle.\n */\nexport const USER_PROBE_ENTITY = 'anzuUserProbe'\n\n/** What reporting does until an application says otherwise; exported so a test can put it back. */\nexport const defaultApiErrorLogger: ApiErrorLogger = (error, context) => {\n if (context.status === 404 && context.entity === USER_PROBE_ENTITY) return\n console.error('Api error: ' + (context.url ?? ''), error)\n}\n\nlet logger: ApiErrorLogger | null = defaultApiErrorLogger\n\n/**\n * Replaces the logger the api helpers report unexpected failures through, or turns reporting off\n * with `null`.\n *\n * It is one switch for the whole family rather than a flag on each instance, which is what it\n * replaces: whether a failure was written down used to depend on which helper made the call and how\n * that instance happened to be constructed.\n *\n * An application that wants these where it can see them passes its own:\n * `setApiErrorLogger((e, ctx) => Sentry.captureException(e, { extra: ctx }))`.\n */\nexport const setApiErrorLogger = (fn: ApiErrorLogger | null): void => {\n logger = fn\n}\n\n// Only the failures nobody planned for. A validation or forbidden answer is the backend saying\n// something the caller asked about and will show; writing those down as well would be noise that\n// teaches people to ignore the log.\nconst LOGGED = [AnzuApiAxiosError, AnzuFatalError, AnzuApiResponseCodeError]\n\n/**\n * The HTTP status the backend answered with, read off whichever class carries it: the axios response\n * of an `AnzuApiAxiosError`, or the `code` of an `AnzuApiResponseCodeError` (a response axios let\n * through). `undefined` when nothing answered -- a timeout, a network failure, a cancel.\n */\nexport const apiErrorStatus = (error: unknown): number | undefined => {\n if (error instanceof AnzuApiResponseCodeError) return error.code\n if (error instanceof AnzuApiAxiosError) return error.cause.response?.status\n\n return undefined\n}\n\n/**\n * Whether `report` hands this error, once mapped, to the logger: not a timeout, a 401 or a 403, nor\n * anything while reporting is off. For a caller that reports only the first failure of a series: a\n * failure dropped here has told nobody, and the series begins with the first one that was written.\n * What the application's own logger does with it is the application's.\n */\nexport const apiErrorIsReported = (error: unknown): boolean => {\n const status = apiErrorStatus(error)\n // Neither of these is an unplanned failure. A 401 is \"nobody is logged in\", which every admin\n // branches on before sending the user to the login page -- writing it down would mean an \"Api\n // error\" for every unauthenticated start of the app. A 403 is \"this user may not\", which the\n // caller shows. Both are the session rather than an endpoint breaking its contract.\n //\n // By status rather than by class, because the class only keeps it quiet on one of the two paths: a\n // rejected 403 becomes `AnzuApiForbiddenError`, which is outside `LOGGED`, while one that arrives\n // fulfilled -- as `options.validateStatus` allows -- becomes an `AnzuApiResponseCodeError`, which\n // is inside it. Left to the class, the policy would hold or not depending on how the caller\n // configured axios.\n //\n // It is the one thing the `status` field above does not leave to the application, and deliberately:\n // an app that wanted its own unauthenticated starts in the log would be asking for noise it cannot\n // act on, while an app that wants 404 or 409 filtered has the field to do it with.\n if (status === HTTP_STATUS_UNAUTHORIZED || status === HTTP_STATUS_FORBIDDEN) return false\n // The same as a 401, stopped before it went out: the refresh found the session gone.\n if (isInCauseChain(error, (cause) => cause instanceof SessionExpiredError)) return false\n\n return logger !== null && LOGGED.some((cls) => error instanceof cls)\n}\n\n/**\n * Reports an error once, after it has been mapped, and hands it back so the caller can throw it.\n *\n * After, not during: an error the helper raised itself -- a body that never arrived, a status it\n * refuses -- is already an `Anzu*` class by the time it reaches the mapping, so a logger placed\n * inside the mapping would never see the two cases it exists for.\n */\nexport const report = <E>(error: E, context: ApiErrorContext): E => {\n if (logger !== null && apiErrorIsReported(error)) {\n try {\n // Filled in here rather than by the caller: the status belongs to the failure, and only the\n // mapped error knows it -- the helper that built the context has not looked at the error yet.\n logger(error as unknown as Error, { ...context, status: apiErrorStatus(error) })\n } catch {\n // A logger that throws must not replace the failure the caller is waiting for.\n }\n }\n\n return error\n}\n\n/**\n * Turns whatever axios rejected with into one of the Anzu error classes.\n *\n * There used to be a copy of this inside each helper. The order of the checks is what decides which\n * class a failure becomes, so four copies were four chances for the same failure to arrive under\n * different names depending on which helper made the call.\n */\nexport const mapApiError = (err: unknown, context: ApiErrorContext): AnzuError => {\n const { system, entity } = context\n const labelSystem = context.validationSystem ?? system\n const labelEntity = context.validationEntity ?? entity\n // The predicates below are typed against `Error` / `AxiosError` and each begins by checking what\n // it was handed, so narrowing here only satisfies their signatures.\n const error = err as Error\n const axiosError = err as AxiosError\n\n // Already mapped -- including the errors a helper raised about its own contract. Wrapping it again\n // would bury the class the caller branches on.\n if (isAnzuError(err)) return err\n\n // Before everything else, because it is not a failure: the caller stopped this request.\n if (axiosErrorIsCancelled(err)) return new AnzuApiCancelledError(error)\n\n // The rendered url, not `config.url`: that one is relative, carries no params, and would become\n // this error's `message` -- the only url in the family that never went through `requestedUrl`.\n if (axiosErrorResponseIsForbidden(axiosError)) return new AnzuApiForbiddenError(axiosError, context.url)\n\n if (axiosErrorResponseHasValidationData(axiosError)) {\n return new AnzuApiValidationError(axiosError, labelSystem, labelEntity, error)\n }\n\n if (axiosErrorResponseHasDependencyExistsData(axiosError)) {\n return new AnzuApiDependencyExistsError(axiosError, labelSystem, labelEntity, error)\n }\n\n if (axiosErrorResponseHasForbiddenOperationData(axiosError)) {\n return new AnzuApiForbiddenOperationError(axiosError, error)\n }\n\n if (axiosErrorIsTimeout(error)) return new AnzuApiTimeoutError(error)\n\n if (axios.isAxiosError(err)) return new AnzuApiAxiosError(axiosError)\n\n return new AnzuFatalError(error)\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkEA,IAAaC,IAAoB,iBAGpBC,KAAyC,GAAO,MAAY;CACvE,CAAIC,EAAQ,WAAW,OAAOA,EAAQ,WAAA,oBACtC,QAAQ,MAAM,iBAAiBA,EAAQ,OAAO,KAAKC,CAAK;AAC1D,GAEIC,IAAgCH,GAavBI,KAAqB,MAAoC;CACpE,IAASC;AACX,GAKMC,IAAS;CAACC;CAAmBC;CAAgBC;AAAwB,GAO9DC,KAAkB,MAAuC;CACpE,IAAIR,aAAiBO,GAA0B,OAAOP,EAAM;CAC5D,IAAIA,aAAiBK,GAAmB,OAAOL,EAAM,MAAM,UAAU;AAGvE,GAQaS,KAAsB,MAA4B;CAC7D,IAAMC,IAASF,EAAeR,CAAK;CAmBnC,OAJIU,MAAA,OAAuCA,MAAA,OAEvCC,EAAeX,IAAQ,MAAUY,aAAiBC,CAAmB,IAAU,KAE5EZ,MAAW,QAAQG,EAAO,MAAM,MAAQJ,aAAiBc,CAAG;AACrE,GASaC,KAAa,GAAU,MAAgC;CAClE,IAAId,MAAW,QAAQQ,EAAmBT,CAAK,GAC7C,IAAI;EAGF,EAAOA,GAA2B;GAAE,GAAGD;GAAS,QAAQS,EAAeR,CAAK;EAAE,CAAC;CACjF,QAAQ,CAER;CAGF,OAAOA;AACT,GASagB,KAAe,GAAc,MAAwC;CAChF,IAAM,EAAE,WAAQ,cAAWjB,GACrBkB,IAAclB,EAAQ,oBAAoBmB,GAC1CC,IAAcpB,EAAQ,oBAAoBqB,GAG1CpB,IAAQqB,GACRC,IAAaD;CA6BnB,OAzBIE,EAAYF,CAAG,IAAUA,IAGzBG,EAAsBH,CAAG,IAAU,IAAII,EAAsBzB,CAAK,IAIlE0B,EAA8BJ,CAAU,IAAU,IAAIK,EAAsBL,GAAYvB,EAAQ,GAAG,IAEnG6B,EAAoCN,CAAU,IACzC,IAAIO,EAAuBP,GAAYL,GAAaE,GAAanB,CAAK,IAG3E8B,EAA0CR,CAAU,IAC/C,IAAIS,EAA6BT,GAAYL,GAAaE,GAAanB,CAAK,IAGjFgC,EAA4CV,CAAU,IACjD,IAAIW,EAA+BX,GAAYtB,CAAK,IAGzDkC,EAAoBlC,CAAK,IAAU,IAAImC,EAAoBnC,CAAK,IAEhEJ,EAAM,aAAayB,CAAG,IAAU,IAAIhB,EAAkBiB,CAAU,IAE7D,IAAIhB,EAAeN,CAAK;AACjC"}
1
+ {"version":3,"file":"apiErrors.js","names":["axios","USER_PROBE_ENTITY","defaultApiErrorLogger","context","error","logger","setApiErrorLogger","fn","LOGGED","AnzuApiAxiosError","AnzuFatalError","AnzuApiResponseCodeError","apiErrorStatus","apiErrorIsReported","status","isInCauseChain","cause","SessionExpiredError","cls","report","mapApiError","labelSystem","system","labelEntity","entity","err","axiosError","isAnzuError","axiosErrorIsCancelled","AnzuApiCancelledError","axiosErrorResponseIsForbidden","AnzuApiForbiddenError","axiosErrorResponseHasValidationData","AnzuApiValidationError","axiosErrorResponseHasDependencyExistsData","AnzuApiDependencyExistsError","axiosErrorResponseHasForbiddenOperationData","AnzuApiForbiddenOperationError","axiosErrorIsTimeout","AnzuApiTimeoutError"],"sources":["../../../../src/domains/api/utils/apiErrors.ts"],"sourcesContent":["import axios, { type AxiosError } from 'axios'\nimport { AnzuApiAxiosError } from '@/shared/error/AnzuApiAxiosError'\nimport { AnzuApiCancelledError, axiosErrorIsCancelled } from '@/shared/error/AnzuApiCancelledError'\nimport {\n AnzuApiDependencyExistsError,\n axiosErrorResponseHasDependencyExistsData,\n} from '@/shared/error/AnzuApiDependencyExistsError'\nimport { AnzuApiForbiddenError, axiosErrorResponseIsForbidden } from '@/shared/error/AnzuApiForbiddenError'\nimport {\n AnzuApiForbiddenOperationError,\n axiosErrorResponseHasForbiddenOperationData,\n} from '@/shared/error/AnzuApiForbiddenOperationError'\nimport { AnzuApiResponseCodeError } from '@/shared/error/AnzuApiResponseCodeError'\nimport { AnzuApiTimeoutError, axiosErrorIsTimeout } from '@/shared/error/AnzuApiTimeoutError'\nimport { AnzuApiValidationError, axiosErrorResponseHasValidationData } from '@/shared/error/AnzuApiValidationError'\nimport { AnzuError, isAnzuError } from '@/shared/error/AnzuError'\nimport { AnzuFatalError } from '@/shared/error/AnzuFatalError'\nimport { HTTP_STATUS_FORBIDDEN, HTTP_STATUS_UNAUTHORIZED } from '@/shared/statusCodes'\nimport { SessionExpiredError } from '@/shared/error/SessionExpiredError'\nimport { isInCauseChain } from '@/shared/error/isInCauseChain'\n\nexport type ApiErrorContext = {\n system: string\n entity: string\n /** The url actually requested, with parameters substituted and query included. Not the template. */\n url?: string\n /**\n * The status the backend answered with. Absent for a transport failure.\n * The application's logger uses it to decide what to record, for example a 404 that a caller probes for.\n * The library itself handles 401 and 403, because they concern the\n * session and not the endpoint. Every other status reaches the logger.\n */\n status?: number\n /**\n * The i18n scope for field-level validation errors, when it differs from the backend above.\n * `AnzuApiValidationError` builds `<system>.<entity>.model.<field>` translation keys. A component\n * shared by several backends reports which backend failed but uses the library's `common.*` labels.\n * If unset, the backend value is used.\n */\n validationSystem?: string\n validationEntity?: string\n}\n\nexport type ApiErrorLogger = (error: Error, context: ApiErrorContext) => void\n\n/**\n * Entity name of the user probe in the error context.\n * A 404 from the probe means the user has no account, so the default logger skips it. App loggers\n * should filter on this and the status, not the url, which would also silence a real detail read.\n * The validation scope stays the user's, so field errors still resolve real labels.\n * Defined here to avoid an import cycle with the default logger.\n */\nexport const USER_PROBE_ENTITY = 'anzuUserProbe'\n\n/** Default error reporting. Exported so tests can restore it. */\nexport const defaultApiErrorLogger: ApiErrorLogger = (error, context) => {\n if (context.status === 404 && context.entity === USER_PROBE_ENTITY) return\n console.error('Api error: ' + (context.url ?? ''), error)\n}\n\nlet logger: ApiErrorLogger | null = defaultApiErrorLogger\n\n/**\n * Replaces the logger the api helpers report unexpected failures through. `null` turns reporting off.\n * One global switch for all helpers, so reporting does not depend on which helper made the call.\n * @example setApiErrorLogger((e, ctx) => Sentry.captureException(e, { extra: ctx }))\n */\nexport const setApiErrorLogger = (fn: ApiErrorLogger | null): void => {\n logger = fn\n}\n\n// Only unplanned failures. Validation and forbidden errors are shown to the user by the caller.\n// Logging them too would be noise.\nconst LOGGED = [AnzuApiAxiosError, AnzuFatalError, AnzuApiResponseCodeError]\n\n/**\n * HTTP status from the axios response of `AnzuApiAxiosError` or the `code` of `AnzuApiResponseCodeError`.\n * `undefined` when nothing answered: timeout, network failure, cancel.\n */\nexport const apiErrorStatus = (error: unknown): number | undefined => {\n if (error instanceof AnzuApiResponseCodeError) return error.code\n if (error instanceof AnzuApiAxiosError) return error.cause.response?.status\n\n return undefined\n}\n\n/**\n * Whether `report` passes this error to the logger. False for a timeout, 401, 403, or while reporting is off.\n * Lets a caller that reports only the first failure of a series start the series at the first logged one.\n */\nexport const apiErrorIsReported = (error: unknown): boolean => {\n const status = apiErrorStatus(error)\n // 401 and 403 are session states, not endpoint failures. Every\n // admin checks for 401 on startup, so logging it adds noise.\n // Checked by status, not by class. A rejected 403 becomes `AnzuApiForbiddenError` (not in `LOGGED`).\n // A fulfilled 403 allowed by `options.validateStatus` becomes `AnzuApiResponseCodeError` (in `LOGGED`).\n // This is not configurable on purpose. Apps can filter other statuses like 404 or 409 via the `status` field.\n if (status === HTTP_STATUS_UNAUTHORIZED || status === HTTP_STATUS_FORBIDDEN) return false\n // Same as a 401, caught before the request: the refresh found the session gone.\n if (isInCauseChain(error, (cause) => cause instanceof SessionExpiredError)) return false\n\n return logger !== null && LOGGED.some((cls) => error instanceof cls)\n}\n\n/**\n * Reports a mapped error once and returns it so the caller can throw it.\n * Runs after mapping because errors the helper raises itself are\n * already `Anzu*` classes and would bypass a logger inside the mapping.\n */\nexport const report = <E>(error: E, context: ApiErrorContext): E => {\n if (logger !== null && apiErrorIsReported(error)) {\n try {\n // Status is added here because only the mapped error knows it.\n // The caller built the context before looking at the error.\n logger(error as unknown as Error, { ...context, status: apiErrorStatus(error) })\n } catch {\n // A logger that throws must not replace the failure the caller is waiting for.\n }\n }\n\n return error\n}\n\n/**\n * Turns whatever axios rejected with into an Anzu error class.\n * Shared by all helpers. The order of checks decides the class,\n * so separate copies would map the same failure differently.\n */\nexport const mapApiError = (err: unknown, context: ApiErrorContext): AnzuError => {\n const { system, entity } = context\n const labelSystem = context.validationSystem ?? system\n const labelEntity = context.validationEntity ?? entity\n // Casts only satisfy the predicate signatures. Each predicate checks its input itself.\n const error = err as Error\n const axiosError = err as AxiosError\n\n // Already mapped, including contract errors raised by a helper.\n // Wrapping again would hide the class the caller branches on.\n if (isAnzuError(err)) return err\n\n // Checked first because a cancelled request is not a failure. The caller stopped it.\n if (axiosErrorIsCancelled(err)) return new AnzuApiCancelledError(error)\n\n // Use the rendered url, not `config.url`. `config.url` is relative and has no params.\n // It would become this error's `message`, unlike every other error that uses `requestedUrl`.\n if (axiosErrorResponseIsForbidden(axiosError)) return new AnzuApiForbiddenError(axiosError, context.url)\n\n if (axiosErrorResponseHasValidationData(axiosError)) {\n return new AnzuApiValidationError(axiosError, labelSystem, labelEntity, error)\n }\n\n if (axiosErrorResponseHasDependencyExistsData(axiosError)) {\n return new AnzuApiDependencyExistsError(axiosError, labelSystem, labelEntity, error)\n }\n\n if (axiosErrorResponseHasForbiddenOperationData(axiosError)) {\n return new AnzuApiForbiddenOperationError(axiosError, error)\n }\n\n if (axiosErrorIsTimeout(error)) return new AnzuApiTimeoutError(error)\n\n if (axios.isAxiosError(err)) return new AnzuApiAxiosError(axiosError)\n\n return new AnzuFatalError(error)\n}\n"],"mappings":";;;;;;;;;;;;;;;AAoDA,IAAaC,IAAoB,iBAGpBC,KAAyC,GAAO,MAAY;CACvE,CAAIC,EAAQ,WAAW,OAAOA,EAAQ,WAAA,oBACtC,QAAQ,MAAM,iBAAiBA,EAAQ,OAAO,KAAKC,CAAK;AAC1D,GAEIC,IAAgCH,GAOvBI,KAAqB,MAAoC;CACpE,IAASC;AACX,GAIMC,IAAS;CAACC;CAAmBC;CAAgBC;AAAwB,GAM9DC,KAAkB,MAAuC;CACpE,IAAIR,aAAiBO,GAA0B,OAAOP,EAAM;CAC5D,IAAIA,aAAiBK,GAAmB,OAAOL,EAAM,MAAM,UAAU;AAGvE,GAMaS,KAAsB,MAA4B;CAC7D,IAAMC,IAASF,EAAeR,CAAK;CAUnC,OAJIU,MAAA,OAAuCA,MAAA,OAEvCC,EAAeX,IAAQ,MAAUY,aAAiBC,CAAmB,IAAU,KAE5EZ,MAAW,QAAQG,EAAO,MAAM,MAAQJ,aAAiBc,CAAG;AACrE,GAOaC,KAAa,GAAU,MAAgC;CAClE,IAAId,MAAW,QAAQQ,EAAmBT,CAAK,GAC7C,IAAI;EAGF,EAAOA,GAA2B;GAAE,GAAGD;GAAS,QAAQS,EAAeR,CAAK;EAAE,CAAC;CACjF,QAAQ,CAER;CAGF,OAAOA;AACT,GAOagB,KAAe,GAAc,MAAwC;CAChF,IAAM,EAAE,WAAQ,cAAWjB,GACrBkB,IAAclB,EAAQ,oBAAoBmB,GAC1CC,IAAcpB,EAAQ,oBAAoBqB,GAE1CpB,IAAQqB,GACRC,IAAaD;CA6BnB,OAzBIE,EAAYF,CAAG,IAAUA,IAGzBG,EAAsBH,CAAG,IAAU,IAAII,EAAsBzB,CAAK,IAIlE0B,EAA8BJ,CAAU,IAAU,IAAIK,EAAsBL,GAAYvB,EAAQ,GAAG,IAEnG6B,EAAoCN,CAAU,IACzC,IAAIO,EAAuBP,GAAYL,GAAaE,GAAanB,CAAK,IAG3E8B,EAA0CR,CAAU,IAC/C,IAAIS,EAA6BT,GAAYL,GAAaE,GAAanB,CAAK,IAGjFgC,EAA4CV,CAAU,IACjD,IAAIW,EAA+BX,GAAYtB,CAAK,IAGzDkC,EAAoBlC,CAAK,IAAU,IAAImC,EAAoBnC,CAAK,IAEhEJ,EAAM,aAAayB,CAAG,IAAU,IAAIhB,EAAkBiB,CAAU,IAE7D,IAAIhB,EAAeN,CAAK;AACjC"}
@@ -2,64 +2,43 @@ import { Pagination } from '../composables/pagination';
2
2
  export type ListBody<T> = {
3
3
  items: T[];
4
4
  /**
5
- * Which kind of list answered, read from the response rather than inferred from `pagination`.
6
- *
7
- * They are two different things and conflating them cost a bug: `pagination` is what to write, and
8
- * for an infinite list that includes `totalCount: 0` to clear the counted mode's leftovers -- so a
9
- * reader using `totalCount` to recognise the mode sees a counted list of zero items.
5
+ * Which kind of list answered, read from the response, not inferred from `pagination`.
6
+ * `pagination` is what to write. For an infinite list it includes `totalCount: 0` to clear counted-mode leftovers.
7
+ * So reading the mode from `totalCount` sees a counted list of zero items. This caused a bug.
10
8
  */
11
9
  mode: 'counted' | 'infinite' | 'unknown';
12
10
  /**
13
- * What the response said about the mode it is in, plus the other mode's field cleared: a counted
14
- * body carries `hasNextPage: null` and an infinite one `totalCount: 0`, so a value left over from
15
- * the previous query cannot go on describing this one. A missing or malformed field of the mode's
16
- * own kind is not written at all.
11
+ * The fields the response gave for its mode, plus the other mode's field cleared.
12
+ * A counted body gets `hasNextPage: null`, an infinite one
13
+ * `totalCount: 0`, so values from the previous query do not linger.
14
+ * A missing or malformed field of the mode's own kind is not written.
17
15
  */
18
16
  pagination: Partial<Pagination>;
19
17
  /**
20
18
  * Whether `totalCount` is a bound rather than a count.
21
- *
22
- * The backend's counted envelope carries `bigTable`, and with it on -- which is the default -- the
23
- * count it sends is `offset + limit + 1`: a look-ahead that says "there is at least one more page",
24
- * not how many rows exist. It is corrected to the real total only when the page came back short,
25
- * which is to say only when there was nothing more to look ahead to.
26
- *
27
- * Page-by-page navigation does not care: the sentinel is exactly what it needs to enable Next.
28
- * Anything that treats the number as a total does -- dividing by a page size to learn how many
29
- * pages exist yields 2, whatever the real answer is.
19
+ * With the backend's `bigTable` on (the default), the count is `offset
20
+ * + limit + 1`, a look-ahead meaning "at least one more page".
21
+ * It is the real total only when the page came back short.
22
+ * Fine for Next/Previous navigation. Wrong for anything that computes a page count from it.
30
23
  */
31
24
  countIsBound: boolean;
32
25
  };
33
26
  /**
34
27
  * Reads a list response.
35
- *
36
- * The array is the only thing that decides whether this is a list at all. The existing shape guards
37
- * test for a metadata key and nothing else, so `{ totalCount: 1 }` passed as a list and the caller
38
- * got `undefined` typed as an array.
39
- *
40
- * Metadata only picks the mode, and is optional: a well-formed array is not worth discarding because
41
- * the count beside it is missing or of the wrong type.
42
- *
43
- * `hasNextPage` decides, and only its absence falls through to `totalCount`. It has to be that way
44
- * round, because the backend's infinite envelope carries BOTH: `ApiInfiniteResponseList` serialises
45
- * `hasNextPage`, `data` and `totalCount` (the last marked `@deprecated`, which is a docblock and
46
- * suppresses nothing), while the counted one carries `totalCount`, `data` and `bigTable` and never
47
- * `hasNextPage`. So the presence of `hasNextPage` is the only unambiguous signal, and reading
48
- * `totalCount` first would turn every infinite list in the fleet into a counted one -- with a total
49
- * that is not a total: with `bigTable` on, which is the default, the counted number is a look-ahead
50
- * sentinel, `offset + limit + 1`, and the infinite envelope reports that same sentinel unconditionally.
28
+ * Only the `data` array decides whether this is a list. Older guards checked a metadata
29
+ * key only, so `{ totalCount: 1 }` passed and callers got `undefined` as an array.
30
+ * Metadata only picks the mode and is optional. A valid array is kept even if the count is missing or malformed.
31
+ * `hasNextPage` decides the mode. The infinite envelope also carries a
32
+ * deprecated `totalCount`, and the counted one never has `hasNextPage`.
33
+ * Reading `totalCount` first would make every infinite list counted,
34
+ * with a look-ahead sentinel `offset + limit + 1` as its total.
51
35
  */
52
36
  export declare const readListBody: <T>(body: unknown, status: number, url: string | undefined) => ListBody<T>;
53
37
  /**
54
38
  * Reads a list that arrived as a bare array.
55
- *
56
- * The second of the two shapes a list comes in, and a separate reader rather than one that takes
57
- * either: the caller declares which one this endpoint answers with and the reader refuses the
58
- * other, the way `optionalBody` makes the caller declare a body. One reader accepting both shapes
59
- * is a permissive reader, and a permissive reader is what let a malformed answer through in the
60
- * first place.
61
- *
62
- * Returns `T[]` rather than `ListBody<T>`: `mode: 'unknown'` means the envelope named no mode, and
63
- * here there was no envelope to name one.
39
+ * Separate from `readListBody` on purpose. The caller declares the shape
40
+ * its endpoint returns and the other shape is refused, like `optionalBody`.
41
+ * A reader accepting both shapes would let malformed answers through.
42
+ * Returns `T[]`, not `ListBody<T>`, because there is no envelope to name a mode.
64
43
  */
65
44
  export declare const readArrayBody: <T>(body: unknown, status: number, url: string | undefined) => T[];
@@ -1 +1 @@
1
- {"version":3,"file":"listBody.js","names":["readListBody","isObject","body","AnzuApiResponseCodeError","status","url","isBoolean","hasNextPage","data","isNumber","totalCount","bigTable","readArrayBody"],"sources":["../../../../src/domains/api/utils/listBody.ts"],"sourcesContent":["import { AnzuApiResponseCodeError } from '@/shared/error/AnzuApiResponseCodeError'\nimport { isBoolean, isNumber, isObject } from '@/shared/utils/common'\nimport type { Pagination } from '@/domains/api/composables/pagination'\n\nexport type ListBody<T> = {\n items: T[]\n /**\n * Which kind of list answered, read from the response rather than inferred from `pagination`.\n *\n * They are two different things and conflating them cost a bug: `pagination` is what to write, and\n * for an infinite list that includes `totalCount: 0` to clear the counted mode's leftovers -- so a\n * reader using `totalCount` to recognise the mode sees a counted list of zero items.\n */\n mode: 'counted' | 'infinite' | 'unknown'\n /**\n * What the response said about the mode it is in, plus the other mode's field cleared: a counted\n * body carries `hasNextPage: null` and an infinite one `totalCount: 0`, so a value left over from\n * the previous query cannot go on describing this one. A missing or malformed field of the mode's\n * own kind is not written at all.\n */\n pagination: Partial<Pagination>\n /**\n * Whether `totalCount` is a bound rather than a count.\n *\n * The backend's counted envelope carries `bigTable`, and with it on -- which is the default -- the\n * count it sends is `offset + limit + 1`: a look-ahead that says \"there is at least one more page\",\n * not how many rows exist. It is corrected to the real total only when the page came back short,\n * which is to say only when there was nothing more to look ahead to.\n *\n * Page-by-page navigation does not care: the sentinel is exactly what it needs to enable Next.\n * Anything that treats the number as a total does -- dividing by a page size to learn how many\n * pages exist yields 2, whatever the real answer is.\n */\n countIsBound: boolean\n}\n\n/**\n * Reads a list response.\n *\n * The array is the only thing that decides whether this is a list at all. The existing shape guards\n * test for a metadata key and nothing else, so `{ totalCount: 1 }` passed as a list and the caller\n * got `undefined` typed as an array.\n *\n * Metadata only picks the mode, and is optional: a well-formed array is not worth discarding because\n * the count beside it is missing or of the wrong type.\n *\n * `hasNextPage` decides, and only its absence falls through to `totalCount`. It has to be that way\n * round, because the backend's infinite envelope carries BOTH: `ApiInfiniteResponseList` serialises\n * `hasNextPage`, `data` and `totalCount` (the last marked `@deprecated`, which is a docblock and\n * suppresses nothing), while the counted one carries `totalCount`, `data` and `bigTable` and never\n * `hasNextPage`. So the presence of `hasNextPage` is the only unambiguous signal, and reading\n * `totalCount` first would turn every infinite list in the fleet into a counted one -- with a total\n * that is not a total: with `bigTable` on, which is the default, the counted number is a look-ahead\n * sentinel, `offset + limit + 1`, and the infinite envelope reports that same sentinel unconditionally.\n */\nexport const readListBody = <T>(body: unknown, status: number, url: string | undefined): ListBody<T> => {\n if (!isObject(body) || !Array.isArray((body as { data?: unknown }).data)) {\n throw new AnzuApiResponseCodeError(status, undefined, 'Expected a list body, url: ' + url)\n }\n\n const { data, totalCount, hasNextPage, bigTable } = body as {\n data: T[]\n totalCount?: unknown\n hasNextPage?: unknown\n bigTable?: unknown\n }\n\n if (isBoolean(hasNextPage)) {\n return { items: data, mode: 'infinite', pagination: { hasNextPage, totalCount: 0 }, countIsBound: false }\n }\n\n if (isNumber(totalCount)) {\n // `null`, not `false`: the field is three-valued and the paginators read it that way. `isNull`\n // is what picks the mode -- `ADatatablePagination.vue:62,67,73` and both `ASubjectSelect.vue`\n // take a non-null value to mean an infinite list, so `false` here says \"infinite, and there is\n // no next page\": Next and Last go dead on every page and the total renders as the number of\n // rows on screen. `null` is the counted list saying the infinite mode's field does not apply.\n return {\n items: data,\n mode: 'counted',\n pagination: { totalCount, hasNextPage: null },\n countIsBound: bigTable === true,\n }\n }\n\n return { items: data, mode: 'unknown', pagination: {}, countIsBound: false }\n}\n\n/**\n * Reads a list that arrived as a bare array.\n *\n * The second of the two shapes a list comes in, and a separate reader rather than one that takes\n * either: the caller declares which one this endpoint answers with and the reader refuses the\n * other, the way `optionalBody` makes the caller declare a body. One reader accepting both shapes\n * is a permissive reader, and a permissive reader is what let a malformed answer through in the\n * first place.\n *\n * Returns `T[]` rather than `ListBody<T>`: `mode: 'unknown'` means the envelope named no mode, and\n * here there was no envelope to name one.\n */\nexport const readArrayBody = <T>(body: unknown, status: number, url: string | undefined): T[] => {\n if (!Array.isArray(body)) {\n throw new AnzuApiResponseCodeError(status, undefined, 'Expected an array body, url: ' + url)\n }\n\n return body as T[]\n}\n"],"mappings":";;;AAuDA,IAAaA,KAAmB,GAAe,GAAgB,MAAyC;CACtG,IAAI,CAACC,EAASC,CAAI,KAAK,CAAC,MAAM,QAASA,EAA4B,IAAI,GACrE,MAAM,IAAIC,EAAyBC,GAAQ,KAAA,GAAW,gCAAgCC,CAAG;CAG3F,IAAM,EAAE,SAAM,eAAY,gBAAa,gBAAaH;CAyBpD,OAlBII,EAAUC,CAAW,IAChB;EAAE,OAAOC;EAAM,MAAM;EAAY,YAAY;GAAE;GAAa,YAAY;EAAE;EAAG,cAAc;CAAM,IAGtGC,EAASC,CAAU,IAMd;EACL,OAAOF;EACP,MAAM;EACN,YAAY;GAAE;GAAY,aAAa;EAAK;EAC5C,cAAcG,MAAa;CAC7B,IAGK;EAAE,OAAOH;EAAM,MAAM;EAAW,YAAY,CAAC;EAAG,cAAc;CAAM;AAC7E,GAcaI,KAAoB,GAAe,GAAgB,MAAiC;CAC/F,IAAI,CAAC,MAAM,QAAQV,CAAI,GACrB,MAAM,IAAIC,EAAyBC,GAAQ,KAAA,GAAW,kCAAkCC,CAAG;CAG7F,OAAOH;AACT"}
1
+ {"version":3,"file":"listBody.js","names":["readListBody","isObject","body","AnzuApiResponseCodeError","status","url","isBoolean","hasNextPage","data","isNumber","totalCount","bigTable","readArrayBody"],"sources":["../../../../src/domains/api/utils/listBody.ts"],"sourcesContent":["import { AnzuApiResponseCodeError } from '@/shared/error/AnzuApiResponseCodeError'\nimport { isBoolean, isNumber, isObject } from '@/shared/utils/common'\nimport type { Pagination } from '@/domains/api/composables/pagination'\n\nexport type ListBody<T> = {\n items: T[]\n /**\n * Which kind of list answered, read from the response, not inferred from `pagination`.\n * `pagination` is what to write. For an infinite list it includes `totalCount: 0` to clear counted-mode leftovers.\n * So reading the mode from `totalCount` sees a counted list of zero items. This caused a bug.\n */\n mode: 'counted' | 'infinite' | 'unknown'\n /**\n * The fields the response gave for its mode, plus the other mode's field cleared.\n * A counted body gets `hasNextPage: null`, an infinite one\n * `totalCount: 0`, so values from the previous query do not linger.\n * A missing or malformed field of the mode's own kind is not written.\n */\n pagination: Partial<Pagination>\n /**\n * Whether `totalCount` is a bound rather than a count.\n * With the backend's `bigTable` on (the default), the count is `offset\n * + limit + 1`, a look-ahead meaning \"at least one more page\".\n * It is the real total only when the page came back short.\n * Fine for Next/Previous navigation. Wrong for anything that computes a page count from it.\n */\n countIsBound: boolean\n}\n\n/**\n * Reads a list response.\n * Only the `data` array decides whether this is a list. Older guards checked a metadata\n * key only, so `{ totalCount: 1 }` passed and callers got `undefined` as an array.\n * Metadata only picks the mode and is optional. A valid array is kept even if the count is missing or malformed.\n * `hasNextPage` decides the mode. The infinite envelope also carries a\n * deprecated `totalCount`, and the counted one never has `hasNextPage`.\n * Reading `totalCount` first would make every infinite list counted,\n * with a look-ahead sentinel `offset + limit + 1` as its total.\n */\nexport const readListBody = <T>(body: unknown, status: number, url: string | undefined): ListBody<T> => {\n if (!isObject(body) || !Array.isArray((body as { data?: unknown }).data)) {\n throw new AnzuApiResponseCodeError(status, undefined, 'Expected a list body, url: ' + url)\n }\n\n const { data, totalCount, hasNextPage, bigTable } = body as {\n data: T[]\n totalCount?: unknown\n hasNextPage?: unknown\n bigTable?: unknown\n }\n\n if (isBoolean(hasNextPage)) {\n return { items: data, mode: 'infinite', pagination: { hasNextPage, totalCount: 0 }, countIsBound: false }\n }\n\n if (isNumber(totalCount)) {\n // `null`, not `false`. Paginators (`ADatatablePagination.vue`,\n // `ASubjectSelect.vue`) treat any non-null value as an infinite list.\n // `false` would mean \"infinite, no next page\": Next and Last go dead and the total shows the rows on screen.\n // `null` means the counted list has no `hasNextPage`.\n return {\n items: data,\n mode: 'counted',\n pagination: { totalCount, hasNextPage: null },\n countIsBound: bigTable === true,\n }\n }\n\n return { items: data, mode: 'unknown', pagination: {}, countIsBound: false }\n}\n\n/**\n * Reads a list that arrived as a bare array.\n * Separate from `readListBody` on purpose. The caller declares the shape\n * its endpoint returns and the other shape is refused, like `optionalBody`.\n * A reader accepting both shapes would let malformed answers through.\n * Returns `T[]`, not `ListBody<T>`, because there is no envelope to name a mode.\n */\nexport const readArrayBody = <T>(body: unknown, status: number, url: string | undefined): T[] => {\n if (!Array.isArray(body)) {\n throw new AnzuApiResponseCodeError(status, undefined, 'Expected an array body, url: ' + url)\n }\n\n return body as T[]\n}\n"],"mappings":";;;AAuCA,IAAaA,KAAmB,GAAe,GAAgB,MAAyC;CACtG,IAAI,CAACC,EAASC,CAAI,KAAK,CAAC,MAAM,QAASA,EAA4B,IAAI,GACrE,MAAM,IAAIC,EAAyBC,GAAQ,KAAA,GAAW,gCAAgCC,CAAG;CAG3F,IAAM,EAAE,SAAM,eAAY,gBAAa,gBAAaH;CAwBpD,OAjBII,EAAUC,CAAW,IAChB;EAAE,OAAOC;EAAM,MAAM;EAAY,YAAY;GAAE;GAAa,YAAY;EAAE;EAAG,cAAc;CAAM,IAGtGC,EAASC,CAAU,IAKd;EACL,OAAOF;EACP,MAAM;EACN,YAAY;GAAE;GAAY,aAAa;EAAK;EAC5C,cAAcG,MAAa;CAC7B,IAGK;EAAE,OAAOH;EAAM,MAAM;EAAW,YAAY,CAAC;EAAG,cAAc;CAAM;AAC7E,GASaI,KAAoB,GAAe,GAAgB,MAAiC;CAC/F,IAAI,CAAC,MAAM,QAAQV,CAAI,GACrB,MAAM,IAAIC,EAAyBC,GAAQ,KAAA,GAAW,kCAAkCC,CAAG;CAG7F,OAAOH;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"Acl.js","names":["_sfc_main","Acl_vue_vue_type_script_setup_true_lang_default","Acl_default"],"sources":["../../../../src/domains/auth/components/Acl.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TAclValue extends RegisteredAclValue\">\nimport { computed } from 'vue'\nimport type { RegisteredAclValue } from '@/domains/auth/types/Permission'\nimport { useAuthHelpers } from '@/domains/auth/composables/defineAuth'\n\nconst props = withDefaults(\n defineProps<{\n // An array is evaluated with AND. Values from different systems are handled correctly --\n // every system involved must be loaded, or the slot stays hidden -- but keeping them from one\n // system is still the clearer thing to write.\n permission: TAclValue | TAclValue[]\n subject?: object\n }>(),\n {\n subject: undefined,\n }\n)\n\nconst { canSafeHelper } = useAuthHelpers<TAclValue>()\n\n/**\n * A computed, not a watcher that latches on the first `true`: it re-evaluates when its own system's\n * current user arrives, and a permission taken away is taken away without a reload.\n *\n * This is the non-throwing variant of `can()`, for templates that may render before their system is\n * there -- `canSafeHelper` answers false where `canHelper` would throw.\n */\nconst allowed = computed<boolean>(() => canSafeHelper(props.permission, props.subject, 'Acl'))\n</script>\n\n<template>\n <slot v-if=\"allowed\" />\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Acl.js","names":["_sfc_main","Acl_vue_vue_type_script_setup_true_lang_default","Acl_default"],"sources":["../../../../src/domains/auth/components/Acl.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TAclValue extends RegisteredAclValue\">\nimport { computed } from 'vue'\nimport type { RegisteredAclValue } from '@/domains/auth/types/Permission'\nimport { useAuthHelpers } from '@/domains/auth/composables/defineAuth'\n\nconst props = withDefaults(\n defineProps<{\n // An array is evaluated with AND. Values from different systems work:\n // every involved system must be loaded, or the slot stays hidden.\n // Prefer values from one system for clarity.\n permission: TAclValue | TAclValue[]\n subject?: object\n }>(),\n {\n subject: undefined,\n }\n)\n\nconst { canSafeHelper } = useAuthHelpers<TAclValue>()\n\n/**\n * A computed, not a watcher latching on the first `true`. It re-evaluates when its\n * system's current user arrives, and a revoked permission applies without a reload.\n * Uses `canSafeHelper` because the template may render before its system is loaded. `canHelper` would throw.\n */\nconst allowed = computed<boolean>(() => canSafeHelper(props.permission, props.subject, 'Acl'))\n</script>\n\n<template>\n <slot v-if=\"allowed\" />\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Acl.vue_vue_type_script_setup_true_lang.js","names":["_renderSlot","_createCommentVNode","Acl_vue_vue_type_script_setup_true_lang_default","props","__props","useAuthHelpers","allowed","computed","canSafeHelper","renderSlot","_ctx","createCommentVNode"],"sources":["../../../../src/domains/auth/components/Acl.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TAclValue extends RegisteredAclValue\">\nimport { computed } from 'vue'\nimport type { RegisteredAclValue } from '@/domains/auth/types/Permission'\nimport { useAuthHelpers } from '@/domains/auth/composables/defineAuth'\n\nconst props = withDefaults(\n defineProps<{\n // An array is evaluated with AND. Values from different systems are handled correctly --\n // every system involved must be loaded, or the slot stays hidden -- but keeping them from one\n // system is still the clearer thing to write.\n permission: TAclValue | TAclValue[]\n subject?: object\n }>(),\n {\n subject: undefined,\n }\n)\n\nconst { canSafeHelper } = useAuthHelpers<TAclValue>()\n\n/**\n * A computed, not a watcher that latches on the first `true`: it re-evaluates when its own system's\n * current user arrives, and a permission taken away is taken away without a reload.\n *\n * This is the non-throwing variant of `can()`, for templates that may render before their system is\n * there -- `canSafeHelper` answers false where `canHelper` would throw.\n */\nconst allowed = computed<boolean>(() => canSafeHelper(props.permission, props.subject, 'Acl'))\n</script>\n\n<template>\n <slot v-if=\"allowed\" />\n</template>\n"],"mappings":";;;;;;;;;;EAKA,IAAMG,IAAQC,GAaR,EAAE,qBAAkBC,EAA0B,GAS9CC,IAAUC,QAAwBC,EAAcL,EAAM,YAAYA,EAAM,SAAS,KAAK,CAAC;E,iBAI/EG,EAAA,QAAZN,EAAuBU,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,KAAA,GAAA,CAAA,I"}
1
+ {"version":3,"file":"Acl.vue_vue_type_script_setup_true_lang.js","names":["_renderSlot","_createCommentVNode","Acl_vue_vue_type_script_setup_true_lang_default","props","__props","useAuthHelpers","allowed","computed","canSafeHelper","renderSlot","_ctx","createCommentVNode"],"sources":["../../../../src/domains/auth/components/Acl.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TAclValue extends RegisteredAclValue\">\nimport { computed } from 'vue'\nimport type { RegisteredAclValue } from '@/domains/auth/types/Permission'\nimport { useAuthHelpers } from '@/domains/auth/composables/defineAuth'\n\nconst props = withDefaults(\n defineProps<{\n // An array is evaluated with AND. Values from different systems work:\n // every involved system must be loaded, or the slot stays hidden.\n // Prefer values from one system for clarity.\n permission: TAclValue | TAclValue[]\n subject?: object\n }>(),\n {\n subject: undefined,\n }\n)\n\nconst { canSafeHelper } = useAuthHelpers<TAclValue>()\n\n/**\n * A computed, not a watcher latching on the first `true`. It re-evaluates when its\n * system's current user arrives, and a revoked permission applies without a reload.\n * Uses `canSafeHelper` because the template may render before its system is loaded. `canHelper` would throw.\n */\nconst allowed = computed<boolean>(() => canSafeHelper(props.permission, props.subject, 'Acl'))\n</script>\n\n<template>\n <slot v-if=\"allowed\" />\n</template>\n"],"mappings":";;;;;;;;;;EAKA,IAAMG,IAAQC,GAaR,EAAE,qBAAkBC,EAA0B,GAO9CC,IAAUC,QAAwBC,EAAcL,EAAM,YAAYA,EAAM,SAAS,KAAK,CAAC;E,iBAI/EG,EAAA,QAAZN,EAAuBU,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,KAAA,GAAA,CAAA,I"}
@@ -1,8 +1,7 @@
1
1
  import { ComputedRef, MaybeRefOrGetter } from 'vue';
2
2
  import { RegisteredAclValue } from '../types/Permission';
3
3
  /**
4
- * Whether a component guarded by an optional ACL may show itself. No ACL means no guard, so a component
5
- * that takes one keeps its old behaviour for callers that pass none. The check never throws (see
6
- * `canSafeHelper`).
4
+ * Whether a component guarded by an optional ACL may show itself.
5
+ * No ACL means no guard, so callers that pass none keep the old behaviour. Never throws (see `canSafeHelper`).
7
6
  */
8
7
  export declare function useAclAllowed(acl: MaybeRefOrGetter<RegisteredAclValue | RegisteredAclValue[] | undefined>, subject?: MaybeRefOrGetter<object | undefined>): ComputedRef<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"aclAllowed.js","names":["useAclAllowed","useAuthHelpers","computed","value","toValue","acl","isUndefined","canSafeHelper","subject"],"sources":["../../../../src/domains/auth/composables/aclAllowed.ts"],"sourcesContent":["import { computed, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'\nimport type { RegisteredAclValue } from '@/domains/auth/types/Permission'\nimport { useAuthHelpers } from '@/domains/auth/composables/defineAuth'\nimport { isUndefined } from '@/shared/utils/common'\n\n/**\n * Whether a component guarded by an optional ACL may show itself. No ACL means no guard, so a component\n * that takes one keeps its old behaviour for callers that pass none. The check never throws (see\n * `canSafeHelper`).\n */\nexport function useAclAllowed(\n acl: MaybeRefOrGetter<RegisteredAclValue | RegisteredAclValue[] | undefined>,\n subject: MaybeRefOrGetter<object | undefined> = undefined\n): ComputedRef<boolean> {\n const { canSafeHelper } = useAuthHelpers<RegisteredAclValue>()\n\n return computed(() => {\n const value = toValue(acl)\n if (isUndefined(value)) return true\n\n return canSafeHelper(value, toValue(subject))\n })\n}\n"],"mappings":";;;;AAUA,SAAgBA,EACd,GACA,IAAgD,KAAA,GAC1B;CACtB,IAAM,EAAE,qBAAkBC,EAAmC;CAE7D,OAAOC,QAAe;EACpB,IAAMC,IAAQC,EAAQC,CAAG;EAGzB,OAFIC,EAAYH,CAAK,IAAU,KAExBI,EAAcJ,GAAOC,EAAQI,CAAO,CAAC;CAC9C,CAAC;AACH"}
1
+ {"version":3,"file":"aclAllowed.js","names":["useAclAllowed","useAuthHelpers","computed","value","toValue","acl","isUndefined","canSafeHelper","subject"],"sources":["../../../../src/domains/auth/composables/aclAllowed.ts"],"sourcesContent":["import { computed, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'\nimport type { RegisteredAclValue } from '@/domains/auth/types/Permission'\nimport { useAuthHelpers } from '@/domains/auth/composables/defineAuth'\nimport { isUndefined } from '@/shared/utils/common'\n\n/**\n * Whether a component guarded by an optional ACL may show itself.\n * No ACL means no guard, so callers that pass none keep the old behaviour. Never throws (see `canSafeHelper`).\n */\nexport function useAclAllowed(\n acl: MaybeRefOrGetter<RegisteredAclValue | RegisteredAclValue[] | undefined>,\n subject: MaybeRefOrGetter<object | undefined> = undefined\n): ComputedRef<boolean> {\n const { canSafeHelper } = useAuthHelpers<RegisteredAclValue>()\n\n return computed(() => {\n const value = toValue(acl)\n if (isUndefined(value)) return true\n\n return canSafeHelper(value, toValue(subject))\n })\n}\n"],"mappings":";;;;AASA,SAAgBA,EACd,GACA,IAAgD,KAAA,GAC1B;CACtB,IAAM,EAAE,qBAAkBC,EAAmC;CAE7D,OAAOC,QAAe;EACpB,IAAMC,IAAQC,EAAQC,CAAG;EAGzB,OAFIC,EAAYH,CAAK,IAAU,KAExBI,EAAcJ,GAAOC,EAAQI,CAAO,CAAC;CAC9C,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"defineAuth.js","names":["ROLE_SUPER_ADMIN","defaultConfig","defineAuth","mergedConfig","config","authStore","useAuthStore","useAuthHelpers","isAdmin","isAdminHelper","userRoles","system","can","canHelper","acl","subject","canOwner","canOwnerHelper","mainCurrentUserSystem","canForAll","canForAllHelper","acls","canSafe","canSafeHelper","canForSome","currentUserId","computed","user","userIsLoaded","isUndefined","isNull","useCurrentUser","setCurrentUser","currentUser","isCurrentUserLoaded","isSuperAdmin","hasCurrentUser","isAnonymous","storeAdminRoleBySystem","isArray","found","role","useApiRequest","res","execute","endPoint","error","options","getSystemFromAcl","permission","objectGetValueByPath","Grant","adminRole","isOwnerAware","isCreatedByAware","value","key","warnOnceInDevelopment","label"],"sources":["../../../../src/domains/auth/composables/defineAuth.ts"],"sourcesContent":["import { computed } from 'vue'\nimport { useAuthStore } from '@/domains/auth/store/authStore'\nimport { type AxiosInstance } from 'axios'\nimport type { AclValue } from '@/domains/auth/types/Permission'\nimport { isArray, isNull, isUndefined } from '@/shared/utils/common'\nimport { objectGetValueByPath } from '@/shared/utils/object'\nimport { warnOnceInDevelopment } from '@/shared/utils/development'\nimport { Grant } from '@/domains/auth/valueObject/Grant'\nimport { isOwnerAware } from '@/shared/types/OwnerAware'\nimport { isCreatedByAware } from '@/shared/types/CreatedByAware'\nimport type { AnzuUser } from '@/shared/types/AnzuUser'\nimport type { UrlParams } from '@/domains/api/utils/apiHelper'\nimport { useApiRequest } from '@/domains/api/composables/useApiRequest'\n\nexport type DefineAuthConfig = {\n adminRole: string | Array<{ system: string; adminRole: string }>\n}\n\nexport const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN'\n\nconst defaultConfig: DefineAuthConfig = {\n adminRole: ROLE_SUPER_ADMIN,\n}\n\n/**\n * @param mainCurrentUserSystem - By this system currentUser object is used to get user ID.\n * @param config\n */\nexport function defineAuth<TAclValue extends AclValue>(\n mainCurrentUserSystem: string,\n config: Partial<DefineAuthConfig> = {}\n) {\n const mergedConfig = { ...defaultConfig, ...config }\n const authStore = useAuthStore()\n const { canHelper, canForAllHelper, canOwnerHelper, isAdminHelper, canSafeHelper } = useAuthHelpers()\n\n const isAdmin = (userRoles: string[], system: string) => {\n return isAdminHelper(userRoles, system)\n }\n\n const can = (acl: TAclValue, subject?: object) => {\n return canHelper(acl, subject)\n }\n\n function canOwner(subject: object) {\n return canOwnerHelper(subject, mainCurrentUserSystem)\n }\n\n const canForAll = (acls: TAclValue[], subject?: object) => {\n return canForAllHelper(acls, subject)\n }\n\n /** `can()` and `canForAll()` that never throw -- for templates and route guards. See `canSafeHelper`. */\n const canSafe = (acl: TAclValue | TAclValue[], subject?: object) => {\n return canSafeHelper(acl, subject)\n }\n\n const canForSome = (acls: TAclValue[], subject?: object) => {\n if (acls.length === 0) {\n return true\n }\n return acls.some((acl) => {\n return can(acl, subject)\n })\n }\n\n const currentUserId = computed(() => {\n const user = authStore.getCurrentUserBySystem(mainCurrentUserSystem)\n const userIsLoaded = authStore.isCurrentUserLoadedBySystem(mainCurrentUserSystem)\n if (isUndefined(userIsLoaded)) {\n return undefined\n }\n if (isUndefined(user) || isUndefined(user.id) || isNull(user.id) || user.id === 0) {\n return undefined\n }\n return user.id\n })\n\n function useCurrentUser<TCurrentUser extends AnzuUser | undefined>(system: string) {\n const setCurrentUser = (user: TCurrentUser) => {\n authStore.currentUsers.value.set(system, user)\n authStore.currentUsersLoaded.value.set(system, true)\n }\n\n const currentUser = computed((): TCurrentUser | undefined => {\n return authStore.currentUsers.value.get(system) as TCurrentUser | undefined\n })\n\n const isCurrentUserLoaded = computed((): boolean | undefined => {\n return authStore.currentUsersLoaded.value.get(system) as boolean | undefined\n })\n\n const isSuperAdmin = computed(() => {\n if (currentUser.value) {\n return isAdmin(currentUser.value.roles, system)\n }\n return false\n })\n\n const hasCurrentUser = computed(() => {\n return currentUser.value ?? false\n })\n\n const isAnonymous = computed(() => {\n if (isUndefined(isCurrentUserLoaded.value)) return undefined\n return !hasCurrentUser.value\n })\n\n const storeAdminRoleBySystem = () => {\n if (isArray(mergedConfig.adminRole)) {\n const found = mergedConfig.adminRole.find((role) => role.system === system)\n if (found) {\n authStore.isAdminRoleBySystem.value.set(system, found.adminRole)\n }\n } else {\n authStore.isAdminRoleBySystem.value.set(system, mergedConfig.adminRole)\n }\n }\n\n /**\n * Answers `undefined` for every failure by default, which loses the reason. `throwOnError`\n * hands the original error back, for callers that must tell a lost session from a dead backend.\n *\n * A failure leaves `currentUser` as it was: unset before the first successful load, the previous\n * user on a later call, whose permissions `can()` then keeps answering from. The system still\n * counts as loaded either way, so `can()` does not throw for a system that was never loaded.\n */\n const fetchCurrentUser = async (\n client: () => AxiosInstance,\n endPoint = '/adm/v1/users/current',\n urlParams: UrlParams | undefined = undefined,\n entity = 'user',\n options: { throwOnError?: boolean } = {}\n ) => {\n try {\n // `useApiRequest`, not the older `apiFetchOne`: it is where the fleet is going, and it is\n // the difference between a failure arriving as a bare `AnzuFatalError` and arriving as the\n // error it actually was -- `AnzuApiAxiosError` with the response on its cause, or\n // `AnzuApiTimeoutError`. A caller passing `throwOnError` can only tell a dead session from\n // a dead backend if the error says which it was.\n const { execute } = useApiRequest<NonNullable<TCurrentUser>>({\n client,\n method: 'GET',\n system,\n entity,\n })\n const res = await execute({ urlTemplate: endPoint, urlParams })\n setCurrentUser(res)\n authStore.currentUsersLoaded.value.set(system, true)\n storeAdminRoleBySystem()\n return currentUser.value\n } catch (error) {\n // Set before rethrowing too, or `can()` throws \"must try to load currentUser first\".\n authStore.currentUsersLoaded.value.set(system, true)\n if (options.throwOnError) throw error\n return undefined\n }\n }\n\n return {\n currentUser,\n setCurrentUser,\n // `undefined` until something has tried to load this system, which is the one state\n // `currentUser` alone cannot tell apart from \"loaded, but there is no such user\".\n isCurrentUserLoaded,\n isSuperAdmin,\n isAnonymous,\n hasCurrentUser,\n fetchCurrentUser,\n }\n }\n\n return {\n can,\n canForAll,\n canForSome,\n canSafe,\n canOwner,\n useCurrentUser,\n currentUserId,\n config: mergedConfig,\n }\n}\n\nexport function useAuthHelpers<TAclValue extends AclValue>() {\n const authStore = useAuthStore()\n\n const canHelper = (acl: TAclValue, subject: object | undefined) => {\n const system = getSystemFromAcl(acl)\n const user = authStore.getCurrentUserBySystem(system)\n const userIsLoaded = authStore.isCurrentUserLoadedBySystem(system)\n if (isUndefined(userIsLoaded)) {\n throw new Error('Composable defineAuth must try to load currentUser first to use can function.')\n }\n if (isUndefined(user) || isUndefined(user.id) || isNull(user.id) || user.id === 0) {\n return false\n }\n if (isAdminHelper(user.roles, system)) return true\n const permission = objectGetValueByPath(user, 'resolvedPermissions.' + acl)\n if (isUndefined(permission)) return false\n switch (permission) {\n case Grant.Allow:\n return true\n case Grant.Deny:\n return false\n case Grant.AllowOwner:\n if (isUndefined(subject))\n throw new Error(`Required subject for acl \"${acl}\" to determine an ability to access the resource.`)\n return canOwnerHelper(subject, system)\n default:\n return false\n }\n }\n\n const canForAllHelper = (acls: TAclValue[], subject?: object) => {\n if (acls.length === 0) {\n return true\n }\n return acls.every((acl) => {\n return canHelper(acl, subject)\n })\n }\n\n const isAdminHelper = (userRoles: string[], system: string) => {\n const authStore = useAuthStore()\n const adminRole = authStore.getAdminRoleBySystem(system)\n if (isUndefined(adminRole)) return false\n\n return userRoles.includes(adminRole)\n }\n\n function canOwnerHelper(subject: object, system: string) {\n const user = authStore.getCurrentUserBySystem(system)\n const userIsLoaded = authStore.isCurrentUserLoadedBySystem(system)\n if (isUndefined(userIsLoaded)) {\n throw new Error('Composable defineAuth must try to load currentUser first to use canOwner function.')\n }\n if (isUndefined(user) || isUndefined(user.id) || isNull(user.id) || user.id === 0) {\n return false\n }\n if (isOwnerAware(subject)) {\n return subject.owners.includes(user.id)\n }\n if (isCreatedByAware(subject)) {\n return subject.createdBy === user.id\n }\n return false\n }\n\n /**\n * `canForAll` that answers false instead of throwing: for a system nothing has tried to load yet, which a\n * template or a route guard may reach first, and for a check that throws, such as an `allowOwner` grant\n * with no subject. An array is evaluated with AND.\n *\n * Reading each system's current user tracks that key, so a render or a computed re-evaluates when its\n * own system arrives.\n */\n const canSafeHelper = (acl: TAclValue | TAclValue[], subject?: object, label = 'canSafe'): boolean => {\n const acls = isArray(acl) ? acl : [acl]\n if (acls.length === 0) {\n return true\n }\n for (const system of acls.map((value) => getSystemFromAcl(value))) {\n authStore.currentUsers.value.get(system)\n if (isUndefined(authStore.isCurrentUserLoadedBySystem(system))) {\n return false\n }\n }\n try {\n return canForAllHelper(acls, subject)\n } catch (error) {\n // Denied either way; without a word it looks exactly like a missing permission.\n const key = acls.join(', ')\n warnOnceInDevelopment(`${label}:${key}`, `[${label}] the check of ${key} threw, so it is denied:`, error)\n return false\n }\n }\n\n return {\n canHelper,\n canForAllHelper,\n canOwnerHelper,\n isAdminHelper,\n canSafeHelper,\n }\n}\n\n/** An ACL value carries its system in front of the first underscore: `weather_location_ui`. */\nexport function getSystemFromAcl(acl: any) {\n const parts = acl.split('_')\n\n return parts[0]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"defineAuth.js","names":["ROLE_SUPER_ADMIN","defaultConfig","defineAuth","mergedConfig","config","authStore","useAuthStore","useAuthHelpers","isAdmin","isAdminHelper","userRoles","system","can","canHelper","acl","subject","canOwner","canOwnerHelper","mainCurrentUserSystem","canForAll","canForAllHelper","acls","canSafe","canSafeHelper","canForSome","currentUserId","computed","user","userIsLoaded","isUndefined","isNull","useCurrentUser","setCurrentUser","currentUser","isCurrentUserLoaded","isSuperAdmin","hasCurrentUser","isAnonymous","storeAdminRoleBySystem","isArray","found","role","useApiRequest","res","execute","endPoint","error","options","getSystemFromAcl","permission","objectGetValueByPath","Grant","adminRole","isOwnerAware","isCreatedByAware","value","key","warnOnceInDevelopment","label"],"sources":["../../../../src/domains/auth/composables/defineAuth.ts"],"sourcesContent":["import { computed } from 'vue'\nimport { useAuthStore } from '@/domains/auth/store/authStore'\nimport { type AxiosInstance } from 'axios'\nimport type { AclValue } from '@/domains/auth/types/Permission'\nimport { isArray, isNull, isUndefined } from '@/shared/utils/common'\nimport { objectGetValueByPath } from '@/shared/utils/object'\nimport { warnOnceInDevelopment } from '@/shared/utils/development'\nimport { Grant } from '@/domains/auth/valueObject/Grant'\nimport { isOwnerAware } from '@/shared/types/OwnerAware'\nimport { isCreatedByAware } from '@/shared/types/CreatedByAware'\nimport type { AnzuUser } from '@/shared/types/AnzuUser'\nimport type { UrlParams } from '@/domains/api/utils/apiHelper'\nimport { useApiRequest } from '@/domains/api/composables/useApiRequest'\n\nexport type DefineAuthConfig = {\n adminRole: string | Array<{ system: string; adminRole: string }>\n}\n\nexport const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN'\n\nconst defaultConfig: DefineAuthConfig = {\n adminRole: ROLE_SUPER_ADMIN,\n}\n\n/**\n * @param mainCurrentUserSystem - By this system currentUser object is used to get user ID.\n * @param config\n */\nexport function defineAuth<TAclValue extends AclValue>(\n mainCurrentUserSystem: string,\n config: Partial<DefineAuthConfig> = {}\n) {\n const mergedConfig = { ...defaultConfig, ...config }\n const authStore = useAuthStore()\n const { canHelper, canForAllHelper, canOwnerHelper, isAdminHelper, canSafeHelper } = useAuthHelpers()\n\n const isAdmin = (userRoles: string[], system: string) => {\n return isAdminHelper(userRoles, system)\n }\n\n const can = (acl: TAclValue, subject?: object) => {\n return canHelper(acl, subject)\n }\n\n function canOwner(subject: object) {\n return canOwnerHelper(subject, mainCurrentUserSystem)\n }\n\n const canForAll = (acls: TAclValue[], subject?: object) => {\n return canForAllHelper(acls, subject)\n }\n\n /** `can()` and `canForAll()` that never throw -- for templates and route guards. See `canSafeHelper`. */\n const canSafe = (acl: TAclValue | TAclValue[], subject?: object) => {\n return canSafeHelper(acl, subject)\n }\n\n const canForSome = (acls: TAclValue[], subject?: object) => {\n if (acls.length === 0) {\n return true\n }\n return acls.some((acl) => {\n return can(acl, subject)\n })\n }\n\n const currentUserId = computed(() => {\n const user = authStore.getCurrentUserBySystem(mainCurrentUserSystem)\n const userIsLoaded = authStore.isCurrentUserLoadedBySystem(mainCurrentUserSystem)\n if (isUndefined(userIsLoaded)) {\n return undefined\n }\n if (isUndefined(user) || isUndefined(user.id) || isNull(user.id) || user.id === 0) {\n return undefined\n }\n return user.id\n })\n\n function useCurrentUser<TCurrentUser extends AnzuUser | undefined>(system: string) {\n const setCurrentUser = (user: TCurrentUser) => {\n authStore.currentUsers.value.set(system, user)\n authStore.currentUsersLoaded.value.set(system, true)\n }\n\n const currentUser = computed((): TCurrentUser | undefined => {\n return authStore.currentUsers.value.get(system) as TCurrentUser | undefined\n })\n\n const isCurrentUserLoaded = computed((): boolean | undefined => {\n return authStore.currentUsersLoaded.value.get(system) as boolean | undefined\n })\n\n const isSuperAdmin = computed(() => {\n if (currentUser.value) {\n return isAdmin(currentUser.value.roles, system)\n }\n return false\n })\n\n const hasCurrentUser = computed(() => {\n return currentUser.value ?? false\n })\n\n const isAnonymous = computed(() => {\n if (isUndefined(isCurrentUserLoaded.value)) return undefined\n return !hasCurrentUser.value\n })\n\n const storeAdminRoleBySystem = () => {\n if (isArray(mergedConfig.adminRole)) {\n const found = mergedConfig.adminRole.find((role) => role.system === system)\n if (found) {\n authStore.isAdminRoleBySystem.value.set(system, found.adminRole)\n }\n } else {\n authStore.isAdminRoleBySystem.value.set(system, mergedConfig.adminRole)\n }\n }\n\n /**\n * Returns `undefined` on any failure by default, which loses the reason.\n * `throwOnError` rethrows the original error, so callers can tell a lost session from a dead backend.\n * A failure leaves `currentUser` unchanged, so `can()` keeps using the previous user's permissions.\n * The system still counts as loaded, so `can()` does not throw.\n */\n const fetchCurrentUser = async (\n client: () => AxiosInstance,\n endPoint = '/adm/v1/users/current',\n urlParams: UrlParams | undefined = undefined,\n entity = 'user',\n options: { throwOnError?: boolean } = {}\n ) => {\n try {\n // Uses `useApiRequest`, not `apiFetchOne`. `apiFetchOne` wraps failures in a bare `AnzuFatalError`.\n // Callers with `throwOnError` need the real error (`AnzuApiAxiosError`\n // or `AnzuApiTimeoutError`) to tell a dead session from a dead backend.\n const { execute } = useApiRequest<NonNullable<TCurrentUser>>({\n client,\n method: 'GET',\n system,\n entity,\n })\n const res = await execute({ urlTemplate: endPoint, urlParams })\n setCurrentUser(res)\n authStore.currentUsersLoaded.value.set(system, true)\n storeAdminRoleBySystem()\n return currentUser.value\n } catch (error) {\n // Set before rethrowing too, or `can()` throws \"must try to load currentUser first\".\n authStore.currentUsersLoaded.value.set(system, true)\n if (options.throwOnError) throw error\n return undefined\n }\n }\n\n return {\n currentUser,\n setCurrentUser,\n // `undefined` until something tries to load this system.\n // `currentUser` alone cannot tell this apart from \"loaded, but no such user\".\n isCurrentUserLoaded,\n isSuperAdmin,\n isAnonymous,\n hasCurrentUser,\n fetchCurrentUser,\n }\n }\n\n return {\n can,\n canForAll,\n canForSome,\n canSafe,\n canOwner,\n useCurrentUser,\n currentUserId,\n config: mergedConfig,\n }\n}\n\nexport function useAuthHelpers<TAclValue extends AclValue>() {\n const authStore = useAuthStore()\n\n const canHelper = (acl: TAclValue, subject: object | undefined) => {\n const system = getSystemFromAcl(acl)\n const user = authStore.getCurrentUserBySystem(system)\n const userIsLoaded = authStore.isCurrentUserLoadedBySystem(system)\n if (isUndefined(userIsLoaded)) {\n throw new Error('Composable defineAuth must try to load currentUser first to use can function.')\n }\n if (isUndefined(user) || isUndefined(user.id) || isNull(user.id) || user.id === 0) {\n return false\n }\n if (isAdminHelper(user.roles, system)) return true\n const permission = objectGetValueByPath(user, 'resolvedPermissions.' + acl)\n if (isUndefined(permission)) return false\n switch (permission) {\n case Grant.Allow:\n return true\n case Grant.Deny:\n return false\n case Grant.AllowOwner:\n if (isUndefined(subject))\n throw new Error(`Required subject for acl \"${acl}\" to determine an ability to access the resource.`)\n return canOwnerHelper(subject, system)\n default:\n return false\n }\n }\n\n const canForAllHelper = (acls: TAclValue[], subject?: object) => {\n if (acls.length === 0) {\n return true\n }\n return acls.every((acl) => {\n return canHelper(acl, subject)\n })\n }\n\n const isAdminHelper = (userRoles: string[], system: string) => {\n const authStore = useAuthStore()\n const adminRole = authStore.getAdminRoleBySystem(system)\n if (isUndefined(adminRole)) return false\n\n return userRoles.includes(adminRole)\n }\n\n function canOwnerHelper(subject: object, system: string) {\n const user = authStore.getCurrentUserBySystem(system)\n const userIsLoaded = authStore.isCurrentUserLoadedBySystem(system)\n if (isUndefined(userIsLoaded)) {\n throw new Error('Composable defineAuth must try to load currentUser first to use canOwner function.')\n }\n if (isUndefined(user) || isUndefined(user.id) || isNull(user.id) || user.id === 0) {\n return false\n }\n if (isOwnerAware(subject)) {\n return subject.owners.includes(user.id)\n }\n if (isCreatedByAware(subject)) {\n return subject.createdBy === user.id\n }\n return false\n }\n\n /**\n * `canForAll` that returns false instead of throwing.\n * Covers a system not loaded yet (templates and route guards may get there\n * first) and checks that throw, such as an `allowOwner` grant with no subject.\n * An array is evaluated with AND. Reading each system's current user\n * makes a render or computed re-evaluate when that system loads.\n */\n const canSafeHelper = (acl: TAclValue | TAclValue[], subject?: object, label = 'canSafe'): boolean => {\n const acls = isArray(acl) ? acl : [acl]\n if (acls.length === 0) {\n return true\n }\n for (const system of acls.map((value) => getSystemFromAcl(value))) {\n authStore.currentUsers.value.get(system)\n if (isUndefined(authStore.isCurrentUserLoadedBySystem(system))) {\n return false\n }\n }\n try {\n return canForAllHelper(acls, subject)\n } catch (error) {\n // Denied either way. Without the warning it looks like a missing permission.\n const key = acls.join(', ')\n warnOnceInDevelopment(`${label}:${key}`, `[${label}] the check of ${key} threw, so it is denied:`, error)\n return false\n }\n }\n\n return {\n canHelper,\n canForAllHelper,\n canOwnerHelper,\n isAdminHelper,\n canSafeHelper,\n }\n}\n\n/** An ACL value carries its system in front of the first underscore: `weather_location_ui`. */\nexport function getSystemFromAcl(acl: any) {\n const parts = acl.split('_')\n\n return parts[0]\n}\n"],"mappings":"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"}
@@ -7,19 +7,17 @@ export type RefreshResult = {
7
7
  type: 'auth-unavailable';
8
8
  error: unknown;
9
9
  };
10
- /** What the refresh needs to know about the auth cookies. */
11
10
  export interface AuthCookieState {
12
11
  refreshTokenExists: unknown;
13
12
  jwtPayload: string | null | undefined;
14
13
  }
15
14
  /**
16
- * The session refresh, single flight: a refresh already running is joined, otherwise a new one
17
- * starts; a finished result is never reused.
18
- *
19
- * Only a 401 means the session is gone. A 400 (`unable_to_refresh`) can equally mean another tab
20
- * rotated the token first -- the backend rotation is not atomic -- which a changed JWT cookie shows,
21
- * up to a second later when that tab's answer arrives after this one's.
22
- * Everything else is the auth backend being unavailable, never a reason to log out.
15
+ * Single-flight session refresh. A running refresh is joined,
16
+ * otherwise a new one starts. A finished result is never reused.
17
+ * Only a 401 means the session is gone.
18
+ * A 400 (`unable_to_refresh`) can also mean another tab rotated the token first, because
19
+ * backend rotation is not atomic. A changed JWT cookie shows this, up to a second later.
20
+ * Any other error means the auth backend is unavailable and never causes a logout.
23
21
  */
24
22
  export declare function createRefreshSession(options: {
25
23
  /** Calls the refresh endpoint; rejects with whatever the api helper throws. */
@@ -28,10 +26,9 @@ export declare function createRefreshSession(options: {
28
26
  jwtPayload: () => string | null | undefined;
29
27
  }): () => Promise<RefreshResult>;
30
28
  /**
31
- * The axios request interceptor that refreshes an expired JWT before a request goes out, with the
32
- * `runWhen` that keeps it off the auth endpoints themselves. Concurrent requests share one refresh
33
- * (`refreshSession`), and a request is rejected with `SessionExpiredError` (after `logout`) or
34
- * `AuthUnavailableError` (the user stays logged in).
29
+ * Request interceptor that refreshes an expired JWT before a request goes out. Its `runWhen` skips the auth endpoints.
30
+ * Concurrent requests share one refresh (`refreshSession`). A request is rejected with
31
+ * `SessionExpiredError` (after `logout`) or `AuthUnavailableError` (the user stays logged in).
35
32
  */
36
33
  export declare function createRefreshRequestInterceptor(options: {
37
34
  cookies: () => AuthCookieState;
@@ -39,7 +36,7 @@ export declare function createRefreshRequestInterceptor(options: {
39
36
  logout: () => void;
40
37
  /** Requests to these urls (the auth endpoints) are never held for a refresh. */
41
38
  skipUrlPrefix: string;
42
- /** A JWT that is still there but past its expiry also needs a refresh (default: only a missing one). */
39
+ /** Also refresh a JWT that exists but is expired. By default only a missing JWT is refreshed. */
43
40
  jwtExpired?: () => boolean;
44
41
  }): {
45
42
  interceptor: (requestConfig: InternalAxiosRequestConfig) => Promise<InternalAxiosRequestConfig>;
@@ -1 +1 @@
1
- {"version":3,"file":"refreshSession.js","names":["axios","HTTP_BAD_REQUEST","HTTP_UNAUTHORIZED","ROTATION_GRACE_MS","ROTATION_POLL_MS","httpStatusInCauseChain","status","isInCauseChain","error","value","isDefined","createRefreshSession","inFlight","rotatedMeanwhile","waited","now","options","isNull","before","resolve","run","jwtPayloadBefore","createRefreshRequestInterceptor","loggedOut","refreshTokenExists","jwtPayload","SessionExpiredError","result","requestConfig","AuthUnavailableError","skipUrlPrefixes"],"sources":["../../../../src/domains/auth/composables/refreshSession.ts"],"sourcesContent":["import axios, { type InternalAxiosRequestConfig } from 'axios'\nimport { isDefined, isNull } from '@/shared/utils/common'\nimport { skipUrlPrefixes } from '@/domains/api/composables/defineApiClient'\nimport { AuthUnavailableError } from '@/shared/error/AuthUnavailableError'\nimport { isInCauseChain } from '@/shared/error/isInCauseChain'\nimport { SessionExpiredError } from '@/shared/error/SessionExpiredError'\n\nconst HTTP_BAD_REQUEST = 400\nconst HTTP_UNAUTHORIZED = 401\n// How long a 400 waits for the cookie of the tab whose refresh won: its answer can come after this one's.\nconst ROTATION_GRACE_MS = 1000\nconst ROTATION_POLL_MS = 100\n\nexport type RefreshResult =\n | { type: 'refreshed' }\n | { type: 'session-expired' }\n | { type: 'auth-unavailable'; error: unknown }\n\n/** What the refresh needs to know about the auth cookies. */\nexport interface AuthCookieState {\n refreshTokenExists: unknown\n jwtPayload: string | null | undefined\n}\n\n// `undefined`: no response anywhere in the chain -- a timeout or a network failure.\nconst httpStatusInCauseChain = (error: unknown): number | undefined => {\n let status: number | undefined\n isInCauseChain(error, (value) => {\n if (!axios.isAxiosError(value) || !isDefined(value.response)) return false\n status = value.response.status\n return true\n })\n return status\n}\n\n/**\n * The session refresh, single flight: a refresh already running is joined, otherwise a new one\n * starts; a finished result is never reused.\n *\n * Only a 401 means the session is gone. A 400 (`unable_to_refresh`) can equally mean another tab\n * rotated the token first -- the backend rotation is not atomic -- which a changed JWT cookie shows,\n * up to a second later when that tab's answer arrives after this one's.\n * Everything else is the auth backend being unavailable, never a reason to log out.\n */\nexport function createRefreshSession(options: {\n /** Calls the refresh endpoint; rejects with whatever the api helper throws. */\n refresh: () => Promise<unknown>\n /** The JWT payload cookie as it is now. */\n jwtPayload: () => string | null | undefined\n}): () => Promise<RefreshResult> {\n let inFlight: Promise<RefreshResult> | null = null\n\n const rotatedMeanwhile = async (before: string | null | undefined): Promise<boolean> => {\n for (let waited = 0; ; waited += ROTATION_POLL_MS) {\n const now = options.jwtPayload()\n if (isDefined(now) && !isNull(now) && now !== before) return true\n if (waited >= ROTATION_GRACE_MS) return false\n await new Promise((resolve) => setTimeout(resolve, ROTATION_POLL_MS))\n }\n }\n\n const run = async (): Promise<RefreshResult> => {\n // Before the request: with a refresh in flight the cookie is already there, so only a changed\n // value says something afterwards.\n const jwtPayloadBefore = options.jwtPayload()\n try {\n await options.refresh()\n return { type: 'refreshed' }\n } catch (error) {\n const status = httpStatusInCauseChain(error)\n if (status === HTTP_UNAUTHORIZED) return { type: 'session-expired' }\n if (status === HTTP_BAD_REQUEST) {\n return (await rotatedMeanwhile(jwtPayloadBefore)) ? { type: 'refreshed' } : { type: 'session-expired' }\n }\n return { type: 'auth-unavailable', error }\n }\n }\n\n return () => {\n if (isNull(inFlight)) {\n inFlight = run().finally(() => {\n inFlight = null\n })\n }\n return inFlight\n }\n}\n\n/**\n * The axios request interceptor that refreshes an expired JWT before a request goes out, with the\n * `runWhen` that keeps it off the auth endpoints themselves. Concurrent requests share one refresh\n * (`refreshSession`), and a request is rejected with `SessionExpiredError` (after `logout`) or\n * `AuthUnavailableError` (the user stays logged in).\n */\nexport function createRefreshRequestInterceptor(options: {\n cookies: () => AuthCookieState\n refreshSession: () => Promise<RefreshResult>\n logout: () => void\n /** Requests to these urls (the auth endpoints) are never held for a refresh. */\n skipUrlPrefix: string\n /** A JWT that is still there but past its expiry also needs a refresh (default: only a missing one). */\n jwtExpired?: () => boolean\n}) {\n // Requests waiting on one refresh share its result: log out once for it, not once per request.\n const loggedOut = new WeakSet<RefreshResult>()\n\n const interceptor = async (requestConfig: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n const { refreshTokenExists, jwtPayload } = options.cookies()\n if (!refreshTokenExists && !jwtPayload) {\n options.logout()\n throw new SessionExpiredError()\n }\n if (refreshTokenExists && (!jwtPayload || options.jwtExpired?.())) {\n const result = await options.refreshSession()\n if (result.type === 'session-expired') {\n if (!loggedOut.has(result)) {\n loggedOut.add(result)\n options.logout()\n }\n throw new SessionExpiredError()\n }\n // Stopped while it waited (its page is gone): cancelled, as it would have been on its way out, and not a\n // failure to show on the page the user went to. Axios checks the signal only once the interceptors are done.\n if (requestConfig.signal?.aborted) throw new axios.CanceledError()\n if (result.type === 'auth-unavailable') throw new AuthUnavailableError(result.error)\n }\n return requestConfig\n }\n\n return {\n interceptor,\n options: { runWhen: skipUrlPrefixes(options.skipUrlPrefix) },\n }\n}\n"],"mappings":";;;;;;;AAOA,IAAMC,IAAmB,KACnBC,IAAoB,KAEpBC,IAAoB,KACpBC,IAAmB,KAcnBC,KAA0B,MAAuC;CACrE,IAAIC;CAMJ,OALAC,EAAeC,IAAQ,MACjB,CAACR,EAAM,aAAaS,CAAK,KAAK,CAACC,EAAUD,EAAM,QAAQ,IAAU,MACrE,IAASA,EAAM,SAAS,QACjB,GACR,GACMH;AACT;AAWA,SAAgBK,EAAqB,GAKJ;CAC/B,IAAIC,IAA0C,MAExCC,IAAmB,OAAO,MAAwD;EACtF,KAAK,IAAIC,IAAS,IAAK,KAAUV,GAAkB;GACjD,IAAMW,IAAMC,EAAQ,WAAW;GAC/B,IAAIN,EAAUK,CAAG,KAAK,CAACE,EAAOF,CAAG,KAAKA,MAAQG,GAAQ,OAAO;GAC7D,IAAIJ,KAAUX,GAAmB,OAAO;GACxC,MAAM,IAAI,SAAS,MAAY,WAAWgB,GAASf,CAAgB,CAAC;EACtE;CACF,GAEMgB,IAAM,YAAoC;EAG9C,IAAMC,IAAmBL,EAAQ,WAAW;EAC5C,IAAI;GAEF,OADA,MAAMA,EAAQ,QAAQ,GACf,EAAE,MAAM,YAAY;EAC7B,SAASR,GAAO;GACd,IAAMF,IAASD,EAAuBG,CAAK;GAK3C,OAJIF,MAAWJ,IAA0B,EAAE,MAAM,kBAAkB,IAC/DI,MAAWL,IACL,MAAMY,EAAiBQ,CAAgB,IAAK,EAAE,MAAM,YAAY,IAAI,EAAE,MAAM,kBAAkB,IAEjG;IAAE,MAAM;IAAoB;GAAM;EAC3C;CACF;CAEA,cACMJ,EAAOL,CAAQ,MACjB,IAAWQ,EAAI,CAAC,CAAC,cAAc;EAC7B,IAAW;CACb,CAAC,IAEIR;AAEX;AAQA,SAAgBU,EAAgC,GAQ7C;CAED,IAAMC,oBAAY,IAAI,QAAuB;CAyB7C,OAAO;EACL,oBAxByB,MAAmF;GAC5G,IAAM,EAAE,uBAAoB,kBAAeP,EAAQ,QAAQ;GAC3D,IAAI,CAACQ,KAAsB,CAACC,GAE1B,MADAT,EAAQ,OAAO,GACT,IAAIU,EAAoB;GAEhC,IAAIF,MAAuB,CAACC,KAAcT,EAAQ,aAAa,IAAI;IACjE,IAAMW,IAAS,MAAMX,EAAQ,eAAe;IAC5C,IAAIW,EAAO,SAAS,mBAKlB,MAJKJ,EAAU,IAAII,CAAM,MACvBJ,EAAU,IAAII,CAAM,GACpBX,EAAQ,OAAO,IAEX,IAAIU,EAAoB;IAIhC,IAAIE,EAAc,QAAQ,SAAS,MAAM,IAAI5B,EAAM,cAAc;IACjE,IAAI2B,EAAO,SAAS,oBAAoB,MAAM,IAAIE,EAAqBF,EAAO,KAAK;GACrF;GACA,OAAOC;EACT;EAIE,SAAS,EAAE,SAASE,EAAgBd,EAAQ,aAAa,EAAE;CAC7D;AACF"}
1
+ {"version":3,"file":"refreshSession.js","names":["axios","HTTP_BAD_REQUEST","HTTP_UNAUTHORIZED","ROTATION_GRACE_MS","ROTATION_POLL_MS","httpStatusInCauseChain","status","isInCauseChain","error","value","isDefined","createRefreshSession","inFlight","rotatedMeanwhile","waited","now","options","isNull","before","resolve","run","jwtPayloadBefore","createRefreshRequestInterceptor","loggedOut","refreshTokenExists","jwtPayload","SessionExpiredError","result","requestConfig","AuthUnavailableError","skipUrlPrefixes"],"sources":["../../../../src/domains/auth/composables/refreshSession.ts"],"sourcesContent":["import axios, { type InternalAxiosRequestConfig } from 'axios'\nimport { isDefined, isNull } from '@/shared/utils/common'\nimport { skipUrlPrefixes } from '@/domains/api/composables/defineApiClient'\nimport { AuthUnavailableError } from '@/shared/error/AuthUnavailableError'\nimport { isInCauseChain } from '@/shared/error/isInCauseChain'\nimport { SessionExpiredError } from '@/shared/error/SessionExpiredError'\n\nconst HTTP_BAD_REQUEST = 400\nconst HTTP_UNAUTHORIZED = 401\n// How long a 400 waits for the cookie from the tab whose refresh won. That tab's response can arrive after this one.\nconst ROTATION_GRACE_MS = 1000\nconst ROTATION_POLL_MS = 100\n\nexport type RefreshResult =\n | { type: 'refreshed' }\n | { type: 'session-expired' }\n | { type: 'auth-unavailable'; error: unknown }\n\nexport interface AuthCookieState {\n refreshTokenExists: unknown\n jwtPayload: string | null | undefined\n}\n\n// `undefined` means no response in the chain: a timeout or a network failure.\nconst httpStatusInCauseChain = (error: unknown): number | undefined => {\n let status: number | undefined\n isInCauseChain(error, (value) => {\n if (!axios.isAxiosError(value) || !isDefined(value.response)) return false\n status = value.response.status\n return true\n })\n return status\n}\n\n/**\n * Single-flight session refresh. A running refresh is joined,\n * otherwise a new one starts. A finished result is never reused.\n * Only a 401 means the session is gone.\n * A 400 (`unable_to_refresh`) can also mean another tab rotated the token first, because\n * backend rotation is not atomic. A changed JWT cookie shows this, up to a second later.\n * Any other error means the auth backend is unavailable and never causes a logout.\n */\nexport function createRefreshSession(options: {\n /** Calls the refresh endpoint; rejects with whatever the api helper throws. */\n refresh: () => Promise<unknown>\n /** The JWT payload cookie as it is now. */\n jwtPayload: () => string | null | undefined\n}): () => Promise<RefreshResult> {\n let inFlight: Promise<RefreshResult> | null = null\n\n const rotatedMeanwhile = async (before: string | null | undefined): Promise<boolean> => {\n for (let waited = 0; ; waited += ROTATION_POLL_MS) {\n const now = options.jwtPayload()\n if (isDefined(now) && !isNull(now) && now !== before) return true\n if (waited >= ROTATION_GRACE_MS) return false\n await new Promise((resolve) => setTimeout(resolve, ROTATION_POLL_MS))\n }\n }\n\n const run = async (): Promise<RefreshResult> => {\n // Read before the request. During an in-flight refresh the\n // cookie already exists, so only a changed value is meaningful.\n const jwtPayloadBefore = options.jwtPayload()\n try {\n await options.refresh()\n return { type: 'refreshed' }\n } catch (error) {\n const status = httpStatusInCauseChain(error)\n if (status === HTTP_UNAUTHORIZED) return { type: 'session-expired' }\n if (status === HTTP_BAD_REQUEST) {\n return (await rotatedMeanwhile(jwtPayloadBefore)) ? { type: 'refreshed' } : { type: 'session-expired' }\n }\n return { type: 'auth-unavailable', error }\n }\n }\n\n return () => {\n if (isNull(inFlight)) {\n inFlight = run().finally(() => {\n inFlight = null\n })\n }\n return inFlight\n }\n}\n\n/**\n * Request interceptor that refreshes an expired JWT before a request goes out. Its `runWhen` skips the auth endpoints.\n * Concurrent requests share one refresh (`refreshSession`). A request is rejected with\n * `SessionExpiredError` (after `logout`) or `AuthUnavailableError` (the user stays logged in).\n */\nexport function createRefreshRequestInterceptor(options: {\n cookies: () => AuthCookieState\n refreshSession: () => Promise<RefreshResult>\n logout: () => void\n /** Requests to these urls (the auth endpoints) are never held for a refresh. */\n skipUrlPrefix: string\n /** Also refresh a JWT that exists but is expired. By default only a missing JWT is refreshed. */\n jwtExpired?: () => boolean\n}) {\n // Requests waiting on one refresh share its result. Log out once per refresh, not once per request.\n const loggedOut = new WeakSet<RefreshResult>()\n\n const interceptor = async (requestConfig: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> => {\n const { refreshTokenExists, jwtPayload } = options.cookies()\n if (!refreshTokenExists && !jwtPayload) {\n options.logout()\n throw new SessionExpiredError()\n }\n if (refreshTokenExists && (!jwtPayload || options.jwtExpired?.())) {\n const result = await options.refreshSession()\n if (result.type === 'session-expired') {\n if (!loggedOut.has(result)) {\n loggedOut.add(result)\n options.logout()\n }\n throw new SessionExpiredError()\n }\n // Aborted while waiting (its page is gone): treat as cancelled, not as a failure to show on the new page.\n // Axios checks the signal only after the interceptors finish.\n if (requestConfig.signal?.aborted) throw new axios.CanceledError()\n if (result.type === 'auth-unavailable') throw new AuthUnavailableError(result.error)\n }\n return requestConfig\n }\n\n return {\n interceptor,\n options: { runWhen: skipUrlPrefixes(options.skipUrlPrefix) },\n }\n}\n"],"mappings":";;;;;;;AAOA,IAAMC,IAAmB,KACnBC,IAAoB,KAEpBC,IAAoB,KACpBC,IAAmB,KAanBC,KAA0B,MAAuC;CACrE,IAAIC;CAMJ,OALAC,EAAeC,IAAQ,MACjB,CAACR,EAAM,aAAaS,CAAK,KAAK,CAACC,EAAUD,EAAM,QAAQ,IAAU,MACrE,IAASA,EAAM,SAAS,QACjB,GACR,GACMH;AACT;AAUA,SAAgBK,EAAqB,GAKJ;CAC/B,IAAIC,IAA0C,MAExCC,IAAmB,OAAO,MAAwD;EACtF,KAAK,IAAIC,IAAS,IAAK,KAAUV,GAAkB;GACjD,IAAMW,IAAMC,EAAQ,WAAW;GAC/B,IAAIN,EAAUK,CAAG,KAAK,CAACE,EAAOF,CAAG,KAAKA,MAAQG,GAAQ,OAAO;GAC7D,IAAIJ,KAAUX,GAAmB,OAAO;GACxC,MAAM,IAAI,SAAS,MAAY,WAAWgB,GAASf,CAAgB,CAAC;EACtE;CACF,GAEMgB,IAAM,YAAoC;EAG9C,IAAMC,IAAmBL,EAAQ,WAAW;EAC5C,IAAI;GAEF,OADA,MAAMA,EAAQ,QAAQ,GACf,EAAE,MAAM,YAAY;EAC7B,SAASR,GAAO;GACd,IAAMF,IAASD,EAAuBG,CAAK;GAK3C,OAJIF,MAAWJ,IAA0B,EAAE,MAAM,kBAAkB,IAC/DI,MAAWL,IACL,MAAMY,EAAiBQ,CAAgB,IAAK,EAAE,MAAM,YAAY,IAAI,EAAE,MAAM,kBAAkB,IAEjG;IAAE,MAAM;IAAoB;GAAM;EAC3C;CACF;CAEA,cACMJ,EAAOL,CAAQ,MACjB,IAAWQ,EAAI,CAAC,CAAC,cAAc;EAC7B,IAAW;CACb,CAAC,IAEIR;AAEX;AAOA,SAAgBU,EAAgC,GAQ7C;CAED,IAAMC,oBAAY,IAAI,QAAuB;CAyB7C,OAAO;EACL,oBAxByB,MAAmF;GAC5G,IAAM,EAAE,uBAAoB,kBAAeP,EAAQ,QAAQ;GAC3D,IAAI,CAACQ,KAAsB,CAACC,GAE1B,MADAT,EAAQ,OAAO,GACT,IAAIU,EAAoB;GAEhC,IAAIF,MAAuB,CAACC,KAAcT,EAAQ,aAAa,IAAI;IACjE,IAAMW,IAAS,MAAMX,EAAQ,eAAe;IAC5C,IAAIW,EAAO,SAAS,mBAKlB,MAJKJ,EAAU,IAAII,CAAM,MACvBJ,EAAU,IAAII,CAAM,GACpBX,EAAQ,OAAO,IAEX,IAAIU,EAAoB;IAIhC,IAAIE,EAAc,QAAQ,SAAS,MAAM,IAAI5B,EAAM,cAAc;IACjE,IAAI2B,EAAO,SAAS,oBAAoB,MAAM,IAAIE,EAAqBF,EAAO,KAAK;GACrF;GACA,OAAOC;EACT;EAIE,SAAS,EAAE,SAASE,EAAgBd,EAAQ,aAAa,EAAE;CAC7D;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ACachedChip.js","names":["_sfc_main","ACachedChip_vue_vue_type_script_setup_true_lang_default","ACachedChip_default"],"sources":["../../../../src/domains/cached/components/ACachedChip.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed } from 'vue'\nimport { useI18n } from 'vue-i18n'\nimport { useRouter } from 'vue-router'\nimport type { DocId, IntegerId } from '@/shared/types/common'\nimport { objectGetValueByPath } from '@/shared/utils/object'\nimport { isNull, isUndefined } from '@/shared/utils/common'\nimport { COMMON_CONFIG } from '@/shared/commonConfig'\nimport { useCachedItem } from '@/domains/cached/composables/useCachedItem'\n\nconst props = withDefaults(\n defineProps<{\n id?: null | undefined | IntegerId | DocId\n title?: string\n containerClass?: undefined | string\n getCachedFn: (id: any) => any\n displayTextPath: string\n route: string\n disableClick?: boolean\n openInNew?: boolean\n size?: string\n forceRounded?: boolean\n textOnly?: boolean\n fallbackIdText?: boolean\n wrapText?: boolean\n closable?: boolean\n customTitleFn?: (\n cachedItem: any,\n defaultTitle: string,\n displayTextPath: string,\n fallbackIdText: boolean\n ) => string | undefined\n }>(),\n {\n id: null,\n title: '',\n containerClass: 'd-inline-flex',\n disableClick: false,\n openInNew: false,\n size: 'small',\n forceRounded: false,\n textOnly: false,\n fallbackIdText: false,\n wrapText: false,\n closable: false,\n customTitleFn: undefined,\n }\n)\n\nconst emit = defineEmits<{\n (e: 'close', id: null | undefined | IntegerId | DocId): void\n}>()\n\nconst { t } = useI18n()\nconst router = useRouter()\nconst { cached, loaded, unresolved } = useCachedItem(() => props.getCachedFn(props.id as any))\n\n// An item the fetch could not resolve has only its placeholder to show: its id, and no link to a\n// detail that would not load either.\nconst linkDisabled = computed(() => props.disableClick || unresolved.value)\n\nconst containerClassComputed = computed(() => {\n return props.wrapText ? props.containerClass + ' a-chip--wrap' : props.containerClass\n})\n\n// A title given by the caller still wins over the placeholder.\nconst showUnresolved = computed(() => unresolved.value && props.title.length === 0)\n\nconst displayTitle = computed(() => {\n if (showUnresolved.value) return '#' + props.id\n if (props.customTitleFn && cached.value) {\n const customTitle = props.customTitleFn(cached.value, props.title, props.displayTextPath, props.fallbackIdText)\n if (customTitle !== undefined) {\n return customTitle\n }\n }\n if (props.title.length > 0) return props.title\n if (cached.value) {\n return objectGetValueByPath(cached.value, props.displayTextPath)\n }\n return props.fallbackIdText ? props.id : ''\n})\n\nconst onClick = () => {\n router.push({ name: props.route, params: { id: props.id } })\n}\n</script>\n\n<template>\n <div :class=\"containerClassComputed\">\n <template v-if=\"isNull(id) || isUndefined(id)\">\n <slot name=\"empty\">-</slot>\n </template>\n <div\n v-else-if=\"textOnly\"\n :title=\"unresolved ? t('common.model.cachedUnavailable') : undefined\"\n >\n <slot\n v-if=\"showUnresolved\"\n :id=\"id\"\n name=\"unresolved\"\n >\n {{ displayTitle }}\n </slot>\n <template v-else>{{ displayTitle }}</template>\n <VProgressCircular\n v-if=\"!loaded && title.length === 0\"\n :size=\"12\"\n :width=\"2\"\n indeterminate\n class=\"mx-1\"\n />\n </div>\n <VChip\n v-else-if=\"linkDisabled\"\n :size=\"size\"\n :label=\"forceRounded ? undefined : true\"\n :closable=\"closable\"\n close-label=\"common.button.remove\"\n @click:close=\"() => emit('close', id)\"\n >\n <slot\n v-if=\"showUnresolved\"\n :id=\"id\"\n name=\"unresolved\"\n >\n {{ displayTitle }}\n </slot>\n <template v-else>{{ displayTitle }}</template>\n <VTooltip\n v-if=\"unresolved\"\n activator=\"parent\"\n location=\"bottom\"\n >\n {{ t('common.model.cachedUnavailable') }}\n </VTooltip>\n <VProgressCircular\n v-if=\"!loaded && title.length === 0\"\n :size=\"12\"\n :width=\"2\"\n indeterminate\n class=\"mx-1\"\n />\n </VChip>\n <VChip\n v-else\n :size=\"size\"\n :append-icon=\"openInNew ? COMMON_CONFIG.CHIP.ICON.LINK_EXTERNAL : COMMON_CONFIG.CHIP.ICON.LINK\"\n :label=\"forceRounded ? undefined : true\"\n :closable=\"closable\"\n close-label=\"common.button.remove\"\n @click.stop=\"onClick\"\n @click:close=\"() => emit('close', id)\"\n >\n {{ displayTitle }}\n <VProgressCircular\n v-if=\"!loaded && title.length === 0\"\n :size=\"12\"\n :width=\"2\"\n indeterminate\n class=\"mx-1\"\n />\n </VChip>\n </div>\n</template>\n\n<style lang=\"scss\">\n.a-chip--wrap {\n .v-chip {\n height: auto !important;\n }\n\n .v-chip .v-chip__content {\n max-width: 100%;\n height: auto;\n min-height: 26px;\n white-space: pre-wrap;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"ACachedChip.js","names":["_sfc_main","ACachedChip_vue_vue_type_script_setup_true_lang_default","ACachedChip_default"],"sources":["../../../../src/domains/cached/components/ACachedChip.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { computed } from 'vue'\nimport { useI18n } from 'vue-i18n'\nimport { useRouter } from 'vue-router'\nimport type { DocId, IntegerId } from '@/shared/types/common'\nimport { objectGetValueByPath } from '@/shared/utils/object'\nimport { isNull, isUndefined } from '@/shared/utils/common'\nimport { COMMON_CONFIG } from '@/shared/commonConfig'\nimport { useCachedItem } from '@/domains/cached/composables/useCachedItem'\n\nconst props = withDefaults(\n defineProps<{\n id?: null | undefined | IntegerId | DocId\n title?: string\n containerClass?: undefined | string\n getCachedFn: (id: any) => any\n displayTextPath: string\n route: string\n disableClick?: boolean\n openInNew?: boolean\n size?: string\n forceRounded?: boolean\n textOnly?: boolean\n fallbackIdText?: boolean\n wrapText?: boolean\n closable?: boolean\n customTitleFn?: (\n cachedItem: any,\n defaultTitle: string,\n displayTextPath: string,\n fallbackIdText: boolean\n ) => string | undefined\n }>(),\n {\n id: null,\n title: '',\n containerClass: 'd-inline-flex',\n disableClick: false,\n openInNew: false,\n size: 'small',\n forceRounded: false,\n textOnly: false,\n fallbackIdText: false,\n wrapText: false,\n closable: false,\n customTitleFn: undefined,\n }\n)\n\nconst emit = defineEmits<{\n (e: 'close', id: null | undefined | IntegerId | DocId): void\n}>()\n\nconst { t } = useI18n()\nconst router = useRouter()\nconst { cached, loaded, unresolved } = useCachedItem(() => props.getCachedFn(props.id as any))\n\n// An item the fetch could not resolve shows only its id placeholder.\n// It gets no link, because its detail would not load either.\nconst linkDisabled = computed(() => props.disableClick || unresolved.value)\n\nconst containerClassComputed = computed(() => {\n return props.wrapText ? props.containerClass + ' a-chip--wrap' : props.containerClass\n})\n\n// A title given by the caller still wins over the placeholder.\nconst showUnresolved = computed(() => unresolved.value && props.title.length === 0)\n\nconst displayTitle = computed(() => {\n if (showUnresolved.value) return '#' + props.id\n if (props.customTitleFn && cached.value) {\n const customTitle = props.customTitleFn(cached.value, props.title, props.displayTextPath, props.fallbackIdText)\n if (customTitle !== undefined) {\n return customTitle\n }\n }\n if (props.title.length > 0) return props.title\n if (cached.value) {\n return objectGetValueByPath(cached.value, props.displayTextPath)\n }\n return props.fallbackIdText ? props.id : ''\n})\n\nconst onClick = () => {\n router.push({ name: props.route, params: { id: props.id } })\n}\n</script>\n\n<template>\n <div :class=\"containerClassComputed\">\n <template v-if=\"isNull(id) || isUndefined(id)\">\n <slot name=\"empty\">-</slot>\n </template>\n <div\n v-else-if=\"textOnly\"\n :title=\"unresolved ? t('common.model.cachedUnavailable') : undefined\"\n >\n <slot\n v-if=\"showUnresolved\"\n :id=\"id\"\n name=\"unresolved\"\n >\n {{ displayTitle }}\n </slot>\n <template v-else>{{ displayTitle }}</template>\n <VProgressCircular\n v-if=\"!loaded && title.length === 0\"\n :size=\"12\"\n :width=\"2\"\n indeterminate\n class=\"mx-1\"\n />\n </div>\n <VChip\n v-else-if=\"linkDisabled\"\n :size=\"size\"\n :label=\"forceRounded ? undefined : true\"\n :closable=\"closable\"\n close-label=\"common.button.remove\"\n @click:close=\"() => emit('close', id)\"\n >\n <slot\n v-if=\"showUnresolved\"\n :id=\"id\"\n name=\"unresolved\"\n >\n {{ displayTitle }}\n </slot>\n <template v-else>{{ displayTitle }}</template>\n <VTooltip\n v-if=\"unresolved\"\n activator=\"parent\"\n location=\"bottom\"\n >\n {{ t('common.model.cachedUnavailable') }}\n </VTooltip>\n <VProgressCircular\n v-if=\"!loaded && title.length === 0\"\n :size=\"12\"\n :width=\"2\"\n indeterminate\n class=\"mx-1\"\n />\n </VChip>\n <VChip\n v-else\n :size=\"size\"\n :append-icon=\"openInNew ? COMMON_CONFIG.CHIP.ICON.LINK_EXTERNAL : COMMON_CONFIG.CHIP.ICON.LINK\"\n :label=\"forceRounded ? undefined : true\"\n :closable=\"closable\"\n close-label=\"common.button.remove\"\n @click.stop=\"onClick\"\n @click:close=\"() => emit('close', id)\"\n >\n {{ displayTitle }}\n <VProgressCircular\n v-if=\"!loaded && title.length === 0\"\n :size=\"12\"\n :width=\"2\"\n indeterminate\n class=\"mx-1\"\n />\n </VChip>\n </div>\n</template>\n\n<style lang=\"scss\">\n.a-chip--wrap {\n .v-chip {\n height: auto !important;\n }\n\n .v-chip .v-chip__content {\n max-width: 100%;\n height: auto;\n min-height: 26px;\n white-space: pre-wrap;\n }\n}\n</style>\n"],"mappings":""}