@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.
- package/dist/{Media-CR0V1zvB.js → Media-DW8RLbfM.js} +1 -1
- package/dist/{Media-C4Ges_Sd.mjs → Media-y_TX6us_.mjs} +1 -1
- package/dist/_virtual/index.cjs +1 -1
- package/dist/_virtual/index.js +1 -1
- package/dist/auth.server.js +1 -1
- package/dist/auth.server.mjs +1 -1
- package/dist/chats.server.js +1 -1
- package/dist/chats.server.mjs +1 -1
- package/dist/community.server.js +1 -1
- package/dist/community.server.mjs +1 -1
- package/dist/events.server.js +1 -1
- package/dist/events.server.mjs +1 -1
- package/dist/files.server.js +1 -1
- package/dist/files.server.mjs +1 -1
- package/dist/gallery.server.js +1 -1
- package/dist/gallery.server.mjs +1 -1
- package/dist/{index-DQqZReAr.js → index-CVXl1rB5.js} +0 -1
- package/dist/{index-DICZTQ-1.mjs → index-Df8vtZx7.mjs} +0 -1
- package/dist/{main-CsZAG5Wz.js → main-CCfQH-Dd.js} +2 -2
- package/dist/{main-CTcal9qN.mjs → main-CgmHzhq5.mjs} +74 -74
- 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
- package/dist/martyrs/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs.map +1 -0
- 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
- package/dist/martyrs/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js.map +1 -0
- package/dist/martyrs/node_modules/@vue/shared/dist/shared.esm-bundler.cjs.map +1 -0
- package/dist/martyrs/node_modules/@vue/shared/dist/shared.esm-bundler.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.cjs +5 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.js +5 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.js.map +1 -0
- package/dist/{node_modules/.pnpm/uuid@11.1.0 → martyrs}/node_modules/uuid/dist/esm-browser/rng.cjs +4 -4
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.js +15 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.cjs +17 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.js +17 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.cjs +13 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.js +13 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.cjs +8 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.js +8 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.js.map +1 -0
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs +2 -2
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.js +2 -2
- package/dist/martyrs/src/components/Feed/Feed.vue.js.map +1 -1
- package/dist/martyrs/src/components/Menu/{Menu.vue.cjs → Menu.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.cjs +5 -5
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.js +5 -5
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.js.map +1 -1
- package/dist/martyrs/src/components/Tab/{Tab.vue2.cjs → Tab.vue.cjs} +2 -2
- package/dist/martyrs/src/components/Tab/{Tab.vue2.js.map → Tab.vue.cjs.map} +1 -1
- package/dist/martyrs/src/components/Tab/{Tab.vue2.js → Tab.vue.js} +2 -2
- package/dist/martyrs/src/components/Tab/Tab.vue.js.map +1 -0
- package/dist/martyrs/src/components/Tree/Tree.vue.cjs +3 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.js +3 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/store/auth.cjs +1 -0
- package/dist/martyrs/src/modules/auth/views/store/auth.cjs.map +1 -1
- package/dist/martyrs/src/modules/auth/views/store/auth.js +1 -0
- package/dist/martyrs/src/modules/auth/views/store/auth.js.map +1 -1
- package/dist/martyrs/src/modules/constructor/components/sections/Constructor.vue.cjs +1 -1
- package/dist/martyrs/src/modules/constructor/components/sections/Constructor.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs +107 -21
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.js +107 -21
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs +10 -14
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js +12 -16
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.cjs +7 -13
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.js +7 -13
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs +6 -7
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +7 -8
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.cjs +11 -5
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +12 -6
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs +34 -13
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +35 -14
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +20 -9
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +21 -10
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +2 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
- package/dist/martyrs.cjs.js +1 -1
- package/dist/martyrs.css +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/notifications.server.js +35 -2
- package/dist/notifications.server.mjs +35 -2
- package/dist/orders.server.js +3 -3
- package/dist/orders.server.mjs +3 -3
- package/dist/organizations.server.js +1 -1
- package/dist/organizations.server.mjs +1 -1
- package/dist/products.server.js +78 -53
- package/dist/products.server.mjs +78 -53
- package/dist/rents.server.js +1 -1
- package/dist/rents.server.mjs +1 -1
- package/dist/style.css +37 -38
- package/dist/wallet.server.js +1 -1
- package/dist/wallet.server.mjs +1 -1
- package/package.json +2 -1
- package/src/components/Feed/Feed.vue +2 -7
- package/src/components/Skeleton/Skeleton.vue +4 -5
- package/src/components/Tree/Tree.vue +5 -2
- package/src/modules/auth/controllers/middlewares/authJwt.js +1 -1
- package/src/modules/auth/views/store/auth.js +2 -1
- package/src/modules/globals/controllers/classes/globals.crud.js +2 -2
- package/src/modules/globals/views/classes/globals.store.js +119 -31
- package/src/modules/globals/views/components/partials/Navigation.vue +11 -10
- package/src/modules/globals/views/utils/vue-app-renderer.js +7 -16
- package/src/modules/icons/entities/IconMusic.vue +14 -0
- package/src/modules/icons/navigation/IconCheck.vue +31 -0
- package/src/modules/icons/navigation/IconHeart.vue +26 -0
- package/src/modules/icons/navigation/IconPause.vue +31 -0
- package/src/modules/icons/navigation/IconPlay.vue +17 -0
- package/src/modules/icons/navigation/IconRefresh.vue +31 -0
- package/src/modules/icons/navigation/IconShuffle.vue +31 -0
- package/src/modules/icons/navigation/IconVolume.vue +31 -0
- package/src/modules/music/components/SidebarMusic.vue +156 -0
- package/src/modules/music/components/cards/AlbumCard.vue +107 -0
- package/src/modules/music/components/cards/ArtistCard.vue +37 -0
- package/src/modules/music/components/cards/PlaylistCard.vue +100 -0
- package/src/modules/music/components/cards/TrackCard.vue +86 -0
- package/src/modules/music/components/forms/PlaylistForm.vue +156 -0
- package/src/modules/music/components/forms/SearchForm.vue +82 -0
- package/src/modules/music/components/forms/UploadForm.vue +313 -0
- package/src/modules/music/components/layouts/MusicLayout.vue +137 -0
- package/src/modules/music/components/lists/AlbumList.vue +25 -0
- package/src/modules/music/components/lists/ArtistList.vue +25 -0
- package/src/modules/music/components/lists/PlaylistList.vue +25 -0
- package/src/modules/music/components/lists/TrackList.vue +175 -0
- package/src/modules/music/components/pages/AlbumDetail.vue +265 -0
- package/src/modules/music/components/pages/ArtistDetail.vue +247 -0
- package/src/modules/music/components/pages/MusicHome.vue +177 -0
- package/src/modules/music/components/pages/MusicLibrary.vue +192 -0
- package/src/modules/music/components/pages/MusicUpload.vue +44 -0
- package/src/modules/music/components/pages/PlaylistDetail.vue +504 -0
- package/src/modules/music/components/pages/SearchResults.vue +397 -0
- package/src/modules/music/components/pages/TrackDetail.vue +143 -0
- package/src/modules/music/components/player/MusicPlayer.vue +202 -0
- package/src/modules/music/components/player/TrackProgress.vue +110 -0
- package/src/modules/music/components/player/VolumeControl.vue +98 -0
- package/src/modules/music/controllers/album.controller.js +98 -0
- package/src/modules/music/controllers/artist.controller.js +111 -0
- package/src/modules/music/controllers/genre.controller.js +71 -0
- package/src/modules/music/controllers/music.controller.js +174 -0
- package/src/modules/music/controllers/playlist.controller.js +182 -0
- package/src/modules/music/controllers/search.controller.js +103 -0
- package/src/modules/music/controllers/stream.controller.js +106 -0
- package/src/modules/music/models/album.model.js +61 -0
- package/src/modules/music/models/artist.model.js +67 -0
- package/src/modules/music/models/genre.model.js +42 -0
- package/src/modules/music/models/play-history.model.js +51 -0
- package/src/modules/music/models/playlist.model.js +69 -0
- package/src/modules/music/models/track.model.js +94 -0
- package/src/modules/music/music.client.js +186 -0
- package/src/modules/music/music.server.js +114 -0
- package/src/modules/music/policies/music.policies.js +84 -0
- package/src/modules/music/router/music.js +77 -0
- package/src/modules/music/routes/album.routes.js +62 -0
- package/src/modules/music/routes/artist.routes.js +67 -0
- package/src/modules/music/routes/genre.routes.js +60 -0
- package/src/modules/music/routes/music.routes.js +145 -0
- package/src/modules/music/routes/playlist.routes.js +99 -0
- package/src/modules/music/routes/search.routes.js +10 -0
- package/src/modules/music/routes/stream.routes.js +38 -0
- package/src/modules/music/store/albums.js +200 -0
- package/src/modules/music/store/artists.js +180 -0
- package/src/modules/music/store/player.js +397 -0
- package/src/modules/music/store/playlists.js +211 -0
- package/src/modules/music/store/search.js +126 -0
- package/src/modules/music/store/tracks.js +230 -0
- package/src/modules/music/websocket/streaming.handler.js +151 -0
- package/src/modules/notifications/controllers/notifications.controller.js +44 -1
- package/src/modules/notifications/notifications.server.js +0 -1
- package/src/modules/notifications/routes/notifications.routes.js +3 -0
- package/src/modules/orders/components/pages/OrderCreate.vue +0 -2
- package/src/modules/products/components/blocks/CardCategory.vue +5 -4
- package/src/modules/products/components/pages/Categories.vue +38 -20
- package/src/modules/products/components/pages/CategoryEdit.vue +16 -7
- package/src/modules/products/components/pages/ProductEdit.vue +1 -0
- package/src/modules/products/controllers/categories.controller.js +155 -103
- package/dist/martyrs/src/components/Menu/Menu.vue.cjs.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
- package/dist/martyrs/src/components/Tab/Tab.vue2.cjs.map +0 -1
- 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
- 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
- package/dist/node_modules/.pnpm/@vue_shared@3.5.13/node_modules/@vue/shared/dist/shared.esm-bundler.cjs.map +0 -1
- package/dist/node_modules/.pnpm/@vue_shared@3.5.13/node_modules/@vue/shared/dist/shared.esm-bundler.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.cjs +0 -6
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.js +0 -6
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.js +0 -15
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.cjs +0 -11
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js +0 -11
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.cjs +0 -21
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.js +0 -21
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.js.map +0 -1
- /package/dist/{node_modules/.pnpm/@vue_shared@3.5.13 → martyrs}/node_modules/@vue/shared/dist/shared.esm-bundler.cjs +0 -0
- /package/dist/{node_modules/.pnpm/@vue_shared@3.5.13 → martyrs}/node_modules/@vue/shared/dist/shared.esm-bundler.js +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.cjs +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.cjs.map +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.js +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.js.map +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// controllers/music.controller.js
|
|
2
|
+
const CRUD = require('@martyrs/src/modules/globals/controllers/classes/globals.crud');
|
|
3
|
+
const Logger = require('@martyrs/src/modules/globals/controllers/classes/globals.logger');
|
|
4
|
+
const Cache = require('@martyrs/src/modules/globals/controllers/classes/globals.cache');
|
|
5
|
+
const { getInstance } = require('@martyrs/src/modules/globals/controllers/classes/globals.abac.js');
|
|
6
|
+
|
|
7
|
+
module.exports = function(app, db) {
|
|
8
|
+
const logger = new Logger(db);
|
|
9
|
+
const cache = new Cache();
|
|
10
|
+
const abac = getInstance(db);
|
|
11
|
+
|
|
12
|
+
class MusicController extends CRUD {
|
|
13
|
+
constructor(basePath, app, db, model, options) {
|
|
14
|
+
super(basePath, app, db, model, options);
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
this.cache = cache;
|
|
17
|
+
this.abac = abac;
|
|
18
|
+
|
|
19
|
+
// Log initialization to help debugging
|
|
20
|
+
console.log(`[MusicController] Initialized with basePath: ${basePath}`);
|
|
21
|
+
console.log(`[MusicController] Model: ${model?.modelName || 'No model provided'}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Override the create method to handle ownership
|
|
25
|
+
async create(req, res) {
|
|
26
|
+
try {
|
|
27
|
+
console.log(`[MusicController] Create request received:`, {
|
|
28
|
+
userId: req.userId,
|
|
29
|
+
body: req.body
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Ensure userId exists
|
|
33
|
+
if (!req.userId) {
|
|
34
|
+
console.error('[MusicController] No userId found in request, auth middleware may have failed');
|
|
35
|
+
return res.status(401).json({
|
|
36
|
+
errorCode: 'AUTHENTICATION_REQUIRED',
|
|
37
|
+
message: 'You must be authenticated to perform this action'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Set creator and owner if not provided
|
|
42
|
+
if (!req.body.creator) {
|
|
43
|
+
req.body.creator = {
|
|
44
|
+
type: 'user', // Note lowercase - must match your schema expectations
|
|
45
|
+
target: req.userId
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!req.body.owner) {
|
|
50
|
+
req.body.owner = {
|
|
51
|
+
type: 'user', // Note lowercase - must match your schema expectations
|
|
52
|
+
target: req.userId
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log(`[MusicController] Checking access with ABAC`);
|
|
57
|
+
|
|
58
|
+
// Check access using ABAC
|
|
59
|
+
const accessResult = await this.abac.checkAccess({
|
|
60
|
+
user: req.userId,
|
|
61
|
+
resource: this.model.collection.collectionName,
|
|
62
|
+
action: 'create',
|
|
63
|
+
data: req.body
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log(`[MusicController] Access check result:`, accessResult);
|
|
67
|
+
|
|
68
|
+
if (!accessResult.allowed) {
|
|
69
|
+
console.error(`[MusicController] Access denied:`, accessResult.reason);
|
|
70
|
+
return res.status(403).json({
|
|
71
|
+
errorCode: accessResult.reason,
|
|
72
|
+
message: 'Access Denied'
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(`[MusicController] Creating record with data:`, req.body);
|
|
77
|
+
|
|
78
|
+
// Continue with the creation
|
|
79
|
+
const createdData = await this.model.create(req.body);
|
|
80
|
+
await this.cache.flush();
|
|
81
|
+
|
|
82
|
+
console.log(`[MusicController] Record created successfully:`, createdData._id);
|
|
83
|
+
|
|
84
|
+
res.status(201).json(createdData);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error(`[MusicController] Error creating record:`, error);
|
|
87
|
+
this.logger.error(`Error creating ${this.model.collection.collectionName}: ${error.message}`);
|
|
88
|
+
res.status(500).json({ error: error.message });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// Override the update method to check ownership
|
|
94
|
+
async update(req, res) {
|
|
95
|
+
try {
|
|
96
|
+
const resourceId = req.body._id;
|
|
97
|
+
const resource = await this.model.findById(resourceId);
|
|
98
|
+
|
|
99
|
+
if (!resource) {
|
|
100
|
+
return res.status(404).json({ error: 'Resource not found' });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check access using ABAC
|
|
104
|
+
const accessResult = await this.abac.checkAccess({
|
|
105
|
+
user: req.userId,
|
|
106
|
+
resource: this.model.collection.collectionName,
|
|
107
|
+
action: 'update',
|
|
108
|
+
data: req.body,
|
|
109
|
+
currentResource: resource
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (!accessResult.allowed) {
|
|
113
|
+
return res.status(403).json({
|
|
114
|
+
errorCode: accessResult.reason,
|
|
115
|
+
message: 'Access Denied'
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Continue with the update
|
|
120
|
+
const updatedData = await this.model.findOneAndUpdate(
|
|
121
|
+
{ _id: resourceId },
|
|
122
|
+
req.body,
|
|
123
|
+
{ new: true, runValidators: true }
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
await this.cache.flush();
|
|
127
|
+
res.json(updatedData);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
this.logger.error(`Error updating ${this.model.collection.collectionName}: ${error.message}`);
|
|
130
|
+
res.status(500).json({ error: error.message });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Override the delete method to check ownership
|
|
135
|
+
async delete(req, res) {
|
|
136
|
+
try {
|
|
137
|
+
const resourceId = req.body._id;
|
|
138
|
+
const resource = await this.model.findById(resourceId);
|
|
139
|
+
|
|
140
|
+
if (!resource) {
|
|
141
|
+
return res.status(404).json({ error: 'Resource not found' });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check access using ABAC
|
|
145
|
+
const accessResult = await this.abac.checkAccess({
|
|
146
|
+
user: req.userId,
|
|
147
|
+
resource: this.model.collection.collectionName,
|
|
148
|
+
action: 'delete',
|
|
149
|
+
data: req.body,
|
|
150
|
+
currentResource: resource
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
if (!accessResult.allowed) {
|
|
154
|
+
return res.status(403).json({
|
|
155
|
+
errorCode: accessResult.reason,
|
|
156
|
+
message: 'Access Denied'
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Continue with the deletion
|
|
161
|
+
await this.model.findOneAndDelete({ _id: resourceId });
|
|
162
|
+
await this.cache.flush();
|
|
163
|
+
res.status(204).send();
|
|
164
|
+
} catch (error) {
|
|
165
|
+
this.logger.error(`Error deleting ${this.model.collection.collectionName}: ${error.message}`);
|
|
166
|
+
res.status(500).json({ error: error.message });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
MusicController
|
|
173
|
+
};
|
|
174
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// controllers/playlist.controller.js
|
|
2
|
+
module.exports = function(app,db) {
|
|
3
|
+
const { MusicController } = require('./music.controller')(app,db);
|
|
4
|
+
|
|
5
|
+
class PlaylistController extends MusicController {
|
|
6
|
+
constructor(app, db) {
|
|
7
|
+
super('/api/playlists', app, db, db.playlist);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Add track to playlist
|
|
11
|
+
async addTrack(req, res) {
|
|
12
|
+
try {
|
|
13
|
+
const { playlistId, trackId } = req.params;
|
|
14
|
+
|
|
15
|
+
// Find the playlist
|
|
16
|
+
const playlist = await db.playlist.findById(playlistId);
|
|
17
|
+
if (!playlist) {
|
|
18
|
+
return res.status(404).json({ error: 'Playlist not found' });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check access using ABAC
|
|
22
|
+
const accessResult = await this.abac.checkAccess({
|
|
23
|
+
user: req.userId,
|
|
24
|
+
resource: 'playlists',
|
|
25
|
+
action: 'update',
|
|
26
|
+
currentResource: playlist
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (!accessResult.allowed) {
|
|
30
|
+
return res.status(403).json({
|
|
31
|
+
errorCode: accessResult.reason,
|
|
32
|
+
message: 'Access Denied'
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Check if track exists
|
|
37
|
+
const track = await db.track.findById(trackId);
|
|
38
|
+
if (!track) {
|
|
39
|
+
return res.status(404).json({ error: 'Track not found' });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Check if track is already in playlist
|
|
43
|
+
const trackExists = playlist.tracks.some(item =>
|
|
44
|
+
item.track.toString() === trackId
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (trackExists) {
|
|
48
|
+
return res.status(400).json({ error: 'Track already in playlist' });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Add track to playlist
|
|
52
|
+
playlist.tracks.push({
|
|
53
|
+
track: trackId,
|
|
54
|
+
addedAt: new Date()
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await playlist.save();
|
|
58
|
+
await this.cache.flush();
|
|
59
|
+
|
|
60
|
+
res.json(playlist);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
this.logger.error(`Error adding track to playlist: ${error.message}`);
|
|
63
|
+
res.status(500).json({ error: error.message });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Remove track from playlist
|
|
68
|
+
async removeTrack(req, res) {
|
|
69
|
+
try {
|
|
70
|
+
const { playlistId, trackId } = req.params;
|
|
71
|
+
|
|
72
|
+
// Find the playlist
|
|
73
|
+
const playlist = await db.playlist.findById(playlistId);
|
|
74
|
+
if (!playlist) {
|
|
75
|
+
return res.status(404).json({ error: 'Playlist not found' });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check access using ABAC
|
|
79
|
+
const accessResult = await this.abac.checkAccess({
|
|
80
|
+
user: req.userId,
|
|
81
|
+
resource: 'playlists',
|
|
82
|
+
action: 'update',
|
|
83
|
+
currentResource: playlist
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!accessResult.allowed) {
|
|
87
|
+
return res.status(403).json({
|
|
88
|
+
errorCode: accessResult.reason,
|
|
89
|
+
message: 'Access Denied'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Remove track from playlist
|
|
94
|
+
playlist.tracks = playlist.tracks.filter(item =>
|
|
95
|
+
item.track.toString() !== trackId
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
await playlist.save();
|
|
99
|
+
await this.cache.flush();
|
|
100
|
+
|
|
101
|
+
res.json(playlist);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
this.logger.error(`Error removing track from playlist: ${error.message}`);
|
|
104
|
+
res.status(500).json({ error: error.message });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Get user playlists
|
|
109
|
+
async getUserPlaylists(req, res) {
|
|
110
|
+
try {
|
|
111
|
+
const userId = req.params.userId || req.userId;
|
|
112
|
+
|
|
113
|
+
// Get playlists where user is owner or collaborator
|
|
114
|
+
const playlists = await db.playlist.find({
|
|
115
|
+
$or: [
|
|
116
|
+
{ 'owner.target': userId, 'owner.type': 'User' },
|
|
117
|
+
{ collaborators: userId }
|
|
118
|
+
]
|
|
119
|
+
}).sort({ updatedAt: -1 });
|
|
120
|
+
|
|
121
|
+
res.json(playlists);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
this.logger.error(`Error getting user playlists: ${error.message}`);
|
|
124
|
+
res.status(500).json({ error: error.message });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Add collaborator to playlist
|
|
129
|
+
async addCollaborator(req, res) {
|
|
130
|
+
try {
|
|
131
|
+
const { playlistId, userId } = req.params;
|
|
132
|
+
|
|
133
|
+
// Find the playlist
|
|
134
|
+
const playlist = await db.playlist.findById(playlistId);
|
|
135
|
+
if (!playlist) {
|
|
136
|
+
return res.status(404).json({ error: 'Playlist not found' });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Only owner can add collaborators
|
|
140
|
+
if (playlist.owner.target.toString() !== req.userId) {
|
|
141
|
+
return res.status(403).json({ error: 'Only playlist owner can add collaborators' });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check if user exists
|
|
145
|
+
const user = await db.mongoose.model('User').findById(userId);
|
|
146
|
+
if (!user) {
|
|
147
|
+
return res.status(404).json({ error: 'User not found' });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Check if user is already a collaborator
|
|
151
|
+
if (playlist.collaborators.includes(userId)) {
|
|
152
|
+
return res.status(400).json({ error: 'User is already a collaborator' });
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Add collaborator
|
|
156
|
+
playlist.collaborators.push(userId);
|
|
157
|
+
playlist.isCollaborative = true;
|
|
158
|
+
|
|
159
|
+
await playlist.save();
|
|
160
|
+
await this.cache.flush();
|
|
161
|
+
|
|
162
|
+
res.json(playlist);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
this.logger.error(`Error adding collaborator to playlist: ${error.message}`);
|
|
165
|
+
res.status(500).json({ error: error.message });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const playlistController = new PlaylistController(app,db);
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
create: playlistController.create.bind(playlistController),
|
|
174
|
+
read: playlistController.read.bind(playlistController),
|
|
175
|
+
update: playlistController.update.bind(playlistController),
|
|
176
|
+
delete: playlistController.delete.bind(playlistController),
|
|
177
|
+
addTrack: playlistController.addTrack.bind(playlistController),
|
|
178
|
+
removeTrack: playlistController.removeTrack.bind(playlistController),
|
|
179
|
+
getUserPlaylists: playlistController.getUserPlaylists.bind(playlistController),
|
|
180
|
+
addCollaborator: playlistController.addCollaborator.bind(playlistController)
|
|
181
|
+
};
|
|
182
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// controllers/search.controller.js
|
|
2
|
+
module.exports = function(app,db) {
|
|
3
|
+
const Logger = require('@martyrs/src/modules/globals/controllers/classes/globals.logger');
|
|
4
|
+
const Cache = require('@martyrs/src/modules/globals/controllers/classes/globals.cache');
|
|
5
|
+
|
|
6
|
+
const logger = new Logger(db);
|
|
7
|
+
const cache = new Cache();
|
|
8
|
+
|
|
9
|
+
// Search across all music entities
|
|
10
|
+
async function search(req, res) {
|
|
11
|
+
try {
|
|
12
|
+
const { query, type, limit = 10 } = req.query;
|
|
13
|
+
|
|
14
|
+
if (!query || query.length < 2) {
|
|
15
|
+
return res.status(400).json({ error: 'Search query must be at least 2 characters' });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const limitNum = parseInt(limit, 10);
|
|
19
|
+
const cacheKey = `search:${query}:${type || 'all'}:${limitNum}`;
|
|
20
|
+
|
|
21
|
+
// Try to get from cache first
|
|
22
|
+
let results = await cache.get(cacheKey);
|
|
23
|
+
|
|
24
|
+
if (!results) {
|
|
25
|
+
results = {};
|
|
26
|
+
|
|
27
|
+
// Create text search regex
|
|
28
|
+
const searchRegex = new RegExp(query, 'i');
|
|
29
|
+
|
|
30
|
+
// Filter queries based on type
|
|
31
|
+
const types = type ? [type] : ['tracks', 'albums', 'artists', 'playlists', 'genres'];
|
|
32
|
+
|
|
33
|
+
// Perform search for each requested type
|
|
34
|
+
if (types.includes('tracks') || types.includes('all')) {
|
|
35
|
+
results.tracks = await db.track.find({
|
|
36
|
+
$or: [
|
|
37
|
+
{ title: searchRegex },
|
|
38
|
+
{ tags: searchRegex }
|
|
39
|
+
],
|
|
40
|
+
status: 'published',
|
|
41
|
+
isPublic: true
|
|
42
|
+
}).limit(limitNum);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (types.includes('albums') || types.includes('all')) {
|
|
46
|
+
results.albums = await db.album.find({
|
|
47
|
+
$or: [
|
|
48
|
+
{ title: searchRegex },
|
|
49
|
+
{ description: searchRegex },
|
|
50
|
+
{ tags: searchRegex }
|
|
51
|
+
],
|
|
52
|
+
status: 'published',
|
|
53
|
+
isPublic: true
|
|
54
|
+
}).limit(limitNum);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (types.includes('artists') || types.includes('all')) {
|
|
58
|
+
results.artists = await db.artist.find({
|
|
59
|
+
$or: [
|
|
60
|
+
{ name: searchRegex },
|
|
61
|
+
{ bio: searchRegex },
|
|
62
|
+
{ tags: searchRegex }
|
|
63
|
+
],
|
|
64
|
+
status: 'published'
|
|
65
|
+
}).limit(limitNum);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (types.includes('playlists') || types.includes('all')) {
|
|
69
|
+
results.playlists = await db.playlist.find({
|
|
70
|
+
$or: [
|
|
71
|
+
{ title: searchRegex },
|
|
72
|
+
{ description: searchRegex },
|
|
73
|
+
{ tags: searchRegex }
|
|
74
|
+
],
|
|
75
|
+
isPublic: true
|
|
76
|
+
}).limit(limitNum);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (types.includes('genres') || types.includes('all')) {
|
|
80
|
+
results.genres = await db.genre.find({
|
|
81
|
+
$or: [
|
|
82
|
+
{ name: searchRegex },
|
|
83
|
+
{ description: searchRegex }
|
|
84
|
+
],
|
|
85
|
+
status: 'published'
|
|
86
|
+
}).limit(limitNum);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Cache results for 10 minutes
|
|
90
|
+
await cache.set(cacheKey, results, 600);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
res.json(results);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
logger.error(`Error searching: ${error.message}`);
|
|
96
|
+
res.status(500).json({ error: error.message });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
search
|
|
102
|
+
};
|
|
103
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// controllers/stream.controller.js
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
module.exports = function(app,db,publicPath) {
|
|
6
|
+
const Logger = require('@martyrs/src/modules/globals/controllers/classes/globals.logger');
|
|
7
|
+
const { getInstance } = require('@martyrs/src/modules/globals/controllers/classes/globals.abac.js');
|
|
8
|
+
|
|
9
|
+
const logger = new Logger(db);
|
|
10
|
+
const abac = getInstance(db);
|
|
11
|
+
|
|
12
|
+
// Stream track audio
|
|
13
|
+
async function streamAudio(req, res) {
|
|
14
|
+
try {
|
|
15
|
+
const trackId = req.params.trackId;
|
|
16
|
+
|
|
17
|
+
// Find track
|
|
18
|
+
const track = await db.track.findById(trackId);
|
|
19
|
+
if (!track) {
|
|
20
|
+
return res.status(404).json({ error: 'Track not found' });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check access using ABAC
|
|
24
|
+
const accessResult = await abac.checkAccess({
|
|
25
|
+
user: req.userId,
|
|
26
|
+
resource: 'tracks',
|
|
27
|
+
action: 'read',
|
|
28
|
+
currentResource: track
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!accessResult.allowed && !track.isPublic) {
|
|
32
|
+
return res.status(403).json({
|
|
33
|
+
errorCode: accessResult.reason,
|
|
34
|
+
message: 'Access Denied'
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Extract file path from fileUrl
|
|
39
|
+
const fileUrl = track.fileUrl;
|
|
40
|
+
console.log('public is', publicPath)
|
|
41
|
+
const filePath = path.join(publicPath, fileUrl);
|
|
42
|
+
|
|
43
|
+
// Check if file exists
|
|
44
|
+
if (!fs.existsSync(filePath)) {
|
|
45
|
+
logger.error(`File not found: ${filePath}`);
|
|
46
|
+
return res.status(404).json({ error: 'Audio file not found' });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Get file stats
|
|
50
|
+
const stat = fs.statSync(filePath);
|
|
51
|
+
const fileSize = stat.size;
|
|
52
|
+
const range = req.headers.range;
|
|
53
|
+
|
|
54
|
+
// Log play history if user is authenticated
|
|
55
|
+
if (req.userId) {
|
|
56
|
+
try {
|
|
57
|
+
await db.playHistory.create({
|
|
58
|
+
user: req.userId,
|
|
59
|
+
track: trackId,
|
|
60
|
+
playedAt: new Date(),
|
|
61
|
+
deviceInfo: req.headers['user-agent'],
|
|
62
|
+
playedFrom: req.query.from || 'other',
|
|
63
|
+
contextId: req.query.contextId || null
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Increment playCount
|
|
67
|
+
await db.track.findByIdAndUpdate(trackId, { $inc: { playCount: 1 } });
|
|
68
|
+
} catch (error) {
|
|
69
|
+
logger.error(`Error logging play history: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Handle range requests for audio streaming
|
|
74
|
+
if (range) {
|
|
75
|
+
const parts = range.replace(/bytes=/, '').split('-');
|
|
76
|
+
const start = parseInt(parts[0], 10);
|
|
77
|
+
const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
|
|
78
|
+
const chunksize = (end - start) + 1;
|
|
79
|
+
const file = fs.createReadStream(filePath, { start, end });
|
|
80
|
+
|
|
81
|
+
res.writeHead(206, {
|
|
82
|
+
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
|
|
83
|
+
'Accept-Ranges': 'bytes',
|
|
84
|
+
'Content-Length': chunksize,
|
|
85
|
+
'Content-Type': 'audio/mpeg'
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
file.pipe(res);
|
|
89
|
+
} else {
|
|
90
|
+
res.writeHead(200, {
|
|
91
|
+
'Content-Length': fileSize,
|
|
92
|
+
'Content-Type': 'audio/mpeg'
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
fs.createReadStream(filePath).pipe(res);
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
logger.error(`Error streaming audio: ${error.message}`);
|
|
99
|
+
res.status(500).json({ error: error.message });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
streamAudio
|
|
105
|
+
};
|
|
106
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const applyOwnershipSchema = require('@martyrs/src/modules/globals/models/schemas/ownership.schema.js');
|
|
2
|
+
const applyMetadataSchema = require('@martyrs/src/modules/globals/models/schemas/metadata.schema.js');
|
|
3
|
+
const applyCommonSchema = require('@martyrs/src/modules/globals/models/schemas/common.schema.js');
|
|
4
|
+
const applyEngagementSchema = require('@martyrs/src/modules/globals/models/schemas/engagement.schema.js');
|
|
5
|
+
|
|
6
|
+
module.exports = function(db) {
|
|
7
|
+
const albumSchema = new db.mongoose.Schema({
|
|
8
|
+
title: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true
|
|
11
|
+
},
|
|
12
|
+
description: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: ''
|
|
15
|
+
},
|
|
16
|
+
releaseDate: {
|
|
17
|
+
type: Date,
|
|
18
|
+
required: true
|
|
19
|
+
},
|
|
20
|
+
coverArt: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: null
|
|
23
|
+
},
|
|
24
|
+
artists: [{
|
|
25
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
26
|
+
ref: 'Artist',
|
|
27
|
+
required: true
|
|
28
|
+
}],
|
|
29
|
+
type: {
|
|
30
|
+
type: String,
|
|
31
|
+
enum: ['album', 'single', 'EP', 'compilation'],
|
|
32
|
+
default: 'album'
|
|
33
|
+
},
|
|
34
|
+
genres: [{
|
|
35
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
36
|
+
ref: 'Genre'
|
|
37
|
+
}],
|
|
38
|
+
totalTracks: {
|
|
39
|
+
type: Number,
|
|
40
|
+
default: 0
|
|
41
|
+
}
|
|
42
|
+
}, {
|
|
43
|
+
timestamps: true,
|
|
44
|
+
versionKey: false
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Apply global schemas
|
|
48
|
+
applyOwnershipSchema(albumSchema, db);
|
|
49
|
+
applyMetadataSchema(albumSchema, db);
|
|
50
|
+
applyCommonSchema(albumSchema, db);
|
|
51
|
+
applyEngagementSchema(albumSchema, db);
|
|
52
|
+
|
|
53
|
+
// Indexing
|
|
54
|
+
albumSchema.index({ title: 'text', description: 'text' });
|
|
55
|
+
albumSchema.index({ 'artists': 1 });
|
|
56
|
+
albumSchema.index({ 'releaseDate': -1 });
|
|
57
|
+
albumSchema.index({ 'type': 1 });
|
|
58
|
+
albumSchema.index({ 'genres': 1 });
|
|
59
|
+
|
|
60
|
+
return db.mongoose.models.Album || db.mongoose.model('Album', albumSchema);
|
|
61
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// models/artist.model.js
|
|
2
|
+
module.exports = function(db) {
|
|
3
|
+
const mongoose = db.mongoose;
|
|
4
|
+
const Schema = mongoose.Schema;
|
|
5
|
+
|
|
6
|
+
// Apply common schemas
|
|
7
|
+
const applyCommonSchema = require('@martyrs/src/modules/globals/models/schemas/common.schema.js');
|
|
8
|
+
const applyMetadataSchema = require('@martyrs/src/modules/globals/models/schemas/metadata.schema.js');
|
|
9
|
+
const applyOwnershipSchema = require('@martyrs/src/modules/globals/models/schemas/ownership.schema.js');
|
|
10
|
+
const applySocialsSchema = require('@martyrs/src/modules/globals/models/schemas/socials.schema.js');
|
|
11
|
+
const applyEngagementSchema = require('@martyrs/src/modules/globals/models/schemas/engagement.schema.js');
|
|
12
|
+
|
|
13
|
+
const ArtistSchema = new Schema({
|
|
14
|
+
name: {
|
|
15
|
+
type: String,
|
|
16
|
+
required: true,
|
|
17
|
+
trim: true
|
|
18
|
+
},
|
|
19
|
+
bio: {
|
|
20
|
+
type: String,
|
|
21
|
+
trim: true
|
|
22
|
+
},
|
|
23
|
+
photoUrl: {
|
|
24
|
+
type: String
|
|
25
|
+
},
|
|
26
|
+
coverUrl: {
|
|
27
|
+
type: String
|
|
28
|
+
},
|
|
29
|
+
genre: [{
|
|
30
|
+
type: Schema.Types.ObjectId,
|
|
31
|
+
ref: 'Genre'
|
|
32
|
+
}],
|
|
33
|
+
isVerified: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
37
|
+
website: {
|
|
38
|
+
type: String,
|
|
39
|
+
trim: true
|
|
40
|
+
},
|
|
41
|
+
location: {
|
|
42
|
+
type: String,
|
|
43
|
+
trim: true
|
|
44
|
+
},
|
|
45
|
+
popularity: {
|
|
46
|
+
type: Number,
|
|
47
|
+
default: 0
|
|
48
|
+
}
|
|
49
|
+
}, {
|
|
50
|
+
timestamps: true,
|
|
51
|
+
versionKey: false
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Apply common schemas
|
|
55
|
+
applyCommonSchema(ArtistSchema, db);
|
|
56
|
+
applyMetadataSchema(ArtistSchema, db);
|
|
57
|
+
applyOwnershipSchema(ArtistSchema, db);
|
|
58
|
+
applySocialsSchema(ArtistSchema, db);
|
|
59
|
+
applyEngagementSchema(ArtistSchema, db);
|
|
60
|
+
|
|
61
|
+
// Create indexes
|
|
62
|
+
ArtistSchema.index({ name: 'text', bio: 'text' });
|
|
63
|
+
ArtistSchema.index({ popularity: -1 });
|
|
64
|
+
ArtistSchema.index({ isVerified: 1 });
|
|
65
|
+
|
|
66
|
+
return mongoose.models.Artist || mongoose.model('Artist', ArtistSchema);
|
|
67
|
+
};
|