@wwdrew/expo-apple-music 1.0.0
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/ATTRIBUTION.md +24 -0
- package/LICENSE +190 -0
- package/NOTICE +7 -0
- package/README.md +81 -0
- package/android/build.gradle +26 -0
- package/android/libs/mediaplayback-release-1.1.1.aar +0 -0
- package/android/libs/musickitauth-release-1.1.2.aar +0 -0
- package/android/src/main/AndroidManifest.xml +16 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidCatalogService.kt +86 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidDeveloperToken.kt +39 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidHistoryService.kt +24 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidLibraryMutationsService.kt +30 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidLibraryService.kt +61 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidPlaybackController.kt +484 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidPlaybackObserver.kt +173 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidQueueService.kt +78 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidRatingsService.kt +27 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidRecommendationsService.kt +15 -0
- package/android/src/main/java/expo/modules/applemusic/AndroidSubscriptionService.kt +24 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicErrorCodes.kt +13 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicErrors.kt +46 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicHttpMethod.kt +8 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicJsonMapper.kt +258 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicNativeLoader.kt +32 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicRestJson.kt +40 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicRestQuery.kt +12 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicRestStack.kt +19 -0
- package/android/src/main/java/expo/modules/applemusic/AppleMusicRestTransport.kt +118 -0
- package/android/src/main/java/expo/modules/applemusic/AuthenticatedSession.kt +57 -0
- package/android/src/main/java/expo/modules/applemusic/BridgeResponses.kt +55 -0
- package/android/src/main/java/expo/modules/applemusic/CatalogRestClient.kt +306 -0
- package/android/src/main/java/expo/modules/applemusic/ExpoAppleMusicModule.kt +152 -0
- package/android/src/main/java/expo/modules/applemusic/HistoryRestClient.kt +60 -0
- package/android/src/main/java/expo/modules/applemusic/LibraryIds.kt +6 -0
- package/android/src/main/java/expo/modules/applemusic/LibraryMutationsRestClient.kt +95 -0
- package/android/src/main/java/expo/modules/applemusic/LibraryRestClient.kt +195 -0
- package/android/src/main/java/expo/modules/applemusic/MusicKitAuthContract.kt +78 -0
- package/android/src/main/java/expo/modules/applemusic/MusicKitAuthStorage.kt +76 -0
- package/android/src/main/java/expo/modules/applemusic/MusicKitTokenProvider.kt +13 -0
- package/android/src/main/java/expo/modules/applemusic/PaginationOptions.kt +14 -0
- package/android/src/main/java/expo/modules/applemusic/RatingsRestClient.kt +72 -0
- package/android/src/main/java/expo/modules/applemusic/RecommendationsRestClient.kt +37 -0
- package/android/src/main/java/expo/modules/applemusic/StorefrontRestClient.kt +44 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeAuth.kt +69 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeCatalog.kt +76 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeHistory.kt +35 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeLibrary.kt +54 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeLibraryMutations.kt +30 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgePlayer.kt +89 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeRatings.kt +29 -0
- package/android/src/main/java/expo/modules/applemusic/bridge/ExpoBridgeRecommendations.kt +18 -0
- package/app.plugin.js +1 -0
- package/build/ExpoAppleMusicModule.web.d.ts +15 -0
- package/build/ExpoAppleMusicModule.web.d.ts.map +1 -0
- package/build/ExpoAppleMusicModule.web.js +33 -0
- package/build/ExpoAppleMusicModule.web.js.map +1 -0
- package/build/api/call-native.d.ts +6 -0
- package/build/api/call-native.d.ts.map +1 -0
- package/build/api/call-native.js +35 -0
- package/build/api/call-native.js.map +1 -0
- package/build/api/decode-jwt-exp.d.ts +5 -0
- package/build/api/decode-jwt-exp.d.ts.map +1 -0
- package/build/api/decode-jwt-exp.js +28 -0
- package/build/api/decode-jwt-exp.js.map +1 -0
- package/build/api/library-ids.d.ts +4 -0
- package/build/api/library-ids.d.ts.map +1 -0
- package/build/api/library-ids.js +11 -0
- package/build/api/library-ids.js.map +1 -0
- package/build/api/pagination.d.ts +12 -0
- package/build/api/pagination.d.ts.map +1 -0
- package/build/api/pagination.js +13 -0
- package/build/api/pagination.js.map +1 -0
- package/build/api/parse-authorize-result.d.ts +3 -0
- package/build/api/parse-authorize-result.d.ts.map +1 -0
- package/build/api/parse-authorize-result.js +27 -0
- package/build/api/parse-authorize-result.js.map +1 -0
- package/build/api/require-music-user-token.d.ts +2 -0
- package/build/api/require-music-user-token.d.ts.map +1 -0
- package/build/api/require-music-user-token.js +14 -0
- package/build/api/require-music-user-token.js.map +1 -0
- package/build/api/sync-developer-token.d.ts +4 -0
- package/build/api/sync-developer-token.d.ts.map +1 -0
- package/build/api/sync-developer-token.js +27 -0
- package/build/api/sync-developer-token.js.map +1 -0
- package/build/bridge/bridge-methods.d.ts +17 -0
- package/build/bridge/bridge-methods.d.ts.map +1 -0
- package/build/bridge/bridge-methods.js +71 -0
- package/build/bridge/bridge-methods.js.map +1 -0
- package/build/bridge/bridge-responses.d.ts +64 -0
- package/build/bridge/bridge-responses.d.ts.map +1 -0
- package/build/bridge/bridge-responses.js +67 -0
- package/build/bridge/bridge-responses.js.map +1 -0
- package/build/bridge/handlers/auth-bridge.d.ts +11 -0
- package/build/bridge/handlers/auth-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/auth-bridge.js +49 -0
- package/build/bridge/handlers/auth-bridge.js.map +1 -0
- package/build/bridge/handlers/catalog-bridge.d.ts +34 -0
- package/build/bridge/handlers/catalog-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/catalog-bridge.js +58 -0
- package/build/bridge/handlers/catalog-bridge.js.map +1 -0
- package/build/bridge/handlers/history-bridge.d.ts +19 -0
- package/build/bridge/handlers/history-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/history-bridge.js +31 -0
- package/build/bridge/handlers/history-bridge.js.map +1 -0
- package/build/bridge/handlers/index.d.ts +124 -0
- package/build/bridge/handlers/index.d.ts.map +1 -0
- package/build/bridge/handlers/index.js +21 -0
- package/build/bridge/handlers/index.js.map +1 -0
- package/build/bridge/handlers/library-bridge.d.ts +23 -0
- package/build/bridge/handlers/library-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/library-bridge.js +41 -0
- package/build/bridge/handlers/library-bridge.js.map +1 -0
- package/build/bridge/handlers/library-mutations-bridge.d.ts +16 -0
- package/build/bridge/handlers/library-mutations-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/library-mutations-bridge.js +20 -0
- package/build/bridge/handlers/library-mutations-bridge.js.map +1 -0
- package/build/bridge/handlers/player-bridge.d.ts +18 -0
- package/build/bridge/handlers/player-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/player-bridge.js +42 -0
- package/build/bridge/handlers/player-bridge.js.map +1 -0
- package/build/bridge/handlers/ratings-bridge.d.ts +15 -0
- package/build/bridge/handlers/ratings-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/ratings-bridge.js +16 -0
- package/build/bridge/handlers/ratings-bridge.js.map +1 -0
- package/build/bridge/handlers/recommendations-bridge.d.ts +10 -0
- package/build/bridge/handlers/recommendations-bridge.d.ts.map +1 -0
- package/build/bridge/handlers/recommendations-bridge.js +14 -0
- package/build/bridge/handlers/recommendations-bridge.js.map +1 -0
- package/build/constants/apple-music-error-codes.d.ts +22 -0
- package/build/constants/apple-music-error-codes.d.ts.map +1 -0
- package/build/constants/apple-music-error-codes.js +21 -0
- package/build/constants/apple-music-error-codes.js.map +1 -0
- package/build/hooks/use-current-song.d.ts +10 -0
- package/build/hooks/use-current-song.d.ts.map +1 -0
- package/build/hooks/use-current-song.js +35 -0
- package/build/hooks/use-current-song.js.map +1 -0
- package/build/hooks/use-is-playing.d.ts +6 -0
- package/build/hooks/use-is-playing.d.ts.map +1 -0
- package/build/hooks/use-is-playing.js +21 -0
- package/build/hooks/use-is-playing.js.map +1 -0
- package/build/hooks/use-playback-state.d.ts +12 -0
- package/build/hooks/use-playback-state.d.ts.map +1 -0
- package/build/hooks/use-playback-state.js +41 -0
- package/build/hooks/use-playback-state.js.map +1 -0
- package/build/index.d.ts +52 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +44 -0
- package/build/index.js.map +1 -0
- package/build/mappers/apple-music-json-mapper.d.ts +94 -0
- package/build/mappers/apple-music-json-mapper.d.ts.map +1 -0
- package/build/mappers/apple-music-json-mapper.js +212 -0
- package/build/mappers/apple-music-json-mapper.js.map +1 -0
- package/build/modules/auth.d.ts +32 -0
- package/build/modules/auth.d.ts.map +1 -0
- package/build/modules/auth.js +60 -0
- package/build/modules/auth.js.map +1 -0
- package/build/modules/catalog.d.ts +46 -0
- package/build/modules/catalog.d.ts.map +1 -0
- package/build/modules/catalog.js +47 -0
- package/build/modules/catalog.js.map +1 -0
- package/build/modules/history.d.ts +17 -0
- package/build/modules/history.d.ts.map +1 -0
- package/build/modules/history.js +28 -0
- package/build/modules/history.js.map +1 -0
- package/build/modules/library-mutations.d.ts +9 -0
- package/build/modules/library-mutations.d.ts.map +1 -0
- package/build/modules/library-mutations.js +41 -0
- package/build/modules/library-mutations.js.map +1 -0
- package/build/modules/library.d.ts +21 -0
- package/build/modules/library.d.ts.map +1 -0
- package/build/modules/library.js +38 -0
- package/build/modules/library.js.map +1 -0
- package/build/modules/player.d.ts +53 -0
- package/build/modules/player.d.ts.map +1 -0
- package/build/modules/player.js +68 -0
- package/build/modules/player.js.map +1 -0
- package/build/modules/ratings.d.ts +10 -0
- package/build/modules/ratings.d.ts.map +1 -0
- package/build/modules/ratings.js +37 -0
- package/build/modules/ratings.js.map +1 -0
- package/build/modules/recommendations.d.ts +7 -0
- package/build/modules/recommendations.d.ts.map +1 -0
- package/build/modules/recommendations.js +15 -0
- package/build/modules/recommendations.js.map +1 -0
- package/build/native-module.d.ts +5 -0
- package/build/native-module.d.ts.map +1 -0
- package/build/native-module.js +5 -0
- package/build/native-module.js.map +1 -0
- package/build/native-module.web.d.ts +11 -0
- package/build/native-module.web.d.ts.map +1 -0
- package/build/native-module.web.js +11 -0
- package/build/native-module.web.js.map +1 -0
- package/build/rest/apple-music-rest-stack.d.ts +21 -0
- package/build/rest/apple-music-rest-stack.d.ts.map +1 -0
- package/build/rest/apple-music-rest-stack.js +21 -0
- package/build/rest/apple-music-rest-stack.js.map +1 -0
- package/build/rest/apple-music-rest-transport.d.ts +8 -0
- package/build/rest/apple-music-rest-transport.d.ts.map +1 -0
- package/build/rest/apple-music-rest-transport.js +2 -0
- package/build/rest/apple-music-rest-transport.js.map +1 -0
- package/build/rest/catalog-rest-client.d.ts +38 -0
- package/build/rest/catalog-rest-client.d.ts.map +1 -0
- package/build/rest/catalog-rest-client.js +189 -0
- package/build/rest/catalog-rest-client.js.map +1 -0
- package/build/rest/history-rest-client.d.ts +37 -0
- package/build/rest/history-rest-client.d.ts.map +1 -0
- package/build/rest/history-rest-client.js +30 -0
- package/build/rest/history-rest-client.js.map +1 -0
- package/build/rest/library-ids.d.ts +2 -0
- package/build/rest/library-ids.d.ts.map +1 -0
- package/build/rest/library-ids.js +2 -0
- package/build/rest/library-ids.js.map +1 -0
- package/build/rest/library-mutations-rest-client.d.ts +22 -0
- package/build/rest/library-mutations-rest-client.d.ts.map +1 -0
- package/build/rest/library-mutations-rest-client.js +37 -0
- package/build/rest/library-mutations-rest-client.js.map +1 -0
- package/build/rest/library-rest-client.d.ts +59 -0
- package/build/rest/library-rest-client.d.ts.map +1 -0
- package/build/rest/library-rest-client.js +141 -0
- package/build/rest/library-rest-client.js.map +1 -0
- package/build/rest/ratings-rest-client.d.ts +18 -0
- package/build/rest/ratings-rest-client.d.ts.map +1 -0
- package/build/rest/ratings-rest-client.js +37 -0
- package/build/rest/ratings-rest-client.js.map +1 -0
- package/build/rest/recommendations-rest-client.d.ts +32 -0
- package/build/rest/recommendations-rest-client.d.ts.map +1 -0
- package/build/rest/recommendations-rest-client.js +26 -0
- package/build/rest/recommendations-rest-client.js.map +1 -0
- package/build/rest/resource-ids-query.d.ts +2 -0
- package/build/rest/resource-ids-query.d.ts.map +1 -0
- package/build/rest/resource-ids-query.js +10 -0
- package/build/rest/resource-ids-query.js.map +1 -0
- package/build/rest/rest-json.d.ts +11 -0
- package/build/rest/rest-json.d.ts.map +1 -0
- package/build/rest/rest-json.js +29 -0
- package/build/rest/rest-json.js.map +1 -0
- package/build/rest/storefront-rest-client.d.ts +14 -0
- package/build/rest/storefront-rest-client.d.ts.map +1 -0
- package/build/rest/storefront-rest-client.js +36 -0
- package/build/rest/storefront-rest-client.js.map +1 -0
- package/build/types/album.d.ts +8 -0
- package/build/types/album.d.ts.map +1 -0
- package/build/types/album.js +2 -0
- package/build/types/album.js.map +1 -0
- package/build/types/albums-response.d.ts +5 -0
- package/build/types/albums-response.d.ts.map +1 -0
- package/build/types/albums-response.js +2 -0
- package/build/types/albums-response.js.map +1 -0
- package/build/types/android-authorize-options.d.ts +18 -0
- package/build/types/android-authorize-options.d.ts.map +1 -0
- package/build/types/android-authorize-options.js +2 -0
- package/build/types/android-authorize-options.js.map +1 -0
- package/build/types/artist.d.ts +9 -0
- package/build/types/artist.d.ts.map +1 -0
- package/build/types/artist.js +2 -0
- package/build/types/artist.js.map +1 -0
- package/build/types/auth-status.d.ts +19 -0
- package/build/types/auth-status.d.ts.map +1 -0
- package/build/types/auth-status.js +18 -0
- package/build/types/auth-status.js.map +1 -0
- package/build/types/authorize-result.d.ts +8 -0
- package/build/types/authorize-result.d.ts.map +1 -0
- package/build/types/authorize-result.js +2 -0
- package/build/types/authorize-result.js.map +1 -0
- package/build/types/catalog-album-tracks.d.ts +5 -0
- package/build/types/catalog-album-tracks.d.ts.map +1 -0
- package/build/types/catalog-album-tracks.js +2 -0
- package/build/types/catalog-album-tracks.js.map +1 -0
- package/build/types/catalog-charts.d.ts +25 -0
- package/build/types/catalog-charts.d.ts.map +1 -0
- package/build/types/catalog-charts.js +7 -0
- package/build/types/catalog-charts.js.map +1 -0
- package/build/types/catalog-resource-type.d.ts +11 -0
- package/build/types/catalog-resource-type.d.ts.map +1 -0
- package/build/types/catalog-resource-type.js +10 -0
- package/build/types/catalog-resource-type.js.map +1 -0
- package/build/types/catalog-search.d.ts +24 -0
- package/build/types/catalog-search.d.ts.map +1 -0
- package/build/types/catalog-search.js +9 -0
- package/build/types/catalog-search.js.map +1 -0
- package/build/types/check-subscription.d.ts +31 -0
- package/build/types/check-subscription.d.ts.map +1 -0
- package/build/types/check-subscription.js +5 -0
- package/build/types/check-subscription.js.map +1 -0
- package/build/types/library-music-videos.d.ts +5 -0
- package/build/types/library-music-videos.d.ts.map +1 -0
- package/build/types/library-music-videos.js +2 -0
- package/build/types/library-music-videos.js.map +1 -0
- package/build/types/library-mutations.d.ts +21 -0
- package/build/types/library-mutations.d.ts.map +1 -0
- package/build/types/library-mutations.js +8 -0
- package/build/types/library-mutations.js.map +1 -0
- package/build/types/library-search.d.ts +22 -0
- package/build/types/library-search.d.ts.map +1 -0
- package/build/types/library-search.js +9 -0
- package/build/types/library-search.js.map +1 -0
- package/build/types/music-item.d.ts +8 -0
- package/build/types/music-item.d.ts.map +1 -0
- package/build/types/music-item.js +7 -0
- package/build/types/music-item.js.map +1 -0
- package/build/types/music-video.d.ts +8 -0
- package/build/types/music-video.d.ts.map +1 -0
- package/build/types/music-video.js +2 -0
- package/build/types/music-video.js.map +1 -0
- package/build/types/pagination.d.ts +11 -0
- package/build/types/pagination.d.ts.map +1 -0
- package/build/types/pagination.js +2 -0
- package/build/types/pagination.js.map +1 -0
- package/build/types/playback-state.d.ts +9 -0
- package/build/types/playback-state.d.ts.map +1 -0
- package/build/types/playback-state.js +2 -0
- package/build/types/playback-state.js.map +1 -0
- package/build/types/playback-status.d.ts +10 -0
- package/build/types/playback-status.d.ts.map +1 -0
- package/build/types/playback-status.js +9 -0
- package/build/types/playback-status.js.map +1 -0
- package/build/types/playlist.d.ts +15 -0
- package/build/types/playlist.d.ts.map +1 -0
- package/build/types/playlist.js +2 -0
- package/build/types/playlist.js.map +1 -0
- package/build/types/rating.d.ts +34 -0
- package/build/types/rating.d.ts.map +1 -0
- package/build/types/rating.js +26 -0
- package/build/types/rating.js.map +1 -0
- package/build/types/recent-resource.d.ts +11 -0
- package/build/types/recent-resource.d.ts.map +1 -0
- package/build/types/recent-resource.js +2 -0
- package/build/types/recent-resource.js.map +1 -0
- package/build/types/recommendation.d.ts +37 -0
- package/build/types/recommendation.d.ts.map +1 -0
- package/build/types/recommendation.js +2 -0
- package/build/types/recommendation.js.map +1 -0
- package/build/types/song.d.ts +8 -0
- package/build/types/song.d.ts.map +1 -0
- package/build/types/song.js +2 -0
- package/build/types/song.js.map +1 -0
- package/build/types/station.d.ts +9 -0
- package/build/types/station.d.ts.map +1 -0
- package/build/types/station.js +2 -0
- package/build/types/station.js.map +1 -0
- package/build/types/storefront.d.ts +4 -0
- package/build/types/storefront.d.ts.map +1 -0
- package/build/types/storefront.js +2 -0
- package/build/types/storefront.js.map +1 -0
- package/build/types/tracks-from-library.d.ts +11 -0
- package/build/types/tracks-from-library.d.ts.map +1 -0
- package/build/types/tracks-from-library.js +2 -0
- package/build/types/tracks-from-library.js.map +1 -0
- package/build/utils/apple-music-error.d.ts +10 -0
- package/build/utils/apple-music-error.d.ts.map +1 -0
- package/build/utils/apple-music-error.js +13 -0
- package/build/utils/apple-music-error.js.map +1 -0
- package/build/utils/get-error-message.d.ts +2 -0
- package/build/utils/get-error-message.d.ts.map +1 -0
- package/build/utils/get-error-message.js +21 -0
- package/build/utils/get-error-message.js.map +1 -0
- package/build/utils/is-library-item.d.ts +2 -0
- package/build/utils/is-library-item.d.ts.map +1 -0
- package/build/utils/is-library-item.js +4 -0
- package/build/utils/is-library-item.js.map +1 -0
- package/build/utils/normalize-resource-ids.d.ts +4 -0
- package/build/utils/normalize-resource-ids.d.ts.map +1 -0
- package/build/utils/normalize-resource-ids.js +12 -0
- package/build/utils/normalize-resource-ids.js.map +1 -0
- package/build/web/MusicKitLoader.d.ts +11 -0
- package/build/web/MusicKitLoader.d.ts.map +1 -0
- package/build/web/MusicKitLoader.js +135 -0
- package/build/web/MusicKitLoader.js.map +1 -0
- package/build/web/WebAppleMusicApiClient.d.ts +151 -0
- package/build/web/WebAppleMusicApiClient.d.ts.map +1 -0
- package/build/web/WebAppleMusicApiClient.js +139 -0
- package/build/web/WebAppleMusicApiClient.js.map +1 -0
- package/build/web/WebAppleMusicRestTransport.d.ts +9 -0
- package/build/web/WebAppleMusicRestTransport.d.ts.map +1 -0
- package/build/web/WebAppleMusicRestTransport.js +31 -0
- package/build/web/WebAppleMusicRestTransport.js.map +1 -0
- package/build/web/WebPlaybackController.d.ts +12 -0
- package/build/web/WebPlaybackController.d.ts.map +1 -0
- package/build/web/WebPlaybackController.js +90 -0
- package/build/web/WebPlaybackController.js.map +1 -0
- package/build/web/WebPlaybackObserver.d.ts +22 -0
- package/build/web/WebPlaybackObserver.d.ts.map +1 -0
- package/build/web/WebPlaybackObserver.js +106 -0
- package/build/web/WebPlaybackObserver.js.map +1 -0
- package/build/web/WebQueueService.d.ts +10 -0
- package/build/web/WebQueueService.d.ts.map +1 -0
- package/build/web/WebQueueService.js +53 -0
- package/build/web/WebQueueService.js.map +1 -0
- package/build/web/WebSubscriptionService.d.ts +7 -0
- package/build/web/WebSubscriptionService.d.ts.map +1 -0
- package/build/web/WebSubscriptionService.js +24 -0
- package/build/web/WebSubscriptionService.js.map +1 -0
- package/build/web/apple-music-errors.d.ts +11 -0
- package/build/web/apple-music-errors.d.ts.map +1 -0
- package/build/web/apple-music-errors.js +31 -0
- package/build/web/apple-music-errors.js.map +1 -0
- package/build/web/extract-music-user-token.d.ts +4 -0
- package/build/web/extract-music-user-token.d.ts.map +1 -0
- package/build/web/extract-music-user-token.js +15 -0
- package/build/web/extract-music-user-token.js.map +1 -0
- package/build/web/map-auth-status.d.ts +17 -0
- package/build/web/map-auth-status.d.ts.map +1 -0
- package/build/web/map-auth-status.js +85 -0
- package/build/web/map-auth-status.js.map +1 -0
- package/build/web/music-kit-api.d.ts +18 -0
- package/build/web/music-kit-api.d.ts.map +1 -0
- package/build/web/music-kit-api.js +120 -0
- package/build/web/music-kit-api.js.map +1 -0
- package/build/web/musickit-types.d.ts +70 -0
- package/build/web/musickit-types.d.ts.map +1 -0
- package/build/web/musickit-types.js +3 -0
- package/build/web/musickit-types.js.map +1 -0
- package/build/web/pagination.d.ts +2 -0
- package/build/web/pagination.d.ts.map +1 -0
- package/build/web/pagination.js +2 -0
- package/build/web/pagination.js.map +1 -0
- package/expo-module.config.json +19 -0
- package/ios/AppleMusicBridgeError.swift +60 -0
- package/ios/AppleMusicErrorCodes.swift +11 -0
- package/ios/AppleMusicRestClient.swift +213 -0
- package/ios/AuthenticatedSession.swift +64 -0
- package/ios/BridgePagination.swift +17 -0
- package/ios/BridgeResponses.swift +82 -0
- package/ios/CatalogSearchStore.swift +13 -0
- package/ios/CatalogSearchStoreFactory.swift +31 -0
- package/ios/CatalogService.swift +307 -0
- package/ios/ExpoAppleMusic.podspec +29 -0
- package/ios/ExpoAppleMusicModule.swift +505 -0
- package/ios/HistoryService.swift +53 -0
- package/ios/LibraryMutationsService.swift +63 -0
- package/ios/LibraryService.swift +313 -0
- package/ios/MusicItemMapper.swift +171 -0
- package/ios/MusicKitAuthStorage.swift +38 -0
- package/ios/MusicKitCatalogSearchStore.swift +62 -0
- package/ios/PlaybackController.swift +201 -0
- package/ios/PlaybackObserver.swift +225 -0
- package/ios/QueueService.swift +166 -0
- package/ios/RatingsService.swift +66 -0
- package/ios/RecommendationsService.swift +34 -0
- package/ios/RestCatalogSearchStore.swift +62 -0
- package/ios/RestJsonMapper.swift +268 -0
- package/ios/StorefrontService.swift +55 -0
- package/ios/SubscriptionService.swift +119 -0
- package/ios/bridge/ExpoBridgeCatalog.swift +98 -0
- package/ios/bridge/ExpoBridgeHistory.swift +71 -0
- package/ios/bridge/ExpoBridgeLibrary.swift +93 -0
- package/ios/bridge/ExpoBridgeRecommendations.swift +28 -0
- package/package.json +89 -0
- package/plugin/build/index.d.ts +5 -0
- package/plugin/build/index.js +10 -0
- package/plugin/build/with-expo-apple-music.d.ts +10 -0
- package/plugin/build/with-expo-apple-music.js +50 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// CatalogService.swift
|
|
2
|
+
// Handles Apple Music catalog search and item fetching.
|
|
3
|
+
|
|
4
|
+
import Foundation
|
|
5
|
+
import MusicKit
|
|
6
|
+
|
|
7
|
+
@available(iOS 16.0, *)
|
|
8
|
+
final class CatalogService {
|
|
9
|
+
|
|
10
|
+
enum CatalogServiceError: LocalizedError {
|
|
11
|
+
case notFound(String)
|
|
12
|
+
case configurationRequired(String)
|
|
13
|
+
case unknownResourceType(String)
|
|
14
|
+
|
|
15
|
+
var errorDescription: String? {
|
|
16
|
+
switch self {
|
|
17
|
+
case .notFound(let item):
|
|
18
|
+
return "\(item) not found"
|
|
19
|
+
case .configurationRequired(let message):
|
|
20
|
+
return message
|
|
21
|
+
case .unknownResourceType(let type):
|
|
22
|
+
return "Unknown catalog resource type: \(type)"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// MARK: - Search
|
|
28
|
+
|
|
29
|
+
struct SearchOptions {
|
|
30
|
+
let limit: Int
|
|
31
|
+
let offset: Int
|
|
32
|
+
|
|
33
|
+
init(from dictionary: NSDictionary) {
|
|
34
|
+
limit = dictionary["limit"] as? Int ?? 25
|
|
35
|
+
offset = dictionary["offset"] as? Int ?? 0
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
init(limit: Int, offset: Int) {
|
|
39
|
+
self.limit = limit
|
|
40
|
+
self.offset = offset
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
struct SearchResult {
|
|
45
|
+
let songs: [[String: Any]]
|
|
46
|
+
let albums: [[String: Any]]
|
|
47
|
+
let artists: [[String: Any]]
|
|
48
|
+
let playlists: [[String: Any]]
|
|
49
|
+
let stations: [[String: Any]]
|
|
50
|
+
let musicVideos: [[String: Any]]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func search(term: String, types: [String], options: SearchOptions) async throws -> SearchResult {
|
|
54
|
+
try await CatalogSearchStoreFactory.search(term: term, types: types, options: options)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// MARK: - Fetch Single Items
|
|
58
|
+
|
|
59
|
+
func getSong(id: String) async throws -> [String: Any] {
|
|
60
|
+
guard let song = try await fetchSong(id: MusicItemID(id)) else {
|
|
61
|
+
throw CatalogServiceError.notFound("Song")
|
|
62
|
+
}
|
|
63
|
+
return MusicItemMapper.map(song)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func getAlbum(id: String) async throws -> [String: Any] {
|
|
67
|
+
guard let album = try await fetchAlbum(id: MusicItemID(id)) else {
|
|
68
|
+
throw CatalogServiceError.notFound("Album")
|
|
69
|
+
}
|
|
70
|
+
return MusicItemMapper.map(album)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func getArtist(id: String) async throws -> [String: Any] {
|
|
74
|
+
guard let artist = try await fetchArtist(id: MusicItemID(id)) else {
|
|
75
|
+
throw CatalogServiceError.notFound("Artist")
|
|
76
|
+
}
|
|
77
|
+
return MusicItemMapper.map(artist)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
func getPlaylist(id: String) async throws -> [String: Any] {
|
|
81
|
+
guard let playlist = try await fetchPlaylist(id: MusicItemID(id)) else {
|
|
82
|
+
throw CatalogServiceError.notFound("Playlist")
|
|
83
|
+
}
|
|
84
|
+
return MusicItemMapper.map(playlist)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
func getStation(id: String) async throws -> [String: Any] {
|
|
88
|
+
guard let station = try await fetchStation(id: MusicItemID(id)) else {
|
|
89
|
+
throw CatalogServiceError.notFound("Station")
|
|
90
|
+
}
|
|
91
|
+
return MusicItemMapper.map(station)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func getMusicVideo(id: String) async throws -> [String: Any] {
|
|
95
|
+
guard let musicVideo = try await fetchMusicVideo(id: MusicItemID(id)) else {
|
|
96
|
+
throw CatalogServiceError.notFound("Music video")
|
|
97
|
+
}
|
|
98
|
+
return MusicItemMapper.map(musicVideo)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
func getAlbumTracks(albumId: String, options: SearchOptions) async throws -> [[String: Any]] {
|
|
102
|
+
try await getCatalogRelationship(
|
|
103
|
+
path: "/albums/\(albumId)/tracks",
|
|
104
|
+
options: options,
|
|
105
|
+
typeContains: "song",
|
|
106
|
+
mapper: RestJsonMapper.mapSong
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
func getArtistAlbums(artistId: String, options: SearchOptions) async throws -> [[String: Any]] {
|
|
111
|
+
try await getCatalogRelationship(
|
|
112
|
+
path: "/artists/\(artistId)/albums",
|
|
113
|
+
options: options,
|
|
114
|
+
typeContains: "album",
|
|
115
|
+
mapper: RestJsonMapper.mapAlbum
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
func getPlaylistTracks(playlistId: String, options: SearchOptions) async throws -> [[String: Any]] {
|
|
120
|
+
try await getCatalogRelationship(
|
|
121
|
+
path: "/playlists/\(playlistId)/tracks",
|
|
122
|
+
options: options,
|
|
123
|
+
typeContains: "song",
|
|
124
|
+
mapper: RestJsonMapper.mapSong
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
struct ChartsResult {
|
|
129
|
+
let songs: [[String: Any]]
|
|
130
|
+
let albums: [[String: Any]]
|
|
131
|
+
let playlists: [[String: Any]]
|
|
132
|
+
let musicVideos: [[String: Any]]
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func getCharts(
|
|
136
|
+
types: [String],
|
|
137
|
+
options: SearchOptions,
|
|
138
|
+
genre: String?,
|
|
139
|
+
chart: String?
|
|
140
|
+
) async throws -> ChartsResult {
|
|
141
|
+
let storefront = StorefrontService.getCatalogStorefront()
|
|
142
|
+
var query: [String: String] = [
|
|
143
|
+
"types": types.isEmpty ? "songs,albums" : types.joined(separator: ","),
|
|
144
|
+
"limit": "\(options.limit)",
|
|
145
|
+
"offset": "\(options.offset)",
|
|
146
|
+
]
|
|
147
|
+
if let genre, !genre.isEmpty { query["genre"] = genre }
|
|
148
|
+
if let chart, !chart.isEmpty { query["chart"] = chart }
|
|
149
|
+
|
|
150
|
+
let json = try await AppleMusicRestClient.get(
|
|
151
|
+
path: "/v1/catalog/\(storefront)/charts",
|
|
152
|
+
query: query
|
|
153
|
+
)
|
|
154
|
+
let results = json["results"] as? [String: Any] ?? [:]
|
|
155
|
+
|
|
156
|
+
return ChartsResult(
|
|
157
|
+
songs: parseChartsEntries(results: results, key: "songs", typeContains: "song", mapper: RestJsonMapper.mapSong),
|
|
158
|
+
albums: parseChartsEntries(results: results, key: "albums", typeContains: "album", mapper: RestJsonMapper.mapAlbum),
|
|
159
|
+
playlists: parseChartsEntries(
|
|
160
|
+
results: results, key: "playlists", typeContains: "playlist", mapper: RestJsonMapper.mapPlaylist),
|
|
161
|
+
musicVideos: parseChartsEntries(
|
|
162
|
+
results: results, key: "music-videos", typeContains: "music-video", mapper: RestJsonMapper.mapMusicVideo)
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private func parseChartsEntries(
|
|
167
|
+
results: [String: Any],
|
|
168
|
+
key: String,
|
|
169
|
+
typeContains: String,
|
|
170
|
+
mapper: ([String: Any]) -> [String: Any]
|
|
171
|
+
) -> [[String: Any]] {
|
|
172
|
+
guard let charts = results[key] as? [[String: Any]] else { return [] }
|
|
173
|
+
var items: [[String: Any]] = []
|
|
174
|
+
for chart in charts {
|
|
175
|
+
guard let data = chart["data"] as? [[String: Any]] else { continue }
|
|
176
|
+
for resource in data {
|
|
177
|
+
let type = resource["type"] as? String ?? ""
|
|
178
|
+
guard type.contains(typeContains) else { continue }
|
|
179
|
+
items.append(mapper(resource))
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return items
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private func getCatalogRelationship(
|
|
186
|
+
path: String,
|
|
187
|
+
options: SearchOptions,
|
|
188
|
+
typeContains: String,
|
|
189
|
+
mapper: ([String: Any]) -> [String: Any]
|
|
190
|
+
) async throws -> [[String: Any]] {
|
|
191
|
+
let storefront = StorefrontService.getCatalogStorefront()
|
|
192
|
+
let fullPath = "/v1/catalog/\(storefront)\(path)"
|
|
193
|
+
let query = [
|
|
194
|
+
"limit": "\(options.limit)",
|
|
195
|
+
"offset": "\(options.offset)",
|
|
196
|
+
]
|
|
197
|
+
let data = try await AppleMusicRestClient.getDataArray(path: fullPath, query: query)
|
|
198
|
+
return data.compactMap { resource in
|
|
199
|
+
let type = resource["type"] as? String ?? ""
|
|
200
|
+
guard type.contains(typeContains) else { return nil }
|
|
201
|
+
return mapper(resource)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
func fetchSong(id: MusicItemID) async throws -> Song? {
|
|
206
|
+
if let song = try await musicKitFetchSong(id: id) {
|
|
207
|
+
return song
|
|
208
|
+
}
|
|
209
|
+
guard let resource = try await restCatalogSongResource(id: id.rawValue) else {
|
|
210
|
+
return nil
|
|
211
|
+
}
|
|
212
|
+
for candidate in RestJsonMapper.catalogSongLookupIds(primaryId: id.rawValue, resource: resource) {
|
|
213
|
+
if candidate == id.rawValue { continue }
|
|
214
|
+
if let song = try await musicKitFetchSong(id: MusicItemID(candidate)) {
|
|
215
|
+
return song
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return nil
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private func musicKitFetchSong(id: MusicItemID) async throws -> Song? {
|
|
222
|
+
let request = MusicCatalogResourceRequest<Song>(matching: \.id, equalTo: id)
|
|
223
|
+
let response = try await request.response()
|
|
224
|
+
return response.items.first
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/// REST catalog song resource — used when MusicKit lookup by playback id misses (e.g. after REST search).
|
|
228
|
+
private func restCatalogSongResource(id: String) async throws -> [String: Any]? {
|
|
229
|
+
let storefront = StorefrontService.getCatalogStorefront()
|
|
230
|
+
let path = "/v1/catalog/\(storefront)/songs/\(id)"
|
|
231
|
+
do {
|
|
232
|
+
let json = try await AppleMusicRestClient.get(path: path)
|
|
233
|
+
guard let data = json["data"] as? [[String: Any]], let resource = data.first else {
|
|
234
|
+
return nil
|
|
235
|
+
}
|
|
236
|
+
return resource
|
|
237
|
+
} catch {
|
|
238
|
+
return nil
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
func fetchAlbum(id: MusicItemID) async throws -> Album? {
|
|
243
|
+
let request = MusicCatalogResourceRequest<Album>(matching: \.id, equalTo: id)
|
|
244
|
+
let response = try await request.response()
|
|
245
|
+
return response.items.first
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
func fetchArtist(id: MusicItemID) async throws -> Artist? {
|
|
249
|
+
let request = MusicCatalogResourceRequest<Artist>(matching: \.id, equalTo: id)
|
|
250
|
+
let response = try await request.response()
|
|
251
|
+
return response.items.first
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
func fetchPlaylist(id: MusicItemID) async throws -> Playlist? {
|
|
255
|
+
let request = MusicCatalogResourceRequest<Playlist>(matching: \.id, equalTo: id)
|
|
256
|
+
let response = try await request.response()
|
|
257
|
+
return response.items.first
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
func fetchStation(id: MusicItemID) async throws -> Station? {
|
|
261
|
+
let request = MusicCatalogResourceRequest<Station>(matching: \.id, equalTo: id)
|
|
262
|
+
let response = try await request.response()
|
|
263
|
+
return response.items.first
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
func fetchMusicVideo(id: MusicItemID) async throws -> MusicVideo? {
|
|
267
|
+
let request = MusicCatalogResourceRequest<MusicVideo>(matching: \.id, equalTo: id)
|
|
268
|
+
let response = try await request.response()
|
|
269
|
+
return response.items.first
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// MARK: - Batch catalog resources (REST)
|
|
273
|
+
|
|
274
|
+
func getResources(type: String, ids: [String]) async throws -> [[String: Any]] {
|
|
275
|
+
let trimmed = ids.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }.filter { !$0.isEmpty }
|
|
276
|
+
if trimmed.isEmpty {
|
|
277
|
+
return []
|
|
278
|
+
}
|
|
279
|
+
let storefront = StorefrontService.getCatalogStorefront()
|
|
280
|
+
let path = "/v1/catalog/\(storefront)/\(type)"
|
|
281
|
+
let json = try await AppleMusicRestClient.get(path: path, query: ["ids": trimmed.joined(separator: ",")])
|
|
282
|
+
let data = try AppleMusicRestClient.parseDataArray(from: json)
|
|
283
|
+
return data.compactMap { resource in
|
|
284
|
+
mapCatalogResource(type: type, resource: resource)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private func mapCatalogResource(type: String, resource: [String: Any]) -> [String: Any]? {
|
|
289
|
+
let apiType = resource["type"] as? String ?? ""
|
|
290
|
+
switch type {
|
|
291
|
+
case "songs" where apiType.contains("song"):
|
|
292
|
+
return RestJsonMapper.mapSong(resource)
|
|
293
|
+
case "albums" where apiType.contains("album"):
|
|
294
|
+
return RestJsonMapper.mapAlbum(resource)
|
|
295
|
+
case "artists" where apiType.contains("artist"):
|
|
296
|
+
return RestJsonMapper.mapArtist(resource)
|
|
297
|
+
case "playlists" where apiType.contains("playlist"):
|
|
298
|
+
return RestJsonMapper.mapPlaylist(resource)
|
|
299
|
+
case "stations" where apiType.contains("station"):
|
|
300
|
+
return RestJsonMapper.mapStation(resource)
|
|
301
|
+
case "music-videos" where apiType.contains("music-video"):
|
|
302
|
+
return RestJsonMapper.mapMusicVideo(resource)
|
|
303
|
+
default:
|
|
304
|
+
return nil
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ExpoAppleMusic'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platforms = {
|
|
14
|
+
:ios => '16.4',
|
|
15
|
+
:tvos => '16.4'
|
|
16
|
+
}
|
|
17
|
+
s.swift_version = '5.9'
|
|
18
|
+
s.source = { git: 'https://github.com/wwdrew/expo-apple-music' }
|
|
19
|
+
s.static_framework = true
|
|
20
|
+
|
|
21
|
+
s.dependency 'ExpoModulesCore'
|
|
22
|
+
|
|
23
|
+
# Swift/Objective-C compatibility
|
|
24
|
+
s.pod_target_xcconfig = {
|
|
25
|
+
'DEFINES_MODULE' => 'YES',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
|
29
|
+
end
|