@ozdao/martyrs 0.2.486 → 0.2.487

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 (591) hide show
  1. package/dist/Media-B2jWzwLB.cjs +1 -0
  2. package/dist/{Media-CXQSPHt2.js → Media-DZ5_ItXQ.js} +3 -3
  3. package/dist/auth.server.cjs +1 -1
  4. package/dist/auth.server.js +1 -1
  5. package/dist/{authJwt-DBB51Iql.cjs → authJwt-D35KyJlE.cjs} +31 -2
  6. package/dist/{authJwt-DcYNNwcr.js → authJwt-DqxhUym0.js} +31 -2
  7. package/dist/chats.server.cjs +1 -1
  8. package/dist/chats.server.js +1 -1
  9. package/dist/community.server.cjs +1 -1
  10. package/dist/community.server.js +1 -1
  11. package/dist/crud-BDIArc5A.cjs +1096 -0
  12. package/dist/crud-DJvpe0aZ.js +1097 -0
  13. package/dist/events.server.cjs +1 -1
  14. package/dist/events.server.js +1 -1
  15. package/dist/files.server.cjs +1 -1
  16. package/dist/files.server.js +1 -1
  17. package/dist/gallery.server.cjs +1 -1
  18. package/dist/gallery.server.js +1 -1
  19. package/dist/{index-CsJwdsBW.js → index-CVuQC4k1.js} +1 -1
  20. package/dist/{index-YNOkL1mu.cjs → index-DiSKVCaA.cjs} +1 -1
  21. package/dist/main-C6_DPWGX.cjs +11 -0
  22. package/dist/{main-Cfh5138F.js → main-nQmkbWsW.js} +825 -826
  23. package/dist/martyrs/src/components/Chips/{Chips.vue2.cjs → Chips.vue.cjs} +2 -2
  24. package/dist/martyrs/src/components/Chips/Chips.vue.cjs.map +1 -0
  25. package/dist/martyrs/src/components/Chips/{Chips.vue2.js → Chips.vue.js} +2 -2
  26. package/dist/martyrs/src/components/Chips/Chips.vue.js.map +1 -0
  27. package/dist/martyrs/src/components/Field/{Field.vue.cjs → Field.vue2.cjs} +5 -6
  28. package/dist/martyrs/src/components/Field/Field.vue2.cjs.map +1 -0
  29. package/dist/martyrs/src/components/Field/{Field.vue.js → Field.vue2.js} +5 -6
  30. package/dist/martyrs/src/components/Field/Field.vue2.js.map +1 -0
  31. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.cjs +10 -9
  32. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.cjs.map +1 -1
  33. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js +13 -12
  34. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js.map +1 -1
  35. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.cjs +1 -1
  36. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.cjs.map +1 -1
  37. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js +1 -1
  38. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js.map +1 -1
  39. package/dist/martyrs/src/components/Media/Media.vue.cjs +2 -2
  40. package/dist/martyrs/src/components/Media/Media.vue.cjs.map +1 -1
  41. package/dist/martyrs/src/components/Media/Media.vue.js +2 -2
  42. package/dist/martyrs/src/components/Media/Media.vue.js.map +1 -1
  43. package/dist/martyrs/src/components/Select/Select.vue.cjs +2 -2
  44. package/dist/martyrs/src/components/Select/Select.vue.cjs.map +1 -1
  45. package/dist/martyrs/src/components/Select/Select.vue.js +2 -2
  46. package/dist/martyrs/src/components/Select/Select.vue.js.map +1 -1
  47. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.cjs +1 -0
  48. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.cjs.map +1 -1
  49. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js +1 -0
  50. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js.map +1 -1
  51. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
  52. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +5 -5
  53. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
  54. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +5 -5
  55. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +1 -0
  56. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs.map +1 -1
  57. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +1 -0
  58. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js.map +1 -1
  59. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.cjs +1 -1
  60. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +10 -10
  61. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
  62. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +4 -4
  63. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
  64. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +5 -5
  65. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
  66. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +4 -4
  67. package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.cjs +1 -1
  68. package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +23 -23
  69. package/dist/martyrs/src/modules/community/components/blocks/CardBlogpost.vue.cjs +1 -1
  70. package/dist/martyrs/src/modules/community/components/blocks/CardBlogpost.vue.js +1 -1
  71. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.cjs +1 -1
  72. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +1 -1
  73. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +1 -1
  74. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +11 -11
  75. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.cjs +1 -1
  76. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.js +3 -3
  77. package/dist/martyrs/src/modules/constructor/components/elements/Embed.vue.cjs +1 -1
  78. package/dist/martyrs/src/modules/constructor/components/elements/Embed.vue.js +2 -2
  79. package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.cjs +1 -1
  80. package/dist/martyrs/src/modules/events/components/blocks/CardEvent.vue.js +1 -1
  81. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.cjs +1 -1
  82. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +25 -25
  83. package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.cjs +1 -1
  84. package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +15 -15
  85. package/dist/martyrs/src/modules/events/components/pages/Event.vue.cjs +9 -2
  86. package/dist/martyrs/src/modules/events/components/pages/Event.vue.cjs.map +1 -1
  87. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +9 -2
  88. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js.map +1 -1
  89. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.cjs +2 -1
  90. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.cjs.map +1 -1
  91. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +2 -1
  92. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js.map +1 -1
  93. package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs +24 -58
  94. package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs.map +1 -1
  95. package/dist/martyrs/src/modules/globals/views/classes/globals.store.js +24 -58
  96. package/dist/martyrs/src/modules/globals/views/classes/globals.store.js.map +1 -1
  97. package/dist/martyrs/src/modules/globals/views/components/blocks/BlockSearch.vue.cjs +1 -1
  98. package/dist/martyrs/src/modules/globals/views/components/blocks/BlockSearch.vue.js +2 -2
  99. package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.cjs +1 -0
  100. package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.cjs.map +1 -1
  101. package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.js +1 -0
  102. package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.js.map +1 -1
  103. package/dist/martyrs/src/modules/globals/views/components/sections/filters/FilterOptions.vue.cjs +1 -1
  104. package/dist/martyrs/src/modules/globals/views/components/sections/filters/FilterOptions.vue.js +2 -2
  105. package/dist/martyrs/src/modules/globals/views/components/sections/filters/FilterPrice.vue.cjs +1 -1
  106. package/dist/martyrs/src/modules/globals/views/components/sections/filters/FilterPrice.vue.js +3 -3
  107. package/dist/martyrs/src/modules/globals/views/store/globals.cjs +6 -0
  108. package/dist/martyrs/src/modules/globals/views/store/globals.cjs.map +1 -1
  109. package/dist/martyrs/src/modules/globals/views/store/globals.js +6 -0
  110. package/dist/martyrs/src/modules/globals/views/store/globals.js.map +1 -1
  111. package/dist/martyrs/src/modules/globals/views/utils/query-serializer.cjs +100 -0
  112. package/dist/martyrs/src/modules/globals/views/utils/query-serializer.cjs.map +1 -0
  113. package/dist/martyrs/src/modules/globals/views/utils/query-serializer.js +100 -0
  114. package/dist/martyrs/src/modules/globals/views/utils/query-serializer.js.map +1 -0
  115. package/dist/martyrs/src/modules/icons/components/IconSearchPopup.vue.cjs +224 -0
  116. package/dist/martyrs/src/modules/icons/components/IconSearchPopup.vue.cjs.map +1 -0
  117. package/dist/martyrs/src/modules/icons/components/IconSearchPopup.vue.js +224 -0
  118. package/dist/martyrs/src/modules/icons/components/IconSearchPopup.vue.js.map +1 -0
  119. package/dist/martyrs/src/modules/icons/entities/IconAddress.vue.cjs +40 -0
  120. package/dist/martyrs/src/modules/icons/entities/IconAddress.vue.cjs.map +1 -0
  121. package/dist/martyrs/src/modules/icons/entities/IconAddress.vue.js +40 -0
  122. package/dist/martyrs/src/modules/icons/entities/IconAddress.vue.js.map +1 -0
  123. package/dist/martyrs/src/modules/icons/entities/IconDate.vue.cjs +6 -6
  124. package/dist/martyrs/src/modules/icons/entities/IconDate.vue.js +6 -6
  125. package/dist/martyrs/src/modules/icons/entities/IconEmail.vue.cjs +32 -0
  126. package/dist/martyrs/src/modules/icons/entities/IconEmail.vue.cjs.map +1 -0
  127. package/dist/martyrs/src/modules/icons/entities/IconEmail.vue.js +32 -0
  128. package/dist/martyrs/src/modules/icons/entities/IconEmail.vue.js.map +1 -0
  129. package/dist/martyrs/src/modules/icons/entities/IconMusic.vue.cjs +10 -12
  130. package/dist/martyrs/src/modules/icons/entities/IconMusic.vue.cjs.map +1 -1
  131. package/dist/martyrs/src/modules/icons/entities/IconMusic.vue.js +11 -13
  132. package/dist/martyrs/src/modules/icons/entities/IconMusic.vue.js.map +1 -1
  133. package/dist/martyrs/src/modules/icons/entities/IconPhone.vue.cjs +32 -0
  134. package/dist/martyrs/src/modules/icons/entities/IconPhone.vue.cjs.map +1 -0
  135. package/dist/martyrs/src/modules/icons/entities/IconPhone.vue.js +32 -0
  136. package/dist/martyrs/src/modules/icons/entities/IconPhone.vue.js.map +1 -0
  137. package/dist/martyrs/src/modules/icons/icons.client.cjs +48 -4
  138. package/dist/martyrs/src/modules/icons/icons.client.cjs.map +1 -1
  139. package/dist/martyrs/src/modules/icons/icons.client.js +172 -128
  140. package/dist/martyrs/src/modules/icons/icons.client.js.map +1 -1
  141. package/dist/martyrs/src/modules/icons/navigation/IconCross.vue.cjs +5 -7
  142. package/dist/martyrs/src/modules/icons/navigation/IconCross.vue.cjs.map +1 -1
  143. package/dist/martyrs/src/modules/icons/navigation/IconCross.vue.js +5 -7
  144. package/dist/martyrs/src/modules/icons/navigation/IconCross.vue.js.map +1 -1
  145. package/dist/martyrs/src/modules/icons/navigation/IconPause.vue.cjs +6 -11
  146. package/dist/martyrs/src/modules/icons/navigation/IconPause.vue.cjs.map +1 -1
  147. package/dist/martyrs/src/modules/icons/navigation/IconPause.vue.js +6 -11
  148. package/dist/martyrs/src/modules/icons/navigation/IconPause.vue.js.map +1 -1
  149. package/dist/martyrs/src/modules/icons/navigation/IconRefresh.vue.cjs +6 -11
  150. package/dist/martyrs/src/modules/icons/navigation/IconRefresh.vue.cjs.map +1 -1
  151. package/dist/martyrs/src/modules/icons/navigation/IconRefresh.vue.js +6 -11
  152. package/dist/martyrs/src/modules/icons/navigation/IconRefresh.vue.js.map +1 -1
  153. package/dist/martyrs/src/modules/icons/pages/IconsPage.vue.cjs +62 -6
  154. package/dist/martyrs/src/modules/icons/pages/IconsPage.vue.cjs.map +1 -1
  155. package/dist/martyrs/src/modules/icons/pages/IconsPage.vue.js +189 -133
  156. package/dist/martyrs/src/modules/icons/pages/IconsPage.vue.js.map +1 -1
  157. package/dist/martyrs/src/modules/icons/socials/dribbble.vue.cjs +21 -12
  158. package/dist/martyrs/src/modules/icons/socials/dribbble.vue.cjs.map +1 -1
  159. package/dist/martyrs/src/modules/icons/socials/dribbble.vue.js +21 -12
  160. package/dist/martyrs/src/modules/icons/socials/dribbble.vue.js.map +1 -1
  161. package/dist/martyrs/src/modules/icons/socials/facebook.vue.cjs +21 -12
  162. package/dist/martyrs/src/modules/icons/socials/facebook.vue.cjs.map +1 -1
  163. package/dist/martyrs/src/modules/icons/socials/facebook.vue.js +21 -12
  164. package/dist/martyrs/src/modules/icons/socials/facebook.vue.js.map +1 -1
  165. package/dist/martyrs/src/modules/icons/socials/instagram.vue.cjs +25 -17
  166. package/dist/martyrs/src/modules/icons/socials/instagram.vue.cjs.map +1 -1
  167. package/dist/martyrs/src/modules/icons/socials/instagram.vue.js +25 -17
  168. package/dist/martyrs/src/modules/icons/socials/instagram.vue.js.map +1 -1
  169. package/dist/martyrs/src/modules/icons/socials/line.vue.cjs +23 -14
  170. package/dist/martyrs/src/modules/icons/socials/line.vue.cjs.map +1 -1
  171. package/dist/martyrs/src/modules/icons/socials/line.vue.js +23 -14
  172. package/dist/martyrs/src/modules/icons/socials/line.vue.js.map +1 -1
  173. package/dist/martyrs/src/modules/icons/socials/linkedin.vue.cjs +26 -17
  174. package/dist/martyrs/src/modules/icons/socials/linkedin.vue.cjs.map +1 -1
  175. package/dist/martyrs/src/modules/icons/socials/linkedin.vue.js +26 -17
  176. package/dist/martyrs/src/modules/icons/socials/linkedin.vue.js.map +1 -1
  177. package/dist/martyrs/src/modules/icons/socials/reddit.vue.cjs +21 -12
  178. package/dist/martyrs/src/modules/icons/socials/reddit.vue.cjs.map +1 -1
  179. package/dist/martyrs/src/modules/icons/socials/reddit.vue.js +21 -12
  180. package/dist/martyrs/src/modules/icons/socials/reddit.vue.js.map +1 -1
  181. package/dist/martyrs/src/modules/icons/socials/telegram.vue.cjs +29 -20
  182. package/dist/martyrs/src/modules/icons/socials/telegram.vue.cjs.map +1 -1
  183. package/dist/martyrs/src/modules/icons/socials/telegram.vue.js +29 -20
  184. package/dist/martyrs/src/modules/icons/socials/telegram.vue.js.map +1 -1
  185. package/dist/martyrs/src/modules/icons/socials/twitter.vue.cjs +21 -12
  186. package/dist/martyrs/src/modules/icons/socials/twitter.vue.cjs.map +1 -1
  187. package/dist/martyrs/src/modules/icons/socials/twitter.vue.js +21 -12
  188. package/dist/martyrs/src/modules/icons/socials/twitter.vue.js.map +1 -1
  189. package/dist/martyrs/src/modules/icons/socials/vk.vue.cjs +21 -12
  190. package/dist/martyrs/src/modules/icons/socials/vk.vue.cjs.map +1 -1
  191. package/dist/martyrs/src/modules/icons/socials/vk.vue.js +21 -12
  192. package/dist/martyrs/src/modules/icons/socials/vk.vue.js.map +1 -1
  193. package/dist/martyrs/src/modules/icons/socials/whatsapp.vue.cjs +32 -0
  194. package/dist/martyrs/src/modules/icons/socials/whatsapp.vue.cjs.map +1 -0
  195. package/dist/martyrs/src/modules/icons/socials/whatsapp.vue.js +32 -0
  196. package/dist/martyrs/src/modules/icons/socials/whatsapp.vue.js.map +1 -0
  197. package/dist/martyrs/src/modules/icons/socials/youtube.vue.cjs +21 -12
  198. package/dist/martyrs/src/modules/icons/socials/youtube.vue.cjs.map +1 -1
  199. package/dist/martyrs/src/modules/icons/socials/youtube.vue.js +21 -12
  200. package/dist/martyrs/src/modules/icons/socials/youtube.vue.js.map +1 -1
  201. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.cjs +3 -3
  202. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.cjs.map +1 -1
  203. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +3 -3
  204. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js.map +1 -1
  205. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.cjs +3 -3
  206. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.cjs.map +1 -1
  207. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.js +3 -3
  208. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.js.map +1 -1
  209. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.cjs +3 -3
  210. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.cjs.map +1 -1
  211. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +3 -3
  212. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js.map +1 -1
  213. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.cjs +2 -2
  214. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.cjs.map +1 -1
  215. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.js +2 -2
  216. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.js.map +1 -1
  217. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs +162 -0
  218. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs.map +1 -0
  219. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +162 -0
  220. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js.map +1 -0
  221. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.cjs +437 -0
  222. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.cjs.map +1 -0
  223. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +437 -0
  224. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js.map +1 -0
  225. package/dist/martyrs/src/modules/music/components/{pages → forms}/ArtistForm.vue.cjs +140 -106
  226. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.cjs.map +1 -0
  227. package/dist/martyrs/src/modules/music/components/{pages → forms}/ArtistForm.vue.js +162 -128
  228. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js.map +1 -0
  229. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.cjs +11 -11
  230. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.cjs.map +1 -1
  231. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +23 -23
  232. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js.map +1 -1
  233. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs +2 -2
  234. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs.map +1 -1
  235. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +2 -2
  236. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js.map +1 -1
  237. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.cjs +554 -0
  238. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.cjs.map +1 -0
  239. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +554 -0
  240. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js.map +1 -0
  241. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.cjs +57 -68
  242. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.cjs.map +1 -1
  243. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.js +58 -69
  244. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.js.map +1 -1
  245. package/dist/martyrs/src/modules/music/components/pages/{AlbumDetail.vue.cjs → Album.vue.cjs} +47 -23
  246. package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs.map +1 -0
  247. package/dist/martyrs/src/modules/music/components/pages/{AlbumDetail.vue.js → Album.vue.js} +47 -23
  248. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js.map +1 -0
  249. package/dist/martyrs/src/modules/music/components/pages/AlbumCreate.vue.cjs +14 -0
  250. package/dist/martyrs/src/modules/music/components/pages/AlbumCreate.vue.cjs.map +1 -0
  251. package/dist/martyrs/src/modules/music/components/pages/AlbumCreate.vue.js +14 -0
  252. package/dist/martyrs/src/modules/music/components/pages/AlbumCreate.vue.js.map +1 -0
  253. package/dist/martyrs/src/modules/music/components/pages/AlbumEdit.vue.cjs +23 -0
  254. package/dist/martyrs/src/modules/music/components/pages/AlbumEdit.vue.cjs.map +1 -0
  255. package/dist/martyrs/src/modules/music/components/pages/AlbumEdit.vue.js +23 -0
  256. package/dist/martyrs/src/modules/music/components/pages/AlbumEdit.vue.js.map +1 -0
  257. package/dist/martyrs/src/modules/music/components/pages/{ArtistDetail.vue.cjs → Artist.vue.cjs} +11 -11
  258. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs.map +1 -0
  259. package/dist/martyrs/src/modules/music/components/pages/{ArtistDetail.vue.js → Artist.vue.js} +11 -11
  260. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js.map +1 -0
  261. package/dist/martyrs/src/modules/music/components/pages/ArtistCreate.vue.cjs +14 -0
  262. package/dist/martyrs/src/modules/music/components/pages/ArtistCreate.vue.cjs.map +1 -0
  263. package/dist/martyrs/src/modules/music/components/pages/ArtistCreate.vue.js +14 -0
  264. package/dist/martyrs/src/modules/music/components/pages/ArtistCreate.vue.js.map +1 -0
  265. package/dist/martyrs/src/modules/music/components/pages/ArtistEdit.vue.cjs +23 -0
  266. package/dist/martyrs/src/modules/music/components/pages/ArtistEdit.vue.cjs.map +1 -0
  267. package/dist/martyrs/src/modules/music/components/pages/ArtistEdit.vue.js +23 -0
  268. package/dist/martyrs/src/modules/music/components/pages/ArtistEdit.vue.js.map +1 -0
  269. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.cjs +94 -59
  270. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.cjs.map +1 -1
  271. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.js +95 -60
  272. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.js.map +1 -1
  273. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs +168 -120
  274. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs.map +1 -1
  275. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +170 -122
  276. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js.map +1 -1
  277. package/dist/martyrs/src/modules/music/components/pages/{PlaylistDetail.vue.cjs → Playlist.vue.cjs} +60 -36
  278. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs.map +1 -0
  279. package/dist/martyrs/src/modules/music/components/pages/{PlaylistDetail.vue.js → Playlist.vue.js} +73 -49
  280. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js.map +1 -0
  281. package/dist/martyrs/src/modules/music/components/pages/PlaylistCreate.vue.cjs +14 -0
  282. package/dist/martyrs/src/modules/music/components/pages/PlaylistCreate.vue.cjs.map +1 -0
  283. package/dist/martyrs/src/modules/music/components/pages/PlaylistCreate.vue.js +14 -0
  284. package/dist/martyrs/src/modules/music/components/pages/PlaylistCreate.vue.js.map +1 -0
  285. package/dist/martyrs/src/modules/music/components/pages/PlaylistEdit.vue.cjs +23 -0
  286. package/dist/martyrs/src/modules/music/components/pages/PlaylistEdit.vue.cjs.map +1 -0
  287. package/dist/martyrs/src/modules/music/components/pages/PlaylistEdit.vue.js +23 -0
  288. package/dist/martyrs/src/modules/music/components/pages/PlaylistEdit.vue.js.map +1 -0
  289. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs +52 -28
  290. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs.map +1 -1
  291. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +52 -28
  292. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js.map +1 -1
  293. package/dist/martyrs/src/modules/music/components/pages/{TrackDetail.vue.cjs → Track.vue.cjs} +37 -13
  294. package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs.map +1 -0
  295. package/dist/martyrs/src/modules/music/components/pages/{TrackDetail.vue.js → Track.vue.js} +38 -14
  296. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js.map +1 -0
  297. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.cjs +28 -0
  298. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.cjs.map +1 -0
  299. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +28 -0
  300. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js.map +1 -0
  301. package/dist/martyrs/src/modules/music/components/pages/TrackEdit.vue.cjs +23 -0
  302. package/dist/martyrs/src/modules/music/components/pages/TrackEdit.vue.cjs.map +1 -0
  303. package/dist/martyrs/src/modules/music/components/pages/TrackEdit.vue.js +23 -0
  304. package/dist/martyrs/src/modules/music/components/pages/TrackEdit.vue.js.map +1 -0
  305. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.cjs +3 -3
  306. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.cjs.map +1 -1
  307. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +3 -3
  308. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js.map +1 -1
  309. package/dist/martyrs/src/modules/music/music.client.cjs +31 -31
  310. package/dist/martyrs/src/modules/music/music.client.cjs.map +1 -1
  311. package/dist/martyrs/src/modules/music/music.client.js +31 -31
  312. package/dist/martyrs/src/modules/music/music.client.js.map +1 -1
  313. package/dist/martyrs/src/modules/music/router/albums.cjs +34 -0
  314. package/dist/martyrs/src/modules/music/router/albums.cjs.map +1 -0
  315. package/dist/martyrs/src/modules/music/router/albums.js +34 -0
  316. package/dist/martyrs/src/modules/music/router/albums.js.map +1 -0
  317. package/dist/martyrs/src/modules/music/router/artists.cjs +34 -0
  318. package/dist/martyrs/src/modules/music/router/artists.cjs.map +1 -0
  319. package/dist/martyrs/src/modules/music/router/artists.js +34 -0
  320. package/dist/martyrs/src/modules/music/router/artists.js.map +1 -0
  321. package/dist/martyrs/src/modules/music/router/music.cjs +12 -64
  322. package/dist/martyrs/src/modules/music/router/music.cjs.map +1 -1
  323. package/dist/martyrs/src/modules/music/router/music.js +12 -64
  324. package/dist/martyrs/src/modules/music/router/music.js.map +1 -1
  325. package/dist/martyrs/src/modules/music/router/playlists.cjs +34 -0
  326. package/dist/martyrs/src/modules/music/router/playlists.cjs.map +1 -0
  327. package/dist/martyrs/src/modules/music/router/playlists.js +34 -0
  328. package/dist/martyrs/src/modules/music/router/playlists.js.map +1 -0
  329. package/dist/martyrs/src/modules/music/router/tracks.cjs +34 -0
  330. package/dist/martyrs/src/modules/music/router/tracks.cjs.map +1 -0
  331. package/dist/martyrs/src/modules/music/router/tracks.js +34 -0
  332. package/dist/martyrs/src/modules/music/router/tracks.js.map +1 -0
  333. package/dist/martyrs/src/modules/music/store/artists.cjs +12 -6
  334. package/dist/martyrs/src/modules/music/store/artists.cjs.map +1 -1
  335. package/dist/martyrs/src/modules/music/store/artists.js +12 -6
  336. package/dist/martyrs/src/modules/music/store/artists.js.map +1 -1
  337. package/dist/martyrs/src/modules/music/store/genres.cjs +123 -0
  338. package/dist/martyrs/src/modules/music/store/genres.cjs.map +1 -0
  339. package/dist/martyrs/src/modules/music/store/genres.js +123 -0
  340. package/dist/martyrs/src/modules/music/store/genres.js.map +1 -0
  341. package/dist/martyrs/src/modules/music/store/playlists.cjs +14 -6
  342. package/dist/martyrs/src/modules/music/store/playlists.cjs.map +1 -1
  343. package/dist/martyrs/src/modules/music/store/playlists.js +14 -6
  344. package/dist/martyrs/src/modules/music/store/playlists.js.map +1 -1
  345. package/dist/martyrs/src/modules/music/store/tracks.cjs +6 -2
  346. package/dist/martyrs/src/modules/music/store/tracks.cjs.map +1 -1
  347. package/dist/martyrs/src/modules/music/store/tracks.js +6 -2
  348. package/dist/martyrs/src/modules/music/store/tracks.js.map +1 -1
  349. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -0
  350. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs.map +1 -1
  351. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -0
  352. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js.map +1 -1
  353. package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.cjs +1 -0
  354. package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.cjs.map +1 -1
  355. package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.js +1 -0
  356. package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.js.map +1 -1
  357. package/dist/martyrs/src/modules/orders/components/sections/FormCustomerDetails.vue.cjs +1 -1
  358. package/dist/martyrs/src/modules/orders/components/sections/FormCustomerDetails.vue.js +5 -5
  359. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.cjs +1 -1
  360. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
  361. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.cjs +1 -1
  362. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +1 -1
  363. package/dist/martyrs/src/modules/organizations/components/blocks/Socials.vue.js +16 -16
  364. package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +1 -1
  365. package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +15 -15
  366. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +1 -1
  367. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +16 -16
  368. package/dist/martyrs/src/modules/organizations/components/sections/DetailsTabSection.vue.cjs +1 -1
  369. package/dist/martyrs/src/modules/organizations/components/sections/DetailsTabSection.vue.js +1 -1
  370. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.cjs +1 -1
  371. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +2 -2
  372. package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.cjs +1 -1
  373. package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +8 -8
  374. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -0
  375. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs.map +1 -1
  376. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -0
  377. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js.map +1 -1
  378. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.cjs +1 -0
  379. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.cjs.map +1 -1
  380. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +1 -0
  381. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js.map +1 -1
  382. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.cjs +1 -0
  383. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.cjs.map +1 -1
  384. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +1 -0
  385. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js.map +1 -1
  386. package/dist/martyrs/src/modules/products/components/blocks/ProductDiscounts.vue.cjs +1 -1
  387. package/dist/martyrs/src/modules/products/components/blocks/ProductDiscounts.vue.js +1 -1
  388. package/dist/martyrs/src/modules/products/components/forms/ReorderSettingsForm.vue.cjs +1 -1
  389. package/dist/martyrs/src/modules/products/components/forms/ReorderSettingsForm.vue.js +8 -8
  390. package/dist/martyrs/src/modules/products/components/forms/StockAuditForm.vue.cjs +1 -1
  391. package/dist/martyrs/src/modules/products/components/forms/StockAuditForm.vue.js +12 -12
  392. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +1 -1
  393. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +11 -11
  394. package/dist/martyrs/src/modules/products/components/pages/LeftoverEdit.vue.cjs +1 -1
  395. package/dist/martyrs/src/modules/products/components/pages/LeftoverEdit.vue.js +10 -10
  396. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +1 -1
  397. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +17 -17
  398. package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.cjs +1 -1
  399. package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +6 -6
  400. package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.cjs +1 -1
  401. package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +12 -12
  402. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.cjs +1 -1
  403. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +16 -16
  404. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.cjs +1 -1
  405. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +4 -4
  406. package/dist/martyrs/src/modules/spots/components/blocks/CardSpot.vue.cjs +1 -1
  407. package/dist/martyrs/src/modules/spots/components/blocks/CardSpot.vue.js +1 -1
  408. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.cjs +1 -0
  409. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.cjs.map +1 -1
  410. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +1 -0
  411. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js.map +1 -1
  412. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.cjs +1 -0
  413. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.cjs.map +1 -1
  414. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -0
  415. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js.map +1 -1
  416. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +1 -1
  417. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +12 -12
  418. package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.cjs +1 -1
  419. package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +7 -7
  420. package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.cjs +1 -1
  421. package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.js +2 -2
  422. package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.cjs +1 -1
  423. package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +2 -2
  424. package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.cjs +1 -1
  425. package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js +1 -1
  426. package/dist/martyrs.cjs.js +1 -1
  427. package/dist/martyrs.css +1 -1
  428. package/dist/martyrs.es.js +1 -1
  429. package/dist/music.server.cjs +1165 -551
  430. package/dist/music.server.js +1161 -547
  431. package/dist/orders.server.cjs +89 -4
  432. package/dist/orders.server.js +88 -3
  433. package/dist/organizations.server.cjs +1 -1
  434. package/dist/organizations.server.js +1 -1
  435. package/dist/products.server.cjs +3 -1093
  436. package/dist/products.server.js +2 -1092
  437. package/dist/rents.server.cjs +1 -1
  438. package/dist/rents.server.js +1 -1
  439. package/dist/style.css +121 -77
  440. package/dist/wallet.server.cjs +1 -1
  441. package/dist/wallet.server.js +1 -1
  442. package/package.json +1 -1
  443. package/src/components/Field/Field.vue +13 -8
  444. package/src/components/FieldBig/FieldBig.vue +3 -5
  445. package/src/components/FieldPhone/FieldPhone.vue +1 -1
  446. package/src/components/Media/Media.vue +1 -1
  447. package/src/components/Select/Select.vue +1 -1
  448. package/src/components/Status/Snack.vue +83 -0
  449. package/src/modules/auth/controllers/middlewares/authJwt.js +59 -6
  450. package/src/modules/globals/views/classes/globals.store.js +31 -66
  451. package/src/modules/globals/views/components/partials/FooterAlt.vue +363 -0
  452. package/src/modules/globals/views/store/globals.js +42 -0
  453. package/src/modules/globals/views/utils/query-serializer.js +182 -0
  454. package/src/modules/icons/components/IconSearchPopup.vue +254 -0
  455. package/src/modules/icons/entities/IconAddress.vue +17 -0
  456. package/src/modules/icons/entities/IconDate.vue +3 -3
  457. package/src/modules/icons/entities/IconEmail.vue +14 -0
  458. package/src/modules/icons/entities/IconMusic.vue +3 -3
  459. package/src/modules/icons/entities/IconPhone.vue +14 -0
  460. package/src/modules/icons/icons.client.js +85 -31
  461. package/src/modules/icons/icons.server.js +292 -0
  462. package/src/modules/icons/navigation/IconCross.vue +4 -16
  463. package/src/modules/icons/navigation/IconPause.vue +9 -24
  464. package/src/modules/icons/navigation/IconRefresh.vue +9 -24
  465. package/src/modules/icons/pages/IconsPage.vue +78 -2
  466. package/src/modules/icons/routes/icons.routes.js +81 -0
  467. package/src/modules/icons/socials/dribbble.vue +11 -2
  468. package/src/modules/icons/socials/facebook.vue +11 -2
  469. package/src/modules/icons/socials/instagram.vue +11 -4
  470. package/src/modules/icons/socials/line.vue +11 -2
  471. package/src/modules/icons/socials/linkedin.vue +11 -2
  472. package/src/modules/icons/socials/reddit.vue +10 -1
  473. package/src/modules/icons/socials/telegram.vue +11 -2
  474. package/src/modules/icons/socials/twitter.vue +11 -2
  475. package/src/modules/icons/socials/vk.vue +11 -2
  476. package/src/modules/icons/socials/whatsapp.vue +12 -0
  477. package/src/modules/icons/socials/youtube.vue +11 -2
  478. package/src/modules/music/.claude/settings.local.json +8 -0
  479. package/src/modules/music/CLAUDE.md +312 -0
  480. package/src/modules/music/components/SidebarMusic.vue +8 -8
  481. package/src/modules/music/components/cards/AlbumCard.vue +2 -2
  482. package/src/modules/music/components/cards/ArtistCard.vue +2 -2
  483. package/src/modules/music/components/cards/PlaylistCard.vue +2 -2
  484. package/src/modules/music/components/cards/TrackCard.vue +1 -1
  485. package/src/modules/music/components/cards/TrackListCard.vue +135 -0
  486. package/src/modules/music/components/forms/AlbumForm.vue +463 -0
  487. package/src/modules/music/components/{pages → forms}/ArtistForm.vue +127 -96
  488. package/src/modules/music/components/forms/PlaylistForm.vue +10 -10
  489. package/src/modules/music/components/forms/SearchForm.vue +1 -1
  490. package/src/modules/music/components/forms/TrackForm.vue +577 -0
  491. package/src/modules/music/components/layouts/MusicLayout.vue +35 -41
  492. package/src/modules/music/components/pages/{AlbumDetail.vue → Album.vue} +42 -20
  493. package/src/modules/music/components/pages/AlbumCreate.vue +7 -0
  494. package/src/modules/music/components/pages/AlbumEdit.vue +14 -0
  495. package/src/modules/music/components/pages/{ArtistDetail.vue → Artist.vue} +9 -9
  496. package/src/modules/music/components/pages/ArtistCreate.vue +7 -0
  497. package/src/modules/music/components/pages/ArtistEdit.vue +14 -0
  498. package/src/modules/music/components/pages/MusicHome.vue +86 -67
  499. package/src/modules/music/components/pages/MusicLibrary.vue +136 -105
  500. package/src/modules/music/components/pages/{PlaylistDetail.vue → Playlist.vue} +56 -34
  501. package/src/modules/music/components/pages/PlaylistCreate.vue +7 -0
  502. package/src/modules/music/components/pages/PlaylistEdit.vue +14 -0
  503. package/src/modules/music/components/pages/SearchResults.vue +49 -27
  504. package/src/modules/music/components/pages/{TrackDetail.vue → Track.vue} +36 -14
  505. package/src/modules/music/components/pages/TrackCreate.vue +23 -0
  506. package/src/modules/music/components/pages/TrackEdit.vue +14 -0
  507. package/src/modules/music/components/player/MusicPlayer.vue +2 -2
  508. package/src/modules/music/middlewares/albums.verifier.js +234 -0
  509. package/src/modules/music/middlewares/artists.verifier.js +213 -0
  510. package/src/modules/music/middlewares/genres.verifier.js +148 -0
  511. package/src/modules/music/middlewares/playlists.verifier.js +219 -0
  512. package/src/modules/music/middlewares/tracks.verifier.js +263 -0
  513. package/src/modules/music/music.client.js +31 -33
  514. package/src/modules/music/music.server.js +33 -26
  515. package/src/modules/music/router/albums.js +31 -0
  516. package/src/modules/music/router/artists.js +31 -0
  517. package/src/modules/music/router/music.js +14 -65
  518. package/src/modules/music/router/playlists.js +31 -0
  519. package/src/modules/music/router/tracks.js +31 -0
  520. package/src/modules/music/routes/albums.routes.js +126 -0
  521. package/src/modules/music/routes/artists.routes.js +171 -0
  522. package/src/modules/music/routes/genres.routes.js +118 -0
  523. package/src/modules/music/routes/playlists.routes.js +239 -0
  524. package/src/modules/music/routes/tracks.routes.js +149 -0
  525. package/src/modules/music/store/artists.js +17 -7
  526. package/src/modules/music/store/genres.js +150 -0
  527. package/src/modules/music/store/playlists.js +19 -6
  528. package/src/modules/music/store/tracks.js +9 -2
  529. package/dist/Media-DhpD64nT.cjs +0 -1
  530. package/dist/globals.crud-BQG1Lm0A.js +0 -90
  531. package/dist/globals.crud-Dv7UXbRM.cjs +0 -89
  532. package/dist/main-DKJqboZy.cjs +0 -11
  533. package/dist/martyrs/src/components/Chips/Chips.vue2.cjs.map +0 -1
  534. package/dist/martyrs/src/components/Chips/Chips.vue2.js.map +0 -1
  535. package/dist/martyrs/src/components/Field/Field.vue.cjs.map +0 -1
  536. package/dist/martyrs/src/components/Field/Field.vue.js.map +0 -1
  537. package/dist/martyrs/src/modules/music/components/forms/UploadForm.vue.cjs +0 -328
  538. package/dist/martyrs/src/modules/music/components/forms/UploadForm.vue.cjs.map +0 -1
  539. package/dist/martyrs/src/modules/music/components/forms/UploadForm.vue.js +0 -328
  540. package/dist/martyrs/src/modules/music/components/forms/UploadForm.vue.js.map +0 -1
  541. package/dist/martyrs/src/modules/music/components/lists/AlbumList.vue.cjs +0 -44
  542. package/dist/martyrs/src/modules/music/components/lists/AlbumList.vue.cjs.map +0 -1
  543. package/dist/martyrs/src/modules/music/components/lists/AlbumList.vue.js +0 -44
  544. package/dist/martyrs/src/modules/music/components/lists/AlbumList.vue.js.map +0 -1
  545. package/dist/martyrs/src/modules/music/components/lists/ArtistList.vue.cjs +0 -305
  546. package/dist/martyrs/src/modules/music/components/lists/ArtistList.vue.cjs.map +0 -1
  547. package/dist/martyrs/src/modules/music/components/lists/ArtistList.vue.js +0 -305
  548. package/dist/martyrs/src/modules/music/components/lists/ArtistList.vue.js.map +0 -1
  549. package/dist/martyrs/src/modules/music/components/lists/PlaylistList.vue.cjs +0 -44
  550. package/dist/martyrs/src/modules/music/components/lists/PlaylistList.vue.cjs.map +0 -1
  551. package/dist/martyrs/src/modules/music/components/lists/PlaylistList.vue.js +0 -44
  552. package/dist/martyrs/src/modules/music/components/lists/PlaylistList.vue.js.map +0 -1
  553. package/dist/martyrs/src/modules/music/components/lists/TrackList.vue.cjs +0 -199
  554. package/dist/martyrs/src/modules/music/components/lists/TrackList.vue.cjs.map +0 -1
  555. package/dist/martyrs/src/modules/music/components/lists/TrackList.vue.js +0 -199
  556. package/dist/martyrs/src/modules/music/components/lists/TrackList.vue.js.map +0 -1
  557. package/dist/martyrs/src/modules/music/components/pages/AlbumDetail.vue.cjs.map +0 -1
  558. package/dist/martyrs/src/modules/music/components/pages/AlbumDetail.vue.js.map +0 -1
  559. package/dist/martyrs/src/modules/music/components/pages/ArtistDetail.vue.cjs.map +0 -1
  560. package/dist/martyrs/src/modules/music/components/pages/ArtistDetail.vue.js.map +0 -1
  561. package/dist/martyrs/src/modules/music/components/pages/ArtistForm.vue.cjs.map +0 -1
  562. package/dist/martyrs/src/modules/music/components/pages/ArtistForm.vue.js.map +0 -1
  563. package/dist/martyrs/src/modules/music/components/pages/ArtistManager.vue.cjs +0 -303
  564. package/dist/martyrs/src/modules/music/components/pages/ArtistManager.vue.cjs.map +0 -1
  565. package/dist/martyrs/src/modules/music/components/pages/ArtistManager.vue.js +0 -303
  566. package/dist/martyrs/src/modules/music/components/pages/ArtistManager.vue.js.map +0 -1
  567. package/dist/martyrs/src/modules/music/components/pages/MusicUpload.vue.cjs +0 -50
  568. package/dist/martyrs/src/modules/music/components/pages/MusicUpload.vue.cjs.map +0 -1
  569. package/dist/martyrs/src/modules/music/components/pages/MusicUpload.vue.js +0 -50
  570. package/dist/martyrs/src/modules/music/components/pages/MusicUpload.vue.js.map +0 -1
  571. package/dist/martyrs/src/modules/music/components/pages/PlaylistDetail.vue.cjs.map +0 -1
  572. package/dist/martyrs/src/modules/music/components/pages/PlaylistDetail.vue.js.map +0 -1
  573. package/dist/martyrs/src/modules/music/components/pages/TrackDetail.vue.cjs.map +0 -1
  574. package/dist/martyrs/src/modules/music/components/pages/TrackDetail.vue.js.map +0 -1
  575. package/src/modules/music/components/forms/UploadForm.vue +0 -313
  576. package/src/modules/music/components/lists/AlbumList.vue +0 -25
  577. package/src/modules/music/components/lists/ArtistList.vue +0 -280
  578. package/src/modules/music/components/lists/PlaylistList.vue +0 -25
  579. package/src/modules/music/components/lists/TrackList.vue +0 -175
  580. package/src/modules/music/components/pages/ArtistManager.vue +0 -277
  581. package/src/modules/music/components/pages/MusicUpload.vue +0 -44
  582. package/src/modules/music/controllers/album.controller.js +0 -82
  583. package/src/modules/music/controllers/artist.controller.js +0 -99
  584. package/src/modules/music/controllers/genre.controller.js +0 -63
  585. package/src/modules/music/controllers/music.controller.js +0 -145
  586. package/src/modules/music/controllers/playlist.controller.js +0 -146
  587. package/src/modules/music/routes/album.routes.js +0 -28
  588. package/src/modules/music/routes/artist.routes.js +0 -30
  589. package/src/modules/music/routes/genre.routes.js +0 -28
  590. package/src/modules/music/routes/music.routes.js +0 -106
  591. package/src/modules/music/routes/playlist.routes.js +0 -47
@@ -3,7 +3,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
3
3
  const globals_abac = require("./globals.abac-Cm9e8Jdk.cjs");
4
4
  const globals_logger = require("./globals.logger-CZMgIMlM.cjs");
5
5
  const globals_websocket = require("./globals.websocket-k6_B1T7k.cjs");
6
- const globals_crud = require("./globals.crud-Dv7UXbRM.cjs");
6
+ const crud = require("./crud-BDIArc5A.cjs");
7
+ const abac = require("./abac-6LjoG9u-.cjs");
8
+ const globals_verifier = require("./globals.verifier-D68mHEBl.cjs");
7
9
  const fs$1 = require("fs");
8
10
  const path$1 = require("path");
9
11
  const common_schema = require("./common.schema-BzFEVNn3.cjs");
@@ -11,385 +13,1035 @@ const engagement_schema = require("./engagement.schema-JADHu8pj.cjs");
11
13
  const metadata_schema = require("./metadata.schema-RlxNv46L.cjs");
12
14
  const ownership_schema = require("./ownership.schema-DCosqOc1.cjs");
13
15
  const socials_schema = require("./socials.schema-CtpSF9dE.cjs");
14
- const index = require("./index-YNOkL1mu.cjs");
15
- const { getInstance: getInstance$1 } = globals_abac.globalsabac;
16
- const MusicController = function(app, db) {
17
- const logger = new globals_logger.Logger(db);
18
- const cache = new globals_logger.Cache();
19
- const abac = getInstance$1(db);
20
- class MusicController2 extends globals_crud.CRUD {
21
- constructor(basePath, app2, db2, model, options) {
22
- super(basePath, app2, db2, model, options);
23
- this.logger = logger;
24
- this.cache = cache;
25
- this.abac = abac;
16
+ function tracksVerifierFactory(db) {
17
+ const createVerifier = new globals_verifier.Verifier({
18
+ title: {
19
+ rule: "required",
20
+ validator: globals_verifier.Validator.schema().string().required("Track title is required").min(1, "Title cannot be empty").max(200, "Title must not exceed 200 characters")
21
+ },
22
+ artist: {
23
+ rule: "required",
24
+ validator: globals_verifier.Validator.schema().string().required("Artist is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
25
+ },
26
+ album: {
27
+ rule: "optional",
28
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid album ID format")
29
+ },
30
+ fileUrl: {
31
+ rule: "required",
32
+ validator: globals_verifier.Validator.schema().string().required("File URL is required").pattern(/^https?:\/\/.+/, "Invalid file URL format")
33
+ },
34
+ coverUrl: {
35
+ rule: "optional",
36
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover URL format")
37
+ },
38
+ duration: {
39
+ rule: "optional",
40
+ default: 0,
41
+ validator: globals_verifier.Validator.schema().number().min(0, "Duration cannot be negative").max(3600, "Duration cannot exceed 1 hour")
42
+ },
43
+ genre: {
44
+ rule: "optional",
45
+ validator: globals_verifier.Validator.schema().array().items(
46
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
47
+ )
48
+ },
49
+ releaseDate: {
50
+ rule: "optional",
51
+ validator: globals_verifier.Validator.schema().date()
52
+ },
53
+ isExplicit: {
54
+ rule: "optional",
55
+ default: false,
56
+ validator: globals_verifier.Validator.schema().boolean()
57
+ },
58
+ lyrics: {
59
+ rule: "optional",
60
+ validator: globals_verifier.Validator.schema().string().max(1e4, "Lyrics too long")
61
+ },
62
+ isPublic: {
63
+ rule: "optional",
64
+ default: true,
65
+ validator: globals_verifier.Validator.schema().boolean()
66
+ },
67
+ owner: {
68
+ rule: "required",
69
+ validator: globals_verifier.Validator.schema().object({
70
+ type: globals_verifier.Validator.schema().string().oneOf(["user", "organization"]),
71
+ target: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/)
72
+ })
73
+ }
74
+ });
75
+ const updateVerifier = new globals_verifier.Verifier({
76
+ _id: {
77
+ rule: "required",
78
+ validator: globals_verifier.Validator.schema().string().required("Track ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid track ID format")
79
+ },
80
+ title: {
81
+ rule: "optional",
82
+ validator: globals_verifier.Validator.schema().string().min(1, "Title cannot be empty").max(200, "Title must not exceed 200 characters")
83
+ },
84
+ artist: {
85
+ rule: "optional",
86
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
87
+ },
88
+ album: {
89
+ rule: "optional",
90
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid album ID format")
91
+ },
92
+ fileUrl: {
93
+ rule: "optional",
94
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid file URL format")
95
+ },
96
+ coverUrl: {
97
+ rule: "optional",
98
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover URL format")
99
+ },
100
+ duration: {
101
+ rule: "optional",
102
+ validator: globals_verifier.Validator.schema().number().min(0, "Duration cannot be negative").max(3600, "Duration cannot exceed 1 hour")
103
+ },
104
+ genre: {
105
+ rule: "optional",
106
+ validator: globals_verifier.Validator.schema().array().items(
107
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
108
+ )
109
+ },
110
+ releaseDate: {
111
+ rule: "optional",
112
+ validator: globals_verifier.Validator.schema().date()
113
+ },
114
+ isExplicit: {
115
+ rule: "optional",
116
+ validator: globals_verifier.Validator.schema().boolean()
117
+ },
118
+ lyrics: {
119
+ rule: "optional",
120
+ validator: globals_verifier.Validator.schema().string().max(1e4, "Lyrics too long")
121
+ },
122
+ isPublic: {
123
+ rule: "optional",
124
+ validator: globals_verifier.Validator.schema().boolean()
125
+ },
126
+ status: {
127
+ rule: "optional",
128
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"], "Invalid status")
26
129
  }
27
- // Override the create method to handle ownership
28
- async create(req, res) {
130
+ });
131
+ const readVerifier = new globals_verifier.Verifier({
132
+ _id: {
133
+ rule: "optional",
134
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid track ID format")
135
+ },
136
+ artist: {
137
+ rule: "optional",
138
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
139
+ },
140
+ album: {
141
+ rule: "optional",
142
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid album ID format")
143
+ },
144
+ genre: {
145
+ rule: "optional",
146
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
147
+ },
148
+ isPublic: {
149
+ rule: "optional",
150
+ validator: globals_verifier.Validator.schema().boolean()
151
+ },
152
+ status: {
153
+ rule: "optional",
154
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"])
155
+ },
156
+ skip: {
157
+ rule: "optional",
158
+ default: 0,
159
+ validator: globals_verifier.Validator.schema().integer().min(0)
160
+ },
161
+ limit: {
162
+ rule: "optional",
163
+ default: 20,
164
+ validator: globals_verifier.Validator.schema().integer().min(1).max(100)
165
+ },
166
+ sortParam: {
167
+ rule: "optional",
168
+ validator: globals_verifier.Validator.schema().string().oneOf(["title", "playCount", "releaseDate", "createdAt", "updatedAt"])
169
+ },
170
+ sortOrder: {
171
+ rule: "optional",
172
+ default: "desc",
173
+ validator: globals_verifier.Validator.schema().string().oneOf(["asc", "desc"])
174
+ }
175
+ });
176
+ const deleteVerifier = new globals_verifier.Verifier({
177
+ _id: {
178
+ rule: "required",
179
+ validator: globals_verifier.Validator.schema().string().required("Track ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid track ID format")
180
+ }
181
+ });
182
+ return {
183
+ createVerifier,
184
+ readVerifier,
185
+ updateVerifier,
186
+ deleteVerifier
187
+ };
188
+ }
189
+ const { getInstance: getInstance$4 } = abac.ABAC;
190
+ function setupTracksRoutes(app, db) {
191
+ const abac2 = getInstance$4(db);
192
+ const verifier = tracksVerifierFactory();
193
+ const tracksCRUD = new crud.CRUD({
194
+ app,
195
+ db,
196
+ model: db.track,
197
+ modelName: "track",
198
+ basePath: "/api/tracks",
199
+ auth: true,
200
+ verifiers: {
201
+ create: verifier.createVerifier,
202
+ read: verifier.readVerifier,
203
+ update: verifier.updateVerifier,
204
+ delete: verifier.deleteVerifier
205
+ },
206
+ abac: abac2,
207
+ cache: {
208
+ enabled: true,
209
+ ttl: 300,
210
+ tags: ["tracks", "music"]
211
+ },
212
+ events: {
213
+ enabled: true,
214
+ logReads: false
215
+ }
216
+ });
217
+ tracksCRUD.addAction("get-by-url", {
218
+ method: "get",
219
+ path: "/url/:url",
220
+ auth: false,
221
+ handler: async (req, res) => {
29
222
  try {
30
- console.log(`[MusicController] Create request received:`, {
31
- userId: req.userId,
32
- body: req.body
33
- });
34
- if (!req.userId) {
35
- console.error("[MusicController] No userId found in request, auth middleware may have failed");
36
- return res.status(401).json({
37
- errorCode: "AUTHENTICATION_REQUIRED",
38
- message: "You must be authenticated to perform this action"
39
- });
40
- }
41
- if (!req.body.creator) {
42
- req.body.creator = {
43
- type: "user",
44
- // Note lowercase - must match your schema expectations
45
- target: req.userId
46
- };
47
- }
48
- if (!req.body.owner) {
49
- req.body.owner = {
50
- type: "user",
51
- // Note lowercase - must match your schema expectations
52
- target: req.userId
53
- };
223
+ const track = await db.track.findOne({ url: req.params.url });
224
+ if (!track) {
225
+ return res.status(404).json({ error: "Track not found" });
54
226
  }
55
- console.log(`[MusicController] Checking access with ABAC`);
56
- const accessResult = await this.abac.checkAccess({
227
+ const accessResult = await abac2.checkAccess({
57
228
  user: req.userId,
58
- resource: this.model.collection.collectionName,
59
- action: "create",
60
- data: req.body
229
+ resource: "tracks",
230
+ action: "read",
231
+ currentResource: track
61
232
  });
62
- console.log(`[MusicController] Access check result:`, accessResult);
63
- if (!accessResult.allowed) {
64
- console.error(`[MusicController] Access denied:`, accessResult.reason);
233
+ if (!accessResult.allowed && !track.isPublic) {
65
234
  return res.status(403).json({
66
235
  errorCode: accessResult.reason,
67
236
  message: "Access Denied"
68
237
  });
69
238
  }
70
- console.log(`[MusicController] Creating record with data:`, req.body);
71
- const createdData = await this.model.create(req.body);
72
- await this.cache.flush();
73
- console.log(`[MusicController] Record created successfully:`, createdData._id);
74
- res.status(201).json(createdData);
239
+ res.json(track);
75
240
  } catch (error) {
76
- console.error(`[MusicController] Error creating record:`, error);
77
- this.logger.error(`Error creating ${this.model.collection.collectionName}: ${error.message}`);
241
+ console.error(error);
78
242
  res.status(500).json({ error: error.message });
79
243
  }
80
244
  }
81
- // Override the update method to check ownership
82
- async update(req, res) {
245
+ });
246
+ tracksCRUD.addAction("recent", {
247
+ method: "get",
248
+ path: "/recent",
249
+ auth: false,
250
+ handler: async (req, res) => {
83
251
  try {
84
- const resourceId = req.body._id;
85
- const resource = await this.model.findById(resourceId);
86
- if (!resource) {
87
- return res.status(404).json({ error: "Resource not found" });
88
- }
89
- const accessResult = await this.abac.checkAccess({
90
- user: req.userId,
91
- resource: this.model.collection.collectionName,
92
- action: "update",
93
- data: req.body,
94
- currentResource: resource
95
- });
96
- if (!accessResult.allowed) {
97
- return res.status(403).json({
98
- errorCode: accessResult.reason,
99
- message: "Access Denied"
100
- });
101
- }
102
- const updatedData = await this.model.findOneAndUpdate({ _id: resourceId }, req.body, {
103
- new: true,
104
- runValidators: true
105
- });
106
- await this.cache.flush();
107
- res.json(updatedData);
252
+ const limit = parseInt(req.query.limit) || 10;
253
+ const recentTracks = await db.track.find({
254
+ status: "published",
255
+ isPublic: true
256
+ }).sort({ createdAt: -1 }).limit(limit);
257
+ res.json(recentTracks);
108
258
  } catch (error) {
109
- this.logger.error(`Error updating ${this.model.collection.collectionName}: ${error.message}`);
259
+ console.error(error);
110
260
  res.status(500).json({ error: error.message });
111
261
  }
112
262
  }
113
- // Override the delete method to check ownership
114
- async delete(req, res) {
263
+ });
264
+ tracksCRUD.addAction("popular", {
265
+ method: "get",
266
+ path: "/popular",
267
+ auth: false,
268
+ handler: async (req, res) => {
115
269
  try {
116
- const resourceId = req.body._id;
117
- const resource = await this.model.findById(resourceId);
118
- if (!resource) {
119
- return res.status(404).json({ error: "Resource not found" });
120
- }
121
- const accessResult = await this.abac.checkAccess({
122
- user: req.userId,
123
- resource: this.model.collection.collectionName,
124
- action: "delete",
125
- data: req.body,
126
- currentResource: resource
127
- });
128
- if (!accessResult.allowed) {
129
- return res.status(403).json({
130
- errorCode: accessResult.reason,
131
- message: "Access Denied"
132
- });
133
- }
134
- await this.model.findOneAndDelete({ _id: resourceId });
135
- await this.cache.flush();
136
- res.status(204).send();
270
+ const limit = parseInt(req.query.limit) || 10;
271
+ const popularTracks = await db.track.find({
272
+ status: "published",
273
+ isPublic: true
274
+ }).sort({ playCount: -1 }).limit(limit);
275
+ res.json(popularTracks);
137
276
  } catch (error) {
138
- this.logger.error(`Error deleting ${this.model.collection.collectionName}: ${error.message}`);
277
+ console.error(error);
139
278
  res.status(500).json({ error: error.message });
140
279
  }
141
280
  }
142
- }
143
- return {
144
- MusicController: MusicController2
145
- };
146
- };
147
- const AlbumController = function(app, db) {
148
- const { MusicController: MusicController$1 } = MusicController(app, db);
149
- class AlbumController2 extends MusicController$1 {
150
- constructor(app2) {
151
- super("/api/albums", app2, db, db.album);
152
- }
153
- // Get tracks for a specific album
154
- async getAlbumTracks(req, res) {
281
+ });
282
+ tracksCRUD.addAction("by-genre", {
283
+ method: "get",
284
+ path: "/genre/:genreId",
285
+ auth: false,
286
+ handler: async (req, res) => {
155
287
  try {
156
- const albumId = req.params.albumId;
157
- const album = await db.album.findById(albumId);
158
- if (!album) {
159
- return res.status(404).json({ error: "Album not found" });
160
- }
161
- const accessResult = await this.abac.checkAccess({
162
- user: req.userId,
163
- resource: "albums",
164
- action: "read",
165
- currentResource: album
166
- });
167
- if (!accessResult.allowed && !album.isPublic) {
168
- return res.status(403).json({
169
- errorCode: accessResult.reason,
170
- message: "Access Denied"
171
- });
172
- }
173
- const tracks = await db.track.find({ album: albumId, status: "published" }).sort({ releaseDate: -1 });
288
+ const tracks = await db.track.find({
289
+ genre: req.params.genreId,
290
+ status: "published",
291
+ isPublic: true
292
+ }).sort({ releaseDate: -1 });
174
293
  res.json(tracks);
175
294
  } catch (error) {
176
- this.logger.error(`Error getting album tracks: ${error.message}`);
295
+ console.error(error);
177
296
  res.status(500).json({ error: error.message });
178
297
  }
179
298
  }
180
- // Get featured albums
181
- async getFeaturedAlbums(req, res) {
182
- try {
183
- const cacheKey = "featured-albums";
184
- let featuredAlbums = await this.cache.get(cacheKey);
185
- if (!featuredAlbums) {
186
- featuredAlbums = await db.album.aggregate([
187
- { $match: { status: "featured", isPublic: true } },
188
- {
189
- $lookup: {
190
- from: "tracks",
191
- localField: "_id",
192
- foreignField: "album",
193
- as: "tracks"
194
- }
195
- },
196
- {
197
- $addFields: {
198
- trackCount: { $size: "$tracks" }
199
- }
200
- },
201
- { $project: { tracks: 0 } },
202
- { $sort: { releaseDate: -1 } },
203
- { $limit: 10 }
204
- ]);
205
- await this.cache.set(cacheKey, featuredAlbums, 3600);
206
- }
207
- res.json(featuredAlbums);
208
- } catch (error) {
209
- this.logger.error(`Error getting featured albums: ${error.message}`);
210
- res.status(500).json({ error: error.message });
211
- }
299
+ });
300
+ return tracksCRUD;
301
+ }
302
+ function artistsVerifierFactory(db) {
303
+ const createVerifier = new globals_verifier.Verifier({
304
+ name: {
305
+ rule: "required",
306
+ validator: globals_verifier.Validator.schema().string().required("Artist name is required").min(1, "Name cannot be empty").max(100, "Name must not exceed 100 characters")
307
+ },
308
+ bio: {
309
+ rule: "optional",
310
+ validator: globals_verifier.Validator.schema().string().max(2e3, "Bio must not exceed 2000 characters")
311
+ },
312
+ photoUrl: {
313
+ rule: "optional",
314
+ validator: globals_verifier.Validator.schema().string().pattern(/^\/(?!\/)/, 'Only relative URLs starting with "/" are allowed')
315
+ },
316
+ coverUrl: {
317
+ rule: "optional",
318
+ validator: globals_verifier.Validator.schema().string().pattern(/^\/(?!\/)/, 'Only relative URLs starting with "/" are allowed')
319
+ },
320
+ genre: {
321
+ rule: "optional",
322
+ validator: globals_verifier.Validator.schema().array().items(
323
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
324
+ )
325
+ },
326
+ website: {
327
+ rule: "optional",
328
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid website URL format")
329
+ },
330
+ location: {
331
+ rule: "optional",
332
+ validator: globals_verifier.Validator.schema().string().max(100, "Location must not exceed 100 characters")
333
+ },
334
+ owner: {
335
+ rule: "required",
336
+ validator: globals_verifier.Validator.schema().object({
337
+ type: globals_verifier.Validator.schema().string().oneOf(["user", "organization"]),
338
+ target: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/)
339
+ })
212
340
  }
213
- }
214
- const albumController = new AlbumController2(app, db);
341
+ });
342
+ const updateVerifier = new globals_verifier.Verifier({
343
+ _id: {
344
+ rule: "required",
345
+ validator: globals_verifier.Validator.schema().string().required("Artist ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
346
+ },
347
+ name: {
348
+ rule: "optional",
349
+ validator: globals_verifier.Validator.schema().string().min(1, "Name cannot be empty").max(100, "Name must not exceed 100 characters")
350
+ },
351
+ bio: {
352
+ rule: "optional",
353
+ validator: globals_verifier.Validator.schema().string().max(2e3, "Bio must not exceed 2000 characters")
354
+ },
355
+ photoUrl: {
356
+ rule: "optional",
357
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid photo URL format")
358
+ },
359
+ coverUrl: {
360
+ rule: "optional",
361
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover URL format")
362
+ },
363
+ genre: {
364
+ rule: "optional",
365
+ validator: globals_verifier.Validator.schema().array().items(
366
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
367
+ )
368
+ },
369
+ website: {
370
+ rule: "optional",
371
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid website URL format")
372
+ },
373
+ location: {
374
+ rule: "optional",
375
+ validator: globals_verifier.Validator.schema().string().max(100, "Location must not exceed 100 characters")
376
+ },
377
+ isVerified: {
378
+ rule: "optional",
379
+ validator: globals_verifier.Validator.schema().boolean()
380
+ },
381
+ status: {
382
+ rule: "optional",
383
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"], "Invalid status")
384
+ }
385
+ });
386
+ const readVerifier = new globals_verifier.Verifier({
387
+ _id: {
388
+ rule: "optional",
389
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
390
+ },
391
+ genre: {
392
+ rule: "optional",
393
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
394
+ },
395
+ isVerified: {
396
+ rule: "optional",
397
+ validator: globals_verifier.Validator.schema().boolean()
398
+ },
399
+ status: {
400
+ rule: "optional",
401
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"])
402
+ },
403
+ location: {
404
+ rule: "optional",
405
+ validator: globals_verifier.Validator.schema().string()
406
+ },
407
+ skip: {
408
+ rule: "optional",
409
+ default: 0,
410
+ validator: globals_verifier.Validator.schema().integer().min(0)
411
+ },
412
+ limit: {
413
+ rule: "optional",
414
+ default: 20,
415
+ validator: globals_verifier.Validator.schema().integer().min(1).max(100)
416
+ },
417
+ sortParam: {
418
+ rule: "optional",
419
+ validator: globals_verifier.Validator.schema().string().oneOf(["name", "popularity", "createdAt", "updatedAt"])
420
+ },
421
+ sortOrder: {
422
+ rule: "optional",
423
+ default: "desc",
424
+ validator: globals_verifier.Validator.schema().string().oneOf(["asc", "desc"])
425
+ }
426
+ });
427
+ const deleteVerifier = new globals_verifier.Verifier({
428
+ _id: {
429
+ rule: "required",
430
+ validator: globals_verifier.Validator.schema().string().required("Artist ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
431
+ }
432
+ });
215
433
  return {
216
- create: albumController.create.bind(albumController),
217
- read: albumController.read.bind(albumController),
218
- update: albumController.update.bind(albumController),
219
- delete: albumController.delete.bind(albumController),
220
- getAlbumTracks: albumController.getAlbumTracks.bind(albumController),
221
- getFeaturedAlbums: albumController.getFeaturedAlbums.bind(albumController)
434
+ createVerifier,
435
+ readVerifier,
436
+ updateVerifier,
437
+ deleteVerifier
222
438
  };
223
- };
224
- const ArtistController = function(app, db) {
225
- const { MusicController: MusicController$1 } = MusicController(app, db);
226
- class ArtistController2 extends MusicController$1 {
227
- constructor(app2) {
228
- super("/api/artists", app2, db, db.artist);
439
+ }
440
+ const { getInstance: getInstance$3 } = abac.ABAC;
441
+ function setupArtistsRoutes(app, db) {
442
+ const abac2 = getInstance$3(db);
443
+ const verifier = artistsVerifierFactory();
444
+ const artistsCRUD = new crud.CRUD({
445
+ app,
446
+ db,
447
+ model: db.artist,
448
+ modelName: "artist",
449
+ basePath: "/api/artists",
450
+ auth: true,
451
+ verifiers: {
452
+ create: verifier.createVerifier,
453
+ read: verifier.readVerifier,
454
+ update: verifier.updateVerifier,
455
+ delete: verifier.deleteVerifier
456
+ },
457
+ abac: abac2,
458
+ cache: {
459
+ enabled: true,
460
+ ttl: 300,
461
+ tags: ["artists", "music"]
462
+ },
463
+ events: {
464
+ enabled: true,
465
+ logReads: false
229
466
  }
230
- // Get artist discography
231
- async getDiscography(req, res) {
467
+ });
468
+ artistsCRUD.addAction("get-by-url", {
469
+ method: "get",
470
+ path: "/url/:url",
471
+ auth: false,
472
+ handler: async (req, res) => {
232
473
  try {
233
- const artistId = req.params.artistId;
234
- const artist = await db.artist.findById(artistId);
474
+ const artist = await db.artist.findOne({ url: req.params.url });
235
475
  if (!artist) {
236
476
  return res.status(404).json({ error: "Artist not found" });
237
477
  }
238
- const albums = await db.album.find({
239
- artist: artistId,
240
- status: "published",
241
- isPublic: true
242
- }).sort({ releaseDate: -1 });
243
- const singleTracks = await db.track.find({
478
+ res.json(artist);
479
+ } catch (error) {
480
+ console.error(error);
481
+ res.status(500).json({ error: error.message });
482
+ }
483
+ }
484
+ });
485
+ artistsCRUD.addAction("discography", {
486
+ method: "get",
487
+ path: "/:artistId/discography",
488
+ auth: false,
489
+ handler: async (req, res) => {
490
+ try {
491
+ const { artistId } = req.params;
492
+ const albums = await db.album.find({ artists: artistId }).populate("artists", "name").sort({ releaseDate: -1 });
493
+ const tracks = await db.track.find({
244
494
  artist: artistId,
245
- album: { $exists: false },
246
495
  status: "published",
247
496
  isPublic: true
248
- }).sort({ releaseDate: -1 });
497
+ }).populate("album", "title").sort({ releaseDate: -1 });
249
498
  res.json({
250
- artist,
251
499
  albums,
252
- singles: singleTracks
500
+ tracks,
501
+ artist: artistId
253
502
  });
254
503
  } catch (error) {
255
- this.logger.error(`Error getting artist discography: ${error.message}`);
504
+ console.error(error);
256
505
  res.status(500).json({ error: error.message });
257
506
  }
258
507
  }
259
- // Verify an artist (admin only)
260
- async verifyArtist(req, res) {
508
+ });
509
+ artistsCRUD.addAction("verify-artist", {
510
+ method: "put",
511
+ path: "/:artistId/verify",
512
+ auth: true,
513
+ abac: {
514
+ resource: "artists",
515
+ action: "verify",
516
+ strict: true
517
+ },
518
+ handler: async (req, res) => {
261
519
  try {
262
- const artistId = req.params.artistId;
263
- if (!req.userRoles.includes("ROLE_ADMIN")) {
264
- return res.status(403).json({ error: "Only administrators can verify artists" });
265
- }
266
- const artist = await db.artist.findById(artistId);
520
+ const { artistId } = req.params;
521
+ const artist = await db.artist.findByIdAndUpdate(
522
+ artistId,
523
+ { isVerified: true },
524
+ { new: true }
525
+ );
267
526
  if (!artist) {
268
527
  return res.status(404).json({ error: "Artist not found" });
269
528
  }
270
- artist.isVerified = true;
271
- await artist.save();
272
- await this.cache.flush();
273
- res.json({ success: true, artist });
529
+ res.json({
530
+ message: "Artist verified successfully",
531
+ artist
532
+ });
274
533
  } catch (error) {
275
- this.logger.error(`Error verifying artist: ${error.message}`);
534
+ console.error(error);
276
535
  res.status(500).json({ error: error.message });
277
536
  }
278
537
  }
279
- // Get related artists
280
- async getRelatedArtists(req, res) {
538
+ });
539
+ artistsCRUD.addAction("related-artists", {
540
+ method: "get",
541
+ path: "/:artistId/related",
542
+ auth: false,
543
+ handler: async (req, res) => {
281
544
  try {
282
- const artistId = req.params.artistId;
545
+ const { artistId } = req.params;
546
+ const limit = parseInt(req.query.limit) || 10;
283
547
  const artist = await db.artist.findById(artistId);
284
548
  if (!artist) {
285
549
  return res.status(404).json({ error: "Artist not found" });
286
550
  }
287
551
  const relatedArtists = await db.artist.find({
288
552
  _id: { $ne: artistId },
553
+ // исключаем самого артиста
289
554
  genre: { $in: artist.genre },
555
+ // общие жанры
290
556
  status: "published"
291
- }).limit(5);
557
+ }).limit(limit).sort({ popularity: -1 });
292
558
  res.json(relatedArtists);
293
559
  } catch (error) {
294
- this.logger.error(`Error getting related artists: ${error.message}`);
560
+ console.error(error);
295
561
  res.status(500).json({ error: error.message });
296
562
  }
297
563
  }
298
- }
299
- const artistController = new ArtistController2(app, db);
564
+ });
565
+ return artistsCRUD;
566
+ }
567
+ function albumsVerifierFactory(db) {
568
+ const createVerifier = new globals_verifier.Verifier({
569
+ title: {
570
+ rule: "required",
571
+ validator: globals_verifier.Validator.schema().string().required("Album title is required").min(1, "Title cannot be empty").max(200, "Title must not exceed 200 characters")
572
+ },
573
+ description: {
574
+ rule: "optional",
575
+ validator: globals_verifier.Validator.schema().string().max(1e3, "Description must not exceed 1000 characters")
576
+ },
577
+ releaseDate: {
578
+ rule: "required",
579
+ validator: globals_verifier.Validator.schema().date().required("Release date is required")
580
+ },
581
+ coverArt: {
582
+ rule: "optional",
583
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover art URL format")
584
+ },
585
+ artists: {
586
+ rule: "required",
587
+ validator: globals_verifier.Validator.schema().array().items(
588
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
589
+ ).min(1, "At least one artist is required")
590
+ },
591
+ type: {
592
+ rule: "optional",
593
+ default: "album",
594
+ validator: globals_verifier.Validator.schema().string().oneOf(["album", "single", "EP", "compilation"], "Invalid album type")
595
+ },
596
+ genres: {
597
+ rule: "optional",
598
+ validator: globals_verifier.Validator.schema().array().items(
599
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
600
+ )
601
+ },
602
+ totalTracks: {
603
+ rule: "optional",
604
+ default: 0,
605
+ validator: globals_verifier.Validator.schema().integer().min(0, "Total tracks cannot be negative").max(100, "Too many tracks")
606
+ },
607
+ owner: {
608
+ rule: "required",
609
+ validator: globals_verifier.Validator.schema().object({
610
+ type: globals_verifier.Validator.schema().string().oneOf(["user", "organization"]),
611
+ target: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/)
612
+ })
613
+ }
614
+ });
615
+ const updateVerifier = new globals_verifier.Verifier({
616
+ _id: {
617
+ rule: "required",
618
+ validator: globals_verifier.Validator.schema().string().required("Album ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid album ID format")
619
+ },
620
+ title: {
621
+ rule: "optional",
622
+ validator: globals_verifier.Validator.schema().string().min(1, "Title cannot be empty").max(200, "Title must not exceed 200 characters")
623
+ },
624
+ description: {
625
+ rule: "optional",
626
+ validator: globals_verifier.Validator.schema().string().max(1e3, "Description must not exceed 1000 characters")
627
+ },
628
+ releaseDate: {
629
+ rule: "optional",
630
+ validator: globals_verifier.Validator.schema().date()
631
+ },
632
+ coverArt: {
633
+ rule: "optional",
634
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover art URL format")
635
+ },
636
+ artists: {
637
+ rule: "optional",
638
+ validator: globals_verifier.Validator.schema().array().items(
639
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
640
+ ).min(1, "At least one artist is required")
641
+ },
642
+ type: {
643
+ rule: "optional",
644
+ validator: globals_verifier.Validator.schema().string().oneOf(["album", "single", "EP", "compilation"], "Invalid album type")
645
+ },
646
+ genres: {
647
+ rule: "optional",
648
+ validator: globals_verifier.Validator.schema().array().items(
649
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
650
+ )
651
+ },
652
+ totalTracks: {
653
+ rule: "optional",
654
+ validator: globals_verifier.Validator.schema().integer().min(0, "Total tracks cannot be negative").max(100, "Too many tracks")
655
+ },
656
+ status: {
657
+ rule: "optional",
658
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"], "Invalid status")
659
+ }
660
+ });
661
+ const readVerifier = new globals_verifier.Verifier({
662
+ _id: {
663
+ rule: "optional",
664
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid album ID format")
665
+ },
666
+ artists: {
667
+ rule: "optional",
668
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid artist ID format")
669
+ },
670
+ type: {
671
+ rule: "optional",
672
+ validator: globals_verifier.Validator.schema().string().oneOf(["album", "single", "EP", "compilation"])
673
+ },
674
+ genres: {
675
+ rule: "optional",
676
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
677
+ },
678
+ status: {
679
+ rule: "optional",
680
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"])
681
+ },
682
+ skip: {
683
+ rule: "optional",
684
+ default: 0,
685
+ validator: globals_verifier.Validator.schema().integer().min(0)
686
+ },
687
+ limit: {
688
+ rule: "optional",
689
+ default: 20,
690
+ validator: globals_verifier.Validator.schema().integer().min(1).max(100)
691
+ },
692
+ sortParam: {
693
+ rule: "optional",
694
+ validator: globals_verifier.Validator.schema().string().oneOf(["title", "releaseDate", "totalTracks", "createdAt", "updatedAt"])
695
+ },
696
+ sortOrder: {
697
+ rule: "optional",
698
+ default: "desc",
699
+ validator: globals_verifier.Validator.schema().string().oneOf(["asc", "desc"])
700
+ }
701
+ });
702
+ const deleteVerifier = new globals_verifier.Verifier({
703
+ _id: {
704
+ rule: "required",
705
+ validator: globals_verifier.Validator.schema().string().required("Album ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid album ID format")
706
+ }
707
+ });
300
708
  return {
301
- create: artistController.create.bind(artistController),
302
- read: artistController.read.bind(artistController),
303
- update: artistController.update.bind(artistController),
304
- delete: artistController.delete.bind(artistController),
305
- getDiscography: artistController.getDiscography.bind(artistController),
306
- verifyArtist: artistController.verifyArtist.bind(artistController),
307
- getRelatedArtists: artistController.getRelatedArtists.bind(artistController)
709
+ createVerifier,
710
+ readVerifier,
711
+ updateVerifier,
712
+ deleteVerifier
308
713
  };
309
- };
310
- const GenreController = function(app, db) {
311
- const { MusicController: MusicController$1 } = MusicController(app, db);
312
- class GenreController2 extends MusicController$1 {
313
- constructor(app2) {
314
- super("/api/genres", app2, db, db.genre);
714
+ }
715
+ const { getInstance: getInstance$2 } = abac.ABAC;
716
+ function setupAlbumsRoutes(app, db) {
717
+ const abac2 = getInstance$2(db);
718
+ const verifier = albumsVerifierFactory();
719
+ const albumsCRUD = new crud.CRUD({
720
+ app,
721
+ db,
722
+ model: db.album,
723
+ modelName: "album",
724
+ basePath: "/api/albums",
725
+ auth: true,
726
+ verifiers: {
727
+ create: verifier.createVerifier,
728
+ read: verifier.readVerifier,
729
+ update: verifier.updateVerifier,
730
+ delete: verifier.deleteVerifier
731
+ },
732
+ abac: abac2,
733
+ cache: {
734
+ enabled: true,
735
+ ttl: 300,
736
+ tags: ["albums", "music"]
737
+ },
738
+ events: {
739
+ enabled: true,
740
+ logReads: false
315
741
  }
316
- // Get tracks by genre
317
- async getGenreTracks(req, res) {
742
+ });
743
+ albumsCRUD.addAction("get-by-url", {
744
+ method: "get",
745
+ path: "/url/:url",
746
+ auth: false,
747
+ handler: async (req, res) => {
318
748
  try {
319
- const genreId = req.params.genreId;
320
- const genre = await db.genre.findById(genreId);
321
- if (!genre) {
322
- return res.status(404).json({ error: "Genre not found" });
749
+ const album = await db.album.findOne({ url: req.params.url }).populate("artists", "name url");
750
+ if (!album) {
751
+ return res.status(404).json({ error: "Album not found" });
323
752
  }
753
+ res.json(album);
754
+ } catch (error) {
755
+ console.error(error);
756
+ res.status(500).json({ error: error.message });
757
+ }
758
+ }
759
+ });
760
+ albumsCRUD.addAction("album-tracks", {
761
+ method: "get",
762
+ path: "/:albumId/tracks",
763
+ auth: false,
764
+ handler: async (req, res) => {
765
+ try {
766
+ const { albumId } = req.params;
324
767
  const tracks = await db.track.find({
325
- genre: genreId,
768
+ album: albumId,
326
769
  status: "published",
327
770
  isPublic: true
328
- }).sort({ releaseDate: -1 }).limit(50).populate("artist", "name").populate("album", "title coverUrl");
329
- res.json({
330
- genre,
331
- tracks
332
- });
771
+ }).populate("artist", "name url").populate("genre", "name").sort({ trackNumber: 1, createdAt: 1 });
772
+ res.json(tracks);
333
773
  } catch (error) {
334
- this.logger.error(`Error getting genre tracks: ${error.message}`);
774
+ console.error(error);
335
775
  res.status(500).json({ error: error.message });
336
776
  }
337
777
  }
338
- // Get popular genres
339
- async getPopularGenres(req, res) {
778
+ });
779
+ albumsCRUD.addAction("featured", {
780
+ method: "get",
781
+ path: "/featured",
782
+ auth: false,
783
+ handler: async (req, res) => {
340
784
  try {
341
785
  const limit = parseInt(req.query.limit) || 10;
342
- const genres = await db.genre.find({
343
- status: "published"
344
- }).sort({ popularity: -1 }).limit(limit);
345
- res.json(genres);
786
+ const featuredAlbums = await db.album.find({
787
+ status: "published",
788
+ releaseDate: {
789
+ $gte: new Date(Date.now() - 90 * 24 * 60 * 60 * 1e3)
790
+ // последние 90 дней
791
+ }
792
+ }).populate("artists", "name url").sort({ createdAt: -1 }).limit(limit);
793
+ res.json(featuredAlbums);
346
794
  } catch (error) {
347
- this.logger.error(`Error getting popular genres: ${error.message}`);
795
+ console.error(error);
348
796
  res.status(500).json({ error: error.message });
349
797
  }
350
798
  }
351
- }
352
- const genreController = new GenreController2(app, db);
799
+ });
800
+ return albumsCRUD;
801
+ }
802
+ function playlistsVerifierFactory(db) {
803
+ const createVerifier = new globals_verifier.Verifier({
804
+ title: {
805
+ rule: "required",
806
+ validator: globals_verifier.Validator.schema().string().required("Playlist title is required").min(1, "Title cannot be empty").max(200, "Title must not exceed 200 characters")
807
+ },
808
+ description: {
809
+ rule: "optional",
810
+ validator: globals_verifier.Validator.schema().string().max(1e3, "Description must not exceed 1000 characters")
811
+ },
812
+ coverUrl: {
813
+ rule: "optional",
814
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover URL format")
815
+ },
816
+ tracks: {
817
+ rule: "optional",
818
+ validator: globals_verifier.Validator.schema().array().items(
819
+ globals_verifier.Validator.schema().object({
820
+ track: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid track ID format").required(),
821
+ addedAt: globals_verifier.Validator.schema().date()
822
+ })
823
+ )
824
+ },
825
+ isPublic: {
826
+ rule: "optional",
827
+ default: true,
828
+ validator: globals_verifier.Validator.schema().boolean()
829
+ },
830
+ isCollaborative: {
831
+ rule: "optional",
832
+ default: false,
833
+ validator: globals_verifier.Validator.schema().boolean()
834
+ },
835
+ collaborators: {
836
+ rule: "optional",
837
+ validator: globals_verifier.Validator.schema().array().items(
838
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid collaborator ID format")
839
+ )
840
+ },
841
+ owner: {
842
+ rule: "required",
843
+ validator: globals_verifier.Validator.schema().object({
844
+ type: globals_verifier.Validator.schema().string().oneOf(["user", "organization"]),
845
+ target: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/)
846
+ })
847
+ }
848
+ });
849
+ const updateVerifier = new globals_verifier.Verifier({
850
+ _id: {
851
+ rule: "required",
852
+ validator: globals_verifier.Validator.schema().string().required("Playlist ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid playlist ID format")
853
+ },
854
+ title: {
855
+ rule: "optional",
856
+ validator: globals_verifier.Validator.schema().string().min(1, "Title cannot be empty").max(200, "Title must not exceed 200 characters")
857
+ },
858
+ description: {
859
+ rule: "optional",
860
+ validator: globals_verifier.Validator.schema().string().max(1e3, "Description must not exceed 1000 characters")
861
+ },
862
+ coverUrl: {
863
+ rule: "optional",
864
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid cover URL format")
865
+ },
866
+ tracks: {
867
+ rule: "optional",
868
+ validator: globals_verifier.Validator.schema().array().items(
869
+ globals_verifier.Validator.schema().object({
870
+ track: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid track ID format").required(),
871
+ addedAt: globals_verifier.Validator.schema().date()
872
+ })
873
+ )
874
+ },
875
+ isPublic: {
876
+ rule: "optional",
877
+ validator: globals_verifier.Validator.schema().boolean()
878
+ },
879
+ isCollaborative: {
880
+ rule: "optional",
881
+ validator: globals_verifier.Validator.schema().boolean()
882
+ },
883
+ collaborators: {
884
+ rule: "optional",
885
+ validator: globals_verifier.Validator.schema().array().items(
886
+ globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid collaborator ID format")
887
+ )
888
+ },
889
+ status: {
890
+ rule: "optional",
891
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"], "Invalid status")
892
+ }
893
+ });
894
+ const readVerifier = new globals_verifier.Verifier({
895
+ _id: {
896
+ rule: "optional",
897
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid playlist ID format")
898
+ },
899
+ owner: {
900
+ rule: "optional",
901
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid owner ID format")
902
+ },
903
+ isPublic: {
904
+ rule: "optional",
905
+ validator: globals_verifier.Validator.schema().boolean()
906
+ },
907
+ isCollaborative: {
908
+ rule: "optional",
909
+ validator: globals_verifier.Validator.schema().boolean()
910
+ },
911
+ status: {
912
+ rule: "optional",
913
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"])
914
+ },
915
+ skip: {
916
+ rule: "optional",
917
+ default: 0,
918
+ validator: globals_verifier.Validator.schema().integer().min(0)
919
+ },
920
+ limit: {
921
+ rule: "optional",
922
+ default: 20,
923
+ validator: globals_verifier.Validator.schema().integer().min(1).max(100)
924
+ },
925
+ sortParam: {
926
+ rule: "optional",
927
+ validator: globals_verifier.Validator.schema().string().oneOf(["title", "followers", "createdAt", "updatedAt"])
928
+ },
929
+ sortOrder: {
930
+ rule: "optional",
931
+ default: "desc",
932
+ validator: globals_verifier.Validator.schema().string().oneOf(["asc", "desc"])
933
+ }
934
+ });
935
+ const deleteVerifier = new globals_verifier.Verifier({
936
+ _id: {
937
+ rule: "required",
938
+ validator: globals_verifier.Validator.schema().string().required("Playlist ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid playlist ID format")
939
+ }
940
+ });
353
941
  return {
354
- create: genreController.create.bind(genreController),
355
- read: genreController.read.bind(genreController),
356
- update: genreController.update.bind(genreController),
357
- delete: genreController.delete.bind(genreController),
358
- getGenreTracks: genreController.getGenreTracks.bind(genreController),
359
- getPopularGenres: genreController.getPopularGenres.bind(genreController)
942
+ createVerifier,
943
+ readVerifier,
944
+ updateVerifier,
945
+ deleteVerifier
360
946
  };
361
- };
362
- const PlaylistController = function(app, db) {
363
- const { MusicController: MusicController$1 } = MusicController(app, db);
364
- class PlaylistController2 extends MusicController$1 {
365
- constructor(app2, db2) {
366
- super("/api/playlists", app2, db2, db2.playlist);
947
+ }
948
+ const { getInstance: getInstance$1 } = abac.ABAC;
949
+ function setupPlaylistsRoutes(app, db) {
950
+ const abac2 = getInstance$1(db);
951
+ const verifier = playlistsVerifierFactory();
952
+ const playlistsCRUD = new crud.CRUD({
953
+ app,
954
+ db,
955
+ model: db.playlist,
956
+ modelName: "playlist",
957
+ basePath: "/api/playlists",
958
+ auth: true,
959
+ verifiers: {
960
+ create: verifier.createVerifier,
961
+ read: verifier.readVerifier,
962
+ update: verifier.updateVerifier,
963
+ delete: verifier.deleteVerifier
964
+ },
965
+ abac: abac2,
966
+ cache: {
967
+ enabled: true,
968
+ ttl: 300,
969
+ tags: ["playlists", "music"]
970
+ },
971
+ events: {
972
+ enabled: true,
973
+ logReads: false
367
974
  }
368
- // Add track to playlist
369
- async addTrack(req, res) {
975
+ });
976
+ playlistsCRUD.addAction("get-by-url", {
977
+ method: "get",
978
+ path: "/url/:url",
979
+ auth: false,
980
+ handler: async (req, res) => {
370
981
  try {
371
- const { playlistId, trackId } = req.params;
372
- const playlist = await db.playlist.findById(playlistId);
982
+ const playlist = await db.playlist.findOne({ url: req.params.url }).populate({
983
+ path: "tracks.track",
984
+ select: "-lyrics"
985
+ });
373
986
  if (!playlist) {
374
987
  return res.status(404).json({ error: "Playlist not found" });
375
988
  }
376
- const accessResult = await this.abac.checkAccess({
377
- user: req.userId,
378
- resource: "playlists",
379
- action: "update",
380
- currentResource: playlist
381
- });
382
- if (!accessResult.allowed) {
383
- return res.status(403).json({
384
- errorCode: accessResult.reason,
385
- message: "Access Denied"
386
- });
989
+ if (!playlist.isPublic) {
990
+ if (!req.userId) {
991
+ return res.status(403).json({ error: "Access denied to private playlist" });
992
+ }
993
+ const isOwner = playlist.owner.target.toString() === req.userId;
994
+ const isCollaborator = playlist.collaborators.some((collab) => collab.toString() === req.userId);
995
+ if (!isOwner && !isCollaborator) {
996
+ return res.status(403).json({ error: "Access denied to private playlist" });
997
+ }
998
+ }
999
+ res.json(playlist);
1000
+ } catch (error) {
1001
+ console.error(error);
1002
+ res.status(500).json({ error: error.message });
1003
+ }
1004
+ }
1005
+ });
1006
+ playlistsCRUD.addAction("user-playlists", {
1007
+ method: "get",
1008
+ path: "/user/:userId?",
1009
+ auth: true,
1010
+ handler: async (req, res) => {
1011
+ try {
1012
+ const userId = req.params.userId || req.userId;
1013
+ const query = { "owner.target": userId };
1014
+ if (userId !== req.userId) {
1015
+ query.isPublic = true;
387
1016
  }
1017
+ const playlists = await db.playlist.find(query).populate("tracks.track", "title artist").sort({ updatedAt: -1 });
1018
+ res.json(playlists);
1019
+ } catch (error) {
1020
+ console.error(error);
1021
+ res.status(500).json({ error: error.message });
1022
+ }
1023
+ }
1024
+ });
1025
+ playlistsCRUD.addAction("add-track", {
1026
+ method: "post",
1027
+ path: "/:playlistId/tracks/:trackId",
1028
+ auth: true,
1029
+ abac: {
1030
+ resource: "playlists",
1031
+ action: "update"
1032
+ },
1033
+ handler: async (req, res) => {
1034
+ try {
1035
+ const { playlistId, trackId } = req.params;
388
1036
  const track = await db.track.findById(trackId);
389
1037
  if (!track) {
390
1038
  return res.status(404).json({ error: "Track not found" });
391
1039
  }
392
- const trackExists = playlist.tracks.some((item) => item.track.toString() === trackId);
1040
+ const playlist = await db.playlist.findById(playlistId);
1041
+ if (!playlist) {
1042
+ return res.status(404).json({ error: "Playlist not found" });
1043
+ }
1044
+ const trackExists = playlist.tracks.some((t) => t.track.toString() === trackId);
393
1045
  if (trackExists) {
394
1046
  return res.status(400).json({ error: "Track already in playlist" });
395
1047
  }
@@ -398,96 +1050,253 @@ const PlaylistController = function(app, db) {
398
1050
  addedAt: /* @__PURE__ */ new Date()
399
1051
  });
400
1052
  await playlist.save();
401
- await this.cache.flush();
402
- res.json(playlist);
1053
+ res.json({
1054
+ message: "Track added to playlist successfully",
1055
+ playlist
1056
+ });
403
1057
  } catch (error) {
404
- this.logger.error(`Error adding track to playlist: ${error.message}`);
1058
+ console.error(error);
405
1059
  res.status(500).json({ error: error.message });
406
1060
  }
407
1061
  }
408
- // Remove track from playlist
409
- async removeTrack(req, res) {
1062
+ });
1063
+ playlistsCRUD.addAction("remove-track", {
1064
+ method: "delete",
1065
+ path: "/:playlistId/tracks/:trackId",
1066
+ auth: true,
1067
+ abac: {
1068
+ resource: "playlists",
1069
+ action: "update"
1070
+ },
1071
+ handler: async (req, res) => {
410
1072
  try {
411
1073
  const { playlistId, trackId } = req.params;
412
1074
  const playlist = await db.playlist.findById(playlistId);
413
1075
  if (!playlist) {
414
1076
  return res.status(404).json({ error: "Playlist not found" });
415
1077
  }
416
- const accessResult = await this.abac.checkAccess({
417
- user: req.userId,
418
- resource: "playlists",
419
- action: "update",
420
- currentResource: playlist
421
- });
422
- if (!accessResult.allowed) {
423
- return res.status(403).json({
424
- errorCode: accessResult.reason,
425
- message: "Access Denied"
426
- });
427
- }
428
- playlist.tracks = playlist.tracks.filter((item) => item.track.toString() !== trackId);
1078
+ playlist.tracks = playlist.tracks.filter(
1079
+ (t) => t.track.toString() !== trackId
1080
+ );
429
1081
  await playlist.save();
430
- await this.cache.flush();
431
- res.json(playlist);
432
- } catch (error) {
433
- this.logger.error(`Error removing track from playlist: ${error.message}`);
434
- res.status(500).json({ error: error.message });
435
- }
436
- }
437
- // Get user playlists
438
- async getUserPlaylists(req, res) {
439
- try {
440
- const userId = req.params.userId || req.userId;
441
- const playlists = await db.playlist.find({
442
- $or: [{ "owner.target": userId, "owner.type": "User" }, { collaborators: userId }]
443
- }).sort({ updatedAt: -1 });
444
- res.json(playlists);
1082
+ res.json({
1083
+ message: "Track removed from playlist successfully",
1084
+ playlist
1085
+ });
445
1086
  } catch (error) {
446
- this.logger.error(`Error getting user playlists: ${error.message}`);
1087
+ console.error(error);
447
1088
  res.status(500).json({ error: error.message });
448
1089
  }
449
1090
  }
450
- // Add collaborator to playlist
451
- async addCollaborator(req, res) {
1091
+ });
1092
+ playlistsCRUD.addAction("add-collaborator", {
1093
+ method: "post",
1094
+ path: "/:playlistId/collaborators/:userId",
1095
+ auth: true,
1096
+ abac: {
1097
+ resource: "playlists",
1098
+ action: "update"
1099
+ },
1100
+ handler: async (req, res) => {
452
1101
  try {
453
1102
  const { playlistId, userId } = req.params;
454
1103
  const playlist = await db.playlist.findById(playlistId);
455
1104
  if (!playlist) {
456
1105
  return res.status(404).json({ error: "Playlist not found" });
457
1106
  }
458
- if (playlist.owner.target.toString() !== req.userId) {
459
- return res.status(403).json({ error: "Only playlist owner can add collaborators" });
460
- }
461
- const user = await db.mongoose.model("User").findById(userId);
462
- if (!user) {
463
- return res.status(404).json({ error: "User not found" });
464
- }
465
1107
  if (playlist.collaborators.includes(userId)) {
466
1108
  return res.status(400).json({ error: "User is already a collaborator" });
467
1109
  }
468
1110
  playlist.collaborators.push(userId);
469
1111
  playlist.isCollaborative = true;
470
1112
  await playlist.save();
471
- await this.cache.flush();
472
- res.json(playlist);
1113
+ res.json({
1114
+ message: "Collaborator added successfully",
1115
+ playlist
1116
+ });
473
1117
  } catch (error) {
474
- this.logger.error(`Error adding collaborator to playlist: ${error.message}`);
1118
+ console.error(error);
475
1119
  res.status(500).json({ error: error.message });
476
1120
  }
477
1121
  }
478
- }
479
- const playlistController = new PlaylistController2(app, db);
1122
+ });
1123
+ return playlistsCRUD;
1124
+ }
1125
+ function genresVerifierFactory(db) {
1126
+ const createVerifier = new globals_verifier.Verifier({
1127
+ name: {
1128
+ rule: "required",
1129
+ validator: globals_verifier.Validator.schema().string().required("Genre name is required").min(1, "Name cannot be empty").max(50, "Name must not exceed 50 characters")
1130
+ },
1131
+ description: {
1132
+ rule: "optional",
1133
+ validator: globals_verifier.Validator.schema().string().max(500, "Description must not exceed 500 characters")
1134
+ },
1135
+ iconUrl: {
1136
+ rule: "optional",
1137
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid icon URL format")
1138
+ },
1139
+ popularity: {
1140
+ rule: "optional",
1141
+ default: 0,
1142
+ validator: globals_verifier.Validator.schema().number().min(0, "Popularity cannot be negative").max(100, "Popularity cannot exceed 100")
1143
+ }
1144
+ });
1145
+ const updateVerifier = new globals_verifier.Verifier({
1146
+ _id: {
1147
+ rule: "required",
1148
+ validator: globals_verifier.Validator.schema().string().required("Genre ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
1149
+ },
1150
+ name: {
1151
+ rule: "optional",
1152
+ validator: globals_verifier.Validator.schema().string().min(1, "Name cannot be empty").max(50, "Name must not exceed 50 characters")
1153
+ },
1154
+ description: {
1155
+ rule: "optional",
1156
+ validator: globals_verifier.Validator.schema().string().max(500, "Description must not exceed 500 characters")
1157
+ },
1158
+ iconUrl: {
1159
+ rule: "optional",
1160
+ validator: globals_verifier.Validator.schema().string().pattern(/^https?:\/\/.+/, "Invalid icon URL format")
1161
+ },
1162
+ popularity: {
1163
+ rule: "optional",
1164
+ validator: globals_verifier.Validator.schema().number().min(0, "Popularity cannot be negative").max(100, "Popularity cannot exceed 100")
1165
+ },
1166
+ status: {
1167
+ rule: "optional",
1168
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"], "Invalid status")
1169
+ }
1170
+ });
1171
+ const readVerifier = new globals_verifier.Verifier({
1172
+ _id: {
1173
+ rule: "optional",
1174
+ validator: globals_verifier.Validator.schema().string().pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
1175
+ },
1176
+ name: {
1177
+ rule: "optional",
1178
+ validator: globals_verifier.Validator.schema().string()
1179
+ },
1180
+ status: {
1181
+ rule: "optional",
1182
+ validator: globals_verifier.Validator.schema().string().oneOf(["draft", "published", "archived"])
1183
+ },
1184
+ skip: {
1185
+ rule: "optional",
1186
+ default: 0,
1187
+ validator: globals_verifier.Validator.schema().integer().min(0)
1188
+ },
1189
+ limit: {
1190
+ rule: "optional",
1191
+ default: 20,
1192
+ validator: globals_verifier.Validator.schema().integer().min(1).max(100)
1193
+ },
1194
+ sortParam: {
1195
+ rule: "optional",
1196
+ validator: globals_verifier.Validator.schema().string().oneOf(["name", "popularity", "createdAt", "updatedAt"])
1197
+ },
1198
+ sortOrder: {
1199
+ rule: "optional",
1200
+ default: "desc",
1201
+ validator: globals_verifier.Validator.schema().string().oneOf(["asc", "desc"])
1202
+ }
1203
+ });
1204
+ const deleteVerifier = new globals_verifier.Verifier({
1205
+ _id: {
1206
+ rule: "required",
1207
+ validator: globals_verifier.Validator.schema().string().required("Genre ID is required").pattern(/^[0-9a-fA-F]{24}$/, "Invalid genre ID format")
1208
+ }
1209
+ });
480
1210
  return {
481
- create: playlistController.create.bind(playlistController),
482
- read: playlistController.read.bind(playlistController),
483
- update: playlistController.update.bind(playlistController),
484
- delete: playlistController.delete.bind(playlistController),
485
- addTrack: playlistController.addTrack.bind(playlistController),
486
- removeTrack: playlistController.removeTrack.bind(playlistController),
487
- getUserPlaylists: playlistController.getUserPlaylists.bind(playlistController),
488
- addCollaborator: playlistController.addCollaborator.bind(playlistController)
1211
+ createVerifier,
1212
+ readVerifier,
1213
+ updateVerifier,
1214
+ deleteVerifier
489
1215
  };
490
- };
1216
+ }
1217
+ const { getInstance } = abac.ABAC;
1218
+ function setupGenresRoutes(app, db) {
1219
+ const abac2 = getInstance(db);
1220
+ const verifier = genresVerifierFactory();
1221
+ const genresCRUD = new crud.CRUD({
1222
+ app,
1223
+ db,
1224
+ model: db.genre,
1225
+ modelName: "genre",
1226
+ basePath: "/api/genres",
1227
+ auth: true,
1228
+ verifiers: {
1229
+ create: verifier.createVerifier,
1230
+ read: verifier.readVerifier,
1231
+ update: verifier.updateVerifier,
1232
+ delete: verifier.deleteVerifier
1233
+ },
1234
+ abac: abac2,
1235
+ cache: {
1236
+ enabled: true,
1237
+ ttl: 300,
1238
+ tags: ["genres", "music"]
1239
+ },
1240
+ events: {
1241
+ enabled: true,
1242
+ logReads: false
1243
+ }
1244
+ });
1245
+ genresCRUD.addAction("get-by-url", {
1246
+ method: "get",
1247
+ path: "/url/:url",
1248
+ auth: false,
1249
+ handler: async (req, res) => {
1250
+ try {
1251
+ const genre = await db.genre.findOne({ url: req.params.url });
1252
+ if (!genre) {
1253
+ return res.status(404).json({ error: "Genre not found" });
1254
+ }
1255
+ res.json(genre);
1256
+ } catch (error) {
1257
+ console.error(error);
1258
+ res.status(500).json({ error: error.message });
1259
+ }
1260
+ }
1261
+ });
1262
+ genresCRUD.addAction("genre-tracks", {
1263
+ method: "get",
1264
+ path: "/:genreId/tracks",
1265
+ auth: false,
1266
+ handler: async (req, res) => {
1267
+ try {
1268
+ const { genreId } = req.params;
1269
+ const limit = parseInt(req.query.limit) || 50;
1270
+ const skip = parseInt(req.query.skip) || 0;
1271
+ const tracks = await db.track.find({
1272
+ genre: genreId,
1273
+ status: "published",
1274
+ isPublic: true
1275
+ }).populate("artist", "name url").populate("album", "title url").sort({ playCount: -1, releaseDate: -1 }).skip(skip).limit(limit);
1276
+ res.json(tracks);
1277
+ } catch (error) {
1278
+ console.error(error);
1279
+ res.status(500).json({ error: error.message });
1280
+ }
1281
+ }
1282
+ });
1283
+ genresCRUD.addAction("popular", {
1284
+ method: "get",
1285
+ path: "/popular",
1286
+ auth: false,
1287
+ handler: async (req, res) => {
1288
+ try {
1289
+ const limit = parseInt(req.query.limit) || 20;
1290
+ const popularGenres = await db.genre.find({ status: "published" }).sort({ popularity: -1 }).limit(limit);
1291
+ res.json(popularGenres);
1292
+ } catch (error) {
1293
+ console.error(error);
1294
+ res.status(500).json({ error: error.message });
1295
+ }
1296
+ }
1297
+ });
1298
+ return genresCRUD;
1299
+ }
491
1300
  const SearchController = function(app, db) {
492
1301
  const logger = new globals_logger.Logger(db);
493
1302
  const cache = new globals_logger.Cache();
@@ -551,7 +1360,7 @@ const SearchController = function(app, db) {
551
1360
  const StreamController = function(app, db, publicPath) {
552
1361
  const { getInstance: getInstance2 } = globals_abac.globalsabac;
553
1362
  const logger = new globals_logger.Logger(db);
554
- const abac = getInstance2(db);
1363
+ const abac2 = getInstance2(db);
555
1364
  async function streamAudio(req, res) {
556
1365
  try {
557
1366
  const trackId = req.params.trackId;
@@ -559,7 +1368,7 @@ const StreamController = function(app, db, publicPath) {
559
1368
  if (!track) {
560
1369
  return res.status(404).json({ error: "Track not found" });
561
1370
  }
562
- const accessResult = await abac.checkAccess({
1371
+ const accessResult = await abac2.checkAccess({
563
1372
  user: req.userId,
564
1373
  resource: "tracks",
565
1374
  action: "read",
@@ -1014,199 +1823,6 @@ const musicPolicies = function initializeMusicPolicies(abacAccessControl) {
1014
1823
  });
1015
1824
  return abacAccessControl;
1016
1825
  };
1017
- const albumRoutes = function(app, db, origins, publicPath) {
1018
- const controller = AlbumController(app, db);
1019
- const { authJwt } = index.middlewareIndexFactory(db);
1020
- app.post("/api/albums/create", [authJwt.verifyToken], controller.create);
1021
- app.get("/api/albums/read", controller.read);
1022
- app.put("/api/albums/update", [authJwt.verifyToken], controller.update);
1023
- app.delete("/api/albums/delete", [authJwt.verifyToken], controller.delete);
1024
- app.get("/api/albums/:albumId/tracks", controller.getAlbumTracks);
1025
- app.get("/api/albums/featured", controller.getFeaturedAlbums);
1026
- app.get("/api/albums/url/:url", async (req, res) => {
1027
- try {
1028
- const album = await db.album.findOne({ url: req.params.url }).populate("artist");
1029
- if (!album) {
1030
- return res.status(404).json({ error: "Album not found" });
1031
- }
1032
- res.json(album);
1033
- } catch (error) {
1034
- console.error(error);
1035
- res.status(500).json({ error: error.message });
1036
- }
1037
- });
1038
- };
1039
- const artistRoutes = function(app, db, origins, publicPath) {
1040
- const controller = ArtistController(app, db);
1041
- const { authJwt } = index.middlewareIndexFactory(db);
1042
- app.post("/api/artists/create", [authJwt.verifyToken], controller.create);
1043
- app.get("/api/artists/read", controller.read);
1044
- app.put("/api/artists/update", [authJwt.verifyToken], controller.update);
1045
- app.delete("/api/artists/delete", [authJwt.verifyToken], controller.delete);
1046
- app.get("/api/artists/:artistId/discography", controller.getDiscography);
1047
- app.put("/api/artists/:artistId/verify", [authJwt.verifyToken, authJwt.isAdmin], controller.verifyArtist);
1048
- app.get("/api/artists/:artistId/related", controller.getRelatedArtists);
1049
- app.get("/api/artists/url/:url", async (req, res) => {
1050
- try {
1051
- const artist = await db.artist.findOne({ url: req.params.url });
1052
- if (!artist) {
1053
- return res.status(404).json({ error: "Artist not found" });
1054
- }
1055
- res.json(artist);
1056
- } catch (error) {
1057
- console.error(error);
1058
- res.status(500).json({ error: error.message });
1059
- }
1060
- });
1061
- };
1062
- const genreRoutes = function(app, db, origins, publicPath) {
1063
- const controller = GenreController(app, db);
1064
- const { authJwt } = index.middlewareIndexFactory(db);
1065
- app.post("/api/genres/create", [authJwt.verifyToken, authJwt.isAdmin], controller.create);
1066
- app.get("/api/genres/read", controller.read);
1067
- app.put("/api/genres/update", [authJwt.verifyToken, authJwt.isAdmin], controller.update);
1068
- app.delete("/api/genres/delete", [authJwt.verifyToken, authJwt.isAdmin], controller.delete);
1069
- app.get("/api/genres/:genreId/tracks", controller.getGenreTracks);
1070
- app.get("/api/genres/popular", controller.getPopularGenres);
1071
- app.get("/api/genres/url/:url", async (req, res) => {
1072
- try {
1073
- const genre = await db.genre.findOne({ url: req.params.url });
1074
- if (!genre) {
1075
- return res.status(404).json({ error: "Genre not found" });
1076
- }
1077
- res.json(genre);
1078
- } catch (error) {
1079
- console.error(error);
1080
- res.status(500).json({ error: error.message });
1081
- }
1082
- });
1083
- };
1084
- const { getInstance } = globals_abac.globalsabac;
1085
- const musicRoutes = function(app, db, origins, publicPath) {
1086
- const { MusicController: MusicController$1 } = MusicController(app, db);
1087
- const { authJwt } = index.middlewareIndexFactory(db);
1088
- const controller = new MusicController$1("/api/tracks", app, db, db.track, {
1089
- disableDefaultRoutes: true
1090
- });
1091
- const abac = getInstance(db);
1092
- app.post(
1093
- "/api/tracks/create",
1094
- [
1095
- authJwt.verifyToken(),
1096
- // Auth middleware
1097
- (req, res, next) => {
1098
- console.log("[Route] /api/tracks/create - Request received");
1099
- console.log("[Route] User ID from token:", req.userId);
1100
- next();
1101
- }
1102
- ],
1103
- controller.create.bind(controller)
1104
- // Bind to ensure 'this' context
1105
- );
1106
- app.get("/api/tracks/read", controller.read.bind(controller));
1107
- app.put("/api/tracks/update", [authJwt.verifyToken], controller.update.bind(controller));
1108
- app.delete("/api/tracks/delete", [authJwt.verifyToken], controller.delete.bind(controller));
1109
- app.get("/api/tracks/url/:url", async (req, res) => {
1110
- try {
1111
- const track = await db.track.findOne({ url: req.params.url });
1112
- if (!track) {
1113
- return res.status(404).json({ error: "Track not found" });
1114
- }
1115
- const accessResult = await abac.checkAccess({
1116
- user: req.userId,
1117
- resource: "tracks",
1118
- action: "read",
1119
- currentResource: track
1120
- });
1121
- if (!accessResult.allowed && !track.isPublic) {
1122
- return res.status(403).json({
1123
- errorCode: accessResult.reason,
1124
- message: "Access Denied"
1125
- });
1126
- }
1127
- res.json(track);
1128
- } catch (error) {
1129
- console.error(error);
1130
- res.status(500).json({ error: error.message });
1131
- }
1132
- });
1133
- app.get("/api/tracks/recent", async (req, res) => {
1134
- try {
1135
- const limit = parseInt(req.query.limit) || 10;
1136
- const recentTracks = await db.track.find({
1137
- status: "published",
1138
- isPublic: true
1139
- }).sort({ createdAt: -1 }).limit(limit);
1140
- res.json(recentTracks);
1141
- } catch (error) {
1142
- console.error(error);
1143
- res.status(500).json({ error: error.message });
1144
- }
1145
- });
1146
- app.get("/api/tracks/popular", async (req, res) => {
1147
- try {
1148
- const limit = parseInt(req.query.limit) || 10;
1149
- const popularTracks = await db.track.find({
1150
- status: "published",
1151
- isPublic: true
1152
- }).sort({ playCount: -1 }).limit(limit);
1153
- res.json(popularTracks);
1154
- } catch (error) {
1155
- console.error(error);
1156
- res.status(500).json({ error: error.message });
1157
- }
1158
- });
1159
- app.get("/api/tracks/genre/:genreId", async (req, res) => {
1160
- try {
1161
- const tracks = await db.track.find({
1162
- genre: req.params.genreId,
1163
- status: "published",
1164
- isPublic: true
1165
- }).sort({ releaseDate: -1 });
1166
- res.json(tracks);
1167
- } catch (error) {
1168
- console.error(error);
1169
- res.status(500).json({ error: error.message });
1170
- }
1171
- });
1172
- };
1173
- const playlistRoutes = function(app, db, origins, publicPath) {
1174
- const controller = PlaylistController(app, db);
1175
- const { authJwt } = index.middlewareIndexFactory(db);
1176
- app.post("/api/playlists/create", [authJwt.verifyToken], controller.create);
1177
- app.get("/api/playlists/read", controller.read);
1178
- app.put("/api/playlists/update", [authJwt.verifyToken], controller.update);
1179
- app.delete("/api/playlists/delete", [authJwt.verifyToken], controller.delete);
1180
- app.get("/api/playlists/user/:userId?", [authJwt.verifyToken], controller.getUserPlaylists);
1181
- app.post("/api/playlists/:playlistId/tracks/:trackId", [authJwt.verifyToken], controller.addTrack);
1182
- app.delete("/api/playlists/:playlistId/tracks/:trackId", [authJwt.verifyToken], controller.removeTrack);
1183
- app.post("/api/playlists/:playlistId/collaborators/:userId", [authJwt.verifyToken], controller.addCollaborator);
1184
- app.get("/api/playlists/url/:url", async (req, res) => {
1185
- try {
1186
- const playlist = await db.playlist.findOne({ url: req.params.url }).populate({
1187
- path: "tracks.track",
1188
- select: "-lyrics"
1189
- });
1190
- if (!playlist) {
1191
- return res.status(404).json({ error: "Playlist not found" });
1192
- }
1193
- if (!playlist.isPublic) {
1194
- if (!req.userId) {
1195
- return res.status(403).json({ error: "Access denied to private playlist" });
1196
- }
1197
- const isOwner = playlist.owner.target.toString() === req.userId;
1198
- const isCollaborator = playlist.collaborators.some((collab) => collab.toString() === req.userId);
1199
- if (!isOwner && !isCollaborator) {
1200
- return res.status(403).json({ error: "Access denied to private playlist" });
1201
- }
1202
- }
1203
- res.json(playlist);
1204
- } catch (error) {
1205
- console.error(error);
1206
- res.status(500).json({ error: error.message });
1207
- }
1208
- });
1209
- };
1210
1826
  const searchRoutes = function(app, db, origins, publicPath) {
1211
1827
  const controller = SearchController(app, db);
1212
1828
  app.get("/api/music/search", controller.search);
@@ -1349,17 +1965,17 @@ function initializeMusic({ app, db, wss, origins, publicPath }) {
1349
1965
  db.playHistory = PlayHistoryModel(db);
1350
1966
  console.log("server publioc is", publicPath);
1351
1967
  if (app) {
1352
- musicRoutes(app, db);
1353
- playlistRoutes(app, db);
1354
- albumRoutes(app, db);
1355
- artistRoutes(app, db);
1968
+ setupTracksRoutes(app, db);
1969
+ setupArtistsRoutes(app, db);
1970
+ setupAlbumsRoutes(app, db);
1971
+ setupPlaylistsRoutes(app, db);
1972
+ setupGenresRoutes(app, db);
1356
1973
  streamRoutes(app, db, origins, publicPath);
1357
1974
  searchRoutes(app, db);
1358
- genreRoutes(app, db);
1359
1975
  }
1360
1976
  const { getInstance: getInstance2 } = globals_abac.globalsabac;
1361
- const abac = getInstance2(db);
1362
- musicPolicies(abac);
1977
+ const abac2 = getInstance2(db);
1978
+ musicPolicies(abac2);
1363
1979
  const { WebSocketManager } = globals_websocket.WebSocketManager;
1364
1980
  if (global.webSocketManager && global.webSocketManager instanceof WebSocketManager) {
1365
1981
  global.webSocketManager.registerModule("music-streaming", StreamingHandler(db).handleStreamingMessage);
@@ -1377,22 +1993,20 @@ const models = {
1377
1993
  PlayHistoryModel
1378
1994
  };
1379
1995
  const routes = {
1380
- musicRoutes,
1381
- playlistRoutes,
1382
- albumRoutes,
1383
- artistRoutes,
1996
+ // NEW CRUD Routes
1997
+ setupTracksRoutes,
1998
+ setupArtistsRoutes,
1999
+ setupAlbumsRoutes,
2000
+ setupPlaylistsRoutes,
2001
+ setupGenresRoutes,
2002
+ // Legacy routes
1384
2003
  streamRoutes,
1385
- searchRoutes,
1386
- genreRoutes
2004
+ searchRoutes
1387
2005
  };
1388
2006
  const controllers = {
1389
- MusicController,
1390
- PlaylistController,
1391
- AlbumController,
1392
- ArtistController,
2007
+ // Keep only non-CRUD controllers
1393
2008
  StreamController,
1394
- SearchController,
1395
- GenreController
2009
+ SearchController
1396
2010
  };
1397
2011
  const music_server = {
1398
2012
  initialize: initializeMusic,