@sriinnu/harmon-apple 0.1.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/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # @sriinnu/harmon-apple
2
+
3
+ ![logo](./logo.svg)
4
+
5
+ > Apple Music API client and provider adapter for catalog search, playlist tracks, library access, recent-play signals, and Apple-backed session discovery.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @sriinnu/harmon-apple
11
+ ```
12
+
13
+ ## Pack Auth
14
+
15
+ These commands are for the provider pack checkout or a profile-aware loader that executes inside the pack root. They are not exposed as a global installed binary. From a fresh repo checkout, run `pnpm build` once before you use them.
16
+
17
+ ```bash
18
+ npm run auth
19
+ npm run auth:status
20
+ npm run auth:refresh
21
+ ```
22
+
23
+ I keep local Apple Music auth state in `~/.chitragupta/harmon/provider-packs/harmon-apple/apple-music.json` by default. Set `HARMON_PACK_STATE_DIR` if you need a different local root. I also ship `.chitragupta-ecosystem/.profile.json` so Chitragupta-style loaders can discover the pack entrypoints and env contract directly.
24
+
25
+ I keep the auth flow honest:
26
+
27
+ - `npm run auth` uses `APPLE_MUSIC_DEVELOPER_TOKEN` directly, or generates one from `APPLE_MUSIC_TEAM_ID`, `APPLE_MUSIC_KEY_ID`, and `APPLE_MUSIC_PRIVATE_KEY_PATH`
28
+ - I then open a local MusicKit page to mint and save the Apple `Music-User-Token`
29
+ - `npm run auth:refresh` refreshes the developer-token side only; if the user token expires, rerun `npm run auth`
30
+
31
+ ## Quick Start
32
+
33
+ ```typescript
34
+ import { createAppleMusicClient } from '@sriinnu/harmon-apple';
35
+
36
+ const client = createAppleMusicClient({
37
+ developerToken: process.env.APPLE_MUSIC_DEVELOPER_TOKEN!,
38
+ userToken: process.env.APPLE_MUSIC_USER_TOKEN,
39
+ });
40
+ const results = await client.search('ambient study', ['songs']);
41
+ console.log(results.songs[0].name);
42
+ ```
43
+
44
+ ## API
45
+
46
+ | Export | Description |
47
+ |---|---|
48
+ | `createAppleMusicClient(config)` | Create authenticated API client |
49
+ | `AppleMusicClient` | Interface: search, getSong, getAlbum, getArtist, getPlaylist, getPlaylistTracks |
50
+ | `client.getLibrarySongs()` | Fetch user's library songs (requires user token) |
51
+ | `client.getLibraryAlbums()` | Fetch user's library albums |
52
+ | `client.getLibraryPlaylists()` | Fetch user's library playlists |
53
+ | `client.getRecentlyPlayedTracks()` | Fetch the user's recent Apple Music tracks (requires user token) |
54
+ | `client.getPlaylistTracks()` | Fetch playlist tracks from catalog playlists, or library playlists when a user token is available |
55
+ | `AppleMusicConfig` | `{ developerToken, userToken?, storefront? }` |
56
+ | `AppleMusicSong` | Song type with id, name, artistName, durationMs |
57
+ | `AppleMusicSearchResult` | Grouped results: songs, albums, artists, playlists |
58
+
59
+ ## Architecture
60
+
61
+ harmon-apple wraps the Apple Music REST API (`api.music.apple.com/v1`) and exposes a `MusicProvider` adapter for catalog search, library access, playlist browsing, recent-play signals, and recommendation seeding. The daemon pairs this package with either macOS AppleScript local playback or a daemon-side iOS remote companion contract, and it keeps local playback available on macOS even when remote companion auth is configured. Catalog endpoints use the developer token; personal library and recent-play endpoints additionally require a user Music-User-Token. I do not synthesize a separate Apple `topTracks` surface because the provider contract cannot distinguish that honestly from recent plays; harmond layers local playback history on top when that signal is needed for sessions.
62
+
63
+ ## License
64
+
65
+ GNU Affero General Public License v3.0 only. See [LICENSE](../../LICENSE).
package/SKILL.md ADDED
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: harmon-apple
3
+ description: Apple Music API client with catalog search, library access, and MusicProvider adapter
4
+ capabilities:
5
+ - Search the Apple Music catalog for songs, albums, artists, and playlists
6
+ - Access user library songs, albums, and playlists with Music-User-Token auth
7
+ - Adapt Apple Music API to the harmon-core MusicProvider interface
8
+ tags:
9
+ - apple-music
10
+ - music
11
+ - api
12
+ - streaming
13
+ provider: harmon
14
+ version: 0.1.0
15
+ ---
16
+
17
+ # Harmon Apple
18
+
19
+ ## What this does
20
+ harmon-apple provides a typed client for the Apple Music API, covering both the public catalog (search, get song/album/artist/playlist) and the authenticated user library. It maps Apple Music song data to the provider-agnostic TrackInfo format and implements the MusicProvider interface so harmon-core can treat Apple Music as a first-class track source alongside Spotify and YouTube Music.
21
+
22
+ ## Pack auth
23
+ - `npm run auth` resolves a developer token and opens a local MusicKit bootstrap page for the user token
24
+ - `npm run auth:refresh` refreshes the developer-token side and validates any stored user token
25
+ - `npm run auth:status` prints the current Apple Music auth posture and local auth file path
26
+ - `.chitragupta-ecosystem/.profile.json` is the explicit loader contract for this pack
27
+
28
+ ## When to use
29
+ - Searching the Apple Music catalog or reading a user's Apple Music library
30
+ - Adding Apple Music as a track source in a harmon session
31
+ - Converting Apple Music song metadata to the shared TrackInfo format
32
+
33
+ ## Key exports
34
+ - `createAppleMusicClient` — factory that returns an AppleMusicClient for catalog and library calls
35
+ - `createAppleMusicProvider` — MusicProvider adapter for harmon-core
36
+
37
+ ## Example
38
+ ```typescript
39
+ import { createAppleMusicClient, createAppleMusicProvider } from '@sriinnu/harmon-apple';
40
+
41
+ const client = createAppleMusicClient({ developerToken, userToken });
42
+ const results = await client.search('Nils Frahm', ['songs'], { limit: 10 });
43
+ const provider = createAppleMusicProvider(client);
44
+ const tracks = await provider.search('Nils Frahm', 10);
45
+ ```
@@ -0,0 +1,5 @@
1
+ /**
2
+ * I bootstrap and validate Apple Music auth for the standalone provider pack.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=auth-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-cli.d.ts","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,328 @@
1
+ /**
2
+ * I bootstrap and validate Apple Music auth for the standalone provider pack.
3
+ */
4
+ import { spawn } from 'node:child_process';
5
+ import { createPrivateKey, createSign, randomBytes } from 'node:crypto';
6
+ import { chmod, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
7
+ import { createServer } from 'node:http';
8
+ import os from 'node:os';
9
+ import path from 'node:path';
10
+ import process from 'node:process';
11
+ import { createAppleMusicClient } from './index.js';
12
+ const authPath = resolveAuthPath('apple-music.json');
13
+ /**
14
+ * I keep Apple Music auth state under user-local storage instead of the
15
+ * package tree so published packs never carry live tokens.
16
+ */
17
+ function resolveAuthPath(fileName) {
18
+ const overrideRoot = process.env.HARMON_PACK_STATE_DIR?.trim();
19
+ const stateRoot = overrideRoot && overrideRoot.length > 0
20
+ ? overrideRoot
21
+ : path.join(os.homedir(), '.chitragupta', 'harmon', 'provider-packs');
22
+ return path.join(stateRoot, 'harmon-apple', fileName);
23
+ }
24
+ async function readJson(filePath) {
25
+ try {
26
+ return JSON.parse(await readFile(filePath, 'utf8'));
27
+ }
28
+ catch (error) {
29
+ if (isNodeError(error) && error.code === 'ENOENT') {
30
+ return null;
31
+ }
32
+ throw error;
33
+ }
34
+ }
35
+ async function writeJson(filePath, value) {
36
+ await mkdir(path.dirname(filePath), { mode: 0o700, recursive: true });
37
+ if (value == null) {
38
+ await rm(filePath, { force: true });
39
+ return;
40
+ }
41
+ await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
42
+ await chmod(filePath, 0o600);
43
+ }
44
+ async function openUrl(url) {
45
+ if (process.env.HARMON_NO_BROWSER === '1') {
46
+ return;
47
+ }
48
+ const opener = process.platform === 'darwin'
49
+ ? ['open', [url]]
50
+ : process.platform === 'win32'
51
+ ? ['cmd', ['/c', 'start', '', url]]
52
+ : ['xdg-open', [url]];
53
+ await new Promise(resolve => {
54
+ const child = spawn(opener[0], opener[1], { stdio: 'ignore' });
55
+ child.on('error', () => resolve());
56
+ child.on('close', () => resolve());
57
+ });
58
+ }
59
+ function readConfig() {
60
+ const port = Number.parseInt(process.env.APPLE_MUSIC_BOOTSTRAP_PORT || '8788', 10);
61
+ return {
62
+ appName: process.env.APPLE_MUSIC_APP_NAME || 'Harmon',
63
+ appBuild: process.env.APPLE_MUSIC_APP_BUILD || '0.1.0',
64
+ bootstrapUrl: process.env.APPLE_MUSIC_BOOTSTRAP_URL || `http://127.0.0.1:${port}/`,
65
+ storefront: process.env.APPLE_MUSIC_STOREFRONT || 'us',
66
+ developerToken: process.env.APPLE_MUSIC_DEVELOPER_TOKEN,
67
+ userToken: process.env.APPLE_MUSIC_USER_TOKEN,
68
+ keyId: process.env.APPLE_MUSIC_KEY_ID,
69
+ teamId: process.env.APPLE_MUSIC_TEAM_ID,
70
+ privateKeyPath: process.env.APPLE_MUSIC_PRIVATE_KEY_PATH,
71
+ privateKey: process.env.APPLE_MUSIC_PRIVATE_KEY?.replace(/\\n/g, '\n'),
72
+ ttlSeconds: Math.min(Number.parseInt(process.env.APPLE_MUSIC_DEVELOPER_TOKEN_TTL_SECONDS || `${30 * 24 * 60 * 60}`, 10), 15_777_000),
73
+ };
74
+ }
75
+ function base64Url(value) {
76
+ return Buffer.from(value).toString('base64url');
77
+ }
78
+ /**
79
+ * I resolve the Apple developer token from direct env input, local key material, or stored state.
80
+ */
81
+ async function resolveDeveloperToken(config, existingState) {
82
+ if (config.developerToken) {
83
+ return { token: config.developerToken, source: 'env', expiresAt: null };
84
+ }
85
+ if (config.keyId && config.teamId && (config.privateKey || config.privateKeyPath)) {
86
+ const privateKeyPath = config.privateKeyPath;
87
+ const privateKey = config.privateKey || (privateKeyPath ? await readFile(privateKeyPath, 'utf8') : null);
88
+ if (!privateKey) {
89
+ throw new Error('APPLE_MUSIC_PRIVATE_KEY_PATH must point to a valid private key file.');
90
+ }
91
+ const now = Math.floor(Date.now() / 1000);
92
+ const payload = { iss: config.teamId, iat: now, exp: now + config.ttlSeconds };
93
+ const encoded = `${base64Url(JSON.stringify({ alg: 'ES256', kid: config.keyId, typ: 'JWT' }))}.${base64Url(JSON.stringify(payload))}`;
94
+ const signer = createSign('SHA256');
95
+ signer.update(encoded);
96
+ signer.end();
97
+ const signature = signer.sign({
98
+ key: createPrivateKey(privateKey),
99
+ dsaEncoding: 'ieee-p1363',
100
+ });
101
+ return {
102
+ token: `${encoded}.${signature.toString('base64url')}`,
103
+ source: 'generated',
104
+ expiresAt: new Date(payload.exp * 1000).toISOString(),
105
+ };
106
+ }
107
+ if (existingState?.developerToken) {
108
+ return {
109
+ token: existingState.developerToken,
110
+ source: existingState.developerTokenSource,
111
+ expiresAt: existingState.developerTokenExpiresAt,
112
+ };
113
+ }
114
+ return null;
115
+ }
116
+ /**
117
+ * I validate both the catalog token and the optional user token against the live Apple Music API.
118
+ */
119
+ async function validateApple(state) {
120
+ const client = createAppleMusicClient({
121
+ developerToken: state.developerToken,
122
+ userToken: state.userToken || undefined,
123
+ storefront: state.storefront,
124
+ });
125
+ await client.search('ambient', ['songs'], { limit: 1 });
126
+ if (state.userToken) {
127
+ await client.getLibraryPlaylists({ limit: 1 });
128
+ }
129
+ }
130
+ function renderBootstrapPage(developerToken, appName, appBuild, tokenPath, state) {
131
+ return `<!doctype html>
132
+ <html lang="en">
133
+ <head>
134
+ <meta charset="utf-8" />
135
+ <title>${appName} Apple Music Auth</title>
136
+ <script src="https://js-cdn.music.apple.com/musickit/v3/musickit.js"></script>
137
+ </head>
138
+ <body>
139
+ <main>
140
+ <h1>${appName} Apple Music Auth</h1>
141
+ <p>I use MusicKit JS to mint a user token for the local provider pack.</p>
142
+ <button id="authorize">Authorize Apple Music</button>
143
+ <pre id="status"></pre>
144
+ </main>
145
+ <script>
146
+ const developerToken = ${JSON.stringify(developerToken)};
147
+ const appName = ${JSON.stringify(appName)};
148
+ const appBuild = ${JSON.stringify(appBuild)};
149
+ const state = ${JSON.stringify(state)};
150
+ const tokenPath = ${JSON.stringify(tokenPath)};
151
+ const status = document.getElementById('status');
152
+ document.getElementById('authorize').addEventListener('click', async () => {
153
+ try {
154
+ MusicKit.configure({ developerToken, app: { name: appName, build: appBuild } });
155
+ const music = MusicKit.getInstance();
156
+ const userToken = await music.authorize();
157
+ const storefront = music.storefrontId || null;
158
+ await fetch(tokenPath, {
159
+ method: 'POST',
160
+ headers: { 'Content-Type': 'application/json' },
161
+ body: JSON.stringify({ state, userToken, storefront }),
162
+ });
163
+ status.textContent = 'Apple Music auth complete. I saved your token locally.';
164
+ } catch (error) {
165
+ status.textContent = String(error && error.message ? error.message : error);
166
+ }
167
+ });
168
+ </script>
169
+ </body>
170
+ </html>`;
171
+ }
172
+ /**
173
+ * I serve a local MusicKit bootstrap page and wait for the browser to post the user token back.
174
+ */
175
+ async function captureUserToken(config, developerToken) {
176
+ const bootstrapUrl = new URL(config.bootstrapUrl);
177
+ const bootstrapState = randomBytes(24).toString('base64url');
178
+ const tokenPath = bootstrapUrl.pathname === '/'
179
+ ? '/token'
180
+ : `${bootstrapUrl.pathname.replace(/\/$/, '')}/token`;
181
+ return new Promise((resolve, reject) => {
182
+ const server = createServer((request, response) => {
183
+ const requestUrl = new URL(request.url || '/', bootstrapUrl);
184
+ if (request.method === 'GET' && requestUrl.pathname === bootstrapUrl.pathname) {
185
+ response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
186
+ response.end(renderBootstrapPage(developerToken, config.appName, config.appBuild, tokenPath, bootstrapState));
187
+ return;
188
+ }
189
+ if (request.method === 'POST' && requestUrl.pathname === tokenPath) {
190
+ let body = '';
191
+ request.on('data', chunk => { body += chunk.toString(); });
192
+ request.on('end', () => {
193
+ try {
194
+ const payload = JSON.parse(body || '{}');
195
+ const origin = request.headers.origin;
196
+ if (origin && origin !== bootstrapUrl.origin) {
197
+ throw new Error('Apple Music bootstrap origin did not match the local bootstrap server.');
198
+ }
199
+ if (payload.state !== bootstrapState) {
200
+ throw new Error('Apple Music bootstrap state did not match the login attempt.');
201
+ }
202
+ response.writeHead(200).end('ok');
203
+ resolve(payload);
204
+ }
205
+ catch (error) {
206
+ response.writeHead(400).end('invalid bootstrap request');
207
+ reject(error);
208
+ }
209
+ finally {
210
+ server.close();
211
+ }
212
+ });
213
+ return;
214
+ }
215
+ response.writeHead(404).end('Not found');
216
+ });
217
+ server.on('error', reject);
218
+ server.listen(Number(bootstrapUrl.port || 80), bootstrapUrl.hostname);
219
+ });
220
+ }
221
+ /**
222
+ * I print the current Apple Music auth posture in a machine-friendly format.
223
+ */
224
+ async function printStatus(state, lifecycle) {
225
+ console.log(JSON.stringify({
226
+ provider: 'apple-music',
227
+ state: lifecycle,
228
+ connected: Boolean(state?.developerToken),
229
+ hasDeveloperToken: Boolean(state?.developerToken),
230
+ hasUserToken: Boolean(state?.userToken),
231
+ mode: !state?.developerToken ? 'disconnected' : state.userToken ? 'catalog-and-library' : 'catalog-only',
232
+ storefront: state?.storefront || null,
233
+ developerTokenSource: state?.developerTokenSource || null,
234
+ developerTokenExpiresAt: state?.developerTokenExpiresAt || null,
235
+ authFile: authPath,
236
+ }, null, 2));
237
+ }
238
+ async function bootstrap() {
239
+ const config = readConfig();
240
+ const existing = await readJson(authPath);
241
+ const developer = await resolveDeveloperToken(config, existing);
242
+ if (!developer) {
243
+ throw new Error('Set APPLE_MUSIC_DEVELOPER_TOKEN or APPLE_MUSIC_TEAM_ID / APPLE_MUSIC_KEY_ID / APPLE_MUSIC_PRIVATE_KEY_PATH.');
244
+ }
245
+ if (existing?.userToken && process.env.HARMON_AUTH_FORCE !== '1' && !config.userToken) {
246
+ const current = {
247
+ ...existing,
248
+ storefront: config.storefront || existing.storefront,
249
+ developerToken: developer.token,
250
+ developerTokenSource: developer.source,
251
+ developerTokenExpiresAt: developer.expiresAt,
252
+ };
253
+ try {
254
+ await validateApple(current);
255
+ await writeJson(authPath, current);
256
+ await printStatus(current, 'already-authenticated');
257
+ return;
258
+ }
259
+ catch {
260
+ // I fall through to MusicKit bootstrap so rerunning auth can repair an
261
+ // expired stored user token without requiring an undocumented force flag.
262
+ }
263
+ }
264
+ console.error(`Apple Music bootstrap URL: ${config.bootstrapUrl}`);
265
+ const tokenPromise = config.userToken
266
+ ? Promise.resolve({ userToken: config.userToken, storefront: config.storefront })
267
+ : captureUserToken(config, developer.token);
268
+ if (!config.userToken) {
269
+ await openUrl(config.bootstrapUrl);
270
+ }
271
+ const tokenPayload = await tokenPromise;
272
+ const state = {
273
+ provider: 'apple-music',
274
+ updatedAt: new Date().toISOString(),
275
+ developerToken: developer.token,
276
+ developerTokenSource: developer.source,
277
+ developerTokenExpiresAt: developer.expiresAt,
278
+ userToken: tokenPayload.userToken || null,
279
+ storefront: tokenPayload.storefront || config.storefront,
280
+ appName: config.appName,
281
+ appBuild: config.appBuild,
282
+ };
283
+ await validateApple(state);
284
+ await writeJson(authPath, state);
285
+ await printStatus(state, 'bootstrapped');
286
+ }
287
+ async function refresh() {
288
+ const config = readConfig();
289
+ const existing = await readJson(authPath);
290
+ const developer = await resolveDeveloperToken(config, existing);
291
+ if (!developer) {
292
+ throw new Error('I cannot refresh Apple Music auth without a developer token or key material.');
293
+ }
294
+ const state = {
295
+ provider: 'apple-music',
296
+ updatedAt: new Date().toISOString(),
297
+ developerToken: developer.token,
298
+ developerTokenSource: developer.source,
299
+ developerTokenExpiresAt: developer.expiresAt,
300
+ userToken: config.userToken || existing?.userToken || null,
301
+ storefront: config.storefront || existing?.storefront || 'us',
302
+ appName: config.appName,
303
+ appBuild: config.appBuild,
304
+ };
305
+ await validateApple(state);
306
+ await writeJson(authPath, state);
307
+ await printStatus(state, 'refreshed');
308
+ }
309
+ async function status() {
310
+ const state = await readJson(authPath);
311
+ await printStatus(state, 'status');
312
+ }
313
+ function isNodeError(error) {
314
+ return error !== null && typeof error === 'object' && 'code' in error;
315
+ }
316
+ const action = process.argv[2] || 'bootstrap';
317
+ const handlers = { bootstrap, refresh, status };
318
+ if (!handlers[action]) {
319
+ console.error(`Unknown Apple Music auth command: ${action}`);
320
+ process.exitCode = 1;
321
+ }
322
+ else {
323
+ handlers[action]().catch(error => {
324
+ console.error(error instanceof Error ? error.message : String(error));
325
+ process.exitCode = 1;
326
+ });
327
+ }
328
+ //# sourceMappingURL=auth-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-cli.js","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Harmon Apple - Apple Music API client
3
+ */
4
+ import type { TrackInfo } from '@sriinnu/harmon-protocol';
5
+ import type { MusicProvider, AudioFeatures } from '@sriinnu/harmon-core';
6
+ export interface AppleMusicConfig {
7
+ developerToken: string;
8
+ userToken?: string;
9
+ storefront?: string;
10
+ }
11
+ export type AppleSearchType = 'songs' | 'albums' | 'artists' | 'playlists';
12
+ export interface AppleListOptions {
13
+ limit?: number;
14
+ offset?: number;
15
+ }
16
+ export interface AppleMusicSearchResult {
17
+ songs: AppleMusicSong[];
18
+ albums: AppleMusicAlbum[];
19
+ artists: AppleMusicArtist[];
20
+ playlists: AppleMusicPlaylist[];
21
+ }
22
+ export interface AppleMusicSong {
23
+ id: string;
24
+ name: string;
25
+ artistName: string;
26
+ albumName?: string;
27
+ durationMs?: number;
28
+ url?: string;
29
+ }
30
+ export interface AppleMusicAlbum {
31
+ id: string;
32
+ name: string;
33
+ artistName: string;
34
+ releaseDate?: string;
35
+ trackCount?: number;
36
+ url?: string;
37
+ }
38
+ export interface AppleMusicArtist {
39
+ id: string;
40
+ name: string;
41
+ url?: string;
42
+ }
43
+ export interface AppleMusicPlaylist {
44
+ id: string;
45
+ name: string;
46
+ curatorName?: string;
47
+ trackCount?: number;
48
+ url?: string;
49
+ }
50
+ export interface AppleMusicLibrarySong {
51
+ id: string;
52
+ name: string;
53
+ artistName: string;
54
+ albumName?: string;
55
+ }
56
+ export interface AppleMusicLibraryAlbum {
57
+ id: string;
58
+ name: string;
59
+ artistName: string;
60
+ trackCount?: number;
61
+ }
62
+ export interface AppleMusicLibraryPlaylist {
63
+ id: string;
64
+ name: string;
65
+ trackCount?: number;
66
+ }
67
+ export interface AppleMusicClient {
68
+ search(term: string, types: AppleSearchType[], options?: AppleListOptions): Promise<AppleMusicSearchResult>;
69
+ getSong(id: string): Promise<AppleMusicSong | null>;
70
+ getAlbum(id: string): Promise<AppleMusicAlbum | null>;
71
+ getArtist(id: string): Promise<AppleMusicArtist | null>;
72
+ getPlaylist(id: string): Promise<AppleMusicPlaylist | null>;
73
+ getPlaylistTracks(id: string, options?: AppleListOptions): Promise<AppleMusicSong[]>;
74
+ getRecentlyPlayedTracks(options?: AppleListOptions): Promise<AppleMusicSong[]>;
75
+ getLibrarySongs(options?: AppleListOptions): Promise<AppleMusicLibrarySong[]>;
76
+ getLibraryAlbums(options?: AppleListOptions): Promise<AppleMusicLibraryAlbum[]>;
77
+ getLibraryPlaylists(options?: AppleListOptions): Promise<AppleMusicLibraryPlaylist[]>;
78
+ }
79
+ /**
80
+ * Adapts AppleMusicClient to the MusicProvider interface.
81
+ */
82
+ export declare class AppleMusicProvider implements MusicProvider {
83
+ readonly name: "apple";
84
+ private client;
85
+ private connected;
86
+ constructor(client: AppleMusicClient, connected?: boolean);
87
+ isConnected(): boolean;
88
+ search(query: string, limit?: number): Promise<TrackInfo[]>;
89
+ getLibraryTracks(options?: {
90
+ limit?: number;
91
+ }): Promise<TrackInfo[]>;
92
+ /**
93
+ * I reject synthetic top-track semantics so the Apple provider stays honest
94
+ * about the personal-history surface it actually implements.
95
+ */
96
+ getTopTracks(options?: {
97
+ limit?: number;
98
+ }): Promise<TrackInfo[]>;
99
+ getRecentlyPlayed(options?: {
100
+ limit?: number;
101
+ }): Promise<TrackInfo[]>;
102
+ getPlaylistTracks(playlistId: string, options?: {
103
+ limit?: number;
104
+ }): Promise<TrackInfo[]>;
105
+ /**
106
+ * I build Apple recommendations from the user's recent plays plus catalog
107
+ * artist searches because Apple does not expose a simple seed-track
108
+ * recommendations endpoint that matches the shared provider contract.
109
+ */
110
+ getRecommendations(options: {
111
+ seedTrackIds?: string[];
112
+ limit?: number;
113
+ }): Promise<TrackInfo[]>;
114
+ getTrackFeatures(trackIds: string[]): Promise<(AudioFeatures | null)[]>;
115
+ /**
116
+ * I prefer explicit seed tracks and fall back to recent listening history so
117
+ * recommendation discovery remains provider-aware for Apple sessions.
118
+ */
119
+ private resolveRecommendationSeeds;
120
+ }
121
+ export declare function createAppleMusicProvider(client: AppleMusicClient): MusicProvider;
122
+ export declare function createAppleMusicClient(config: AppleMusicConfig): AppleMusicClient;
123
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}