Music API Adapters
Relevant source files
The following files were used as context for generating this wiki page:The Music API Adapter system provides a standardized, extensible, and resilient way to fetch online music data from various third-party APIs. It abstracts the specific implementation details of each API, allowing the application to consume playlist data through a single, unified interface. This design supports multiple music platforms (like NetEase, QQ Music, etc.) and includes a failover mechanism to improve reliability.
The core of this system is the MusicAPIAdapter interface, which defines a contract for building request URLs and parsing API responses. The useMusicData hook orchestrates the data fetching process by iterating through a prioritized list of adapters, ensuring that if one API endpoint fails, another can be tried automatically.
Architecture
The system is built around a central interface, concrete adapter implementations, and a factory function that provides a list of available adapters.
MusicAPIAdapter Interface
This TypeScript interface is the foundation of the adapter pattern used in the application. It ensures that any new music API integration will conform to a standard structure.
This diagram shows the structure of the MusicAPIAdapter interface.
Sources: src/utils/musicApiAdapters.ts:6-20
| Method/Property | Description |
|---|---|
buildUrl(params) | A function that takes server, type, and id parameters and returns a fully-formed request URL. |
parseResponse(data) | A function that takes the raw JSON response from the API and transforms it into an array of MusicTrack objects. |
fetchOptions | An optional RequestInit object for custom fetch configurations. |
Sources: src/utils/musicApiAdapters.ts:6-20
Adapter Implementations
The application currently implements two adapters, both for the Meting API, to provide a primary and a fallback endpoint.
| Adapter Name | API Endpoint | Purpose |
|---|---|---|
metingAdapter | https://api.i-meto.com/meting/api | The primary adapter for fetching music data. |
metingFallbackAdapter | https://api.injahow.cn/meting/ | The secondary (fallback) adapter, used if the primary one fails. It reuses the parseResponse logic from the primary adapter. |
Sources: src/utils/musicApiAdapters.ts:25-53, src/constants.ts:23-24
getAdapters Function
This function returns a prioritized array of MusicAPIAdapter instances. The useMusicData hook iterates through this array in order, implementing a failover strategy. To add a new API or a new fallback, a developer would simply add a new adapter instance to this array.
// src/utils/musicApiAdapters.ts:59-64
export const getAdapters = (): MusicAPIAdapter[] => {
return [
metingAdapter,
metingFallbackAdapter
];
};
Sources: src/utils/musicApiAdapters.ts:59-64
Data Flow and Failover
The process of fetching music data is managed by the useMusicData hook, which leverages the adapter system to handle API requests and responses.
The following sequence diagram illustrates the entire data fetching flow, from the UI component to the API call and back, including the failover mechanism.
Key aspects of this flow:
- The
useMusicDatahook receives configuration (server,type,id) from theMusicPlayercomponent. - It retrieves the list of prioritized adapters from
getAdapters(). - It loops through each adapter, attempting to fetch data.
- Each fetch request has a built-in timeout of
5000ms(API_TIMEOUT_MS). - If a request fails (due to a network error, non-ok HTTP status, or timeout), the hook logs a warning and proceeds to the next adapter in the list.
- Upon a successful response, the data is parsed using the adapter's
parseResponsemethod, the state is updated with the tracklist, and the loop terminates. - If all adapters fail, an error state is set.
Sources: src/hooks/useMusicData.ts:43-93, src/constants.ts:41
Data Structures
MusicTrack Interface
All adapters must parse their API responses into a standardized MusicTrack array. This ensures that the rest of the application, particularly the useOnlinePlayer hook, can handle the data consistently.
| Field | Type | Description |
|---|---|---|
name | string | The name or title of the track. |
artist | string | The name of the artist or author. |
url | string | The direct URL to the audio stream. |
cover | string | The URL for the album art/cover image. |
lrc | string | The URL or content of the song lyrics. |
theme | string (optional) | An optional theme color associated with the track. |
Sources: src/hooks/useMusicData.ts:8-16, src/utils/musicApiAdapters.ts:34-41
The metingAdapter's parseResponse function demonstrates how raw API fields are mapped to the MusicTrack structure, with fallbacks for different property names (name/title, artist/author, pic/cover).
Sources: src/utils/musicApiAdapters.ts:32-42
Integration and Usage
The adapter system is consumed by a chain of React components and hooks, starting from the main App component.
This diagram shows the component and hook hierarchy for the online music player feature.
App.tsx: The top-level component manages the application's settings, including themusicConfigobject (server,type,id). This configuration is defined by the user in the settings panel.AudioPlayer.tsx: This component acts as a switch between the local and online players. When in "online" mode, it passes themusicConfigtoMusicPlayer.MusicPlayer.tsx: This component is the direct consumer of theuseMusicDatahook. It passes the config and receives theaudioList.useMusicData.ts: This hook uses the adapters to fetch theaudioList.useOnlinePlayer.ts: The fetchedplaylistis then passed to this hook, which manages the<audio>element, playback state, and track transitions.
Sources: src/App.tsx:381-419, src/components/AudioPlayer.tsx:82, src/components/MusicPlayer.tsx:16, src/hooks/useOnlinePlayer.ts:13
PWA Network Strategy
The project's PWA configuration in vite.config.ts explicitly defines a NetworkOnly caching strategy for all music API and audio streaming URLs. This ensures that the application always fetches the latest playlist data and streams audio directly from the source, preventing stale data or playback issues that could arise from caching third-party media URLs.
// vite.config.ts (simplified)
runtimeCaching: [
// ...
{
urlPattern: /^https:\/\/api\.injahow\.cn\/meting\/.*/i,
handler: 'NetworkOnly'
},
{
urlPattern: ({ request }) => {
return request.destination === 'audio' || request.destination === 'video';
},
handler: 'NetworkOnly'
},
// ... more rules for specific hostnames
]
Sources: vite.config.ts:67-111
Conclusion
The Music API Adapter system is a robust and well-abstracted module within the Endfield-Pomodoro application. By using a standardized interface, a prioritized list of adapters, and a resilient data-fetching hook, it provides a reliable online music experience. The clear separation of concerns—from UI configuration in App.tsx down to the adapter implementations—makes the system easy to maintain and extend with new music sources in the future.