@audd/sdk 1.4.7 → 1.5.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/dist/index.d.cts CHANGED
@@ -1,159 +1,8 @@
1
- import { H as HttpClient, F as FetchLike } from './http-y2YwjfAl.cjs';
1
+ import { S as StreamCallbackMatch, a as StreamCallbackNotification, H as HttpClient, b as Stream, L as LongpollPoll, c as LyricsResult, F as FetchLike, R as RecognitionResult, E as EnterpriseMatch } from './longpollCore-DMBdcGSM.cjs';
2
+ export { d as EnterpriseChunkResult, e as StreamCallbackSong, f as StreamingProvider } from './longpollCore-DMBdcGSM.cjs';
2
3
 
3
4
  declare const VERSION = "1.4.6";
4
5
 
5
- /**
6
- * Typed models. Forward-compatible: each model captures unknown keys into
7
- * `extras`, mirroring audd-python's Pydantic `extra="allow"` pattern.
8
- */
9
- /** Streaming providers supported by the lis.tn redirect helper. */
10
- type StreamingProvider = "spotify" | "apple_music" | "deezer" | "napster" | "youtube";
11
- interface RecognitionResult {
12
- /** Always present on a match. */
13
- timecode: string;
14
- /** Set on custom-catalog matches. */
15
- audioId?: number | undefined;
16
- artist?: string | undefined;
17
- title?: string | undefined;
18
- album?: string | undefined;
19
- releaseDate?: string | undefined;
20
- label?: string | undefined;
21
- songLink?: string | undefined;
22
- appleMusic?: Record<string, unknown> | undefined;
23
- spotify?: Record<string, unknown> | undefined;
24
- deezer?: Record<string, unknown> | undefined;
25
- napster?: Record<string, unknown> | undefined;
26
- musicbrainz?: ReadonlyArray<Record<string, unknown>> | undefined;
27
- /** Forward-compat: any unknown keys from the server. */
28
- extras: Record<string, unknown>;
29
- /** Full unparsed payload for the caller's own inspection. */
30
- rawResponse: Record<string, unknown>;
31
- /** True when `audioId` is set (custom-catalog match). */
32
- readonly isCustomMatch: boolean;
33
- /** True when `audioId` is unset and `artist` or `title` are present. */
34
- readonly isPublicMatch: boolean;
35
- /** Cover-art URL for `lis.tn`-hosted song_links, else `null`. */
36
- readonly thumbnailUrl: string | null;
37
- /**
38
- * Direct or redirect URL for a streaming provider, with smart fallback.
39
- *
40
- * Resolution order:
41
- * 1. Direct URL from the metadata block (e.g. `apple_music.url`,
42
- * `spotify.external_urls.spotify`, `deezer.link`, `napster.href`) when
43
- * the user requested that provider via `return=`.
44
- * 2. lis.tn redirect (`{songLink}?{provider}`) when `songLink` is on lis.tn.
45
- * 3. `null` otherwise. YouTube has only the lis.tn-redirect path.
46
- */
47
- streamingUrl(provider: StreamingProvider): string | null;
48
- /** Map of every provider with a resolvable URL — direct or via lis.tn redirect. */
49
- streamingUrls(): Partial<Record<StreamingProvider, string>>;
50
- /**
51
- * First available 30-second preview URL across providers, in priority order:
52
- * `apple_music.previews[0].url` → `spotify.preview_url` → `deezer.preview`.
53
- *
54
- * **Note:** previews are governed by the respective providers' terms of use.
55
- * The SDK consumer is responsible for honoring those terms (caching limits,
56
- * attribution, redistribution constraints).
57
- */
58
- previewUrl(): string | null;
59
- }
60
- interface EnterpriseMatch {
61
- score: number;
62
- timecode: string;
63
- artist?: string | undefined;
64
- title?: string | undefined;
65
- album?: string | undefined;
66
- releaseDate?: string | undefined;
67
- label?: string | undefined;
68
- isrc?: string | undefined;
69
- upc?: string | undefined;
70
- songLink?: string | undefined;
71
- startOffset?: number | undefined;
72
- endOffset?: number | undefined;
73
- extras: Record<string, unknown>;
74
- rawResponse: Record<string, unknown>;
75
- readonly thumbnailUrl: string | null;
76
- /** lis.tn redirect URL for the given streaming provider, or null if `songLink` is non-lis.tn. */
77
- streamingUrl(provider: StreamingProvider): string | null;
78
- /** All providers with a resolvable lis.tn redirect URL (or empty when `songLink` is off lis.tn). */
79
- streamingUrls(): Partial<Record<StreamingProvider, string>>;
80
- }
81
- interface EnterpriseChunkResult {
82
- songs: EnterpriseMatch[];
83
- offset: string;
84
- extras: Record<string, unknown>;
85
- rawResponse: Record<string, unknown>;
86
- }
87
- interface Stream {
88
- radioId: number;
89
- url: string;
90
- streamRunning: boolean;
91
- longpollCategory?: string | undefined;
92
- extras: Record<string, unknown>;
93
- rawResponse: Record<string, unknown>;
94
- }
95
- interface StreamCallbackResultEntry {
96
- artist: string;
97
- title: string;
98
- score: number;
99
- album?: string | undefined;
100
- releaseDate?: string | undefined;
101
- label?: string | undefined;
102
- songLink?: string | undefined;
103
- appleMusic?: Record<string, unknown> | undefined;
104
- spotify?: Record<string, unknown> | undefined;
105
- deezer?: Record<string, unknown> | undefined;
106
- napster?: Record<string, unknown> | undefined;
107
- musicbrainz?: ReadonlyArray<Record<string, unknown>> | undefined;
108
- extras: Record<string, unknown>;
109
- rawResponse: Record<string, unknown>;
110
- }
111
- interface StreamCallbackResult {
112
- radioId: number;
113
- timestamp?: string | undefined;
114
- playLength?: number | undefined;
115
- results: StreamCallbackResultEntry[];
116
- extras: Record<string, unknown>;
117
- rawResponse: Record<string, unknown>;
118
- }
119
- interface StreamCallbackNotification {
120
- radioId: number;
121
- streamRunning?: boolean | undefined;
122
- notificationCode: number;
123
- notificationMessage: string;
124
- extras: Record<string, unknown>;
125
- rawResponse: Record<string, unknown>;
126
- }
127
- /**
128
- * Discriminated union: a parsed callback payload is either a recognition
129
- * result or a notification.
130
- */
131
- interface StreamCallbackPayload {
132
- /** Set when this is a recognition result delivery. */
133
- result: StreamCallbackResult | null;
134
- /** Set when this is a stream-state notification. */
135
- notification: StreamCallbackNotification | null;
136
- /** Notification time (epoch seconds). */
137
- time: number | null;
138
- /** Original parsed JSON body. */
139
- rawPayload: Record<string, unknown>;
140
- readonly isResult: boolean;
141
- readonly isNotification: boolean;
142
- }
143
- declare function parseStreamCallback(raw: unknown): StreamCallbackPayload;
144
- interface LyricsResult {
145
- artist: string;
146
- title: string;
147
- lyrics?: string | undefined;
148
- songId?: number | undefined;
149
- fullTitle?: string | undefined;
150
- artistId?: number | undefined;
151
- songLink?: string | undefined;
152
- media?: string | undefined;
153
- extras: Record<string, unknown>;
154
- rawResponse: Record<string, unknown>;
155
- }
156
-
157
6
  /**
158
7
  * Auto-detect what kind of audio source the caller passed and convert to
159
8
  * the right multipart fields.
@@ -201,6 +50,169 @@ interface RetryPolicy {
201
50
  backoffMaxMs: number;
202
51
  }
203
52
 
53
+ /** Exception hierarchy for AudD API errors. */
54
+ interface AudDApiErrorFields {
55
+ errorCode: number;
56
+ message: string;
57
+ httpStatus: number;
58
+ requestId: string | null;
59
+ requestedParams: Record<string, unknown>;
60
+ requestMethod: string | null;
61
+ brandedMessage: string | null;
62
+ rawResponse: unknown;
63
+ }
64
+ type AudDApiErrorInit = Partial<AudDApiErrorFields> & Pick<AudDApiErrorFields, "errorCode" | "message" | "httpStatus">;
65
+ /** Base for everything thrown by this SDK. */
66
+ declare class AudDError extends Error {
67
+ name: string;
68
+ }
69
+ /** Server returned `status: error`. Carries the AudD error code + the full echo. */
70
+ declare class AudDAPIError extends AudDError {
71
+ name: string;
72
+ errorCode: number;
73
+ httpStatus: number;
74
+ requestId: string | null;
75
+ requestedParams: Record<string, unknown>;
76
+ requestMethod: string | null;
77
+ brandedMessage: string | null;
78
+ rawResponse: unknown;
79
+ /** Original `error_message` from the server. (`Error.message` may be overridden by subclasses.) */
80
+ serverMessage: string;
81
+ constructor(init: AudDApiErrorInit);
82
+ }
83
+ declare class AudDAuthenticationError extends AudDAPIError {
84
+ name: string;
85
+ }
86
+ declare class AudDQuotaError extends AudDAPIError {
87
+ name: string;
88
+ }
89
+ declare class AudDSubscriptionError extends AudDAPIError {
90
+ name: string;
91
+ }
92
+ declare class AudDCustomCatalogAccessError extends AudDSubscriptionError {
93
+ name: string;
94
+ }
95
+ declare class AudDInvalidRequestError extends AudDAPIError {
96
+ name: string;
97
+ }
98
+ declare class AudDInvalidAudioError extends AudDAPIError {
99
+ name: string;
100
+ }
101
+ declare class AudDRateLimitError extends AudDAPIError {
102
+ name: string;
103
+ }
104
+ declare class AudDStreamLimitError extends AudDAPIError {
105
+ name: string;
106
+ }
107
+ declare class AudDNotReleasedError extends AudDAPIError {
108
+ name: string;
109
+ }
110
+ declare class AudDBlockedError extends AudDAPIError {
111
+ name: string;
112
+ }
113
+ declare class AudDNeedsUpdateError extends AudDAPIError {
114
+ name: string;
115
+ }
116
+ declare class AudDServerError extends AudDAPIError {
117
+ name: string;
118
+ }
119
+ declare class AudDConnectionError extends AudDError {
120
+ name: string;
121
+ cause?: unknown;
122
+ constructor(message: string, cause?: unknown);
123
+ }
124
+ declare class AudDSerializationError extends AudDError {
125
+ name: string;
126
+ rawText: string;
127
+ constructor(message: string, rawText?: string);
128
+ }
129
+ type AudDAPIErrorCtor = new (init: AudDApiErrorInit) => AudDAPIError;
130
+ declare function errorClassForCode(code: number): AudDAPIErrorCtor;
131
+
132
+ /**
133
+ * Raised by `addReturnToUrl` (and therefore by `streams.setCallbackUrl`)
134
+ * when the URL already contains a `return` query parameter and a
135
+ * `returnMetadata` argument is also passed — conflicting intent.
136
+ */
137
+ declare class DuplicateReturnParameterError extends AudDInvalidRequestError {
138
+ name: string;
139
+ constructor();
140
+ }
141
+ /**
142
+ * Compute the 9-char longpoll category locally from the API token + radio_id.
143
+ *
144
+ * Formula (per docs.audd.io/streams.md): hex-MD5 of (hex-MD5 of api_token,
145
+ * concatenated with the radio_id rendered as a decimal string), truncated
146
+ * to the first 9 hex chars.
147
+ *
148
+ * Pure function — no network call. Lets servers share a longpoll category
149
+ * with browser/mobile clients without leaking the api_token.
150
+ */
151
+ declare function deriveLongpollCategory(apiToken: string, radioId: number): string;
152
+ /**
153
+ * Append `?return=<metadata>` (or merge as `&return=`) to the callback URL.
154
+ *
155
+ * - If `returnMetadata` is `undefined`, returns the URL unchanged.
156
+ * - If the URL already has a `return` query parameter, raises rather than
157
+ * silently overwriting.
158
+ */
159
+ declare function addReturnToUrl(url: string, returnMetadata: string | string[] | undefined): string;
160
+ /**
161
+ * Result of {@link parseCallback} / {@link handleCallback}.
162
+ *
163
+ * Exactly one of `match` or `notification` is non-null on success.
164
+ * Recognition callbacks populate `match`; lifecycle/error callbacks (e.g.
165
+ * "stream stopped", "can't connect") populate `notification`.
166
+ */
167
+ interface ParsedCallback {
168
+ match: StreamCallbackMatch | null;
169
+ notification: StreamCallbackNotification | null;
170
+ }
171
+ /**
172
+ * Parse a callback POST body into a typed match or notification.
173
+ *
174
+ * Accepts either a parsed JSON object or a string (serialized JSON). Throws
175
+ * {@link AudDSerializationError} when the body is unparseable JSON, isn't an
176
+ * object, or carries neither a `result` nor a `notification` block.
177
+ *
178
+ * Prefer {@link handleCallback} when you have a Node `http.IncomingMessage`,
179
+ * a Web `Request`, or anything with a streamed body — that helper reads the
180
+ * body for you.
181
+ */
182
+ declare function parseCallback(body: unknown): ParsedCallback;
183
+ /**
184
+ * Minimum shape we accept from a "request-like" object: anything that exposes
185
+ * a `body` (already-parsed-or-stringified JSON), or that is itself a stream we
186
+ * can drain.
187
+ *
188
+ * Concretely supports:
189
+ * - Node `http.IncomingMessage` (async-iterable of `Buffer | string`)
190
+ * - Web `Request` / `fetch` `Body` (has `.text()`)
191
+ * - Express/Fastify/Hono request (has a `.body` already populated by a JSON parser)
192
+ * - Plain `{ body: <parsed-json | string> }` shapes
193
+ */
194
+ type CallbackRequestLike = {
195
+ text(): Promise<string>;
196
+ } | {
197
+ body?: unknown;
198
+ [k: string]: unknown;
199
+ } | AsyncIterable<unknown>;
200
+ /**
201
+ * Read and parse a callback POST body off a Node, Web, or framework-style
202
+ * request. Picks the right strategy by duck-typing:
203
+ *
204
+ * 1. If the request exposes a `text()` method (Web `Request`, `fetch` body),
205
+ * awaits it and parses the resulting string.
206
+ * 2. Otherwise, if the request has a `body` property that's already an object
207
+ * (Express/Fastify/Hono with a JSON middleware) or string, parses that
208
+ * directly without touching the underlying stream.
209
+ * 3. Otherwise, treats the request as an async-iterable of chunks
210
+ * (`http.IncomingMessage`) and concatenates the body before parsing.
211
+ *
212
+ * Throws {@link AudDSerializationError} on any parse failure.
213
+ */
214
+ declare function handleCallback(req: CallbackRequestLike): Promise<ParsedCallback>;
215
+
204
216
  interface SetCallbackUrlOptions {
205
217
  returnMetadata?: string | string[];
206
218
  }
@@ -245,18 +257,27 @@ declare class Streams {
245
257
  list(): Promise<Stream[]>;
246
258
  /** Compute the 9-char longpoll category locally — pure, no network. */
247
259
  deriveLongpollCategory(radioId: number): string;
248
- /** Parse a callback POST body into a typed `StreamCallbackPayload`. */
249
- parseCallback(body: unknown): StreamCallbackPayload;
250
260
  /**
251
- * Longpoll the AudD subscription endpoint, yielding parsed JSON dicts
252
- * (recognition events, notifications, or `{ timeout: ... }` markers).
261
+ * Parse a callback POST body into `{ match, notification }`. Pass an
262
+ * already-parsed JSON value or a string. Exactly one field is non-null on
263
+ * success. See {@link parseCallback} for details.
264
+ */
265
+ parseCallback(body: unknown): ParsedCallback;
266
+ /**
267
+ * Long-poll the AudD subscription endpoint.
253
268
  *
254
- * By default, performs a one-time `getCallbackUrl` preflight. If the
255
- * server returns code 19 (no callback URL configured), throws
256
- * `AudDInvalidRequestError` with an actionable hint. Pass
257
- * `skipCallbackCheck: true` to bypass.
269
+ * Returns a {@link LongpollPoll} handle with three async-iterables —
270
+ * `matches`, `notifications`, `errors` — that are filled by a background
271
+ * loop. Iterate them independently or in parallel via `Promise.all([...])`.
272
+ *
273
+ * Before the first request the SDK runs a one-time `getCallbackUrl`
274
+ * preflight: AudD silently discards events for accounts that haven't set a
275
+ * callback URL, and the preflight surfaces that misconfiguration as an
276
+ * actionable {@link AudDInvalidRequestError}. Pass `skipCallbackCheck: true`
277
+ * to bypass.
258
278
  */
259
- longpoll(category: string, opts?: LongpollOptions): AsyncIterable<Record<string, unknown>>;
279
+ longpoll(category: string, opts?: LongpollOptions): Promise<LongpollPoll>;
280
+ private preflightCallbackUrl;
260
281
  }
261
282
 
262
283
  interface CustomCatalogAddOptions {
@@ -422,112 +443,4 @@ declare class AudD {
422
443
  [Symbol.asyncDispose](): Promise<void>;
423
444
  }
424
445
 
425
- /** Exception hierarchy for AudD API errors. */
426
- interface AudDApiErrorFields {
427
- errorCode: number;
428
- message: string;
429
- httpStatus: number;
430
- requestId: string | null;
431
- requestedParams: Record<string, unknown>;
432
- requestMethod: string | null;
433
- brandedMessage: string | null;
434
- rawResponse: unknown;
435
- }
436
- type AudDApiErrorInit = Partial<AudDApiErrorFields> & Pick<AudDApiErrorFields, "errorCode" | "message" | "httpStatus">;
437
- /** Base for everything thrown by this SDK. */
438
- declare class AudDError extends Error {
439
- name: string;
440
- }
441
- /** Server returned `status: error`. Carries the AudD error code + the full echo. */
442
- declare class AudDAPIError extends AudDError {
443
- name: string;
444
- errorCode: number;
445
- httpStatus: number;
446
- requestId: string | null;
447
- requestedParams: Record<string, unknown>;
448
- requestMethod: string | null;
449
- brandedMessage: string | null;
450
- rawResponse: unknown;
451
- /** Original `error_message` from the server. (`Error.message` may be overridden by subclasses.) */
452
- serverMessage: string;
453
- constructor(init: AudDApiErrorInit);
454
- }
455
- declare class AudDAuthenticationError extends AudDAPIError {
456
- name: string;
457
- }
458
- declare class AudDQuotaError extends AudDAPIError {
459
- name: string;
460
- }
461
- declare class AudDSubscriptionError extends AudDAPIError {
462
- name: string;
463
- }
464
- declare class AudDCustomCatalogAccessError extends AudDSubscriptionError {
465
- name: string;
466
- }
467
- declare class AudDInvalidRequestError extends AudDAPIError {
468
- name: string;
469
- }
470
- declare class AudDInvalidAudioError extends AudDAPIError {
471
- name: string;
472
- }
473
- declare class AudDRateLimitError extends AudDAPIError {
474
- name: string;
475
- }
476
- declare class AudDStreamLimitError extends AudDAPIError {
477
- name: string;
478
- }
479
- declare class AudDNotReleasedError extends AudDAPIError {
480
- name: string;
481
- }
482
- declare class AudDBlockedError extends AudDAPIError {
483
- name: string;
484
- }
485
- declare class AudDNeedsUpdateError extends AudDAPIError {
486
- name: string;
487
- }
488
- declare class AudDServerError extends AudDAPIError {
489
- name: string;
490
- }
491
- declare class AudDConnectionError extends AudDError {
492
- name: string;
493
- cause?: unknown;
494
- constructor(message: string, cause?: unknown);
495
- }
496
- declare class AudDSerializationError extends AudDError {
497
- name: string;
498
- rawText: string;
499
- constructor(message: string, rawText?: string);
500
- }
501
- type AudDAPIErrorCtor = new (init: AudDApiErrorInit) => AudDAPIError;
502
- declare function errorClassForCode(code: number): AudDAPIErrorCtor;
503
-
504
- /**
505
- * Raised by `addReturnToUrl` (and therefore by `streams.setCallbackUrl`)
506
- * when the URL already contains a `return` query parameter and a
507
- * `returnMetadata` argument is also passed — conflicting intent.
508
- */
509
- declare class DuplicateReturnParameterError extends AudDInvalidRequestError {
510
- name: string;
511
- constructor();
512
- }
513
- /**
514
- * Compute the 9-char longpoll category locally from the API token + radio_id.
515
- *
516
- * Formula (per docs.audd.io/streams.md): hex-MD5 of (hex-MD5 of api_token,
517
- * concatenated with the radio_id rendered as a decimal string), truncated
518
- * to the first 9 hex chars.
519
- *
520
- * Pure function — no network call. Lets servers share a longpoll category
521
- * with browser/mobile clients without leaking the api_token.
522
- */
523
- declare function deriveLongpollCategory(apiToken: string, radioId: number): string;
524
- /**
525
- * Append `?return=<metadata>` (or merge as `&return=`) to the callback URL.
526
- *
527
- * - If `returnMetadata` is `undefined`, returns the URL unchanged.
528
- * - If the URL already has a `return` query parameter, raises rather than
529
- * silently overwriting.
530
- */
531
- declare function addReturnToUrl(url: string, returnMetadata: string | string[] | undefined): string;
532
-
533
- export { type AddStreamOptions, Advanced, AudD, AudDAPIError, AudDAuthenticationError, AudDBlockedError, AudDConnectionError, AudDCustomCatalogAccessError, AudDError, type AudDEvent, type AudDEventKind, AudDInvalidAudioError, AudDInvalidRequestError, AudDNeedsUpdateError, AudDNotReleasedError, type AudDOptions, AudDQuotaError, AudDRateLimitError, AudDSerializationError, AudDServerError, AudDStreamLimitError, AudDSubscriptionError, CustomCatalog, type CustomCatalogAddOptions, DuplicateReturnParameterError, type EnterpriseChunkResult, type EnterpriseMatch, type LongpollOptions, type LyricsResult, type OnEventHook, type RecognitionResult, type RecognizeEnterpriseOptions, type RecognizeOptions, type ReturnMetadata, type SetCallbackUrlOptions, type Source, type StreamCallbackNotification, type StreamCallbackPayload, type StreamCallbackResult, type StreamCallbackResultEntry, type Stream as StreamRecord, type StreamingProvider, Streams, VERSION, addReturnToUrl, deriveLongpollCategory, errorClassForCode, parseStreamCallback as parseCallback };
446
+ export { type AddStreamOptions, Advanced, AudD, AudDAPIError, AudDAuthenticationError, AudDBlockedError, AudDConnectionError, AudDCustomCatalogAccessError, AudDError, type AudDEvent, type AudDEventKind, AudDInvalidAudioError, AudDInvalidRequestError, AudDNeedsUpdateError, AudDNotReleasedError, type AudDOptions, AudDQuotaError, AudDRateLimitError, AudDSerializationError, AudDServerError, AudDStreamLimitError, AudDSubscriptionError, CustomCatalog, type CustomCatalogAddOptions, DuplicateReturnParameterError, EnterpriseMatch, type LongpollOptions, LongpollPoll, LyricsResult, type OnEventHook, type ParsedCallback, RecognitionResult, type RecognizeEnterpriseOptions, type RecognizeOptions, type ReturnMetadata, type SetCallbackUrlOptions, type Source, StreamCallbackMatch, StreamCallbackNotification, Stream as StreamRecord, Streams, VERSION, addReturnToUrl, deriveLongpollCategory, errorClassForCode, handleCallback, parseCallback };