@ozdao/martyrs 0.2.470 → 0.2.472

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 (284) hide show
  1. package/dist/{Media-CR0V1zvB.js → Media-DW8RLbfM.js} +1 -1
  2. package/dist/{Media-C4Ges_Sd.mjs → Media-y_TX6us_.mjs} +1 -1
  3. package/dist/_virtual/index.cjs +1 -1
  4. package/dist/_virtual/index.js +1 -1
  5. package/dist/auth.server.js +1 -1
  6. package/dist/auth.server.mjs +1 -1
  7. package/dist/chats.server.js +1 -1
  8. package/dist/chats.server.mjs +1 -1
  9. package/dist/community.server.js +1 -1
  10. package/dist/community.server.mjs +1 -1
  11. package/dist/events.server.js +1 -1
  12. package/dist/events.server.mjs +1 -1
  13. package/dist/files.server.js +1 -1
  14. package/dist/files.server.mjs +1 -1
  15. package/dist/gallery.server.js +1 -1
  16. package/dist/gallery.server.mjs +1 -1
  17. package/dist/{index-DQqZReAr.js → index-CVXl1rB5.js} +0 -1
  18. package/dist/{index-DICZTQ-1.mjs → index-Df8vtZx7.mjs} +0 -1
  19. package/dist/{main-CsZAG5Wz.js → main-CCfQH-Dd.js} +2 -2
  20. package/dist/{main-CTcal9qN.mjs → main-CgmHzhq5.mjs} +74 -74
  21. package/dist/{node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_ → martyrs}/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs +1 -1
  22. package/dist/martyrs/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs.map +1 -0
  23. package/dist/{node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_ → martyrs}/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js +1 -1
  24. package/dist/martyrs/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js.map +1 -0
  25. package/dist/martyrs/node_modules/@vue/shared/dist/shared.esm-bundler.cjs.map +1 -0
  26. package/dist/martyrs/node_modules/@vue/shared/dist/shared.esm-bundler.js.map +1 -0
  27. package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.cjs +5 -0
  28. package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.cjs.map +1 -0
  29. package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.js +5 -0
  30. package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.js.map +1 -0
  31. package/dist/{node_modules/.pnpm/uuid@11.1.0 → martyrs}/node_modules/uuid/dist/esm-browser/rng.cjs +4 -4
  32. package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.cjs.map +1 -0
  33. package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.js +15 -0
  34. package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.js.map +1 -0
  35. package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.cjs +17 -0
  36. package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.cjs.map +1 -0
  37. package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.js +17 -0
  38. package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.js.map +1 -0
  39. package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.cjs +13 -0
  40. package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.cjs.map +1 -0
  41. package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.js +13 -0
  42. package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.js.map +1 -0
  43. package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.cjs +8 -0
  44. package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.cjs.map +1 -0
  45. package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.js +8 -0
  46. package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.js.map +1 -0
  47. package/dist/martyrs/src/components/Feed/Feed.vue.cjs +2 -2
  48. package/dist/martyrs/src/components/Feed/Feed.vue.cjs.map +1 -1
  49. package/dist/martyrs/src/components/Feed/Feed.vue.js +2 -2
  50. package/dist/martyrs/src/components/Feed/Feed.vue.js.map +1 -1
  51. package/dist/martyrs/src/components/Menu/{Menu.vue.cjs → Menu.vue2.cjs} +2 -2
  52. package/dist/martyrs/src/components/Menu/Menu.vue2.cjs.map +1 -0
  53. package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
  54. package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
  55. package/dist/martyrs/src/components/Skeleton/Skeleton.vue.cjs +5 -5
  56. package/dist/martyrs/src/components/Skeleton/Skeleton.vue.cjs.map +1 -1
  57. package/dist/martyrs/src/components/Skeleton/Skeleton.vue.js +5 -5
  58. package/dist/martyrs/src/components/Skeleton/Skeleton.vue.js.map +1 -1
  59. package/dist/martyrs/src/components/Tab/{Tab.vue2.cjs → Tab.vue.cjs} +2 -2
  60. package/dist/martyrs/src/components/Tab/{Tab.vue2.js.map → Tab.vue.cjs.map} +1 -1
  61. package/dist/martyrs/src/components/Tab/{Tab.vue2.js → Tab.vue.js} +2 -2
  62. package/dist/martyrs/src/components/Tab/Tab.vue.js.map +1 -0
  63. package/dist/martyrs/src/components/Tree/Tree.vue.cjs +3 -1
  64. package/dist/martyrs/src/components/Tree/Tree.vue.cjs.map +1 -1
  65. package/dist/martyrs/src/components/Tree/Tree.vue.js +3 -1
  66. package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
  67. package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.cjs +1 -1
  68. package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.js +1 -1
  69. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
  70. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
  71. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
  72. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
  73. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +1 -1
  74. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +1 -1
  75. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.cjs +1 -1
  76. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
  77. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.cjs +1 -1
  78. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
  79. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
  80. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
  81. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
  82. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
  83. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
  84. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
  85. package/dist/martyrs/src/modules/auth/views/store/auth.cjs +1 -0
  86. package/dist/martyrs/src/modules/auth/views/store/auth.cjs.map +1 -1
  87. package/dist/martyrs/src/modules/auth/views/store/auth.js +1 -0
  88. package/dist/martyrs/src/modules/auth/views/store/auth.js.map +1 -1
  89. package/dist/martyrs/src/modules/constructor/components/sections/Constructor.vue.cjs +1 -1
  90. package/dist/martyrs/src/modules/constructor/components/sections/Constructor.vue.js +1 -1
  91. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +1 -1
  92. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
  93. package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs +107 -21
  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 +107 -21
  96. package/dist/martyrs/src/modules/globals/views/classes/globals.store.js.map +1 -1
  97. package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs +10 -14
  98. package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs.map +1 -1
  99. package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js +12 -16
  100. package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js.map +1 -1
  101. package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.cjs +1 -1
  102. package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.js +1 -1
  103. package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.cjs +7 -13
  104. package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.cjs.map +1 -1
  105. package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.js +7 -13
  106. package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.js.map +1 -1
  107. package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs +6 -7
  108. package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs.map +1 -1
  109. package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +7 -8
  110. package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js.map +1 -1
  111. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -1
  112. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
  113. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.cjs +1 -1
  114. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
  115. package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +1 -1
  116. package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +1 -1
  117. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +2 -2
  118. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +2 -2
  119. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +2 -2
  120. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +2 -2
  121. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.cjs +1 -1
  122. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
  123. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +1 -1
  124. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +1 -1
  125. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.cjs +1 -1
  126. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
  127. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -1
  128. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
  129. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.cjs +11 -5
  130. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.cjs.map +1 -1
  131. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +12 -6
  132. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
  133. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs +34 -13
  134. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs.map +1 -1
  135. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +35 -14
  136. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
  137. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +20 -9
  138. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs.map +1 -1
  139. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +21 -10
  140. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
  141. package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.cjs +1 -1
  142. package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.js +1 -1
  143. package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +1 -1
  144. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
  145. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +2 -1
  146. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs.map +1 -1
  147. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -1
  148. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js.map +1 -1
  149. package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +1 -1
  150. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
  151. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.cjs +1 -1
  152. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
  153. package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.cjs +1 -1
  154. package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.js +1 -1
  155. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs +1 -1
  156. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
  157. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +1 -1
  158. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
  159. package/dist/martyrs.cjs.js +1 -1
  160. package/dist/martyrs.css +1 -1
  161. package/dist/martyrs.es.js +1 -1
  162. package/dist/notifications.server.js +35 -2
  163. package/dist/notifications.server.mjs +35 -2
  164. package/dist/orders.server.js +3 -3
  165. package/dist/orders.server.mjs +3 -3
  166. package/dist/organizations.server.js +1 -1
  167. package/dist/organizations.server.mjs +1 -1
  168. package/dist/products.server.js +78 -53
  169. package/dist/products.server.mjs +78 -53
  170. package/dist/rents.server.js +1 -1
  171. package/dist/rents.server.mjs +1 -1
  172. package/dist/style.css +37 -38
  173. package/dist/wallet.server.js +1 -1
  174. package/dist/wallet.server.mjs +1 -1
  175. package/package.json +2 -1
  176. package/src/components/Feed/Feed.vue +2 -7
  177. package/src/components/Skeleton/Skeleton.vue +4 -5
  178. package/src/components/Tree/Tree.vue +5 -2
  179. package/src/modules/auth/controllers/middlewares/authJwt.js +1 -1
  180. package/src/modules/auth/views/store/auth.js +2 -1
  181. package/src/modules/globals/controllers/classes/globals.crud.js +2 -2
  182. package/src/modules/globals/views/classes/globals.store.js +119 -31
  183. package/src/modules/globals/views/components/partials/Navigation.vue +11 -10
  184. package/src/modules/globals/views/utils/vue-app-renderer.js +7 -16
  185. package/src/modules/icons/entities/IconMusic.vue +14 -0
  186. package/src/modules/icons/navigation/IconCheck.vue +31 -0
  187. package/src/modules/icons/navigation/IconHeart.vue +26 -0
  188. package/src/modules/icons/navigation/IconPause.vue +31 -0
  189. package/src/modules/icons/navigation/IconPlay.vue +17 -0
  190. package/src/modules/icons/navigation/IconRefresh.vue +31 -0
  191. package/src/modules/icons/navigation/IconShuffle.vue +31 -0
  192. package/src/modules/icons/navigation/IconVolume.vue +31 -0
  193. package/src/modules/music/components/SidebarMusic.vue +156 -0
  194. package/src/modules/music/components/cards/AlbumCard.vue +107 -0
  195. package/src/modules/music/components/cards/ArtistCard.vue +37 -0
  196. package/src/modules/music/components/cards/PlaylistCard.vue +100 -0
  197. package/src/modules/music/components/cards/TrackCard.vue +86 -0
  198. package/src/modules/music/components/forms/PlaylistForm.vue +156 -0
  199. package/src/modules/music/components/forms/SearchForm.vue +82 -0
  200. package/src/modules/music/components/forms/UploadForm.vue +313 -0
  201. package/src/modules/music/components/layouts/MusicLayout.vue +137 -0
  202. package/src/modules/music/components/lists/AlbumList.vue +25 -0
  203. package/src/modules/music/components/lists/ArtistList.vue +25 -0
  204. package/src/modules/music/components/lists/PlaylistList.vue +25 -0
  205. package/src/modules/music/components/lists/TrackList.vue +175 -0
  206. package/src/modules/music/components/pages/AlbumDetail.vue +265 -0
  207. package/src/modules/music/components/pages/ArtistDetail.vue +247 -0
  208. package/src/modules/music/components/pages/MusicHome.vue +177 -0
  209. package/src/modules/music/components/pages/MusicLibrary.vue +192 -0
  210. package/src/modules/music/components/pages/MusicUpload.vue +44 -0
  211. package/src/modules/music/components/pages/PlaylistDetail.vue +504 -0
  212. package/src/modules/music/components/pages/SearchResults.vue +397 -0
  213. package/src/modules/music/components/pages/TrackDetail.vue +143 -0
  214. package/src/modules/music/components/player/MusicPlayer.vue +202 -0
  215. package/src/modules/music/components/player/TrackProgress.vue +110 -0
  216. package/src/modules/music/components/player/VolumeControl.vue +98 -0
  217. package/src/modules/music/controllers/album.controller.js +98 -0
  218. package/src/modules/music/controllers/artist.controller.js +111 -0
  219. package/src/modules/music/controllers/genre.controller.js +71 -0
  220. package/src/modules/music/controllers/music.controller.js +174 -0
  221. package/src/modules/music/controllers/playlist.controller.js +182 -0
  222. package/src/modules/music/controllers/search.controller.js +103 -0
  223. package/src/modules/music/controllers/stream.controller.js +106 -0
  224. package/src/modules/music/models/album.model.js +61 -0
  225. package/src/modules/music/models/artist.model.js +67 -0
  226. package/src/modules/music/models/genre.model.js +42 -0
  227. package/src/modules/music/models/play-history.model.js +51 -0
  228. package/src/modules/music/models/playlist.model.js +69 -0
  229. package/src/modules/music/models/track.model.js +94 -0
  230. package/src/modules/music/music.client.js +186 -0
  231. package/src/modules/music/music.server.js +114 -0
  232. package/src/modules/music/policies/music.policies.js +84 -0
  233. package/src/modules/music/router/music.js +77 -0
  234. package/src/modules/music/routes/album.routes.js +62 -0
  235. package/src/modules/music/routes/artist.routes.js +67 -0
  236. package/src/modules/music/routes/genre.routes.js +60 -0
  237. package/src/modules/music/routes/music.routes.js +145 -0
  238. package/src/modules/music/routes/playlist.routes.js +99 -0
  239. package/src/modules/music/routes/search.routes.js +10 -0
  240. package/src/modules/music/routes/stream.routes.js +38 -0
  241. package/src/modules/music/store/albums.js +200 -0
  242. package/src/modules/music/store/artists.js +180 -0
  243. package/src/modules/music/store/player.js +397 -0
  244. package/src/modules/music/store/playlists.js +211 -0
  245. package/src/modules/music/store/search.js +126 -0
  246. package/src/modules/music/store/tracks.js +230 -0
  247. package/src/modules/music/websocket/streaming.handler.js +151 -0
  248. package/src/modules/notifications/controllers/notifications.controller.js +44 -1
  249. package/src/modules/notifications/notifications.server.js +0 -1
  250. package/src/modules/notifications/routes/notifications.routes.js +3 -0
  251. package/src/modules/orders/components/pages/OrderCreate.vue +0 -2
  252. package/src/modules/products/components/blocks/CardCategory.vue +5 -4
  253. package/src/modules/products/components/pages/Categories.vue +38 -20
  254. package/src/modules/products/components/pages/CategoryEdit.vue +16 -7
  255. package/src/modules/products/components/pages/ProductEdit.vue +1 -0
  256. package/src/modules/products/controllers/categories.controller.js +155 -103
  257. package/dist/martyrs/src/components/Menu/Menu.vue.cjs.map +0 -1
  258. package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
  259. package/dist/martyrs/src/components/Tab/Tab.vue2.cjs.map +0 -1
  260. package/dist/node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs.map +0 -1
  261. package/dist/node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js.map +0 -1
  262. package/dist/node_modules/.pnpm/@vue_shared@3.5.13/node_modules/@vue/shared/dist/shared.esm-bundler.cjs.map +0 -1
  263. package/dist/node_modules/.pnpm/@vue_shared@3.5.13/node_modules/@vue/shared/dist/shared.esm-bundler.js.map +0 -1
  264. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.cjs +0 -6
  265. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.cjs.map +0 -1
  266. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.js +0 -6
  267. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.js.map +0 -1
  268. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.cjs.map +0 -1
  269. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.js +0 -15
  270. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.js.map +0 -1
  271. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.cjs +0 -11
  272. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.cjs.map +0 -1
  273. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js +0 -11
  274. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js.map +0 -1
  275. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.cjs +0 -21
  276. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.cjs.map +0 -1
  277. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.js +0 -21
  278. package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.js.map +0 -1
  279. /package/dist/{node_modules/.pnpm/@vue_shared@3.5.13 → martyrs}/node_modules/@vue/shared/dist/shared.esm-bundler.cjs +0 -0
  280. /package/dist/{node_modules/.pnpm/@vue_shared@3.5.13 → martyrs}/node_modules/@vue/shared/dist/shared.esm-bundler.js +0 -0
  281. /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.cjs +0 -0
  282. /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.cjs.map +0 -0
  283. /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.js +0 -0
  284. /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.js.map +0 -0
@@ -0,0 +1,202 @@
1
+ <!-- components/player/MusicPlayer.vue -->
2
+ <template>
3
+ <div class="music-player pd-small flex-between flex-v-center flex bg-dark br-t br-solid br-dark-transp-20 t-white">
4
+ <!-- Current Track Info -->
5
+ <div class="player-track-info flex-v-center flex w-25r">
6
+ <div v-if="currentTrack" class="player-track-cover mn-r-small">
7
+ <Media
8
+ :url="currentTrack.coverUrl || (currentTrack.album && currentTrack.album.coverUrl) || '/assets/placeholder-track.jpg'"
9
+ class="w-3r h-3r object-fit-cover radius-small"
10
+ />
11
+ </div>
12
+
13
+ <div class="player-track-details t-truncate">
14
+ <div class="player-track-title t-white t-medium t-truncate">
15
+ {{ currentTrack?.title || 'No track playing' }}
16
+ </div>
17
+ <div class="player-track-artist t-grey t-small t-truncate">
18
+ {{ getArtistName(currentTrack) }}
19
+ </div>
20
+ </div>
21
+
22
+ <div class="player-favorite mn-l-small">
23
+ <Button
24
+ @click="toggleFavorite"
25
+ class="bg-transparent border-none pd-zero"
26
+ :showLoader="false"
27
+ :showSucces="false"
28
+ >
29
+ <IconHeart class="i-small" :fill="isFavorite ? 'rgb(var(--main))' : 'rgb(var(--grey))'"/>
30
+ </Button>
31
+ </div>
32
+ </div>
33
+
34
+ <!-- Player Controls -->
35
+ <div class="player-controls flex-1 flex flex-column items-center">
36
+ <div class="player-buttons flex-v-center flex gap-small">
37
+ <Button
38
+ @click="toggleShuffle"
39
+ class="bg-transparent border-none pd-zero"
40
+ :showLoader="false"
41
+ :showSucces="false"
42
+ >
43
+ <IconShuffle class="i-small" :fill="shuffle ? 'rgb(var(--main))' : 'rgb(var(--grey))'"/>
44
+ </Button>
45
+
46
+ <Button
47
+ @click="playPrevious"
48
+ class="bg-transparent border-none pd-zero"
49
+ :showLoader="false"
50
+ :showSucces="false"
51
+ >
52
+ <IconPrevious class="i-small" fill="rgb(var(--white))"/>
53
+ </Button>
54
+
55
+ <Button
56
+ @click="togglePlay"
57
+ class="play-pause-btn bg-white radius-round pd-micro flex-center flex"
58
+ :showLoader="false"
59
+ :showSucces="false"
60
+ >
61
+ <IconPause v-if="isPlaying" class="i-medium" fill="rgb(var(--black))"/>
62
+ <IconPlay v-else class="i-medium" fill="rgb(var(--black))"/>
63
+ </Button>
64
+
65
+ <Button
66
+ @click="playNext"
67
+ class="bg-transparent border-none pd-zero"
68
+ :showLoader="false"
69
+ :showSucces="false"
70
+ >
71
+ <IconNext class="i-small" fill="rgb(var(--white))"/>
72
+ </Button>
73
+
74
+ <Button
75
+ @click="toggleRepeat"
76
+ class="bg-transparent border-none pd-zero"
77
+ :showLoader="false"
78
+ :showSucces="false"
79
+ >
80
+ <IconRepeat class="i-small" :fill="repeatIcon"/>
81
+ </Button>
82
+ </div>
83
+
84
+ <TrackProgress class="w-100 mn-t-thin" />
85
+ </div>
86
+
87
+ <!-- Volume Control -->
88
+ <div class="player-volume flex-v-center flex w-15r">
89
+ <Button
90
+ @click="toggleMute"
91
+ class="bg-transparent border-none pd-zero mn-r-small"
92
+ :showLoader="false"
93
+ :showSucces="false"
94
+ >
95
+ <IconVolume v-if="!muted && volume > 0.5" class="i-small" fill="rgb(var(--white))"/>
96
+ <IconVolumeHalf v-else-if="!muted && volume > 0" class="i-small" fill="rgb(var(--white))"/>
97
+ <IconVolumeMute v-else class="i-small" fill="rgb(var(--white))"/>
98
+ </Button>
99
+
100
+ <VolumeControl />
101
+ </div>
102
+ </div>
103
+ </template>
104
+
105
+ <script setup>
106
+ import { computed, ref } from 'vue';
107
+ import Media from '@martyrs/src/components/Media/Media.vue';
108
+ import Button from '@martyrs/src/components/Button/Button.vue';
109
+ import TrackProgress from './TrackProgress.vue';
110
+ import VolumeControl from './VolumeControl.vue';
111
+
112
+ // Import icons
113
+ import IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';
114
+ import IconPause from '@martyrs/src/modules/icons/navigation/IconPause.vue';
115
+ import IconNext from '@martyrs/src/modules/icons/navigation/IconChevronRight.vue';
116
+ import IconPrevious from '@martyrs/src/modules/icons/navigation/IconChevronLeft.vue';
117
+ import IconShuffle from '@martyrs/src/modules/icons/navigation/IconShuffle.vue';
118
+ import IconRepeat from '@martyrs/src/modules/icons/navigation/IconRefresh.vue';
119
+ import IconHeart from '@martyrs/src/modules/icons/navigation/IconHeart.vue';
120
+ import IconVolume from '@martyrs/src/modules/icons/navigation/IconVolume.vue';
121
+ // import IconVolumeHalf from '@martyrs/src/modules/icons/navigation/IconVolume.vue'; // Using same icon but we'd style it differently
122
+ import IconVolumeMute from '@martyrs/src/modules/icons/navigation/IconMute.vue';
123
+
124
+ // Import player store
125
+ import { state as playerState, actions as playerActions } from '../../store/player.js';
126
+
127
+ // State
128
+ const isFavorite = ref(false);
129
+
130
+ // Computed properties
131
+ const currentTrack = computed(() => playerState.currentTrack);
132
+ const isPlaying = computed(() => playerState.isPlaying);
133
+ const volume = computed(() => playerState.volume);
134
+ const muted = computed(() => playerState.muted);
135
+ const shuffle = computed(() => playerState.shuffle);
136
+ const repeat = computed(() => playerState.repeat);
137
+
138
+ const repeatIcon = computed(() => {
139
+ switch(repeat.value) {
140
+ case 'one':
141
+ return 'rgb(var(--main))';
142
+ case 'all':
143
+ return 'rgb(var(--main))';
144
+ default:
145
+ return 'rgb(var(--grey))';
146
+ }
147
+ });
148
+
149
+ // Methods
150
+ const togglePlay = () => {
151
+ playerActions.togglePlay();
152
+ };
153
+
154
+ const playNext = () => {
155
+ playerActions.playNext();
156
+ };
157
+
158
+ const playPrevious = () => {
159
+ playerActions.playPrevious();
160
+ };
161
+
162
+ const toggleShuffle = () => {
163
+ playerActions.toggleShuffle();
164
+ };
165
+
166
+ const toggleRepeat = () => {
167
+ playerActions.toggleRepeat();
168
+ };
169
+
170
+ const toggleMute = () => {
171
+ playerActions.toggleMute();
172
+ };
173
+
174
+ const toggleFavorite = () => {
175
+ isFavorite.value = !isFavorite.value;
176
+ // Implement favorite track logic here
177
+ };
178
+
179
+ const getArtistName = (track) => {
180
+ if (!track) return 'Unknown Artist';
181
+
182
+ if (track.artist) {
183
+ if (typeof track.artist === 'object') {
184
+ return track.artist.name || 'Unknown Artist';
185
+ }
186
+ return track.artist;
187
+ }
188
+ return 'Unknown Artist';
189
+ };
190
+ </script>
191
+
192
+ <style scoped>
193
+ .play-pause-btn {
194
+ width: 32px;
195
+ height: 32px;
196
+ transition: transform 0.2s ease;
197
+ }
198
+
199
+ .play-pause-btn:hover {
200
+ transform: scale(1.1);
201
+ }
202
+ </style>
@@ -0,0 +1,110 @@
1
+ <!-- components/player/TrackProgress.vue -->
2
+ <template>
3
+ <div class="track-progress flex flex-v-center gap-small">
4
+ <div class="current-time t-grey t-small">{{ formatTime(currentTime) }}</div>
5
+
6
+ <div
7
+ ref="progressBarContainer"
8
+ class="progress-bar-container flex-1 h-thin bg-grey radius-extra pos-relative cursor-pointer"
9
+ @click="seek"
10
+ @mousedown="startSeek"
11
+ @mousemove="updateSeekPosition"
12
+ @mouseup="endSeek"
13
+ @mouseleave="endSeek"
14
+ >
15
+ <div
16
+ class="progress-bar h-100 bg-white radius-extra"
17
+ :style="{ width: progressPercentage + '%' }"
18
+ ></div>
19
+ <div
20
+ class="progress-handle w-thin h-thin bg-white radius-round pos-absolute pos-t-50 pos-l-0"
21
+ :style="{ left: `calc(${progressPercentage}% - 4px)`, transform: 'translateY(-50%)' }"
22
+ ></div>
23
+ </div>
24
+
25
+ <div class="total-time t-grey t-small">{{ formatTime(duration) }}</div>
26
+ </div>
27
+ </template>
28
+
29
+ <script setup>
30
+ import { ref, computed, onMounted, onUnmounted } from 'vue';
31
+
32
+ // Import player store
33
+ import { state as playerState, actions as playerActions } from '../../store/player.js';
34
+
35
+ // Refs
36
+ const progressBarContainer = ref(null);
37
+ const isSeeking = ref(false);
38
+ const seekPosition = ref(0);
39
+
40
+ // Computed properties
41
+ const currentTime = computed(() => playerState.currentTime);
42
+ const duration = computed(() => playerState.duration);
43
+ const progressPercentage = computed(() => {
44
+ if (!duration.value) return 0;
45
+ return Math.min(100, (currentTime.value / duration.value) * 100);
46
+ });
47
+
48
+ // Methods
49
+ const formatTime = (seconds) => {
50
+ if (!seconds) return '0:00';
51
+
52
+ const minutes = Math.floor(seconds / 60);
53
+ const remainingSeconds = Math.floor(seconds % 60);
54
+
55
+ return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
56
+ };
57
+
58
+ const calculateSeekTime = (event) => {
59
+ if (!progressBarContainer.value || !duration.value) return 0;
60
+
61
+ const rect = progressBarContainer.value.getBoundingClientRect();
62
+ const offsetX = event.clientX - rect.left;
63
+ const percentage = Math.max(0, Math.min(1, offsetX / rect.width));
64
+
65
+ return percentage * duration.value;
66
+ };
67
+
68
+ const seek = (event) => {
69
+ const seekTime = calculateSeekTime(event);
70
+ playerActions.seek(seekTime);
71
+ };
72
+
73
+ const startSeek = (event) => {
74
+ isSeeking.value = true;
75
+ seekPosition.value = calculateSeekTime(event);
76
+ };
77
+
78
+ const updateSeekPosition = (event) => {
79
+ if (isSeeking.value) {
80
+ seekPosition.value = calculateSeekTime(event);
81
+ }
82
+ };
83
+
84
+ const endSeek = () => {
85
+ if (isSeeking.value) {
86
+ isSeeking.value = false;
87
+ playerActions.seek(seekPosition.value);
88
+ }
89
+ };
90
+
91
+ // Clean up event listeners when component is unmounted
92
+ onUnmounted(() => {
93
+ isSeeking.value = false;
94
+ });
95
+ </script>
96
+
97
+ <style scoped>
98
+ .progress-bar-container:hover .progress-bar {
99
+ background-color: rgb(var(--main));
100
+ }
101
+
102
+ .progress-handle {
103
+ display: none;
104
+ }
105
+
106
+ .progress-bar-container:hover .progress-handle {
107
+ display: block;
108
+ transform: translateY(-50%) scale(1.3);
109
+ }
110
+ </style>
@@ -0,0 +1,98 @@
1
+ <!-- components/player/VolumeControl.vue -->
2
+ <template>
3
+ <div
4
+ ref="volumeBarContainer"
5
+ class="volume-bar-container w-100 h-thin bg-grey-transp-50 radius-extra pos-relative cursor-pointer"
6
+ @click="setVolume"
7
+ @mousedown="startVolumeChange"
8
+ @mousemove="updateVolumePosition"
9
+ @mouseup="endVolumeChange"
10
+ @mouseleave="endVolumeChange"
11
+ >
12
+ <div
13
+ class="volume-bar h-100 bg-white radius-extra"
14
+ :style="{ width: volumePercentage + '%' }"
15
+ :class="{ 'muted': muted }"
16
+ ></div>
17
+ <div
18
+ class="volume-handle w-thin h-thin bg-white radius-round pos-absolute pos-t-50 pos-l-0"
19
+ :style="{
20
+ left: `calc(${volumePercentage}% - 4px)`,
21
+ transform: 'translateY(-50%)',
22
+ opacity: muted ? 0 : 1
23
+ }"
24
+ ></div>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref, computed } from 'vue';
30
+
31
+ // Import player store
32
+ import { state as playerState, actions as playerActions } from '../../store/player.js';
33
+
34
+ // Refs
35
+ const volumeBarContainer = ref(null);
36
+ const isChangingVolume = ref(false);
37
+
38
+ // Computed properties
39
+ const volume = computed(() => playerState.volume);
40
+ const muted = computed(() => playerState.muted);
41
+ const volumePercentage = computed(() => {
42
+ if (muted.value) return 0;
43
+ return volume.value * 100;
44
+ });
45
+
46
+ // Methods
47
+ const calculateVolume = (event) => {
48
+ if (!volumeBarContainer.value) return 0;
49
+
50
+ const rect = volumeBarContainer.value.getBoundingClientRect();
51
+ const offsetX = event.clientX - rect.left;
52
+
53
+ return Math.max(0, Math.min(1, offsetX / rect.width));
54
+ };
55
+
56
+ const setVolume = (event) => {
57
+ const newVolume = calculateVolume(event);
58
+ playerActions.setVolume(newVolume);
59
+
60
+ // Unmute if was muted
61
+ if (muted.value && newVolume > 0) {
62
+ playerActions.toggleMute();
63
+ }
64
+ };
65
+
66
+ const startVolumeChange = (event) => {
67
+ isChangingVolume.value = true;
68
+ setVolume(event);
69
+ };
70
+
71
+ const updateVolumePosition = (event) => {
72
+ if (isChangingVolume.value) {
73
+ setVolume(event);
74
+ }
75
+ };
76
+
77
+ const endVolumeChange = () => {
78
+ isChangingVolume.value = false;
79
+ };
80
+ </script>
81
+
82
+ <style scoped>
83
+ .volume-bar-container:hover .volume-bar:not(.muted) {
84
+ background-color: rgb(var(--main));
85
+ }
86
+
87
+ .volume-handle {
88
+ display: none;
89
+ }
90
+
91
+ .volume-bar-container:hover .volume-handle {
92
+ display: block;
93
+ }
94
+
95
+ .muted {
96
+ opacity: 0.5;
97
+ }
98
+ </style>
@@ -0,0 +1,98 @@
1
+ // controllers/album.controller.js
2
+ const globalsQuery = require('@martyrs/src/modules/globals/controllers/utils/queryProcessor');
3
+
4
+ module.exports = function(app,db) {
5
+ const { MusicController } = require('./music.controller')(app,db);
6
+
7
+ class AlbumController extends MusicController {
8
+ constructor(app) {
9
+ super('/api/albums', app, db, db.album);
10
+ }
11
+
12
+ // Get tracks for a specific album
13
+ async getAlbumTracks(req, res) {
14
+ try {
15
+ const albumId = req.params.albumId;
16
+
17
+ // Check if album exists and user has access
18
+ const album = await db.album.findById(albumId);
19
+ if (!album) {
20
+ return res.status(404).json({ error: 'Album not found' });
21
+ }
22
+
23
+ // Check access using ABAC
24
+ const accessResult = await this.abac.checkAccess({
25
+ user: req.userId,
26
+ resource: 'albums',
27
+ action: 'read',
28
+ currentResource: album
29
+ });
30
+
31
+ if (!accessResult.allowed && !album.isPublic) {
32
+ return res.status(403).json({
33
+ errorCode: accessResult.reason,
34
+ message: 'Access Denied'
35
+ });
36
+ }
37
+
38
+ // Find tracks for this album
39
+ const tracks = await db.track.find({ album: albumId, status: 'published' })
40
+ .sort({ releaseDate: -1 });
41
+
42
+ res.json(tracks);
43
+ } catch (error) {
44
+ this.logger.error(`Error getting album tracks: ${error.message}`);
45
+ res.status(500).json({ error: error.message });
46
+ }
47
+ }
48
+
49
+ // Get featured albums
50
+ async getFeaturedAlbums(req, res) {
51
+ try {
52
+ const cacheKey = 'featured-albums';
53
+ let featuredAlbums = await this.cache.get(cacheKey);
54
+
55
+ if (!featuredAlbums) {
56
+ // Get featured albums with track counts
57
+ featuredAlbums = await db.album.aggregate([
58
+ { $match: { status: 'featured', isPublic: true } },
59
+ {
60
+ $lookup: {
61
+ from: 'tracks',
62
+ localField: '_id',
63
+ foreignField: 'album',
64
+ as: 'tracks'
65
+ }
66
+ },
67
+ {
68
+ $addFields: {
69
+ trackCount: { $size: '$tracks' }
70
+ }
71
+ },
72
+ { $project: { tracks: 0 } },
73
+ { $sort: { releaseDate: -1 } },
74
+ { $limit: 10 }
75
+ ]);
76
+
77
+ await this.cache.set(cacheKey, featuredAlbums, 3600); // Cache for 1 hour
78
+ }
79
+
80
+ res.json(featuredAlbums);
81
+ } catch (error) {
82
+ this.logger.error(`Error getting featured albums: ${error.message}`);
83
+ res.status(500).json({ error: error.message });
84
+ }
85
+ }
86
+ }
87
+
88
+ const albumController = new AlbumController(app,db); // Pass app in actual implementation
89
+
90
+ return {
91
+ create: albumController.create.bind(albumController),
92
+ read: albumController.read.bind(albumController),
93
+ update: albumController.update.bind(albumController),
94
+ delete: albumController.delete.bind(albumController),
95
+ getAlbumTracks: albumController.getAlbumTracks.bind(albumController),
96
+ getFeaturedAlbums: albumController.getFeaturedAlbums.bind(albumController)
97
+ };
98
+ };
@@ -0,0 +1,111 @@
1
+ // controllers/artist.controller.js (continued)
2
+ module.exports = function(app,db) {
3
+ const { MusicController } = require('./music.controller')(app,db);
4
+
5
+ class ArtistController extends MusicController {
6
+ constructor(app) {
7
+ super('/api/artists', app, db, db.artist);
8
+ }
9
+
10
+ // Get artist discography
11
+ async getDiscography(req, res) {
12
+ try {
13
+ const artistId = req.params.artistId;
14
+
15
+ // Verify artist exists
16
+ const artist = await db.artist.findById(artistId);
17
+ if (!artist) {
18
+ return res.status(404).json({ error: 'Artist not found' });
19
+ }
20
+
21
+ // Get all albums by this artist
22
+ const albums = await db.album.find({
23
+ artist: artistId,
24
+ status: 'published',
25
+ isPublic: true
26
+ }).sort({ releaseDate: -1 });
27
+
28
+ // Get all tracks not in albums
29
+ const singleTracks = await db.track.find({
30
+ artist: artistId,
31
+ album: { $exists: false },
32
+ status: 'published',
33
+ isPublic: true
34
+ }).sort({ releaseDate: -1 });
35
+
36
+ res.json({
37
+ artist,
38
+ albums,
39
+ singles: singleTracks
40
+ });
41
+ } catch (error) {
42
+ this.logger.error(`Error getting artist discography: ${error.message}`);
43
+ res.status(500).json({ error: error.message });
44
+ }
45
+ }
46
+
47
+ // Verify an artist (admin only)
48
+ async verifyArtist(req, res) {
49
+ try {
50
+ const artistId = req.params.artistId;
51
+
52
+ // Check if user is admin
53
+ if (!req.userRoles.includes('ROLE_ADMIN')) {
54
+ return res.status(403).json({ error: 'Only administrators can verify artists' });
55
+ }
56
+
57
+ const artist = await db.artist.findById(artistId);
58
+ if (!artist) {
59
+ return res.status(404).json({ error: 'Artist not found' });
60
+ }
61
+
62
+ artist.isVerified = true;
63
+ await artist.save();
64
+
65
+ await this.cache.flush();
66
+
67
+ res.json({ success: true, artist });
68
+ } catch (error) {
69
+ this.logger.error(`Error verifying artist: ${error.message}`);
70
+ res.status(500).json({ error: error.message });
71
+ }
72
+ }
73
+
74
+ // Get related artists
75
+ async getRelatedArtists(req, res) {
76
+ try {
77
+ const artistId = req.params.artistId;
78
+
79
+ // Find genres of this artist
80
+ const artist = await db.artist.findById(artistId);
81
+ if (!artist) {
82
+ return res.status(404).json({ error: 'Artist not found' });
83
+ }
84
+
85
+ // Get artists with similar genres
86
+ const relatedArtists = await db.artist.find({
87
+ _id: { $ne: artistId },
88
+ genre: { $in: artist.genre },
89
+ status: 'published'
90
+ }).limit(5);
91
+
92
+ res.json(relatedArtists);
93
+ } catch (error) {
94
+ this.logger.error(`Error getting related artists: ${error.message}`);
95
+ res.status(500).json({ error: error.message });
96
+ }
97
+ }
98
+ }
99
+
100
+ const artistController = new ArtistController(app,db);
101
+
102
+ return {
103
+ create: artistController.create.bind(artistController),
104
+ read: artistController.read.bind(artistController),
105
+ update: artistController.update.bind(artistController),
106
+ delete: artistController.delete.bind(artistController),
107
+ getDiscography: artistController.getDiscography.bind(artistController),
108
+ verifyArtist: artistController.verifyArtist.bind(artistController),
109
+ getRelatedArtists: artistController.getRelatedArtists.bind(artistController)
110
+ };
111
+ };
@@ -0,0 +1,71 @@
1
+ // controllers/genre.controller.js
2
+ module.exports = function(app,db) {
3
+ const { MusicController } = require('./music.controller')(app,db);
4
+
5
+ class GenreController extends MusicController {
6
+ constructor(app) {
7
+ super('/api/genres', app, db, db.genre);
8
+ }
9
+
10
+ // Get tracks by genre
11
+ async getGenreTracks(req, res) {
12
+ try {
13
+ const genreId = req.params.genreId;
14
+
15
+ // Verify genre exists
16
+ const genre = await db.genre.findById(genreId);
17
+ if (!genre) {
18
+ return res.status(404).json({ error: 'Genre not found' });
19
+ }
20
+
21
+ // Get tracks from this genre
22
+ const tracks = await db.track.find({
23
+ genre: genreId,
24
+ status: 'published',
25
+ isPublic: true
26
+ })
27
+ .sort({ releaseDate: -1 })
28
+ .limit(50)
29
+ .populate('artist', 'name')
30
+ .populate('album', 'title coverUrl');
31
+
32
+ res.json({
33
+ genre,
34
+ tracks
35
+ });
36
+ } catch (error) {
37
+ this.logger.error(`Error getting genre tracks: ${error.message}`);
38
+ res.status(500).json({ error: error.message });
39
+ }
40
+ }
41
+
42
+ // Get popular genres
43
+ async getPopularGenres(req, res) {
44
+ try {
45
+ const limit = parseInt(req.query.limit) || 10;
46
+
47
+ const genres = await db.genre.find({
48
+ status: 'published'
49
+ })
50
+ .sort({ popularity: -1 })
51
+ .limit(limit);
52
+
53
+ res.json(genres);
54
+ } catch (error) {
55
+ this.logger.error(`Error getting popular genres: ${error.message}`);
56
+ res.status(500).json({ error: error.message });
57
+ }
58
+ }
59
+ }
60
+
61
+ const genreController = new GenreController(app,db);
62
+
63
+ return {
64
+ create: genreController.create.bind(genreController),
65
+ read: genreController.read.bind(genreController),
66
+ update: genreController.update.bind(genreController),
67
+ delete: genreController.delete.bind(genreController),
68
+ getGenreTracks: genreController.getGenreTracks.bind(genreController),
69
+ getPopularGenres: genreController.getPopularGenres.bind(genreController)
70
+ };
71
+ };