@anzusystems/common-admin 2.0.0-rc.4 → 2.0.0-rc.6

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 (680) hide show
  1. package/README.md +1 -1
  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.vue.d.ts +17 -15
  424. package/dist/domains/filters/components/AFilterWrapperSidebar.vue.d.ts +5 -3
  425. package/dist/domains/filters/components/FiltersSelected.js.map +1 -1
  426. package/dist/domains/filters/components/FiltersSelected.vue_vue_type_script_setup_true_lang.js.map +1 -1
  427. package/dist/domains/filters/composables/filterFactory.d.ts +16 -26
  428. package/dist/domains/filters/composables/filterFactory.js +38 -31
  429. package/dist/domains/filters/composables/filterFactory.js.map +1 -1
  430. package/dist/domains/filters/datatable/components/ADatatableOrdering.js.map +1 -1
  431. package/dist/domains/filters/datatable/components/ADatatableOrdering.vue_vue_type_script_setup_true_lang.js +3 -1
  432. package/dist/domains/filters/datatable/components/ADatatableOrdering.vue_vue_type_script_setup_true_lang.js.map +1 -1
  433. package/dist/domains/filters/datatable/components/ADatatablePagination.js.map +1 -1
  434. package/dist/domains/filters/datatable/components/ADatatablePagination.vue_vue_type_script_setup_true_lang.js +2 -4
  435. package/dist/domains/filters/datatable/components/ADatatablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  436. package/dist/domains/filters/utils/filterInjectionKeys.js.map +1 -1
  437. package/dist/domains/form/components/AFormDatetimePicker.js.map +1 -1
  438. package/dist/domains/form/components/AFormDatetimePicker.vue.d.ts +7 -5
  439. package/dist/domains/form/components/AFormDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  440. package/dist/domains/form/components/AFormFlagDatetimePicker.js.map +1 -1
  441. package/dist/domains/form/components/AFormFlagDatetimePicker.vue.d.ts +7 -5
  442. package/dist/domains/form/components/AFormFlagDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  443. package/dist/domains/form/components/AFormSwitch.vue.d.ts +7 -5
  444. package/dist/domains/form/components/AFormTextField.js.map +1 -1
  445. package/dist/domains/form/components/AFormTextField.vue.d.ts +9 -7
  446. package/dist/domains/form/components/AFormTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  447. package/dist/domains/form/components/AFormTextarea.vue.d.ts +13 -11
  448. package/dist/domains/form/components/AFormValueObjectOptionsSelect.vue.d.ts +7 -5
  449. package/dist/domains/form/components/ASystemEntityScope.vue.d.ts +5 -3
  450. package/dist/domains/job/api/jobApi.js.map +1 -1
  451. package/dist/domains/job/components/AJobDetailCommon.vue.d.ts +5 -3
  452. package/dist/domains/listEditor/components/AListEditor.js.map +1 -1
  453. package/dist/domains/listEditor/components/AListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  454. package/dist/domains/listEditor/components/ANestedSortableListEditor.js.map +1 -1
  455. package/dist/domains/listEditor/components/ANestedSortableListEditor.vue.d.ts +2 -3
  456. package/dist/domains/listEditor/components/ANestedSortableListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  457. package/dist/domains/listEditor/components/ASortableListEditor.js.map +1 -1
  458. package/dist/domains/listEditor/components/ASortableListEditor.vue.d.ts +2 -3
  459. package/dist/domains/listEditor/components/ASortableListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  460. package/dist/domains/listEditor/composables/useListEditorController.d.ts +4 -5
  461. package/dist/domains/listEditor/composables/useListEditorController.js.map +1 -1
  462. package/dist/domains/listEditor/composables/useNestedListEditor.d.ts +3 -4
  463. package/dist/domains/listEditor/composables/useNestedListEditor.js.map +1 -1
  464. package/dist/domains/listEditor/composables/useNestedListEditorController.d.ts +5 -4
  465. package/dist/domains/listEditor/composables/useNestedListEditorController.js.map +1 -1
  466. package/dist/domains/listEditor/composables/useReorderMode.js.map +1 -1
  467. package/dist/domains/listEditor/types/listEditorTypes.d.ts +2 -2
  468. package/dist/domains/listEditor/utils/listEditorLoader.d.ts +5 -5
  469. package/dist/domains/listEditor/utils/listEditorLoader.js.map +1 -1
  470. package/dist/domains/listEditor/utils/resolveCompactText.js.map +1 -1
  471. package/dist/domains/log/api/logApi.d.ts +2 -3
  472. package/dist/domains/log/api/logApi.js.map +1 -1
  473. package/dist/domains/log/components/ALogDatatable.js.map +1 -1
  474. package/dist/domains/log/components/ALogDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  475. package/dist/domains/log/components/ALogDetailView.js.map +1 -1
  476. package/dist/domains/log/components/ALogDetailView.vue.d.ts +1 -1
  477. package/dist/domains/log/components/ALogDetailView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  478. package/dist/domains/log/components/ALogFilter.js.map +1 -1
  479. package/dist/domains/log/components/ALogFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  480. package/dist/domains/log/components/ALogListView.js.map +1 -1
  481. package/dist/domains/log/components/ALogListView.vue.d.ts +1 -1
  482. package/dist/domains/log/components/ALogListView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  483. package/dist/domains/log/composables/logActions.d.ts +4 -5
  484. package/dist/domains/log/composables/logActions.js.map +1 -1
  485. package/dist/domains/log/composables/logType.d.ts +6 -7
  486. package/dist/domains/log/composables/logType.js.map +1 -1
  487. package/dist/domains/log/filter/logFilter.d.ts +8 -11
  488. package/dist/domains/log/filter/logFilter.js.map +1 -1
  489. package/dist/domains/permission/components/APermissionEditor.js.map +1 -1
  490. package/dist/domains/permission/components/APermissionEditor.vue.d.ts +4 -4
  491. package/dist/domains/permission/components/APermissionEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  492. package/dist/domains/permission/composables/permissionActions.d.ts +3 -6
  493. package/dist/domains/permission/composables/permissionActions.js.map +1 -1
  494. package/dist/domains/permission/config/api/permissionConfigApi.d.ts +2 -2
  495. package/dist/domains/permission/config/api/permissionConfigApi.js.map +1 -1
  496. package/dist/domains/permission/config/composables/permissionConfigActions.d.ts +3 -7
  497. package/dist/domains/permission/config/composables/permissionConfigActions.js.map +1 -1
  498. package/dist/domains/permission/config/store/permissionConfigStore.d.ts +2 -4
  499. package/dist/domains/permission/config/store/permissionConfigStore.js.map +1 -1
  500. package/dist/domains/permission/group/api/permissionGroupApi.d.ts +8 -10
  501. package/dist/domains/permission/group/api/permissionGroupApi.js.map +1 -1
  502. package/dist/domains/permission/group/components/APermissionGroupDatatable.js.map +1 -1
  503. package/dist/domains/permission/group/components/APermissionGroupDatatable.vue.d.ts +12 -10
  504. package/dist/domains/permission/group/components/APermissionGroupDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  505. package/dist/domains/permission/group/components/APermissionGroupDetail.js.map +1 -1
  506. package/dist/domains/permission/group/components/APermissionGroupDetail.vue.d.ts +21 -22
  507. package/dist/domains/permission/group/components/APermissionGroupDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  508. package/dist/domains/permission/group/components/APermissionGroupManage.js.map +1 -1
  509. package/dist/domains/permission/group/components/APermissionGroupManage.vue.d.ts +21 -22
  510. package/dist/domains/permission/group/components/APermissionGroupManage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  511. package/dist/domains/permission/group/composables/cachedPermissionGroups.js.map +1 -1
  512. package/dist/domains/permission/group/composables/permissionGroupActions.d.ts +6 -8
  513. package/dist/domains/permission/group/composables/permissionGroupActions.js.map +1 -1
  514. package/dist/domains/permission/group/composables/permissionGroupValidations.d.ts +2 -3
  515. package/dist/domains/permission/group/composables/permissionGroupValidations.js.map +1 -1
  516. package/dist/domains/permission/group/filter/permissionGroupFilter.d.ts +2 -3
  517. package/dist/domains/permission/group/filter/permissionGroupFilter.js.map +1 -1
  518. package/dist/domains/permission/group/store/permissionGroupStore.d.ts +3 -6
  519. package/dist/domains/permission/group/store/permissionGroupStore.js.map +1 -1
  520. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocomplete.js.map +1 -1
  521. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  522. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocompleteWithMinimal.js.map +1 -1
  523. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocompleteWithMinimal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  524. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocomplete.js.map +1 -1
  525. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  526. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocompleteWithCached.vue.d.ts +5 -3
  527. package/dist/domains/remoteAutocomplete/composables/createRemoteAutocomplete.d.ts +11 -13
  528. package/dist/domains/remoteAutocomplete/composables/createRemoteAutocomplete.js.map +1 -1
  529. package/dist/domains/subjectSelect/components/AFilterWrapperSubjectSelect.vue.d.ts +13 -11
  530. package/dist/domains/subjectSelect/components/ASubjectSelect.js.map +1 -1
  531. package/dist/domains/subjectSelect/components/ASubjectSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  532. package/dist/domains/subjectSelect/composables/useSubjectSelect.js +53 -51
  533. package/dist/domains/subjectSelect/composables/useSubjectSelect.js.map +1 -1
  534. package/dist/domains/system/appShell/components/AActionbar.vue.d.ts +7 -5
  535. package/dist/domains/system/appShell/components/ALayoutSwitch.js.map +1 -1
  536. package/dist/domains/system/appShell/components/ALayoutSwitch.vue.d.ts +7 -5
  537. package/dist/domains/system/appShell/components/ALayoutSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  538. package/dist/domains/system/appShell/composables/teleportSlot.d.ts +0 -1
  539. package/dist/domains/system/appShell/composables/teleportSlot.js.map +1 -1
  540. package/dist/domains/system/components/AAlerts.js.map +1 -1
  541. package/dist/domains/system/components/AAlerts.vue_vue_type_script_setup_true_lang.js.map +1 -1
  542. package/dist/domains/system/composables/alerts.js.map +1 -1
  543. package/dist/domains/system/composables/breadcrumbs.d.ts +3 -3
  544. package/dist/domains/system/composables/breadcrumbs.js.map +1 -1
  545. package/dist/domains/system/composables/languageSettings.js.map +1 -1
  546. package/dist/domains/system/composables/loginStatus.js.map +1 -1
  547. package/dist/domains/system/composables/navigationError.d.ts +6 -8
  548. package/dist/domains/system/composables/navigationError.js.map +1 -1
  549. package/dist/domains/system/composables/pageNavigation.d.ts +9 -10
  550. package/dist/domains/system/composables/pageNavigation.js.map +1 -1
  551. package/dist/domains/system/composables/recordActions.d.ts +14 -22
  552. package/dist/domains/system/composables/recordActions.js.map +1 -1
  553. package/dist/domains/system/composables/recordPage.d.ts +23 -38
  554. package/dist/domains/system/composables/recordPage.js.map +1 -1
  555. package/dist/domains/system/composables/routeHistory.d.ts +4 -5
  556. package/dist/domains/system/composables/routeHistory.js.map +1 -1
  557. package/dist/domains/system/composables/sentry.js.map +1 -1
  558. package/dist/domains/system/composables/useDebugFeatures.d.ts +3 -6
  559. package/dist/domains/system/composables/useDebugFeatures.js.map +1 -1
  560. package/dist/domains/system/store/datatablePageStore.d.ts +8 -1
  561. package/dist/domains/system/store/datatablePageStore.js +10 -3
  562. package/dist/domains/system/store/datatablePageStore.js.map +1 -1
  563. package/dist/domains/system/systemBar/components/ASystemBar.js.map +1 -1
  564. package/dist/domains/system/systemBar/components/ASystemBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  565. package/dist/domains/system/systemBar/utils/appReload.d.ts +5 -5
  566. package/dist/domains/system/systemBar/utils/appReload.js.map +1 -1
  567. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.js.map +1 -1
  568. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.vue.d.ts +2 -3
  569. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.vue_vue_type_script_setup_true_lang.js.map +1 -1
  570. package/dist/domains/ui/buttons/action/components/AActionDeleteButton.js.map +1 -1
  571. package/dist/domains/ui/buttons/action/components/AActionDeleteButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  572. package/dist/domains/ui/buttons/components/ABtnSplit.vue.d.ts +9 -7
  573. package/dist/domains/ui/components/AAvatarColorPicker.js.map +1 -1
  574. package/dist/domains/ui/components/AAvatarColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  575. package/dist/domains/ui/components/ACard.js.map +1 -1
  576. package/dist/domains/ui/components/ACard.vue.d.ts +7 -3
  577. package/dist/domains/ui/components/ACard.vue_vue_type_script_setup_true_lang.js +6 -2
  578. package/dist/domains/ui/components/ACard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  579. package/dist/domains/ui/components/ACardLoader.js.map +1 -1
  580. package/dist/domains/ui/components/ACardLoader.vue.d.ts +1 -0
  581. package/dist/domains/ui/components/ACardLoader.vue_vue_type_script_setup_true_lang.js +13 -7
  582. package/dist/domains/ui/components/ACardLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  583. package/dist/domains/ui/components/AChipNoLink.vue.d.ts +5 -3
  584. package/dist/domains/ui/components/ACopyText.vue.d.ts +9 -7
  585. package/dist/domains/ui/components/ACreateDialog.js.map +1 -1
  586. package/dist/domains/ui/components/ACreateDialog.vue.d.ts +11 -9
  587. package/dist/domains/ui/components/ACreateDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  588. package/dist/domains/ui/components/ADialogToolbar.vue.d.ts +5 -3
  589. package/dist/domains/ui/components/ARow.vue.d.ts +5 -3
  590. package/dist/domains/ui/components/ATimeTrackingFields.js.map +1 -1
  591. package/dist/domains/ui/components/ATimeTrackingFields.vue_vue_type_script_setup_true_lang.js.map +1 -1
  592. package/dist/domains/ui/components/AUserAndTimeTrackingFields.js.map +1 -1
  593. package/dist/domains/ui/components/AUserAndTimeTrackingFields.vue.d.ts +3 -5
  594. package/dist/domains/ui/components/AUserAndTimeTrackingFields.vue_vue_type_script_setup_true_lang.js.map +1 -1
  595. package/dist/domains/ui/datetime/components/ADatetimePicker.js +1 -1
  596. package/dist/domains/ui/datetime/components/ADatetimePicker.js.map +1 -1
  597. package/dist/domains/ui/datetime/components/ADatetimePicker.vue.d.ts +5 -3
  598. package/dist/domains/ui/datetime/components/ADatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  599. package/dist/domains/ui/file/components/AFileDropzone.js.map +1 -1
  600. package/dist/domains/ui/file/components/AFileDropzone.vue.d.ts +1 -1
  601. package/dist/domains/ui/file/components/AFileDropzone.vue_vue_type_script_setup_true_lang.js.map +1 -1
  602. package/dist/domains/ui/file/components/AFileInput.js.map +1 -1
  603. package/dist/domains/ui/file/components/AFileInput.vue.d.ts +9 -7
  604. package/dist/domains/ui/file/components/AFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  605. package/dist/domains/ui/file/components/AFileInputDialog.js.map +1 -1
  606. package/dist/domains/ui/file/components/AFileInputDialog.vue.d.ts +9 -7
  607. package/dist/domains/ui/file/components/AFileInputDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  608. package/dist/domains/ui/file/composables/dropzone.js.map +1 -1
  609. package/dist/domains/ui/file/composables/formatAndSizeCheck.js.map +1 -1
  610. package/dist/domains/ui/view/components/AGenericView.vue.d.ts +7 -5
  611. package/dist/domains/ui/view/components/ALoginView.js +1 -1
  612. package/dist/domains/ui/view/components/ALoginView.js.map +1 -1
  613. package/dist/domains/ui/view/components/ALoginView.vue.d.ts +5 -3
  614. package/dist/domains/ui/view/components/ALoginView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  615. package/dist/domains/ui/view/components/ALogoutView.js.map +1 -1
  616. package/dist/domains/ui/view/components/ALogoutView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  617. package/dist/domains/ui/view/components/ANotFoundView.js.map +1 -1
  618. package/dist/domains/ui/view/components/ANotFoundView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  619. package/dist/domains/unsavedGuard/composables/useUnsavedChangesGuard.d.ts +6 -7
  620. package/dist/domains/unsavedGuard/composables/useUnsavedChangesGuard.js.map +1 -1
  621. package/dist/lib.d.ts +2 -2
  622. package/dist/plugins/commonVuetifyConfig.d.ts +3 -3
  623. package/dist/plugins/commonVuetifyConfig.js.map +1 -1
  624. package/dist/plugins/i18n.d.ts +4 -5
  625. package/dist/plugins/i18n.js.map +1 -1
  626. package/dist/plugins/pluginOptions.d.ts +4 -2
  627. package/dist/plugins/pluginOptions.js.map +1 -1
  628. package/dist/plugins/webfontloader.js.map +1 -1
  629. package/dist/shared/error/AnzuApiCancelledError.d.ts +5 -8
  630. package/dist/shared/error/AnzuApiCancelledError.js.map +1 -1
  631. package/dist/shared/error/AnzuError.d.ts +3 -5
  632. package/dist/shared/error/AnzuError.js.map +1 -1
  633. package/dist/shared/error/AuthUnavailableError.d.ts +3 -3
  634. package/dist/shared/error/AuthUnavailableError.js.map +1 -1
  635. package/dist/shared/error/isInCauseChain.d.ts +2 -2
  636. package/dist/shared/error/isInCauseChain.js.map +1 -1
  637. package/dist/shared/types/UserAndTimeTracking.d.ts +5 -5
  638. package/dist/shared/types/Validation.d.ts +4 -5
  639. package/dist/shared/types/common.d.ts +1 -3
  640. package/dist/shared/types/globalComponents.d.ts +5 -6
  641. package/dist/shared/utils/common.js.map +1 -1
  642. package/dist/shared/utils/datetime.d.ts +0 -1
  643. package/dist/shared/utils/datetime.js.map +1 -1
  644. package/dist/shared/utils/datetimePickerValue.d.ts +4 -7
  645. package/dist/shared/utils/datetimePickerValue.js.map +1 -1
  646. package/dist/shared/utils/development.d.ts +3 -3
  647. package/dist/shared/utils/development.js.map +1 -1
  648. package/dist/shared/utils/envConfig.d.ts +4 -4
  649. package/dist/shared/utils/envConfig.js.map +1 -1
  650. package/dist/shared/utils/json.d.ts +1 -1
  651. package/dist/shared/utils/json.js.map +1 -1
  652. package/dist/shared/utils/userAndTimeTracking.d.ts +5 -7
  653. package/dist/shared/utils/userAndTimeTracking.js.map +1 -1
  654. package/dist/shared/validators/vuelidate/common/useValidateHexColor.d.ts +3 -5
  655. package/dist/shared/validators/vuelidate/common/useValidateHexColor.js.map +1 -1
  656. package/dist/testing/appShell.d.ts +11 -11
  657. package/dist/testing/appShell.js.map +1 -1
  658. package/dist/testing/closeButtons.d.ts +9 -11
  659. package/dist/testing/closeButtons.js.map +1 -1
  660. package/dist/testing/declaredDependencies.d.ts +7 -7
  661. package/dist/testing/declaredDependencies.js.map +1 -1
  662. package/dist/testing/generatedRoutes.d.ts +6 -11
  663. package/dist/testing/generatedRoutes.js.map +1 -1
  664. package/dist/testing/routeHistory.d.ts +5 -12
  665. package/dist/testing/routeHistory.js.map +1 -1
  666. package/dist/testing/sortableLists.d.ts +16 -21
  667. package/dist/testing/sortableLists.js.map +1 -1
  668. package/dist/testing/typedRouter.d.ts +0 -1
  669. package/dist/testing/typedRouter.js.map +1 -1
  670. package/package.json +26 -26
  671. package/src/eslint/adminConfig.mjs +19 -27
  672. package/src/eslint/globalComponentNames.mjs +3 -4
  673. package/src/eslint/oxlint.mjs +7 -20
  674. package/src/eslint/plugin.d.mts +2 -4
  675. package/src/eslint/plugin.mjs +18 -34
  676. package/src/eslint/validRouteName.mjs +6 -7
  677. package/src/vite/devWatch.mjs +30 -43
  678. package/src/vite/index.d.mts +5 -5
  679. package/src/vite/sentry.mjs +7 -12
  680. package/src/vite/sourcemaps.mjs +4 -8
@@ -1 +1 @@
1
- {"version":3,"file":"appShell.js","names":["describeAlertHost","bySrcPath","sources","path","source","globKeyToSrcPath","it","host","template","expect","withHost","CSS_LAYER_ORDER","CSS_SUBLAYER_ORDER","CSS_LAYER_STATEMENTS","parent","layers","layer","describeCssLayerOrder","html","indexHtml","layerList","statement","leadingStatements","css","first","head","statements"],"sources":["../../src/testing/appShell.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath } from '@/testing/typedRouter'\n\nexport interface DescribeAlertHostOptions {\n /** The admin's components: `import.meta.glob(['/src/**\\/*.vue', '!/src/test/**'], { query: '?raw', import: 'default', eager: true })`. */\n sources: Record<string, string>\n /** The component with the layout switch, which mounts `<AAlerts />`. */\n host?: string\n}\n\n/**\n * Where the alerts land.\n *\n * `AAlerts` is the host every `showError` / `showWarning` renders into. It is mounted once, outside the\n * layout switch: by `ALayoutSwitch`, or next to the admin's own `<component :is=\"layout\">`. A host inside a\n * layout took the alerts it was showing away with it when the route switched layouts -- a start-up\n * error raised under the loader vanished the moment the drawer replaced it -- and a layout without one\n * had nowhere to show them at all.\n */\nexport function describeAlertHost({ sources, host = 'src/layouts/AppLayout.vue' }: DescribeAlertHostOptions): void {\n const bySrcPath = new Map(Object.entries(sources).map(([path, source]) => [globKeyToSrcPath(path), source]))\n\n describe('the alerts host', () => {\n it(`is mounted once, in ${host}, before the layout switch`, () => {\n const source = bySrcPath.get(host)\n expect(source).toBeDefined()\n const template = source!.slice(source!.indexOf('<template>'))\n\n // `ALayoutSwitch` mounts it itself, before the layout it switches.\n if (/<ALayoutSwitch\\b/.test(template)) {\n expect(template.match(/<ALayoutSwitch\\b/g)).toHaveLength(1)\n expect(template).not.toMatch(/<AAlerts/)\n return\n }\n expect(template.match(/<AAlerts\\s*\\/>/g)).toHaveLength(1)\n expect(template.indexOf('<AAlerts')).toBeLessThan(template.indexOf('<component :is'))\n })\n\n it('is nowhere else: no layout, page or component of its own', () => {\n // A guard on the guard: the glob has to see the layouts for the assertion below to mean anything.\n expect([...bySrcPath.keys()].filter((path) => path.startsWith('src/layouts/')).length).toBeGreaterThan(2)\n\n const withHost = [...bySrcPath]\n .filter(([path, source]) => !path.startsWith('src/test/') && /<(AAlerts|ALayoutSwitch)\\b/.test(source))\n .map(([path]) => path)\n\n expect(withHost).toEqual([host])\n })\n })\n}\n\n/** The `@layer` statement an admin's index.html opens with: the library's layer sits between Vuetify's overrides and its utilities. */\nexport const CSS_LAYER_ORDER = [\n 'vuetify-core',\n 'vuetify-components',\n 'vuetify-overrides',\n 'anzu-common',\n 'vuetify-utilities',\n 'vuetify-final',\n] as const\n\n/**\n * Vuetify's sub-layers, in the order its `main.css` declares them. Its component stylesheets name them\n * too (13 of them name `vuetify-final.trumps`), and a component stylesheet can load before `main.css`: in a\n * cms build one named `trumps` ahead of `transitions` and put the two in reverse.\n */\nexport const CSS_SUBLAYER_ORDER = {\n 'vuetify-core': ['reset', 'base'],\n 'vuetify-utilities': ['theme-base', 'typography', 'helpers', 'theme-background', 'theme-foreground'],\n 'vuetify-final': ['transitions', 'trumps'],\n} as const\n\n/** The statements an admin's index.html opens its first `<style>` with, one per line. */\nexport const CSS_LAYER_STATEMENTS: readonly string[] = [\n `@layer ${CSS_LAYER_ORDER.join(', ')};`,\n ...Object.entries(CSS_SUBLAYER_ORDER).map(\n ([parent, layers]) => `@layer ${layers.map((layer) => `${parent}.${layer}`).join(', ')};`\n ),\n]\n\n/**\n * The library's stylesheet is one cascade layer, `anzu-common`. The `@layer` statement in index.html\n * comes before every stylesheet, so it alone decides where that layer lands: after Vuetify's overrides\n * and before its utility classes, so that a utility in a template beats the library's styles. A layer\n * the statement does not name is appended after `vuetify-final`, above the utilities.\n *\n * Layers are ordered by first mention, so the statements only decide if nothing names a layer before\n * them: they have to open the first style in the page, in `<head>`, ahead of any stylesheet link and any\n * other rule. The same holds for Vuetify's sub-layers, which follow in the same `<style>`.\n */\nexport function describeCssLayerOrder({ indexHtml }: { indexHtml: string | undefined }): void {\n describe('the cascade layer order in index.html', () => {\n // What the browser does not apply as a style of the page: comments, and the contents of <noscript>\n // and <template>.\n const html = (indexHtml ?? '')\n .replace(/<!--[\\s\\S]*?-->/g, '')\n .replace(/<(noscript|template)\\b[\\s\\S]*?<\\/\\1\\s*>/gi, '')\n const layerList = (statement: string | undefined) =>\n /^@layer\\s+([^;{]+);$/\n .exec(statement ?? '')?.[1]\n ?.split(',')\n .map((layer) => layer.trim())\n // The `@layer a, b;` statements a stylesheet opens with, up to its first other rule.\n const leadingStatements = (css: string) =>\n /^(?:\\s*@layer\\s[^;{]*;)*/.exec(css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''))![0].match(/@layer\\s[^;{]*;/g) ?? []\n\n it('puts the library between the Vuetify overrides and the utilities', () => {\n expect(layerList(/@layer\\s[^;{]*;/.exec(html)?.[0])).toEqual([...CSS_LAYER_ORDER])\n })\n\n const first =\n /<style\\b[^>]*>([\\s\\S]*?)<\\/style>|<link\\b[^>]*\\brel\\s*=\\s*[\"']?(?:stylesheet|preload\\b[^>]*\\bas\\s*=\\s*[\"']?style)\\b[^>]*>/i.exec(\n html\n )\n\n it('opens the first style in the page', () => {\n expect(first?.[0], 'the first <style> or stylesheet <link>').toMatch(/^<style/i)\n const head = html.search(/<\\/head\\s*>/i)\n if (head >= 0) expect(first!.index, 'the first <style> is in <head>').toBeLessThan(head)\n expect(layerList(leadingStatements(first?.[1] ?? '')[0]), 'the first rule of the first <style>').toEqual([\n ...CSS_LAYER_ORDER,\n ])\n })\n\n it(\"orders Vuetify's sub-layers right after it\", () => {\n const statements = leadingStatements(first?.[1] ?? '').slice(1)\n expect(statements.slice(0, CSS_LAYER_STATEMENTS.length - 1).map(layerList)).toEqual(\n CSS_LAYER_STATEMENTS.slice(1).map(layerList)\n )\n })\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"appShell.js","names":["describeAlertHost","bySrcPath","sources","path","source","globKeyToSrcPath","it","host","template","expect","withHost","CSS_LAYER_ORDER","CSS_SUBLAYER_ORDER","CSS_LAYER_STATEMENTS","parent","layers","layer","describeCssLayerOrder","html","indexHtml","layerList","statement","leadingStatements","css","first","head","statements"],"sources":["../../src/testing/appShell.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath } from '@/testing/typedRouter'\n\nexport interface DescribeAlertHostOptions {\n /**\n * The admin's components: `import.meta.glob(['/src/**\\/*.vue', '!/src/test/**'], { query: '?raw', import: 'default', eager: true })`.\n */\n sources: Record<string, string>\n host?: string\n}\n\n/**\n * `AAlerts` is the host every `showError` / `showWarning` renders into. It is mounted once, outside\n * the layout switch: by `ALayoutSwitch`, or next to the admin's own `<component :is=\"layout\">`.\n * A host inside a layout takes its alerts away when the route switches layouts.\n * A start-up error raised under the loader vanished when the drawer replaced it.\n * A layout without a host has nowhere to show alerts.\n */\nexport function describeAlertHost({ sources, host = 'src/layouts/AppLayout.vue' }: DescribeAlertHostOptions): void {\n const bySrcPath = new Map(Object.entries(sources).map(([path, source]) => [globKeyToSrcPath(path), source]))\n\n describe('the alerts host', () => {\n it(`is mounted once, in ${host}, before the layout switch`, () => {\n const source = bySrcPath.get(host)\n expect(source).toBeDefined()\n const template = source!.slice(source!.indexOf('<template>'))\n\n if (/<ALayoutSwitch\\b/.test(template)) {\n expect(template.match(/<ALayoutSwitch\\b/g)).toHaveLength(1)\n expect(template).not.toMatch(/<AAlerts/)\n return\n }\n expect(template.match(/<AAlerts\\s*\\/>/g)).toHaveLength(1)\n expect(template.indexOf('<AAlerts')).toBeLessThan(template.indexOf('<component :is'))\n })\n\n it('is nowhere else: no layout, page or component of its own', () => {\n // A guard on the guard: the glob has to see the layouts for the assertion below to mean anything.\n expect([...bySrcPath.keys()].filter((path) => path.startsWith('src/layouts/')).length).toBeGreaterThan(2)\n\n const withHost = [...bySrcPath]\n .filter(([path, source]) => !path.startsWith('src/test/') && /<(AAlerts|ALayoutSwitch)\\b/.test(source))\n .map(([path]) => path)\n\n expect(withHost).toEqual([host])\n })\n })\n}\n\n/**\n * The `@layer` statement an admin's index.html opens with: the library's layer sits between Vuetify's overrides and its utilities.\n */\nexport const CSS_LAYER_ORDER = [\n 'vuetify-core',\n 'vuetify-components',\n 'vuetify-overrides',\n 'anzu-common',\n 'vuetify-utilities',\n 'vuetify-final',\n] as const\n\n/**\n * Vuetify's sub-layers, in the order its `main.css` declares them. Its component stylesheets name them\n * too (13 of them name `vuetify-final.trumps`), and a component stylesheet can load before `main.css`: in a\n * cms build one named `trumps` ahead of `transitions` and put the two in reverse.\n */\nexport const CSS_SUBLAYER_ORDER = {\n 'vuetify-core': ['reset', 'base'],\n 'vuetify-utilities': ['theme-base', 'typography', 'helpers', 'theme-background', 'theme-foreground'],\n 'vuetify-final': ['transitions', 'trumps'],\n} as const\n\nexport const CSS_LAYER_STATEMENTS: readonly string[] = [\n `@layer ${CSS_LAYER_ORDER.join(', ')};`,\n ...Object.entries(CSS_SUBLAYER_ORDER).map(\n ([parent, layers]) => `@layer ${layers.map((layer) => `${parent}.${layer}`).join(', ')};`\n ),\n]\n\n/**\n * The library's stylesheet is one cascade layer, `anzu-common`. The `@layer` statement in index.html\n * comes before every stylesheet, so it alone decides where that layer lands: after Vuetify's overrides\n * and before its utility classes, so that a utility in a template beats the library's styles. A layer\n * the statement does not name is appended after `vuetify-final`, above the utilities.\n *\n * Layers are ordered by first mention, so the statements only decide if nothing names a layer before\n * them: they have to open the first style in the page, in `<head>`, ahead of any stylesheet link and any\n * other rule. The same holds for Vuetify's sub-layers, which follow in the same `<style>`.\n */\nexport function describeCssLayerOrder({ indexHtml }: { indexHtml: string | undefined }): void {\n describe('the cascade layer order in index.html', () => {\n const html = (indexHtml ?? '')\n .replace(/<!--[\\s\\S]*?-->/g, '')\n .replace(/<(noscript|template)\\b[\\s\\S]*?<\\/\\1\\s*>/gi, '')\n const layerList = (statement: string | undefined) =>\n /^@layer\\s+([^;{]+);$/\n .exec(statement ?? '')?.[1]\n ?.split(',')\n .map((layer) => layer.trim())\n const leadingStatements = (css: string) =>\n /^(?:\\s*@layer\\s[^;{]*;)*/.exec(css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''))![0].match(/@layer\\s[^;{]*;/g) ?? []\n\n it('puts the library between the Vuetify overrides and the utilities', () => {\n expect(layerList(/@layer\\s[^;{]*;/.exec(html)?.[0])).toEqual([...CSS_LAYER_ORDER])\n })\n\n const first =\n /<style\\b[^>]*>([\\s\\S]*?)<\\/style>|<link\\b[^>]*\\brel\\s*=\\s*[\"']?(?:stylesheet|preload\\b[^>]*\\bas\\s*=\\s*[\"']?style)\\b[^>]*>/i.exec(\n html\n )\n\n it('opens the first style in the page', () => {\n expect(first?.[0], 'the first <style> or stylesheet <link>').toMatch(/^<style/i)\n const head = html.search(/<\\/head\\s*>/i)\n if (head >= 0) expect(first!.index, 'the first <style> is in <head>').toBeLessThan(head)\n expect(layerList(leadingStatements(first?.[1] ?? '')[0]), 'the first rule of the first <style>').toEqual([\n ...CSS_LAYER_ORDER,\n ])\n })\n\n it(\"orders Vuetify's sub-layers right after it\", () => {\n const statements = leadingStatements(first?.[1] ?? '').slice(1)\n expect(statements.slice(0, CSS_LAYER_STATEMENTS.length - 1).map(layerList)).toEqual(\n CSS_LAYER_STATEMENTS.slice(1).map(layerList)\n )\n })\n })\n}\n"],"mappings":"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"}
@@ -1,21 +1,19 @@
1
1
  export interface DescribeCloseButtonsOptions {
2
- /** Every `.vue` of the admin: `import.meta.glob('/src/**\/*.vue', { query: '?raw', import: 'default', eager: true })`. */
2
+ /**
3
+ * Every `.vue` of the admin: `import.meta.glob('/src/**\/*.vue', { query: '?raw', import: 'default', eager: true })`.
4
+ */
3
5
  sources: Record<string, string>;
4
- /** `src/typed-router.d.ts`, imported with `?raw`. */
5
6
  declaration: string;
6
- /** The admin's route history blacklist. */
7
7
  routeHistoryBlacklist: readonly string[];
8
8
  /** How many buttons may compute their fallback, which two checks cannot read. */
9
9
  maxComputedFallbacks?: number;
10
10
  }
11
11
  /**
12
- * The close buttons and the two route lists each one carries.
13
- *
14
- * `AActionCloseButtonHistory` walks the recorded history backwards for the first entry whose name is
15
- * not in `skipRouteNames`, and falls back to `fallbackRouteName` only when that walk comes up empty.
16
- * Both lists are plain strings inside a template: `anzu/valid-route-name` only reaches route names
17
- * written in `<script>`, and nothing type-checks a string in an attribute. Rename a page and the lists
18
- * keep the old name, silently -- a skip list that no longer names the view it sits on hands the user
19
- * straight back to the view they just closed.
12
+ * `AActionCloseButtonHistory` walks the recorded history backwards for the first entry
13
+ * not in `skipRouteNames`. It uses `fallbackRouteName` only when that walk finds nothing.
14
+ * Both lists are plain strings in a template. `anzu/valid-route-name` only
15
+ * checks names in `<script>`, and nothing type-checks an attribute string.
16
+ * After a page rename the lists silently keep the old name. A skip list that no
17
+ * longer names its own view sends the user back to the view they just closed.
20
18
  */
21
19
  export declare function describeCloseButtons({ sources, declaration, routeHistoryBlacklist, maxComputedFallbacks, }: DescribeCloseButtonsOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"closeButtons.js","names":["describeCloseButtons","parsed","parseTypedRouterDeclaration","declaration","routeNames","pageRoutes","importedBy","path","source","sources","target","key","globKeyToSrcPath","owningRoutes","seen","file","parent","listOf","match","attrs","name","value","buttons","recordPrefix","parts","i","closableRoutes","it","plain","own","expect","skip","fallback","expected","record","other","listing","created","bad","label","computed","fallbackComputed","maxComputedFallbacks","routeHistoryBlacklist","blacklisted"],"sources":["../../src/testing/closeButtons.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath, parseTypedRouterDeclaration } from '@/testing/typedRouter'\n\nexport interface DescribeCloseButtonsOptions {\n /** Every `.vue` of the admin: `import.meta.glob('/src/**\\/*.vue', { query: '?raw', import: 'default', eager: true })`. */\n sources: Record<string, string>\n /** `src/typed-router.d.ts`, imported with `?raw`. */\n declaration: string\n /** The admin's route history blacklist. */\n routeHistoryBlacklist: readonly string[]\n /** How many buttons may compute their fallback, which two checks cannot read. */\n maxComputedFallbacks?: number\n}\n\n/**\n * The close buttons and the two route lists each one carries.\n *\n * `AActionCloseButtonHistory` walks the recorded history backwards for the first entry whose name is\n * not in `skipRouteNames`, and falls back to `fallbackRouteName` only when that walk comes up empty.\n * Both lists are plain strings inside a template: `anzu/valid-route-name` only reaches route names\n * written in `<script>`, and nothing type-checks a string in an attribute. Rename a page and the lists\n * keep the old name, silently -- a skip list that no longer names the view it sits on hands the user\n * straight back to the view they just closed.\n */\nexport function describeCloseButtons({\n sources,\n declaration,\n routeHistoryBlacklist,\n maxComputedFallbacks = 3,\n}: DescribeCloseButtonsOptions): void {\n const parsed = parseTypedRouterDeclaration(declaration)\n const routeNames = new Set(parsed.names)\n const pageRoutes = parsed.pageRoutes\n\n const importedBy = new Map<string, Set<string>>()\n for (const [path, source] of Object.entries(sources)) {\n for (const [, target] of source.matchAll(/from\\s+'(@\\/[^']+\\.vue)'/g)) {\n const key = target!.replace(/^@\\//, 'src/')\n if (!importedBy.has(key)) importedBy.set(key, new Set())\n importedBy.get(key)!.add(globKeyToSrcPath(path))\n }\n }\n\n // A button sitting in a shared component belongs to whichever pages render it, however many\n // levels of component sit in between.\n const owningRoutes = (file: string, seen = new Set<string>()): string[] => {\n if (seen.has(file)) return []\n seen.add(file)\n const own = pageRoutes.get(file)\n if (own) return own\n return [...(importedBy.get(file) ?? [])].flatMap((parent) => owningRoutes(parent, seen))\n }\n\n const listOf = (attrs: string, name: string) => {\n const match = attrs.match(new RegExp(`:${name}=\"([^\"]*)\"`))\n return match ? [...match[1]!.matchAll(/'([^']*)'/g)].map(([, value]) => value!) : undefined\n }\n\n const buttons = Object.entries(sources).flatMap(([path, source]) =>\n [...source.matchAll(/<AActionCloseButtonHistory(?![A-Za-z])([^>]*?)\\/>/g)].map(([, attrs]) => ({\n file: globKeyToSrcPath(path),\n label: globKeyToSrcPath(path),\n // Absent means \"nothing beyond my own route\", which the library skips anyway -- the button\n // defaults the prop to an empty list, so it still walks back by name.\n skip: listOf(attrs!, 'skip-route-names') ?? [],\n // A handful of buttons compute their destination, and those hold an expression rather than a\n // literal -- the walk still has to be right, only the fallback cannot be read from here.\n fallback: listOf(attrs!, 'fallback-route-name'),\n // Told apart from a missing prop, so the checks that need a literal skip such a button loudly\n // rather than passing over it.\n fallbackComputed: /:fallback-route-name=\"/.test(attrs!) && !listOf(attrs!, 'fallback-route-name')?.length,\n }))\n )\n\n // The longest prefix of a route whose last segment is dynamic -- `/x/[id]/edit` -> `/x/[id]`.\n // Everything at or under it is another view of the same record.\n const recordPrefix = (name: string) => {\n const parts = name.split('/')\n for (let i = parts.length - 1; i > 0; i--) {\n if (/\\[[^\\]]*\\]/.test(parts[i]!)) return parts.slice(0, i + 1).join('/')\n }\n return name\n }\n\n const closableRoutes = [...new Set(buttons.flatMap(({ file }) => owningRoutes(file)))]\n\n describe('close buttons', () => {\n it('finds every button, and none of the plain variant', () => {\n // A guard on the guard: were the glob to stop matching, every assertion below would iterate an\n // empty list and pass while checking nothing.\n expect(buttons.length).toBeGreaterThan(0)\n\n const plain = Object.entries(sources)\n .filter(([, source]) => /<AActionCloseButton(?![A-Za-z])/.test(source))\n .map(([path]) => globKeyToSrcPath(path))\n\n // The plain button navigates to a fixed route, so closing a record always lands on its listing\n // even when the user arrived from somewhere else entirely.\n expect(plain).toEqual([])\n })\n\n it.each(buttons)('$label does not repeat the route it sits on', ({ file, skip }) => {\n // `navigateBack` skips the current route itself, so naming it here says nothing and is one\n // more string to go stale when a page is renamed.\n const own = owningRoutes(file)\n expect(own).not.toEqual([])\n\n if (own.length === 1) {\n expect(skip).not.toContain(own[0])\n return\n }\n\n // A component rendered by more than one page is the other way round: only the ACTIVE route is\n // skipped for it, so every route it can appear on has to be named or closing one view hands the\n // user straight into its sibling.\n expect(own.filter((name) => !skip.includes(name))).toEqual([])\n })\n\n it.each(buttons)('$label names the sibling views of the record it closes', ({ file, skip, fallback }) => {\n // The walk must not hand back another view OF THE SAME RECORD -- its edit form, a deeper\n // record underneath it, or the create form a save redirected away from. Those are the ones\n // the caller still has to name.\n // Minus the fallback: a handful of edit views close one level up into their own detail rather\n // than to a listing, and that route is the destination, not something to walk past.\n const own = [...owningRoutes(file), ...(fallback ?? [])]\n const expected = new Set<string>()\n for (const name of owningRoutes(file)) {\n const record = recordPrefix(name)\n for (const other of closableRoutes) {\n if (own.includes(other)) continue\n if (other === record || other.startsWith(`${record}/`)) expected.add(other)\n }\n // Only when the fallback really is this record's own listing: creating pushes to the detail,\n // so closing the detail must not walk back into the empty form. A button that closes across\n // entities -- a stats detail returning to the jobs listing -- was never reached that way.\n const listing = fallback?.[0] ?? ''\n const created = `${listing}/new`\n const ownListing = listing !== '' && name.startsWith(`${listing}/`)\n if (ownListing && /\\[[^\\]]*\\]/.test(name) && routeNames.has(created) && !own.includes(created)) {\n expected.add(created)\n }\n }\n\n expect([...expected].filter((name) => !skip.includes(name))).toEqual([])\n })\n\n it.each(buttons)('$label points at routes that exist', ({ skip, fallback }) => {\n expect([...skip, ...(fallback ?? [])].filter((name) => !routeNames.has(name))).toEqual([])\n })\n\n it('never skips the route it falls back to', () => {\n // The fallback is where the author wants the user to land -- almost always the listing, but a\n // handful of views close one level up into a parent record instead. Skipping that route would\n // walk straight past the intended destination and only reach it in a fresh tab, where there is\n // no history left to walk.\n const bad = buttons.flatMap(({ label, skip, fallback }) =>\n (fallback ?? []).filter((name) => skip.includes(name)).map((name) => `${label}: ${name}`)\n )\n\n expect(bad).toEqual([])\n })\n\n it('says how many buttons compute their fallback', () => {\n // Two checks need a literal to read: \"points at routes that exist\" and \"never skips the route\n // it falls back to\". A button whose fallback is a template expression is outside both, and\n // silently so -- this states the size of that gap instead of leaving it invisible. The sibling\n // check does still cover them, since it derives from the routes they sit on.\n const computed = buttons.filter(({ fallbackComputed }) => fallbackComputed).map(({ label }) => label)\n\n expect(computed.length).toBeLessThanOrEqual(maxComputedFallbacks)\n })\n\n it('blacklists only routes that exist', () => {\n expect(routeHistoryBlacklist.filter((name) => !routeNames.has(name))).toEqual([])\n })\n\n it('never blacklists a route a close button falls back to', () => {\n // The fallback is the last resort when history holds nothing to return to. Pointing it at a\n // blacklisted route is not an error in itself -- the push still works -- but it means the\n // button leads somewhere the app has decided is not a place to be.\n const blacklisted = new Set(routeHistoryBlacklist)\n const bad = buttons.flatMap(({ label, fallback }) =>\n (fallback ?? []).filter((name) => blacklisted.has(name)).map((name) => `${label}: ${name}`)\n )\n\n expect(bad).toEqual([])\n })\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"closeButtons.js","names":["describeCloseButtons","parsed","parseTypedRouterDeclaration","declaration","routeNames","pageRoutes","importedBy","path","source","sources","target","key","globKeyToSrcPath","owningRoutes","seen","file","parent","listOf","match","attrs","name","value","buttons","recordPrefix","parts","i","closableRoutes","it","plain","own","expect","skip","fallback","expected","record","other","listing","created","bad","label","computed","fallbackComputed","maxComputedFallbacks","routeHistoryBlacklist","blacklisted"],"sources":["../../src/testing/closeButtons.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath, parseTypedRouterDeclaration } from '@/testing/typedRouter'\n\nexport interface DescribeCloseButtonsOptions {\n /**\n * Every `.vue` of the admin: `import.meta.glob('/src/**\\/*.vue', { query: '?raw', import: 'default', eager: true })`.\n */\n sources: Record<string, string>\n declaration: string\n routeHistoryBlacklist: readonly string[]\n /** How many buttons may compute their fallback, which two checks cannot read. */\n maxComputedFallbacks?: number\n}\n\n/**\n * `AActionCloseButtonHistory` walks the recorded history backwards for the first entry\n * not in `skipRouteNames`. It uses `fallbackRouteName` only when that walk finds nothing.\n * Both lists are plain strings in a template. `anzu/valid-route-name` only\n * checks names in `<script>`, and nothing type-checks an attribute string.\n * After a page rename the lists silently keep the old name. A skip list that no\n * longer names its own view sends the user back to the view they just closed.\n */\nexport function describeCloseButtons({\n sources,\n declaration,\n routeHistoryBlacklist,\n maxComputedFallbacks = 3,\n}: DescribeCloseButtonsOptions): void {\n const parsed = parseTypedRouterDeclaration(declaration)\n const routeNames = new Set(parsed.names)\n const pageRoutes = parsed.pageRoutes\n\n const importedBy = new Map<string, Set<string>>()\n for (const [path, source] of Object.entries(sources)) {\n for (const [, target] of source.matchAll(/from\\s+'(@\\/[^']+\\.vue)'/g)) {\n const key = target!.replace(/^@\\//, 'src/')\n if (!importedBy.has(key)) importedBy.set(key, new Set())\n importedBy.get(key)!.add(globKeyToSrcPath(path))\n }\n }\n\n // A button sitting in a shared component belongs to whichever pages render it, however many\n // levels of component sit in between.\n const owningRoutes = (file: string, seen = new Set<string>()): string[] => {\n if (seen.has(file)) return []\n seen.add(file)\n const own = pageRoutes.get(file)\n if (own) return own\n return [...(importedBy.get(file) ?? [])].flatMap((parent) => owningRoutes(parent, seen))\n }\n\n const listOf = (attrs: string, name: string) => {\n const match = attrs.match(new RegExp(`:${name}=\"([^\"]*)\"`))\n return match ? [...match[1]!.matchAll(/'([^']*)'/g)].map(([, value]) => value!) : undefined\n }\n\n const buttons = Object.entries(sources).flatMap(([path, source]) =>\n [...source.matchAll(/<AActionCloseButtonHistory(?![A-Za-z])([^>]*?)\\/>/g)].map(([, attrs]) => ({\n file: globKeyToSrcPath(path),\n label: globKeyToSrcPath(path),\n // Absent means \"nothing beyond my own route\", which the library skips anyway.\n // The button defaults the prop to an empty list, so it still walks back by name.\n skip: listOf(attrs!, 'skip-route-names') ?? [],\n // A few buttons compute their destination, so they hold an expression, not a literal.\n // The walk must still be right. Only the fallback cannot be read here.\n fallback: listOf(attrs!, 'fallback-route-name'),\n // Told apart from a missing prop, so the checks that need a literal skip such a button loudly\n // rather than passing over it.\n fallbackComputed: /:fallback-route-name=\"/.test(attrs!) && !listOf(attrs!, 'fallback-route-name')?.length,\n }))\n )\n\n // The longest prefix of a route whose last segment is dynamic: `/x/[id]/edit` -> `/x/[id]`.\n // Everything at or under it is another view of the same record.\n const recordPrefix = (name: string) => {\n const parts = name.split('/')\n for (let i = parts.length - 1; i > 0; i--) {\n if (/\\[[^\\]]*\\]/.test(parts[i]!)) return parts.slice(0, i + 1).join('/')\n }\n return name\n }\n\n const closableRoutes = [...new Set(buttons.flatMap(({ file }) => owningRoutes(file)))]\n\n describe('close buttons', () => {\n it('finds every button, and none of the plain variant', () => {\n // A guard on the guard: were the glob to stop matching, every assertion below would iterate an\n // empty list and pass while checking nothing.\n expect(buttons.length).toBeGreaterThan(0)\n\n const plain = Object.entries(sources)\n .filter(([, source]) => /<AActionCloseButton(?![A-Za-z])/.test(source))\n .map(([path]) => globKeyToSrcPath(path))\n\n // The plain button navigates to a fixed route, so closing a record always lands on its listing\n // even when the user arrived from somewhere else entirely.\n expect(plain).toEqual([])\n })\n\n it.each(buttons)('$label does not repeat the route it sits on', ({ file, skip }) => {\n // `navigateBack` skips the current route itself, so naming it here says nothing and is one\n // more string to go stale when a page is renamed.\n const own = owningRoutes(file)\n expect(own).not.toEqual([])\n\n if (own.length === 1) {\n expect(skip).not.toContain(own[0])\n return\n }\n\n // A component rendered by more than one page is the other way round: only the ACTIVE route is\n // skipped for it, so every route it can appear on has to be named or closing one view hands the\n // user straight into its sibling.\n expect(own.filter((name) => !skip.includes(name))).toEqual([])\n })\n\n it.each(buttons)('$label names the sibling views of the record it closes', ({ file, skip, fallback }) => {\n // The walk must not hand back another view OF THE SAME RECORD -- its edit form, a deeper\n // record underneath it, or the create form a save redirected away from. Those are the ones\n // the caller still has to name.\n // Minus the fallback: a handful of edit views close one level up into their own detail rather\n // than to a listing, and that route is the destination, not something to walk past.\n const own = [...owningRoutes(file), ...(fallback ?? [])]\n const expected = new Set<string>()\n for (const name of owningRoutes(file)) {\n const record = recordPrefix(name)\n for (const other of closableRoutes) {\n if (own.includes(other)) continue\n if (other === record || other.startsWith(`${record}/`)) expected.add(other)\n }\n // Only when the fallback is this record's own listing: creating pushes to\n // the detail, so closing the detail must not walk back into the empty form.\n // A button that closes across entities, such as a stats detail\n // returning to the jobs listing, was never reached that way.\n const listing = fallback?.[0] ?? ''\n const created = `${listing}/new`\n const ownListing = listing !== '' && name.startsWith(`${listing}/`)\n if (ownListing && /\\[[^\\]]*\\]/.test(name) && routeNames.has(created) && !own.includes(created)) {\n expected.add(created)\n }\n }\n\n expect([...expected].filter((name) => !skip.includes(name))).toEqual([])\n })\n\n it.each(buttons)('$label points at routes that exist', ({ skip, fallback }) => {\n expect([...skip, ...(fallback ?? [])].filter((name) => !routeNames.has(name))).toEqual([])\n })\n\n it('never skips the route it falls back to', () => {\n // The fallback is where the author wants the user to land. Usually that is\n // the listing, but a few views close one level up into a parent record.\n // Skipping that route would walk past the intended destination and\n // reach it only in a fresh tab, where there is no history to walk.\n const bad = buttons.flatMap(({ label, skip, fallback }) =>\n (fallback ?? []).filter((name) => skip.includes(name)).map((name) => `${label}: ${name}`)\n )\n\n expect(bad).toEqual([])\n })\n\n it('says how many buttons compute their fallback', () => {\n // Two checks need a literal: \"points at routes that exist\" and \"never skips the route it falls back to\".\n // A button whose fallback is a template expression is outside\n // both, silently. This test states the size of that gap.\n // The sibling check still covers them, since it derives from the routes they sit on.\n const computed = buttons.filter(({ fallbackComputed }) => fallbackComputed).map(({ label }) => label)\n\n expect(computed.length).toBeLessThanOrEqual(maxComputedFallbacks)\n })\n\n it('blacklists only routes that exist', () => {\n expect(routeHistoryBlacklist.filter((name) => !routeNames.has(name))).toEqual([])\n })\n\n it('never blacklists a route a close button falls back to', () => {\n // The fallback is the last resort when history holds nothing to return to.\n // Pointing it at a blacklisted route is not an error, since the push works. But\n // the button then leads somewhere the app has decided is not a place to be.\n const blacklisted = new Set(routeHistoryBlacklist)\n const bad = buttons.flatMap(({ label, fallback }) =>\n (fallback ?? []).filter((name) => blacklisted.has(name)).map((name) => `${label}: ${name}`)\n )\n\n expect(bad).toEqual([])\n })\n })\n}\n"],"mappings":"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"}
@@ -5,9 +5,10 @@ export interface PackageJsonDependencies {
5
5
  optionalDependencies?: Record<string, string>;
6
6
  }
7
7
  export interface DescribeDeclaredDependenciesOptions {
8
- /** The admin's sources: `import.meta.glob('/src/**\/*.{vue,ts,mts,scss}', { query: '?raw', import: 'default', eager: true })`. */
8
+ /**
9
+ * The admin's sources: `import.meta.glob('/src/**\/*.{vue,ts,mts,scss}', { query: '?raw', import: 'default', eager: true })`.
10
+ */
9
11
  sources: Record<string, string>;
10
- /** The admin's `package.json`. */
11
12
  packageJson: PackageJsonDependencies;
12
13
  /** Bare specifier prefixes that name no package: the admin's own aliases (`@/` is built in). */
13
14
  aliases?: string[];
@@ -15,12 +16,11 @@ export interface DescribeDeclaredDependenciesOptions {
15
16
  export declare const withoutComments: (source: string) => string;
16
17
  /** The package a bare specifier imports from, or `null` for a relative path, an alias or a `scheme:` module. */
17
18
  export declare const packageOfSpecifier: (specifier: string, aliases?: string[]) => string | null;
18
- /** `file: specifier` for every import of a package the `package.json` does not declare. */
19
19
  export declare function undeclaredImports(sources: Record<string, string>, packageJson: PackageJsonDependencies, aliases?: string[]): string[];
20
20
  /**
21
- * A package the admin imports but does not declare works as long as another dependency brings it and the
22
- * package manager hoists it to the top of `node_modules` (yarn's `node-modules` linker does). Its version
23
- * is then whatever that dependency asks for, and a strict layout -- pnpm, or yarn's own PnP -- does not
24
- * hoist: the build stops at the first such import.
21
+ * An undeclared import works while another dependency brings the package and the package
22
+ * manager hoists it to the top of `node_modules` (yarn's `node-modules` linker does).
23
+ * Its version is then whatever that dependency asks for.
24
+ * A strict layout (pnpm, yarn PnP) does not hoist, so the build stops at the first such import.
25
25
  */
26
26
  export declare function describeDeclaredDependencies({ sources, packageJson, aliases, }: DescribeDeclaredDependenciesOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"declaredDependencies.js","names":["SPECIFIER_RE","DECLARE_MODULE_RE","REGEX_AFTER_KEYWORD","REGEX_CAN_FOLLOW","withoutComments","out","previous","i","copyQuoted","start","source","quote","char","next","end","inClass","codeOf","key","block","isStylePartial","dir","at","specifier","sub","name","keys","ext","NODE_BUILTINS","packageOfSpecifier","path","aliases","alias","parts","undeclaredImports","declared","packageJson","deps","sources","found","code","match","globKeyToSrcPath","describeDeclaredDependencies","it"],"sources":["../../src/testing/declaredDependencies.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath } from '@/testing/typedRouter'\n\nexport interface PackageJsonDependencies {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n peerDependencies?: Record<string, string>\n optionalDependencies?: Record<string, string>\n}\n\nexport interface DescribeDeclaredDependenciesOptions {\n /** The admin's sources: `import.meta.glob('/src/**\\/*.{vue,ts,mts,scss}', { query: '?raw', import: 'default', eager: true })`. */\n sources: Record<string, string>\n /** The admin's `package.json`. */\n packageJson: PackageJsonDependencies\n /** Bare specifier prefixes that name no package: the admin's own aliases (`@/` is built in). */\n aliases?: string[]\n}\n\n// Module specifiers in code (static, `export … from`, side-effect and dynamic imports, `require`, the vitest\n// module helpers, `typeof import()`) and in styles (`@use`, `@forward`, `@import`; group 1). A specifier has\n// no whitespace and ends its statement or call, which leaves out prose such as `it('… from \"now\"')`.\nconst SPECIFIER_RE =\n /(?:(@(?:use|forward|import)\\s+)|\\bfrom\\s+|\\bimport\\s*\\(\\s*|\\bimport\\s+|\\brequire\\s*\\(\\s*|\\bvi\\.(?:mock|doMock|importActual)\\s*(?:<[^>]*>)?\\(\\s*)(['\"])([^'\"\\s]+)\\2(?=\\s*(?:[;),]|$|with\\s*[({]|assert\\s*\\{|as\\s+[\\w*-]+\\s*;|show\\b|hide\\b))/gm\n\n// A module augmentation (`declare module 'vue' {`) names a package too; a wildcard one (`'*.vue'`) names none.\nconst DECLARE_MODULE_RE = /\\bdeclare\\s+module\\s+(['\"])([^'\"\\s*]+)\\1\\s*\\{/g\n\n// Comments name modules in passing, so they go -- but only outside strings, template literals and regular\n// expressions: `'image/*'` or `/['\"]/` read as the start of a comment or a string would hide the code after it.\n// A `/` starts a regular expression after an operator or a keyword. Taken for one where it divides (a member\n// named like a keyword: `obj.in / 2`), the scan copies to the next `/` on that line and reads on from there.\nconst REGEX_AFTER_KEYWORD =\n /(?:^|[^\\w$])(?:return|typeof|instanceof|in|of|new|delete|void|throw|case|default|do|else|await|yield)$/\nconst REGEX_CAN_FOLLOW = new Set([\n '',\n '(',\n ',',\n '=',\n ':',\n '[',\n '!',\n '&',\n '|',\n '?',\n '{',\n '}',\n ';',\n '+',\n '-',\n '*',\n '%',\n '<',\n '>',\n '~',\n '^',\n])\nexport const withoutComments = (source: string): string => {\n let out = ''\n let previous = ''\n let i = 0\n const copyQuoted = (quote: string) => {\n const start = i++\n while (i < source.length && source[i] !== quote) {\n if (source[i] === '\\\\') i++\n else if (quote !== '`' && source[i] === '\\n') break\n i++\n }\n i++\n out += source.slice(start, i)\n }\n while (i < source.length) {\n const char = source[i]!\n const next = source[i + 1]\n if (char === '/' && next === '/') {\n const end = source.indexOf('\\n', i)\n i = end === -1 ? source.length : end\n } else if (char === '/' && next === '*') {\n const end = source.indexOf('*/', i + 2)\n i = end === -1 ? source.length : end + 2\n out += ' '\n } else if (char === \"'\" || char === '\"' || char === '`') {\n copyQuoted(char)\n previous = char\n } else if (char === '/' && (REGEX_CAN_FOLLOW.has(previous) || REGEX_AFTER_KEYWORD.test(out.trimEnd()))) {\n const start = i++\n let inClass = false\n while (i < source.length && source[i] !== '\\n' && (inClass || source[i] !== '/')) {\n if (source[i] === '\\\\') i++\n else if (source[i] === '[') inClass = true\n else if (source[i] === ']') inClass = false\n i++\n }\n i++\n out += source.slice(start, i)\n previous = '/'\n } else {\n out += char\n if (!/\\s/.test(char)) previous = char\n i++\n }\n }\n return out\n}\n\n// A `.vue` file imports in its `<script>` and `<style>` blocks; the template's text is prose.\nconst codeOf = (key: string, source: string): string =>\n key.endsWith('.vue')\n ? [...source.matchAll(/<(script|style)\\b[^>]*>([\\s\\S]*?)<\\/\\1>/g)]\n .map((block) => withoutComments(block[2]!))\n .join('\\n')\n : withoutComments(source)\n\n// Sass resolves `@use 'utils/forms'` against the file's own directory first: a partial there is no package.\nconst isStylePartial = (key: string, specifier: string, keys: Set<string>): boolean => {\n const dir = key.slice(0, key.lastIndexOf('/'))\n const at = specifier.lastIndexOf('/')\n const [sub, name] = at === -1 ? ['', specifier] : [`/${specifier.slice(0, at)}`, specifier.slice(at + 1)]\n return ['.scss', '.css'].some(\n (ext) =>\n keys.has(`${dir}/${specifier}${ext}`) ||\n keys.has(`${dir}${sub}/_${name}${ext}`) ||\n keys.has(`${dir}/${specifier}/_index${ext}`) ||\n keys.has(`${dir}/${specifier}/index${ext}`)\n )\n}\n\nconst NODE_BUILTINS = new Set([\n 'assert',\n 'buffer',\n 'child_process',\n 'crypto',\n 'events',\n 'fs',\n 'module',\n 'os',\n 'path',\n 'process',\n 'stream',\n 'url',\n 'util',\n 'worker_threads',\n 'zlib',\n])\n\n/** The package a bare specifier imports from, or `null` for a relative path, an alias or a `scheme:` module. */\nexport const packageOfSpecifier = (specifier: string, aliases: string[] = []): string | null => {\n const path = specifier.split('?')[0]!\n if (/^(?:\\.|\\/|@\\/|#|[a-z][a-z0-9+.-]*:)/.test(path)) return null\n if (aliases.some((alias) => path.startsWith(alias))) return null\n const parts = path.split('/')\n const name = path.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]!\n return NODE_BUILTINS.has(name) ? null : name\n}\n\n/** `file: specifier` for every import of a package the `package.json` does not declare. */\nexport function undeclaredImports(\n sources: Record<string, string>,\n packageJson: PackageJsonDependencies,\n aliases: string[] = []\n): string[] {\n const declared = new Set(\n [\n packageJson.dependencies,\n packageJson.devDependencies,\n packageJson.peerDependencies,\n packageJson.optionalDependencies,\n ]\n .flatMap((deps) => Object.keys(deps ?? {}))\n // `@types/x` declares the types of `x`, `@types/scope__x` those of `@scope/x`.\n .flatMap((name) => (name.startsWith('@types/') ? [name, name.slice(7).replace(/^(.+)__/, '@$1/')] : [name]))\n )\n const keys = new Set(Object.keys(sources))\n const found: string[] = []\n for (const [key, source] of Object.entries(sources)) {\n const code = codeOf(key, source)\n for (const match of code.matchAll(SPECIFIER_RE)) {\n const specifier = match[3]!\n const name = packageOfSpecifier(specifier, aliases)\n if (name === null || declared.has(name)) continue\n if (match[1] && isStylePartial(key, specifier, keys)) continue\n found.push(`${globKeyToSrcPath(key)}: ${specifier}`)\n }\n for (const match of code.matchAll(DECLARE_MODULE_RE)) {\n const name = packageOfSpecifier(match[2]!, aliases)\n if (name !== null && !declared.has(name)) found.push(`${globKeyToSrcPath(key)}: ${match[2]}`)\n }\n }\n return [...new Set(found)].sort()\n}\n\n/**\n * A package the admin imports but does not declare works as long as another dependency brings it and the\n * package manager hoists it to the top of `node_modules` (yarn's `node-modules` linker does). Its version\n * is then whatever that dependency asks for, and a strict layout -- pnpm, or yarn's own PnP -- does not\n * hoist: the build stops at the first such import.\n */\nexport function describeDeclaredDependencies({\n sources,\n packageJson,\n aliases = [],\n}: DescribeDeclaredDependenciesOptions): void {\n describe('declared dependencies', () => {\n it('reads the sources it is meant to check', () => {\n // A guard on the guard: an empty glob would leave nothing to check and pass.\n expect(Object.keys(sources).length).toBeGreaterThan(20)\n })\n\n it('imports only packages its package.json declares', () => {\n expect(undeclaredImports(sources, packageJson, aliases)).toEqual([])\n })\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"declaredDependencies.js","names":["SPECIFIER_RE","DECLARE_MODULE_RE","REGEX_AFTER_KEYWORD","REGEX_CAN_FOLLOW","withoutComments","out","previous","i","copyQuoted","start","source","quote","char","next","end","inClass","codeOf","key","block","isStylePartial","dir","at","specifier","sub","name","keys","ext","NODE_BUILTINS","packageOfSpecifier","path","aliases","alias","parts","undeclaredImports","declared","packageJson","deps","sources","found","code","match","globKeyToSrcPath","describeDeclaredDependencies","it"],"sources":["../../src/testing/declaredDependencies.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath } from '@/testing/typedRouter'\n\nexport interface PackageJsonDependencies {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n peerDependencies?: Record<string, string>\n optionalDependencies?: Record<string, string>\n}\n\nexport interface DescribeDeclaredDependenciesOptions {\n /**\n * The admin's sources: `import.meta.glob('/src/**\\/*.{vue,ts,mts,scss}', { query: '?raw', import: 'default', eager: true })`.\n */\n sources: Record<string, string>\n packageJson: PackageJsonDependencies\n /** Bare specifier prefixes that name no package: the admin's own aliases (`@/` is built in). */\n aliases?: string[]\n}\n\n// Module specifiers in code (static, `export … from`, side-effect and dynamic imports, `require`, the vitest\n// module helpers, `typeof import()`) and in styles (`@use`, `@forward`, `@import`; group 1). A specifier has\n// no whitespace and ends its statement or call, which leaves out prose such as `it('… from \"now\"')`.\nconst SPECIFIER_RE =\n /(?:(@(?:use|forward|import)\\s+)|\\bfrom\\s+|\\bimport\\s*\\(\\s*|\\bimport\\s+|\\brequire\\s*\\(\\s*|\\bvi\\.(?:mock|doMock|importActual)\\s*(?:<[^>]*>)?\\(\\s*)(['\"])([^'\"\\s]+)\\2(?=\\s*(?:[;),]|$|with\\s*[({]|assert\\s*\\{|as\\s+[\\w*-]+\\s*;|show\\b|hide\\b))/gm\n\n// A module augmentation (`declare module 'vue' {`) names a package too; a wildcard one (`'*.vue'`) names none.\nconst DECLARE_MODULE_RE = /\\bdeclare\\s+module\\s+(['\"])([^'\"\\s*]+)\\1\\s*\\{/g\n\n// Comments name modules in passing, so they go -- but only outside strings, template literals and regular\n// expressions: `'image/*'` or `/['\"]/` read as the start of a comment or a string would hide the code after it.\n// A `/` starts a regular expression after an operator or a keyword. Taken for one where it divides (a member\n// named like a keyword: `obj.in / 2`), the scan copies to the next `/` on that line and reads on from there.\nconst REGEX_AFTER_KEYWORD =\n /(?:^|[^\\w$])(?:return|typeof|instanceof|in|of|new|delete|void|throw|case|default|do|else|await|yield)$/\nconst REGEX_CAN_FOLLOW = new Set([\n '',\n '(',\n ',',\n '=',\n ':',\n '[',\n '!',\n '&',\n '|',\n '?',\n '{',\n '}',\n ';',\n '+',\n '-',\n '*',\n '%',\n '<',\n '>',\n '~',\n '^',\n])\nexport const withoutComments = (source: string): string => {\n let out = ''\n let previous = ''\n let i = 0\n const copyQuoted = (quote: string) => {\n const start = i++\n while (i < source.length && source[i] !== quote) {\n if (source[i] === '\\\\') i++\n else if (quote !== '`' && source[i] === '\\n') break\n i++\n }\n i++\n out += source.slice(start, i)\n }\n while (i < source.length) {\n const char = source[i]!\n const next = source[i + 1]\n if (char === '/' && next === '/') {\n const end = source.indexOf('\\n', i)\n i = end === -1 ? source.length : end\n } else if (char === '/' && next === '*') {\n const end = source.indexOf('*/', i + 2)\n i = end === -1 ? source.length : end + 2\n out += ' '\n } else if (char === \"'\" || char === '\"' || char === '`') {\n copyQuoted(char)\n previous = char\n } else if (char === '/' && (REGEX_CAN_FOLLOW.has(previous) || REGEX_AFTER_KEYWORD.test(out.trimEnd()))) {\n const start = i++\n let inClass = false\n while (i < source.length && source[i] !== '\\n' && (inClass || source[i] !== '/')) {\n if (source[i] === '\\\\') i++\n else if (source[i] === '[') inClass = true\n else if (source[i] === ']') inClass = false\n i++\n }\n i++\n out += source.slice(start, i)\n previous = '/'\n } else {\n out += char\n if (!/\\s/.test(char)) previous = char\n i++\n }\n }\n return out\n}\n\n// A `.vue` file imports in its `<script>` and `<style>` blocks; the template's text is prose.\nconst codeOf = (key: string, source: string): string =>\n key.endsWith('.vue')\n ? [...source.matchAll(/<(script|style)\\b[^>]*>([\\s\\S]*?)<\\/\\1>/g)]\n .map((block) => withoutComments(block[2]!))\n .join('\\n')\n : withoutComments(source)\n\n// Sass resolves `@use 'utils/forms'` against the file's own directory first: a partial there is no package.\nconst isStylePartial = (key: string, specifier: string, keys: Set<string>): boolean => {\n const dir = key.slice(0, key.lastIndexOf('/'))\n const at = specifier.lastIndexOf('/')\n const [sub, name] = at === -1 ? ['', specifier] : [`/${specifier.slice(0, at)}`, specifier.slice(at + 1)]\n return ['.scss', '.css'].some(\n (ext) =>\n keys.has(`${dir}/${specifier}${ext}`) ||\n keys.has(`${dir}${sub}/_${name}${ext}`) ||\n keys.has(`${dir}/${specifier}/_index${ext}`) ||\n keys.has(`${dir}/${specifier}/index${ext}`)\n )\n}\n\nconst NODE_BUILTINS = new Set([\n 'assert',\n 'buffer',\n 'child_process',\n 'crypto',\n 'events',\n 'fs',\n 'module',\n 'os',\n 'path',\n 'process',\n 'stream',\n 'url',\n 'util',\n 'worker_threads',\n 'zlib',\n])\n\n/** The package a bare specifier imports from, or `null` for a relative path, an alias or a `scheme:` module. */\nexport const packageOfSpecifier = (specifier: string, aliases: string[] = []): string | null => {\n const path = specifier.split('?')[0]!\n if (/^(?:\\.|\\/|@\\/|#|[a-z][a-z0-9+.-]*:)/.test(path)) return null\n if (aliases.some((alias) => path.startsWith(alias))) return null\n const parts = path.split('/')\n const name = path.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]!\n return NODE_BUILTINS.has(name) ? null : name\n}\n\nexport function undeclaredImports(\n sources: Record<string, string>,\n packageJson: PackageJsonDependencies,\n aliases: string[] = []\n): string[] {\n const declared = new Set(\n [\n packageJson.dependencies,\n packageJson.devDependencies,\n packageJson.peerDependencies,\n packageJson.optionalDependencies,\n ]\n .flatMap((deps) => Object.keys(deps ?? {}))\n // `@types/x` declares the types of `x`, `@types/scope__x` those of `@scope/x`.\n .flatMap((name) => (name.startsWith('@types/') ? [name, name.slice(7).replace(/^(.+)__/, '@$1/')] : [name]))\n )\n const keys = new Set(Object.keys(sources))\n const found: string[] = []\n for (const [key, source] of Object.entries(sources)) {\n const code = codeOf(key, source)\n for (const match of code.matchAll(SPECIFIER_RE)) {\n const specifier = match[3]!\n const name = packageOfSpecifier(specifier, aliases)\n if (name === null || declared.has(name)) continue\n if (match[1] && isStylePartial(key, specifier, keys)) continue\n found.push(`${globKeyToSrcPath(key)}: ${specifier}`)\n }\n for (const match of code.matchAll(DECLARE_MODULE_RE)) {\n const name = packageOfSpecifier(match[2]!, aliases)\n if (name !== null && !declared.has(name)) found.push(`${globKeyToSrcPath(key)}: ${match[2]}`)\n }\n }\n return [...new Set(found)].sort()\n}\n\n/**\n * An undeclared import works while another dependency brings the package and the package\n * manager hoists it to the top of `node_modules` (yarn's `node-modules` linker does).\n * Its version is then whatever that dependency asks for.\n * A strict layout (pnpm, yarn PnP) does not hoist, so the build stops at the first such import.\n */\nexport function describeDeclaredDependencies({\n sources,\n packageJson,\n aliases = [],\n}: DescribeDeclaredDependenciesOptions): void {\n describe('declared dependencies', () => {\n it('reads the sources it is meant to check', () => {\n // A guard on the guard: an empty glob would leave nothing to check and pass.\n expect(Object.keys(sources).length).toBeGreaterThan(20)\n })\n\n it('imports only packages its package.json declares', () => {\n expect(undeclaredImports(sources, packageJson, aliases)).toEqual([])\n })\n })\n}\n"],"mappings":"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"}
@@ -2,7 +2,6 @@ import { RouteRecordRaw } from 'vue-router';
2
2
  export interface DescribeGeneratedRoutesOptions {
3
3
  /** `routes` from `vue-router/auto-routes`. */
4
4
  routes: RouteRecordRaw[];
5
- /** `src/typed-router.d.ts`, imported with `?raw`. */
6
5
  declaration: string;
7
6
  /** `Object.keys(import.meta.glob('/src/pages/**\/*.vue'))`. */
8
7
  pageFiles: string[];
@@ -11,15 +10,11 @@ export interface DescribeGeneratedRoutesOptions {
11
10
  }
12
11
  /**
13
12
  * A smoke test over every generated route.
14
- *
15
- * `anzu/valid-route-name` checks that a name referenced in the code exists. It cannot check that the
16
- * route behind it can be reached: a path whose constraint never matches, or one shadowed by an earlier
17
- * record, still has a perfectly valid name. Navigating to it lands on the catch-all instead, which
18
- * renders a 404 page and throws nothing -- so a broken route looks exactly like a working one until
19
- * somebody clicks it.
20
- *
21
- * Importing `vue-router/auto-routes` is itself half the test: it pulls in every page component and,
22
- * through them, their stores, api clients and composables, so anything that throws while a module is
23
- * evaluated fails there. That half depends on `importMode` being `sync` in the admin's vitest config.
13
+ * `anzu/valid-route-name` checks that a referenced name exists, not that the route can be reached. A
14
+ * path whose constraint never matches, or one shadowed by an earlier record, still has a valid name.
15
+ * Navigating to it lands on the catch-all, which renders a 404 page and throws nothing.
16
+ * Importing `vue-router/auto-routes` is also part of the test: it loads every page
17
+ * component and their stores, api clients and composables, so errors thrown at module
18
+ * evaluation fail here. This needs `importMode` to be `sync` in the admin's vitest config.
24
19
  */
25
20
  export declare function describeGeneratedRoutes({ routes, declaration, pageFiles, catchAll, }: DescribeGeneratedRoutesOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"generatedRoutes.js","names":["PARAM_SAMPLES","describeGeneratedRoutes","declaredPaths","parseTypedRouterDeclaration","declaration","path","catchAll","router","createRouter","createMemoryHistory","fillParams","regex","sample","it","pageFiles","resolved","expect","record","name","runtime","route","declared","withoutComponent"],"sources":["../../src/testing/generatedRoutes.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { createMemoryHistory, createRouter, type RouteRecordRaw } from 'vue-router'\nimport { parseTypedRouterDeclaration } from '@/testing/typedRouter'\n\n// One value per id shape the admins constrain a param to: an integer id, a uuid (any version, the\n// backends make v4, v6 and v7) and a log's Mongo ObjectId.\nconst PARAM_SAMPLES = ['1', '00000000-0000-4000-8000-000000000001', '000000000000000000000001']\n\nexport interface DescribeGeneratedRoutesOptions {\n /** `routes` from `vue-router/auto-routes`. */\n routes: RouteRecordRaw[]\n /** `src/typed-router.d.ts`, imported with `?raw`. */\n declaration: string\n /** `Object.keys(import.meta.glob('/src/pages/**\\/*.vue'))`. */\n pageFiles: string[]\n /** The catch-all's param, whose route is left out. */\n catchAll?: string\n}\n\n/**\n * A smoke test over every generated route.\n *\n * `anzu/valid-route-name` checks that a name referenced in the code exists. It cannot check that the\n * route behind it can be reached: a path whose constraint never matches, or one shadowed by an earlier\n * record, still has a perfectly valid name. Navigating to it lands on the catch-all instead, which\n * renders a 404 page and throws nothing -- so a broken route looks exactly like a working one until\n * somebody clicks it.\n *\n * Importing `vue-router/auto-routes` is itself half the test: it pulls in every page component and,\n * through them, their stores, api clients and composables, so anything that throws while a module is\n * evaluated fails there. That half depends on `importMode` being `sync` in the admin's vitest config.\n */\nexport function describeGeneratedRoutes({\n routes,\n declaration,\n pageFiles,\n catchAll = 'pathMatch',\n}: DescribeGeneratedRoutesOptions): void {\n const declaredPaths = parseTypedRouterDeclaration(declaration).paths.filter(({ path }) => !path.includes(catchAll))\n const router = createRouter({ history: createMemoryHistory(), routes })\n\n // A constrained param -- `:id(\\d+)`, a uuid, a log's ObjectId -- has to be filled with something its\n // regex accepts, or the route would fail to match for a reason that says nothing about the route\n // itself: the first sample the regex takes, else `sample`. The trailing `?` of an optional param\n // goes with it: left in place it starts a query string, and everything after it -- `/edit` in\n // `/articles/:docId/:version?/edit` -- stops being part of the path.\n const fillParams = (path: string) =>\n path.replace(/:[a-zA-Z]+(?:\\(((?:\\\\.|[^\\\\)])*)\\))?\\??/g, (_match, regex?: string) =>\n regex\n ? // vue-router reads `\\)` as a group's closing parenthesis inside a custom regex, `RegExp` would not.\n (PARAM_SAMPLES.find((sample) => new RegExp(`^(?:${regex.replace(/\\\\\\)/g, ')')})$`, 'i').test(sample)) ??\n 'sample')\n : 'sample'\n )\n\n describe('generated routes', () => {\n it('declares exactly the pages that exist on disk', () => {\n // A guard on the guard: if the declaration were missing or the regex stopped matching, every\n // assertion below would iterate an empty list and pass while checking nothing. Counted from\n // disk rather than against a literal, so it cannot go stale as pages are added or removed --\n // the one page file `declaredPaths` filters out is the catch-all.\n expect(declaredPaths.length).toBe(pageFiles.length - 1)\n })\n\n it.each(declaredPaths)('resolves $path to its own record, not the catch-all', ({ name, path }) => {\n const resolved = router.resolve(fillParams(path))\n\n expect(resolved.matched.some((record) => record.path.includes(catchAll))).toBe(false)\n expect(resolved.name).toBe(name)\n })\n\n it('has a runtime route for every declared one, and nothing extra', () => {\n // The declaration is generated from the same scan as `routes`, but they are two artifacts and\n // only one of them is regenerated by `generate:dts`. A stale declaration is exactly the state in\n // which the assertions above would check routes the app no longer has.\n //\n // `router.getRoutes()` rather than `routes`: nested pages are children, so the raw array holds\n // `/blogs/[id]` but not the `/blogs/[id]/edit` underneath it.\n //\n // Worth knowing when this fails locally and not in CI: a dev server left running watches\n // `src/pages` and rewrites the declaration the moment a page file changes, which hides the\n // mismatch this asserts. In CI nothing watches, and `generate:dts` runs before the tests.\n const runtime = new Set(\n router\n .getRoutes()\n .map((route) => route.name)\n .filter((name): name is string => typeof name === 'string')\n )\n const declared = new Set(declaredPaths.map(({ name }) => name))\n\n expect([...declared].filter((name) => !runtime.has(name))).toEqual([])\n expect([...runtime].filter((name) => !declared.has(name) && !name.includes(catchAll))).toEqual([])\n })\n\n it('gives every route a component to render', () => {\n const withoutComponent = router\n .getRoutes()\n .filter((route) => !route.components || Object.keys(route.components).length === 0)\n\n expect(withoutComponent.map((route) => route.path)).toEqual([])\n })\n })\n}\n"],"mappings":";;;;AAMA,IAAMA,IAAgB;CAAC;CAAK;CAAwC;AAA0B;AA0B9F,SAAgBC,EAAwB,EACtC,WACA,gBACA,cACA,cAAW,eAC4B;CACvC,IAAMC,IAAgBC,EAA4BC,CAAW,CAAC,CAAC,MAAM,QAAQ,EAAE,cAAW,CAACC,EAAK,SAASC,CAAQ,CAAC,GAC5GC,IAASC,EAAa;EAAE,SAASC,EAAoB;EAAG;CAAO,CAAC,GAOhEC,KAAc,MAClBL,EAAK,QAAQ,6CAA6C,GAAQ,MAChEM,IAEKX,EAAc,MAAM,MAAe,OAAO,OAAOW,EAAM,QAAQ,SAAS,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,KAAKC,CAAM,CAAC,KACpG,WACA,QACN;CAEF,EAAS,0BAA0B;EAuCjC,AAtCAC,EAAG,uDAAuD;GAKxD,EAAOX,EAAc,MAAM,CAAC,CAAC,KAAKY,EAAU,SAAS,CAAC;EACxD,CAAC,GAEDD,EAAG,KAAKX,CAAa,CAAC,CAAC,wDAAwD,EAAE,SAAM,cAAW;GAChG,IAAMa,IAAWR,EAAO,QAAQG,EAAWL,CAAI,CAAC;GAGhD,AADAW,EAAOD,EAAS,QAAQ,MAAM,MAAWE,EAAO,KAAK,SAASX,CAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,EAAK,GACpFU,EAAOD,EAAS,IAAI,CAAC,CAAC,KAAKG,CAAI;EACjC,CAAC,GAEDL,EAAG,uEAAuE;GAWxE,IAAMM,IAAU,IAAI,IAClBZ,EACG,UAAU,CAAC,CACX,KAAK,MAAUa,EAAM,IAAI,CAAC,CAC1B,QAAQ,MAAyB,OAAOF,KAAS,QAAQ,CAC9D,GACMG,IAAW,IAAI,IAAInB,EAAc,KAAK,EAAE,cAAWgB,CAAI,CAAC;GAG9D,AADAF,EAAO,CAAC,GAAGK,CAAQ,CAAC,CAAC,QAAQ,MAAS,CAACF,EAAQ,IAAID,CAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GACrEF,EAAO,CAAC,GAAGG,CAAO,CAAC,CAAC,QAAQ,MAAS,CAACE,EAAS,IAAIH,CAAI,KAAK,CAACA,EAAK,SAASZ,CAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EACnG,CAAC,GAEDO,EAAG,iDAAiD;GAClD,IAAMS,IAAmBf,EACtB,UAAU,CAAC,CACX,QAAQ,MAAU,CAACa,EAAM,cAAc,OAAO,KAAKA,EAAM,UAAU,CAAC,CAAC,WAAW,CAAC;GAEpF,EAAOE,EAAiB,KAAK,MAAUF,EAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EAChE,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"generatedRoutes.js","names":["PARAM_SAMPLES","describeGeneratedRoutes","declaredPaths","parseTypedRouterDeclaration","declaration","path","catchAll","router","createRouter","createMemoryHistory","fillParams","regex","sample","it","pageFiles","resolved","expect","record","name","runtime","route","declared","withoutComponent"],"sources":["../../src/testing/generatedRoutes.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { createMemoryHistory, createRouter, type RouteRecordRaw } from 'vue-router'\nimport { parseTypedRouterDeclaration } from '@/testing/typedRouter'\n\n// One value per id shape the admins constrain a param to: an integer id, a uuid (any version, the\n// backends make v4, v6 and v7) and a log's Mongo ObjectId.\nconst PARAM_SAMPLES = ['1', '00000000-0000-4000-8000-000000000001', '000000000000000000000001']\n\nexport interface DescribeGeneratedRoutesOptions {\n /** `routes` from `vue-router/auto-routes`. */\n routes: RouteRecordRaw[]\n declaration: string\n /** `Object.keys(import.meta.glob('/src/pages/**\\/*.vue'))`. */\n pageFiles: string[]\n /** The catch-all's param, whose route is left out. */\n catchAll?: string\n}\n\n/**\n * A smoke test over every generated route.\n * `anzu/valid-route-name` checks that a referenced name exists, not that the route can be reached. A\n * path whose constraint never matches, or one shadowed by an earlier record, still has a valid name.\n * Navigating to it lands on the catch-all, which renders a 404 page and throws nothing.\n * Importing `vue-router/auto-routes` is also part of the test: it loads every page\n * component and their stores, api clients and composables, so errors thrown at module\n * evaluation fail here. This needs `importMode` to be `sync` in the admin's vitest config.\n */\nexport function describeGeneratedRoutes({\n routes,\n declaration,\n pageFiles,\n catchAll = 'pathMatch',\n}: DescribeGeneratedRoutesOptions): void {\n const declaredPaths = parseTypedRouterDeclaration(declaration).paths.filter(({ path }) => !path.includes(catchAll))\n const router = createRouter({ history: createMemoryHistory(), routes })\n\n // A constrained param (`:id(\\d+)`, a uuid, an ObjectId) must be filled with a value its\n // regex accepts. Otherwise the route fails to match for a reason unrelated to the route.\n // The value is the first sample the regex takes, else `sample`.\n // The trailing `?` of an optional param is removed too. Left in place it starts a query\n // string, and the rest of the path (`/edit` in `/articles/:docId/:version?/edit`) is lost.\n const fillParams = (path: string) =>\n path.replace(/:[a-zA-Z]+(?:\\(((?:\\\\.|[^\\\\)])*)\\))?\\??/g, (_match, regex?: string) =>\n regex\n ? // vue-router reads `\\)` as a group's closing parenthesis inside a custom regex, `RegExp` would not.\n (PARAM_SAMPLES.find((sample) => new RegExp(`^(?:${regex.replace(/\\\\\\)/g, ')')})$`, 'i').test(sample)) ??\n 'sample')\n : 'sample'\n )\n\n describe('generated routes', () => {\n it('declares exactly the pages that exist on disk', () => {\n // Guards the guard: if the declaration were missing or the regex stopped\n // matching, the assertions below would iterate an empty list and pass.\n // Counted from disk instead of a literal, so it does not go stale when pages\n // change. The one page file `declaredPaths` filters out is the catch-all.\n expect(declaredPaths.length).toBe(pageFiles.length - 1)\n })\n\n it.each(declaredPaths)('resolves $path to its own record, not the catch-all', ({ name, path }) => {\n const resolved = router.resolve(fillParams(path))\n\n expect(resolved.matched.some((record) => record.path.includes(catchAll))).toBe(false)\n expect(resolved.name).toBe(name)\n })\n\n it('has a runtime route for every declared one, and nothing extra', () => {\n // The declaration and `routes` are two artifacts, and only the declaration is regenerated by\n // `generate:dts`. A stale declaration makes the assertions above check routes the app no longer has.\n // `router.getRoutes()` is used instead of `routes` because nested pages are\n // children: the raw array has `/blogs/[id]` but not `/blogs/[id]/edit`.\n // When this fails locally but not in CI: a running dev server watches `src/pages` and rewrites the declaration on\n // every page change, which hides the mismatch. In CI nothing watches, and `generate:dts` runs before the tests.\n const runtime = new Set(\n router\n .getRoutes()\n .map((route) => route.name)\n .filter((name): name is string => typeof name === 'string')\n )\n const declared = new Set(declaredPaths.map(({ name }) => name))\n\n expect([...declared].filter((name) => !runtime.has(name))).toEqual([])\n expect([...runtime].filter((name) => !declared.has(name) && !name.includes(catchAll))).toEqual([])\n })\n\n it('gives every route a component to render', () => {\n const withoutComponent = router\n .getRoutes()\n .filter((route) => !route.components || Object.keys(route.components).length === 0)\n\n expect(withoutComponent.map((route) => route.path)).toEqual([])\n })\n })\n}\n"],"mappings":";;;;AAMA,IAAMA,IAAgB;CAAC;CAAK;CAAwC;AAA0B;AAqB9F,SAAgBC,EAAwB,EACtC,WACA,gBACA,cACA,cAAW,eAC4B;CACvC,IAAMC,IAAgBC,EAA4BC,CAAW,CAAC,CAAC,MAAM,QAAQ,EAAE,cAAW,CAACC,EAAK,SAASC,CAAQ,CAAC,GAC5GC,IAASC,EAAa;EAAE,SAASC,EAAoB;EAAG;CAAO,CAAC,GAOhEC,KAAc,MAClBL,EAAK,QAAQ,6CAA6C,GAAQ,MAChEM,IAEKX,EAAc,MAAM,MAAe,OAAO,OAAOW,EAAM,QAAQ,SAAS,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,KAAKC,CAAM,CAAC,KACpG,WACA,QACN;CAEF,EAAS,0BAA0B;EAmCjC,AAlCAC,EAAG,uDAAuD;GAKxD,EAAOX,EAAc,MAAM,CAAC,CAAC,KAAKY,EAAU,SAAS,CAAC;EACxD,CAAC,GAEDD,EAAG,KAAKX,CAAa,CAAC,CAAC,wDAAwD,EAAE,SAAM,cAAW;GAChG,IAAMa,IAAWR,EAAO,QAAQG,EAAWL,CAAI,CAAC;GAGhD,AADAW,EAAOD,EAAS,QAAQ,MAAM,MAAWE,EAAO,KAAK,SAASX,CAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,EAAK,GACpFU,EAAOD,EAAS,IAAI,CAAC,CAAC,KAAKG,CAAI;EACjC,CAAC,GAEDL,EAAG,uEAAuE;GAOxE,IAAMM,IAAU,IAAI,IAClBZ,EACG,UAAU,CAAC,CACX,KAAK,MAAUa,EAAM,IAAI,CAAC,CAC1B,QAAQ,MAAyB,OAAOF,KAAS,QAAQ,CAC9D,GACMG,IAAW,IAAI,IAAInB,EAAc,KAAK,EAAE,cAAWgB,CAAI,CAAC;GAG9D,AADAF,EAAO,CAAC,GAAGK,CAAQ,CAAC,CAAC,QAAQ,MAAS,CAACF,EAAQ,IAAID,CAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GACrEF,EAAO,CAAC,GAAGG,CAAO,CAAC,CAAC,QAAQ,MAAS,CAACE,EAAS,IAAIH,CAAI,KAAK,CAACA,EAAK,SAASZ,CAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EACnG,CAAC,GAEDO,EAAG,iDAAiD;GAClD,IAAMS,IAAmBf,EACtB,UAAU,CAAC,CACX,QAAQ,MAAU,CAACa,EAAM,cAAc,OAAO,KAAKA,EAAM,UAAU,CAAC,CAAC,WAAW,CAAC;GAEpF,EAAOE,EAAiB,KAAK,MAAUF,EAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EAChE,CAAC;CACH,CAAC;AACH"}
@@ -1,20 +1,13 @@
1
1
  export interface DescribeRouteHistoryOptions {
2
- /** `src/typed-router.d.ts`, imported with `?raw`. */
3
2
  declaration: string;
4
- /** The admin's route history blacklist. */
5
3
  routeHistoryBlacklist: readonly string[];
6
- /** What the admin runs at start-up to set up the history. */
7
4
  initRouteHistory: () => void;
8
5
  }
9
6
  /**
10
- * What the close buttons stand on.
11
- *
12
- * `describeCloseButtons` checks that every button names the right routes; this checks that naming
13
- * them does anything. The history is module state inside the library, filled by the navigation guard
14
- * and read back by `navigateBack`, so the admin's set-up and the library are only correct together.
15
- *
16
- * The route names come out of the declaration rather than being made up: made-up ones would be
17
- * rejected by `anzu/valid-route-name`, and real ones keep the test honest about the strings the app
18
- * actually carries.
7
+ * `describeCloseButtons` checks that every button names the right routes. This checks that naming them does anything.
8
+ * The history is module state in the library, filled by the navigation guard and read
9
+ * by `navigateBack`, so the admin's set-up and the library are only correct together.
10
+ * Route names come from the declaration. Made-up names would be rejected
11
+ * by `anzu/valid-route-name`, and real ones keep the test honest.
19
12
  */
20
13
  export declare function describeRouteHistory({ declaration, routeHistoryBlacklist, initRouteHistory, }: DescribeRouteHistoryOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"routeHistory.js","names":["describeRouteHistory","useRouteHistory","listing","record","parseTypedRouterDeclaration","declaration","routeHistoryBlacklist","name","visit","addRoute","recorded","history","route","routerOn","vi","beforeEach","clearHistory","initRouteHistory","it","expect","router","navigateBack"],"sources":["../../src/testing/routeHistory.ts"],"sourcesContent":["import { beforeEach, describe, expect, it, vi } from 'vitest'\nimport type { RouteRecordName } from 'vue-router'\nimport { useRouteHistory } from '@/domains/system/composables/routeHistory'\nimport { parseTypedRouterDeclaration } from '@/testing/typedRouter'\n\nexport interface DescribeRouteHistoryOptions {\n /** `src/typed-router.d.ts`, imported with `?raw`. */\n declaration: string\n /** The admin's route history blacklist. */\n routeHistoryBlacklist: readonly string[]\n /** What the admin runs at start-up to set up the history. */\n initRouteHistory: () => void\n}\n\n/**\n * What the close buttons stand on.\n *\n * `describeCloseButtons` checks that every button names the right routes; this checks that naming\n * them does anything. The history is module state inside the library, filled by the navigation guard\n * and read back by `navigateBack`, so the admin's set-up and the library are only correct together.\n *\n * The route names come out of the declaration rather than being made up: made-up ones would be\n * rejected by `anzu/valid-route-name`, and real ones keep the test honest about the strings the app\n * actually carries.\n */\nexport function describeRouteHistory({\n declaration,\n routeHistoryBlacklist,\n initRouteHistory,\n}: DescribeRouteHistoryOptions): void {\n const { history, addRoute, clearHistory, navigateBack } = useRouteHistory()\n\n const [listing, record] = parseTypedRouterDeclaration(declaration).names.filter(\n (name) => !routeHistoryBlacklist.includes(name)\n )\n\n // The history only ever reads these two fields of the route.\n const visit = (name: string, fullPath = name) =>\n (addRoute as (route: { name: string; fullPath: string }) => void)({ name, fullPath })\n\n const recorded = () => history.value.map((route) => route.name)\n\n // `navigateBack` reads the route it is called from -- it never hands that one back -- so the\n // double has to carry one. These cases all run as if the user were on a record view.\n const routerOn = (name: string, fullPath = name) => ({\n push: vi.fn(),\n back: vi.fn(),\n currentRoute: { value: { name, fullPath } },\n })\n\n describe('route history', () => {\n beforeEach(() => {\n clearHistory()\n initRouteHistory()\n })\n\n it('has two routes to work with', () => {\n // Guards the guard: were the declaration unreadable, every assertion below would compare\n // `undefined` against `undefined` and pass while checking nothing.\n expect(listing).toBeTypeOf('string')\n expect(record).toBeTypeOf('string')\n expect(routeHistoryBlacklist.length).toBeGreaterThan(0)\n })\n\n it('records an ordinary route, once', () => {\n visit(listing!)\n visit(listing!)\n visit(record!)\n\n // The guard fires again on a navigation that a later guard then cancels, so the same route\n // arrives twice in a row; a second copy would cost one of the ten slots for nothing.\n expect(recorded()).toEqual([listing, record])\n })\n\n it('keeps every blacklisted route out', () => {\n for (const name of routeHistoryBlacklist) visit(name)\n\n expect(recorded()).toEqual([])\n })\n\n it('walks back past the view being closed to the one before it', () => {\n // With an empty skip list, exactly as the buttons pass it: the view being closed is the one the\n // router is on, and `navigateBack` never hands that back.\n visit(listing!)\n visit(record!)\n\n const router = routerOn(record!)\n navigateBack(router as never, { skipRouteNames: [], fallbackRouteName: listing as RouteRecordName })\n\n expect(router.push).toHaveBeenCalledWith(listing)\n expect(router.back).not.toHaveBeenCalled()\n })\n\n it('falls back when history holds nothing but the view being closed', () => {\n // A tab opened straight on a record: nothing was visited before it.\n visit(record!)\n\n const router = routerOn(record!)\n navigateBack(router as never, { skipRouteNames: [], fallbackRouteName: listing as RouteRecordName })\n\n expect(router.push).toHaveBeenCalledWith({ name: listing, params: undefined })\n })\n\n it('does not hand back a route the blacklist rejected', () => {\n visit(listing!)\n visit(routeHistoryBlacklist[0]!)\n\n const router = routerOn(record!)\n navigateBack(router as never, { skipRouteNames: [], fallbackRouteName: listing as RouteRecordName })\n\n expect(router.push).toHaveBeenCalledWith(listing)\n })\n })\n}\n"],"mappings":";;;;AAyBA,SAAgBA,EAAqB,EACnC,gBACA,0BACA,uBACoC;CACpC,IAAM,EAAE,YAAS,aAAU,iBAAc,oBAAiBC,EAAgB,GAEpE,CAACC,GAASC,KAAUC,EAA4BC,CAAW,CAAC,CAAC,MAAM,QACtE,MAAS,CAACC,EAAsB,SAASC,CAAI,CAChD,GAGMC,KAAS,GAAc,IAAWD,MACrCE,EAAiE;EAAE;EAAM;CAAS,CAAC,GAEhFC,UAAiBC,EAAQ,MAAM,KAAK,MAAUC,EAAM,IAAI,GAIxDC,KAAY,GAAc,IAAWN,OAAU;EACnD,MAAMO,EAAG,GAAG;EACZ,MAAMA,EAAG,GAAG;EACZ,cAAc,EAAE,OAAO;GAAE;GAAM;EAAS,EAAE;CAC5C;CAEA,EAAS,uBAAuB;EAqD9B,AApDAC,QAAiB;GAEf,AADAC,EAAa,GACbC,EAAiB;EACnB,CAAC,GAEDC,EAAG,qCAAqC;GAKtC,AAFAC,EAAOjB,CAAO,CAAC,CAAC,WAAW,QAAQ,GACnCiB,EAAOhB,CAAM,CAAC,CAAC,WAAW,QAAQ,GAClCgB,EAAOb,EAAsB,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACxD,CAAC,GAEDY,EAAG,yCAAyC;GAO1C,AANAV,EAAMN,CAAQ,GACdM,EAAMN,CAAQ,GACdM,EAAML,CAAO,GAIbgB,EAAOT,EAAS,CAAC,CAAC,CAAC,QAAQ,CAACR,GAASC,CAAM,CAAC;EAC9C,CAAC,GAEDe,EAAG,2CAA2C;GAC5C,KAAK,IAAMX,KAAQD,GAAuB,EAAMC,CAAI;GAEpD,EAAOG,EAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EAC/B,CAAC,GAEDQ,EAAG,oEAAoE;GAIrE,AADAV,EAAMN,CAAQ,GACdM,EAAML,CAAO;GAEb,IAAMiB,IAASP,EAASV,CAAO;GAI/B,AAHAkB,EAAaD,GAAiB;IAAE,gBAAgB,CAAC;IAAG,mBAAmBlB;GAA2B,CAAC,GAEnGiB,EAAOC,EAAO,IAAI,CAAC,CAAC,qBAAqBlB,CAAO,GAChDiB,EAAOC,EAAO,IAAI,CAAC,CAAC,IAAI,iBAAiB;EAC3C,CAAC,GAEDF,EAAG,yEAAyE;GAE1E,EAAMf,CAAO;GAEb,IAAMiB,IAASP,EAASV,CAAO;GAG/B,AAFAkB,EAAaD,GAAiB;IAAE,gBAAgB,CAAC;IAAG,mBAAmBlB;GAA2B,CAAC,GAEnGiB,EAAOC,EAAO,IAAI,CAAC,CAAC,qBAAqB;IAAE,MAAMlB;IAAS,QAAQ,KAAA;GAAU,CAAC;EAC/E,CAAC,GAEDgB,EAAG,2DAA2D;GAE5D,AADAV,EAAMN,CAAQ,GACdM,EAAMF,EAAsB,EAAG;GAE/B,IAAMc,IAASP,EAASV,CAAO;GAG/B,AAFAkB,EAAaD,GAAiB;IAAE,gBAAgB,CAAC;IAAG,mBAAmBlB;GAA2B,CAAC,GAEnGiB,EAAOC,EAAO,IAAI,CAAC,CAAC,qBAAqBlB,CAAO;EAClD,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"routeHistory.js","names":["describeRouteHistory","useRouteHistory","listing","record","parseTypedRouterDeclaration","declaration","routeHistoryBlacklist","name","visit","addRoute","recorded","history","route","routerOn","vi","beforeEach","clearHistory","initRouteHistory","it","expect","router","navigateBack"],"sources":["../../src/testing/routeHistory.ts"],"sourcesContent":["import { beforeEach, describe, expect, it, vi } from 'vitest'\nimport type { RouteRecordName } from 'vue-router'\nimport { useRouteHistory } from '@/domains/system/composables/routeHistory'\nimport { parseTypedRouterDeclaration } from '@/testing/typedRouter'\n\nexport interface DescribeRouteHistoryOptions {\n declaration: string\n routeHistoryBlacklist: readonly string[]\n initRouteHistory: () => void\n}\n\n/**\n * `describeCloseButtons` checks that every button names the right routes. This checks that naming them does anything.\n * The history is module state in the library, filled by the navigation guard and read\n * by `navigateBack`, so the admin's set-up and the library are only correct together.\n * Route names come from the declaration. Made-up names would be rejected\n * by `anzu/valid-route-name`, and real ones keep the test honest.\n */\nexport function describeRouteHistory({\n declaration,\n routeHistoryBlacklist,\n initRouteHistory,\n}: DescribeRouteHistoryOptions): void {\n const { history, addRoute, clearHistory, navigateBack } = useRouteHistory()\n\n const [listing, record] = parseTypedRouterDeclaration(declaration).names.filter(\n (name) => !routeHistoryBlacklist.includes(name)\n )\n\n // The history only ever reads these two fields of the route.\n const visit = (name: string, fullPath = name) =>\n (addRoute as (route: { name: string; fullPath: string }) => void)({ name, fullPath })\n\n const recorded = () => history.value.map((route) => route.name)\n\n // `navigateBack` reads the route it is called from -- it never hands that one back -- so the\n // double has to carry one. These cases all run as if the user were on a record view.\n const routerOn = (name: string, fullPath = name) => ({\n push: vi.fn(),\n back: vi.fn(),\n currentRoute: { value: { name, fullPath } },\n })\n\n describe('route history', () => {\n beforeEach(() => {\n clearHistory()\n initRouteHistory()\n })\n\n it('has two routes to work with', () => {\n // Guards the guard: were the declaration unreadable, every assertion below would compare\n // `undefined` against `undefined` and pass while checking nothing.\n expect(listing).toBeTypeOf('string')\n expect(record).toBeTypeOf('string')\n expect(routeHistoryBlacklist.length).toBeGreaterThan(0)\n })\n\n it('records an ordinary route, once', () => {\n visit(listing!)\n visit(listing!)\n visit(record!)\n\n // The guard fires again on a navigation that a later guard then cancels, so the same route\n // arrives twice in a row; a second copy would cost one of the ten slots for nothing.\n expect(recorded()).toEqual([listing, record])\n })\n\n it('keeps every blacklisted route out', () => {\n for (const name of routeHistoryBlacklist) visit(name)\n\n expect(recorded()).toEqual([])\n })\n\n it('walks back past the view being closed to the one before it', () => {\n // With an empty skip list, exactly as the buttons pass it: the view being closed is the one the\n // router is on, and `navigateBack` never hands that back.\n visit(listing!)\n visit(record!)\n\n const router = routerOn(record!)\n navigateBack(router as never, { skipRouteNames: [], fallbackRouteName: listing as RouteRecordName })\n\n expect(router.push).toHaveBeenCalledWith(listing)\n expect(router.back).not.toHaveBeenCalled()\n })\n\n it('falls back when history holds nothing but the view being closed', () => {\n visit(record!)\n\n const router = routerOn(record!)\n navigateBack(router as never, { skipRouteNames: [], fallbackRouteName: listing as RouteRecordName })\n\n expect(router.push).toHaveBeenCalledWith({ name: listing, params: undefined })\n })\n\n it('does not hand back a route the blacklist rejected', () => {\n visit(listing!)\n visit(routeHistoryBlacklist[0]!)\n\n const router = routerOn(record!)\n navigateBack(router as never, { skipRouteNames: [], fallbackRouteName: listing as RouteRecordName })\n\n expect(router.push).toHaveBeenCalledWith(listing)\n })\n })\n}\n"],"mappings":";;;;AAkBA,SAAgBA,EAAqB,EACnC,gBACA,0BACA,uBACoC;CACpC,IAAM,EAAE,YAAS,aAAU,iBAAc,oBAAiBC,EAAgB,GAEpE,CAACC,GAASC,KAAUC,EAA4BC,CAAW,CAAC,CAAC,MAAM,QACtE,MAAS,CAACC,EAAsB,SAASC,CAAI,CAChD,GAGMC,KAAS,GAAc,IAAWD,MACrCE,EAAiE;EAAE;EAAM;CAAS,CAAC,GAEhFC,UAAiBC,EAAQ,MAAM,KAAK,MAAUC,EAAM,IAAI,GAIxDC,KAAY,GAAc,IAAWN,OAAU;EACnD,MAAMO,EAAG,GAAG;EACZ,MAAMA,EAAG,GAAG;EACZ,cAAc,EAAE,OAAO;GAAE;GAAM;EAAS,EAAE;CAC5C;CAEA,EAAS,uBAAuB;EAoD9B,AAnDAC,QAAiB;GAEf,AADAC,EAAa,GACbC,EAAiB;EACnB,CAAC,GAEDC,EAAG,qCAAqC;GAKtC,AAFAC,EAAOjB,CAAO,CAAC,CAAC,WAAW,QAAQ,GACnCiB,EAAOhB,CAAM,CAAC,CAAC,WAAW,QAAQ,GAClCgB,EAAOb,EAAsB,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACxD,CAAC,GAEDY,EAAG,yCAAyC;GAO1C,AANAV,EAAMN,CAAQ,GACdM,EAAMN,CAAQ,GACdM,EAAML,CAAO,GAIbgB,EAAOT,EAAS,CAAC,CAAC,CAAC,QAAQ,CAACR,GAASC,CAAM,CAAC;EAC9C,CAAC,GAEDe,EAAG,2CAA2C;GAC5C,KAAK,IAAMX,KAAQD,GAAuB,EAAMC,CAAI;GAEpD,EAAOG,EAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EAC/B,CAAC,GAEDQ,EAAG,oEAAoE;GAIrE,AADAV,EAAMN,CAAQ,GACdM,EAAML,CAAO;GAEb,IAAMiB,IAASP,EAASV,CAAO;GAI/B,AAHAkB,EAAaD,GAAiB;IAAE,gBAAgB,CAAC;IAAG,mBAAmBlB;GAA2B,CAAC,GAEnGiB,EAAOC,EAAO,IAAI,CAAC,CAAC,qBAAqBlB,CAAO,GAChDiB,EAAOC,EAAO,IAAI,CAAC,CAAC,IAAI,iBAAiB;EAC3C,CAAC,GAEDF,EAAG,yEAAyE;GAC1E,EAAMf,CAAO;GAEb,IAAMiB,IAASP,EAASV,CAAO;GAG/B,AAFAkB,EAAaD,GAAiB;IAAE,gBAAgB,CAAC;IAAG,mBAAmBlB;GAA2B,CAAC,GAEnGiB,EAAOC,EAAO,IAAI,CAAC,CAAC,qBAAqB;IAAE,MAAMlB;IAAS,QAAQ,KAAA;GAAU,CAAC;EAC/E,CAAC,GAEDgB,EAAG,2DAA2D;GAE5D,AADAV,EAAMN,CAAQ,GACdM,EAAMF,EAAsB,EAAG;GAE/B,IAAMc,IAASP,EAASV,CAAO;GAG/B,AAFAkB,EAAaD,GAAiB;IAAE,gBAAgB,CAAC;IAAG,mBAAmBlB;GAA2B,CAAC,GAEnGiB,EAAOC,EAAO,IAAI,CAAC,CAAC,qBAAqBlB,CAAO;EAClD,CAAC;CACH,CAAC;AACH"}
@@ -1,31 +1,26 @@
1
1
  export interface DescribeSortableListsOptions {
2
- /** The admin's sources: `import.meta.glob('/src/**\/*.{vue,ts}', { query: '?raw', import: 'default', eager: true })`. */
2
+ /**
3
+ * The admin's sources: `import.meta.glob('/src/**\/*.{vue,ts}', { query: '?raw', import: 'default', eager: true })`.
4
+ */
3
5
  sources: Record<string, string>;
4
- /** Checks that every list editor registers with the unsaved changes guard or opts out of it. */
5
6
  unsavedRegistration?: boolean;
6
7
  }
7
8
  /**
8
- * The list editors replaced older ways of making a list sortable, and a direct `useSortable` is a
9
- * perfectly valid VueUse import, so nothing fails a build if one comes back.
10
- *
11
- * What they cost is not style. The library's editors carry the reorder mode with its own undo, the
12
- * dirty and unsaved bookkeeping, per-row validation, the delete confirmation and keyboard moves; each
13
- * hand-rolled list re-implemented some fraction of that and skipped the rest -- two of the lists they
14
- * replaced wrote a drag into a display array that the save path never read, so reordering them looked
15
- * applied and was thrown away.
9
+ * The list editors replaced older ways of making a list sortable. A direct
10
+ * `useSortable` is a valid VueUse import, so no build fails if one comes back.
11
+ * The editors carry reorder mode with undo, dirty and unsaved bookkeeping, per-row validation,
12
+ * delete confirmation and keyboard moves. Hand-rolled lists re-implement only part of that.
13
+ * Two replaced lists wrote a drag into a display array that the
14
+ * save path never read, so reordering looked applied and was lost.
16
15
  */
17
16
  export declare function describeSortableLists({ sources, unsavedRegistration }: DescribeSortableListsOptions): void;
18
17
  /**
19
- * The opening tags of the list editors in a source that neither register with the unsaved changes guard
20
- * (`:unsaved-section-label`) nor opt out of it (bare `disable-unsaved` or `readonly`).
21
- *
22
- * Each tag is read from its `<` to the first `>` outside quotes: an attribute value can hold a `>` of
23
- * its own (`v-if="items.length > 0"`). Quotes are paired inside the tag only; paired across the file,
24
- * an apostrophe in a comment (`editor's`) would pair with a quote many lines on and swallow the tag.
25
- * Attribute values are blanked before the check, so `:readonly="readonly"` -- read-only when its
26
- * parent happens to say so -- is not taken for the bare attribute.
27
- *
28
- * An editor handed a lifted controller (`:editor=`) is left out: the controller belongs to whoever
29
- * holds it -- the outer editor in whose rows a nested list renders -- and that one registers.
18
+ * The opening tags of list editors in a source that neither register with the unsaved changes
19
+ * guard (`:unsaved-section-label`) nor opt out (bare `disable-unsaved` or `readonly`).
20
+ * Each tag is read from its `<` to the first `>` outside quotes, since a value can hold
21
+ * `>` (`v-if="items.length > 0"`). Quotes are paired inside the tag only: across the
22
+ * file, an apostrophe in a comment would pair with a distant quote and swallow the tag.
23
+ * Attribute values are blanked first, so `:readonly="readonly"` is not taken for the bare attribute.
24
+ * An editor given a lifted controller (`:editor=`) is skipped. The outer editor that owns the controller registers.
30
25
  */
31
26
  export declare function unregisteredListEditorTags(source: string): string[];
@@ -1 +1 @@
1
- {"version":3,"file":"sortableLists.js","names":["describeSortableLists","using","sources","path","source","globKeyToSrcPath","pattern","it","unsavedRegistration","unregistered","unregisteredListEditorTags","tags","match","quote","end","char","tag"],"sources":["../../src/testing/sortableLists.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath } from '@/testing/typedRouter'\n\nexport interface DescribeSortableListsOptions {\n /** The admin's sources: `import.meta.glob('/src/**\\/*.{vue,ts}', { query: '?raw', import: 'default', eager: true })`. */\n sources: Record<string, string>\n /** Checks that every list editor registers with the unsaved changes guard or opts out of it. */\n unsavedRegistration?: boolean\n}\n\n/**\n * The list editors replaced older ways of making a list sortable, and a direct `useSortable` is a\n * perfectly valid VueUse import, so nothing fails a build if one comes back.\n *\n * What they cost is not style. The library's editors carry the reorder mode with its own undo, the\n * dirty and unsaved bookkeeping, per-row validation, the delete confirmation and keyboard moves; each\n * hand-rolled list re-implemented some fraction of that and skipped the rest -- two of the lists they\n * replaced wrote a drag into a display array that the save path never read, so reordering them looked\n * applied and was thrown away.\n */\nexport function describeSortableLists({ sources, unsavedRegistration = true }: DescribeSortableListsOptions): void {\n const using = (pattern: RegExp) =>\n Object.entries(sources)\n .map(([path, source]) => [globKeyToSrcPath(path), source] as const)\n .filter(([path]) => !path.startsWith('src/test/'))\n .filter(([, source]) => pattern.test(source))\n\n describe('sortable lists', () => {\n it('reads the sources it is meant to check', () => {\n // A guard on the guard: were the glob to stop matching, every assertion below would filter an\n // empty list and pass while checking nothing.\n expect(Object.keys(sources).length).toBeGreaterThan(50)\n })\n\n it('uses no removed sortable component', () => {\n // `ASortable` and `ASortableNested` left the library in 2.0.0.\n expect(using(/<ASortable(?:Nested)?(?![A-Za-z])/).map(([path]) => path)).toEqual([])\n })\n\n it('calls no sortable library directly', () => {\n // `ASortableListEditor` wraps `useSortable` itself; what is out of place is an admin reaching\n // past the editor for the same thing.\n expect(using(/from\\s+'(?:@vueuse\\/integrations\\/useSortable|sortablejs)'/).map(([path]) => path)).toEqual([])\n })\n\n it.runIf(unsavedRegistration)('registers every list editor with the guard, or says it is not to be', () => {\n // `unsaved-section-label` reads like a caption and is the whole registration: without it the\n // editor registers no section, and a guard declared with `sources: []` is left with nothing to\n // ask about. The rows still go amber, so the loss is silent: the view stops asking on the way\n // out and looks no different.\n //\n // `disable-unsaved` is the deliberate way out, for a list that is saved by the form around it\n // and has no unsaved state of its own to report; `readonly` never had unsaved state to begin\n // with.\n //\n // Read off the editor's own opening tag rather than the file: every one of these three words\n // appears elsewhere in a component for its own reasons, and a file-wide search would exempt an\n // editor because something further down happened to mention one of them.\n const unregistered = using(/<A(?:Nested)?(?:Sortable)?ListEditor/)\n .filter(([, source]) => unregisteredListEditorTags(source).length > 0)\n .map(([path]) => path)\n\n expect(unregistered).toEqual([])\n })\n })\n}\n\n/**\n * The opening tags of the list editors in a source that neither register with the unsaved changes guard\n * (`:unsaved-section-label`) nor opt out of it (bare `disable-unsaved` or `readonly`).\n *\n * Each tag is read from its `<` to the first `>` outside quotes: an attribute value can hold a `>` of\n * its own (`v-if=\"items.length > 0\"`). Quotes are paired inside the tag only; paired across the file,\n * an apostrophe in a comment (`editor's`) would pair with a quote many lines on and swallow the tag.\n * Attribute values are blanked before the check, so `:readonly=\"readonly\"` -- read-only when its\n * parent happens to say so -- is not taken for the bare attribute.\n *\n * An editor handed a lifted controller (`:editor=`) is left out: the controller belongs to whoever\n * holds it -- the outer editor in whose rows a nested list renders -- and that one registers.\n */\nexport function unregisteredListEditorTags(source: string): string[] {\n const tags: string[] = []\n for (const match of source.matchAll(/<A(?:Nested)?(?:Sortable)?ListEditor\\b/g)) {\n let quote: string | null = null\n let end = match.index + match[0].length\n for (; end < source.length; end++) {\n const char = source[end]\n if (quote) {\n if (char === quote) quote = null\n } else if (char === '\"' || char === \"'\") quote = char\n else if (char === '>') break\n }\n tags.push(source.slice(match.index, end + 1))\n }\n return tags.filter(\n (tag) =>\n !/:unsaved-section-label=|:editor=|(?<![:\\w-])(?:disable-unsaved|readonly)\\b/.test(\n tag.replace(/\"[^\"]*\"/g, '\"\"').replace(/'[^']*'/g, \"''\")\n )\n )\n}\n"],"mappings":";;;AAoBA,SAAgBA,EAAsB,EAAE,YAAS,yBAAsB,MAA4C;CACjH,IAAMC,KAAS,MACb,OAAO,QAAQC,CAAO,CAAC,CACpB,KAAK,CAACC,GAAMC,OAAY,CAACC,EAAiBF,CAAI,GAAGC,CAAM,CAAU,CAAC,CAClE,QAAQ,CAACD,OAAU,CAACA,EAAK,WAAW,WAAW,CAAC,CAAC,CACjD,QAAQ,GAAGC,OAAYE,EAAQ,KAAKF,CAAM,CAAC;CAEhD,EAAS,wBAAwB;EAkB/B,AAjBAG,EAAG,gDAAgD;GAGjD,EAAO,OAAO,KAAKL,CAAO,CAAC,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE;EACxD,CAAC,GAEDK,EAAG,4CAA4C;GAE7C,EAAON,EAAM,mCAAmC,CAAC,CAAC,KAAK,CAACE,OAAUA,CAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EACrF,CAAC,GAEDI,EAAG,4CAA4C;GAG7C,EAAON,EAAM,4DAA4D,CAAC,CAAC,KAAK,CAACE,OAAUA,CAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EAC9G,CAAC,GAEDI,EAAG,MAAMC,CAAmB,CAAC,CAAC,6EAA6E;GAazG,IAAMC,IAAeR,EAAM,sCAAsC,CAAC,CAC/D,QAAQ,GAAGG,OAAYM,EAA2BN,CAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CACrE,KAAK,CAACD,OAAUA,CAAI;GAEvB,EAAOM,CAAY,CAAC,CAAC,QAAQ,CAAC,CAAC;EACjC,CAAC;CACH,CAAC;AACH;AAeA,SAAgBC,EAA2B,GAA0B;CACnE,IAAMC,IAAiB,CAAC;CACxB,KAAK,IAAMC,KAASR,EAAO,SAAS,yCAAyC,GAAG;EAC9E,IAAIS,IAAuB,MACvBC,IAAMF,EAAM,QAAQA,EAAM,EAAE,CAAC;EACjC,OAAOE,IAAMV,EAAO,QAAQ,KAAO;GACjC,IAAMW,IAAOX,EAAOU;GACpB,IAAID,GACE,AAAAE,MAASF,MAAO,IAAQ;QACvB,IAAIE,MAAS,QAAOA,MAAS,KAAK,IAAQA;QAC5C,IAAIA,MAAS,KAAK;EACzB;EACA,EAAK,KAAKX,EAAO,MAAMQ,EAAM,OAAOE,IAAM,CAAC,CAAC;CAC9C;CACA,OAAOH,EAAK,QACT,MACC,CAAC,6EAA6E,KAC5EK,EAAI,QAAQ,YAAY,MAAI,CAAC,CAAC,QAAQ,YAAY,IAAI,CACxD,CACJ;AACF"}
1
+ {"version":3,"file":"sortableLists.js","names":["describeSortableLists","using","sources","path","source","globKeyToSrcPath","pattern","it","unsavedRegistration","unregistered","unregisteredListEditorTags","tags","match","quote","end","char","tag"],"sources":["../../src/testing/sortableLists.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { globKeyToSrcPath } from '@/testing/typedRouter'\n\nexport interface DescribeSortableListsOptions {\n /**\n * The admin's sources: `import.meta.glob('/src/**\\/*.{vue,ts}', { query: '?raw', import: 'default', eager: true })`.\n */\n sources: Record<string, string>\n unsavedRegistration?: boolean\n}\n\n/**\n * The list editors replaced older ways of making a list sortable. A direct\n * `useSortable` is a valid VueUse import, so no build fails if one comes back.\n * The editors carry reorder mode with undo, dirty and unsaved bookkeeping, per-row validation,\n * delete confirmation and keyboard moves. Hand-rolled lists re-implement only part of that.\n * Two replaced lists wrote a drag into a display array that the\n * save path never read, so reordering looked applied and was lost.\n */\nexport function describeSortableLists({ sources, unsavedRegistration = true }: DescribeSortableListsOptions): void {\n const using = (pattern: RegExp) =>\n Object.entries(sources)\n .map(([path, source]) => [globKeyToSrcPath(path), source] as const)\n .filter(([path]) => !path.startsWith('src/test/'))\n .filter(([, source]) => pattern.test(source))\n\n describe('sortable lists', () => {\n it('reads the sources it is meant to check', () => {\n // A guard on the guard: were the glob to stop matching, every assertion below would filter an\n // empty list and pass while checking nothing.\n expect(Object.keys(sources).length).toBeGreaterThan(50)\n })\n\n it('uses no removed sortable component', () => {\n // `ASortable` and `ASortableNested` left the library in 2.0.0.\n expect(using(/<ASortable(?:Nested)?(?![A-Za-z])/).map(([path]) => path)).toEqual([])\n })\n\n it('calls no sortable library directly', () => {\n // `ASortableListEditor` wraps `useSortable` itself; what is out of place is an admin reaching\n // past the editor for the same thing.\n expect(using(/from\\s+'(?:@vueuse\\/integrations\\/useSortable|sortablejs)'/).map(([path]) => path)).toEqual([])\n })\n\n it.runIf(unsavedRegistration)('registers every list editor with the guard, or says it is not to be', () => {\n // `unsaved-section-label` is the whole registration. Without it the editor registers no section,\n // the view stops asking on the way out, and nothing looks different (the rows still go amber).\n // `disable-unsaved` is the deliberate opt-out for a list saved\n // by the surrounding form. `readonly` never had unsaved state.\n // Read from the editor's own opening tag, not the whole file: these words appear\n // elsewhere in a component for other reasons and would wrongly exempt an editor.\n const unregistered = using(/<A(?:Nested)?(?:Sortable)?ListEditor/)\n .filter(([, source]) => unregisteredListEditorTags(source).length > 0)\n .map(([path]) => path)\n\n expect(unregistered).toEqual([])\n })\n })\n}\n\n/**\n * The opening tags of list editors in a source that neither register with the unsaved changes\n * guard (`:unsaved-section-label`) nor opt out (bare `disable-unsaved` or `readonly`).\n * Each tag is read from its `<` to the first `>` outside quotes, since a value can hold\n * `>` (`v-if=\"items.length > 0\"`). Quotes are paired inside the tag only: across the\n * file, an apostrophe in a comment would pair with a distant quote and swallow the tag.\n * Attribute values are blanked first, so `:readonly=\"readonly\"` is not taken for the bare attribute.\n * An editor given a lifted controller (`:editor=`) is skipped. The outer editor that owns the controller registers.\n */\nexport function unregisteredListEditorTags(source: string): string[] {\n const tags: string[] = []\n for (const match of source.matchAll(/<A(?:Nested)?(?:Sortable)?ListEditor\\b/g)) {\n let quote: string | null = null\n let end = match.index + match[0].length\n for (; end < source.length; end++) {\n const char = source[end]\n if (quote) {\n if (char === quote) quote = null\n } else if (char === '\"' || char === \"'\") quote = char\n else if (char === '>') break\n }\n tags.push(source.slice(match.index, end + 1))\n }\n return tags.filter(\n (tag) =>\n !/:unsaved-section-label=|:editor=|(?<![:\\w-])(?:disable-unsaved|readonly)\\b/.test(\n tag.replace(/\"[^\"]*\"/g, '\"\"').replace(/'[^']*'/g, \"''\")\n )\n )\n}\n"],"mappings":";;;AAmBA,SAAgBA,EAAsB,EAAE,YAAS,yBAAsB,MAA4C;CACjH,IAAMC,KAAS,MACb,OAAO,QAAQC,CAAO,CAAC,CACpB,KAAK,CAACC,GAAMC,OAAY,CAACC,EAAiBF,CAAI,GAAGC,CAAM,CAAU,CAAC,CAClE,QAAQ,CAACD,OAAU,CAACA,EAAK,WAAW,WAAW,CAAC,CAAC,CACjD,QAAQ,GAAGC,OAAYE,EAAQ,KAAKF,CAAM,CAAC;CAEhD,EAAS,wBAAwB;EAkB/B,AAjBAG,EAAG,gDAAgD;GAGjD,EAAO,OAAO,KAAKL,CAAO,CAAC,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE;EACxD,CAAC,GAEDK,EAAG,4CAA4C;GAE7C,EAAON,EAAM,mCAAmC,CAAC,CAAC,KAAK,CAACE,OAAUA,CAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EACrF,CAAC,GAEDI,EAAG,4CAA4C;GAG7C,EAAON,EAAM,4DAA4D,CAAC,CAAC,KAAK,CAACE,OAAUA,CAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;EAC9G,CAAC,GAEDI,EAAG,MAAMC,CAAmB,CAAC,CAAC,6EAA6E;GAOzG,IAAMC,IAAeR,EAAM,sCAAsC,CAAC,CAC/D,QAAQ,GAAGG,OAAYM,EAA2BN,CAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CACrE,KAAK,CAACD,OAAUA,CAAI;GAEvB,EAAOM,CAAY,CAAC,CAAC,QAAQ,CAAC,CAAC;EACjC,CAAC;CACH,CAAC;AACH;AAWA,SAAgBC,EAA2B,GAA0B;CACnE,IAAMC,IAAiB,CAAC;CACxB,KAAK,IAAMC,KAASR,EAAO,SAAS,yCAAyC,GAAG;EAC9E,IAAIS,IAAuB,MACvBC,IAAMF,EAAM,QAAQA,EAAM,EAAE,CAAC;EACjC,OAAOE,IAAMV,EAAO,QAAQ,KAAO;GACjC,IAAMW,IAAOX,EAAOU;GACpB,IAAID,GACE,AAAAE,MAASF,MAAO,IAAQ;QACvB,IAAIE,MAAS,QAAOA,MAAS,KAAK,IAAQA;QAC5C,IAAIA,MAAS,KAAK;EACzB;EACA,EAAK,KAAKX,EAAO,MAAMQ,EAAM,OAAOE,IAAM,CAAC,CAAC;CAC9C;CACA,OAAOH,EAAK,QACT,MACC,CAAC,6EAA6E,KAC5EK,EAAI,QAAQ,YAAY,MAAI,CAAC,CAAC,QAAQ,YAAY,IAAI,CACxD,CACJ;AACF"}
@@ -1,6 +1,5 @@
1
1
  /** What the guard tests read out of an admin's generated `src/typed-router.d.ts`. */
2
2
  export interface TypedRouterDeclaration {
3
- /** Every declared route name, in declaration order. */
4
3
  names: string[];
5
4
  /** Every declared route with its path pattern, the catch-all included. */
6
5
  paths: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"typedRouter.js","names":["parseTypedRouterDeclaration","declaration","name","path","file","block","globKeyToSrcPath","key"],"sources":["../../src/testing/typedRouter.ts"],"sourcesContent":["/** What the guard tests read out of an admin's generated `src/typed-router.d.ts`. */\nexport interface TypedRouterDeclaration {\n /** Every declared route name, in declaration order. */\n names: string[]\n /** Every declared route with its path pattern, the catch-all included. */\n paths: Array<{ name: string; path: string }>\n /** The route names each page file defines; a page that defines none is left out. */\n pageRoutes: Map<string, string[]>\n}\n\nexport function parseTypedRouterDeclaration(declaration: string): TypedRouterDeclaration {\n const names = [...declaration.matchAll(/^ {4}'([^']+)': RouteRecordInfo</gm)].map(([, name]) => name!)\n\n // The declaration holds TypeScript source, so a `\\d` constraint is written there as an escaped\n // backslash. Reading it raw would leave `\\\\d`, which matches a literal backslash and nothing else.\n const paths = [...declaration.matchAll(/'[^']+':\\s*RouteRecordInfo<\\s*'([^']*)',\\s*'([^']+)'/g)].map(\n ([, name, path]) => ({ name: name!, path: path!.replace(/\\\\\\\\/g, '\\\\') })\n )\n\n // The declaration lists a `never` for pages that define no route; those blocks carry no quoted\n // name and simply do not match.\n const pageRoutes = new Map(\n [...declaration.matchAll(/'(src\\/pages\\/[^']+)':\\s*\\{\\s*routes:((?:\\s*\\|\\s*'[^']*')+)/g)].map(([, file, block]) => [\n file!,\n [...block!.matchAll(/'([^']*)'/g)].map(([, name]) => name!),\n ])\n )\n\n return { names, paths, pageRoutes }\n}\n\n/**\n * `src/…` for a key of `import.meta.glob`: `../pages/x.vue` from a test in `src/test/`, or\n * `/src/pages/x.vue` from an absolute glob.\n */\nexport const globKeyToSrcPath = (key: string) => key.replace(/^\\/src\\//, 'src/').replace(/^\\.\\.\\//, 'src/')\n"],"mappings":";AAUA,SAAgBA,EAA4B,GAA6C;CAkBvF,OAAO;EAAE,OAjBK,CAAC,GAAGC,EAAY,SAAS,oCAAoC,CAAC,CAAC,CAAC,KAAK,GAAGC,OAAUA,CAiBvF;EAAO,OAbF,CAAC,GAAGD,EAAY,SAAS,uDAAuD,CAAC,CAAC,CAAC,KAC9F,GAAGC,GAAMC,QAAW;GAAQ;GAAO,MAAMA,EAAM,QAAQ,SAAS,IAAI;EAAE,EAYzD;EAAO,YAAA,IAPA,IACrB,CAAC,GAAGF,EAAY,SAAS,8DAA8D,CAAC,CAAC,CAAC,KAAK,GAAGG,GAAMC,OAAW,CACjHD,GACA,CAAC,GAAGC,EAAO,SAAS,YAAY,CAAC,CAAC,CAAC,KAAK,GAAGH,OAAUA,CAAK,CAC5D,CAAC,CAGoB;CAAW;AACpC;AAMA,IAAaI,KAAoB,MAAgBC,EAAI,QAAQ,YAAY,MAAM,CAAC,CAAC,QAAQ,WAAW,MAAM"}
1
+ {"version":3,"file":"typedRouter.js","names":["parseTypedRouterDeclaration","declaration","name","path","file","block","globKeyToSrcPath","key"],"sources":["../../src/testing/typedRouter.ts"],"sourcesContent":["/** What the guard tests read out of an admin's generated `src/typed-router.d.ts`. */\nexport interface TypedRouterDeclaration {\n names: string[]\n /** Every declared route with its path pattern, the catch-all included. */\n paths: Array<{ name: string; path: string }>\n /** The route names each page file defines; a page that defines none is left out. */\n pageRoutes: Map<string, string[]>\n}\n\nexport function parseTypedRouterDeclaration(declaration: string): TypedRouterDeclaration {\n const names = [...declaration.matchAll(/^ {4}'([^']+)': RouteRecordInfo</gm)].map(([, name]) => name!)\n\n // The declaration holds TypeScript source, so a `\\d` constraint is written there as an escaped\n // backslash. Reading it raw would leave `\\\\d`, which matches a literal backslash and nothing else.\n const paths = [...declaration.matchAll(/'[^']+':\\s*RouteRecordInfo<\\s*'([^']*)',\\s*'([^']+)'/g)].map(\n ([, name, path]) => ({ name: name!, path: path!.replace(/\\\\\\\\/g, '\\\\') })\n )\n\n // The declaration lists a `never` for pages that define no route; those blocks carry no quoted\n // name and simply do not match.\n const pageRoutes = new Map(\n [...declaration.matchAll(/'(src\\/pages\\/[^']+)':\\s*\\{\\s*routes:((?:\\s*\\|\\s*'[^']*')+)/g)].map(([, file, block]) => [\n file!,\n [...block!.matchAll(/'([^']*)'/g)].map(([, name]) => name!),\n ])\n )\n\n return { names, paths, pageRoutes }\n}\n\n/**\n * `src/…` for a key of `import.meta.glob`: `../pages/x.vue` from a test in `src/test/`, or\n * `/src/pages/x.vue` from an absolute glob.\n */\nexport const globKeyToSrcPath = (key: string) => key.replace(/^\\/src\\//, 'src/').replace(/^\\.\\.\\//, 'src/')\n"],"mappings":";AASA,SAAgBA,EAA4B,GAA6C;CAkBvF,OAAO;EAAE,OAjBK,CAAC,GAAGC,EAAY,SAAS,oCAAoC,CAAC,CAAC,CAAC,KAAK,GAAGC,OAAUA,CAiBvF;EAAO,OAbF,CAAC,GAAGD,EAAY,SAAS,uDAAuD,CAAC,CAAC,CAAC,KAC9F,GAAGC,GAAMC,QAAW;GAAQ;GAAO,MAAMA,EAAM,QAAQ,SAAS,IAAI;EAAE,EAYzD;EAAO,YAAA,IAPA,IACrB,CAAC,GAAGF,EAAY,SAAS,8DAA8D,CAAC,CAAC,CAAC,KAAK,GAAGG,GAAMC,OAAW,CACjHD,GACA,CAAC,GAAGC,EAAO,SAAS,YAAY,CAAC,CAAC,CAAC,KAAK,GAAGH,OAAUA,CAAK,CAC5D,CAAC,CAGoB;CAAW;AACpC;AAMA,IAAaI,KAAoB,MAAgBC,EAAI,QAAQ,YAAY,MAAM,CAAC,CAAC,QAAQ,WAAW,MAAM"}