@audd/sdk 1.5.5 → 1.5.7
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 +2 -2
- package/dist/index.cjs +43 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -4
- package/dist/index.d.ts +45 -4
- package/dist/index.js +43 -22
- package/dist/index.js.map +1 -1
- package/dist/longpoll.cjs +4 -0
- package/dist/longpoll.cjs.map +1 -1
- package/dist/longpoll.js +4 -0
- package/dist/longpoll.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -38,11 +38,15 @@ type Source = string | URL | Blob | Uint8Array;
|
|
|
38
38
|
* - RECOGNITION — `recognize`, `recognizeEnterprise`, `advanced.findLyrics`:
|
|
39
39
|
* retry on pre-upload connection failures + 5xx.
|
|
40
40
|
* DO NOT retry on read-timeout-after-upload (cost protection).
|
|
41
|
-
* - MUTATING — `streams.add`, `streams.delete`, etc
|
|
41
|
+
* - MUTATING — `streams.add`, `streams.delete`, etc.:
|
|
42
42
|
* retry only on pre-upload connection failures. DO NOT retry
|
|
43
43
|
* 5xx (the side effect may have happened).
|
|
44
|
+
* - NONE — `customCatalog.add`: never retry. Custom-catalog upload is
|
|
45
|
+
* metered; auto-retry on transport failure could double-charge
|
|
46
|
+
* for the same audio fingerprinting. Surface a clean error and
|
|
47
|
+
* let the caller decide.
|
|
44
48
|
*/
|
|
45
|
-
type RetryClass = "read" | "recognition" | "mutating";
|
|
49
|
+
type RetryClass = "read" | "recognition" | "mutating" | "none";
|
|
46
50
|
interface RetryPolicy {
|
|
47
51
|
retryClass: RetryClass;
|
|
48
52
|
maxAttempts: number;
|
|
@@ -228,6 +232,19 @@ interface LongpollOptions {
|
|
|
228
232
|
timeout?: number;
|
|
229
233
|
/** Bypass the default-on `getCallbackUrl` preflight. */
|
|
230
234
|
skipCallbackCheck?: boolean;
|
|
235
|
+
/**
|
|
236
|
+
* Radio id to subscribe to — the SDK derives the 9-char category locally
|
|
237
|
+
* from `(api_token, radio_id)`. Mutually exclusive with `category`. Only
|
|
238
|
+
* meaningful on the object-form call site (`longpoll({ radioId: 42 })`).
|
|
239
|
+
*/
|
|
240
|
+
radioId?: number;
|
|
241
|
+
/**
|
|
242
|
+
* Pre-derived 9-char longpoll category. Mutually exclusive with `radioId`.
|
|
243
|
+
* Only meaningful on the object-form call site
|
|
244
|
+
* (`longpoll({ category: "abc123def" })`); the positional string form
|
|
245
|
+
* `longpoll("abc123def")` is the more common way to pass a category.
|
|
246
|
+
*/
|
|
247
|
+
category?: string;
|
|
231
248
|
}
|
|
232
249
|
declare class Streams {
|
|
233
250
|
private readonly http;
|
|
@@ -266,6 +283,17 @@ declare class Streams {
|
|
|
266
283
|
/**
|
|
267
284
|
* Long-poll the AudD subscription endpoint.
|
|
268
285
|
*
|
|
286
|
+
* Two call shapes:
|
|
287
|
+
*
|
|
288
|
+
* - **Common case** — pass an options object with `radioId`; the SDK
|
|
289
|
+
* derives the 9-char category locally from `(api_token, radio_id)`:
|
|
290
|
+
* `longpoll({ radioId: 42 })`.
|
|
291
|
+
* - **Tokenless / pre-derived category** — pass the category as a positional
|
|
292
|
+
* string (`longpoll("abc123def")`) or via the object form
|
|
293
|
+
* (`longpoll({ category: "abc123def" })`). Useful when the category was
|
|
294
|
+
* shared with you (e.g. a browser/mobile client running without the
|
|
295
|
+
* api_token).
|
|
296
|
+
*
|
|
269
297
|
* Returns a {@link LongpollPoll} handle with three async-iterables —
|
|
270
298
|
* `matches`, `notifications`, `errors` — that are filled by a background
|
|
271
299
|
* loop. Iterate them independently or in parallel via `Promise.all([...])`.
|
|
@@ -275,8 +303,16 @@ declare class Streams {
|
|
|
275
303
|
* callback URL, and the preflight surfaces that misconfiguration as an
|
|
276
304
|
* actionable {@link AudDInvalidRequestError}. Pass `skipCallbackCheck: true`
|
|
277
305
|
* to bypass.
|
|
306
|
+
*
|
|
307
|
+
* Throws {@link AudDInvalidRequestError} if the object form supplies both
|
|
308
|
+
* `radioId` and `category`, or neither.
|
|
278
309
|
*/
|
|
279
310
|
longpoll(category: string, opts?: LongpollOptions): Promise<LongpollPoll>;
|
|
311
|
+
longpoll(opts: LongpollOptions & ({
|
|
312
|
+
radioId: number;
|
|
313
|
+
} | {
|
|
314
|
+
category: string;
|
|
315
|
+
})): Promise<LongpollPoll>;
|
|
280
316
|
private preflightCallbackUrl;
|
|
281
317
|
}
|
|
282
318
|
|
|
@@ -286,8 +322,8 @@ interface CustomCatalogAddOptions {
|
|
|
286
322
|
}
|
|
287
323
|
declare class CustomCatalog {
|
|
288
324
|
private readonly http;
|
|
289
|
-
private readonly
|
|
290
|
-
constructor(http: HttpClient,
|
|
325
|
+
private readonly noRetryPolicy;
|
|
326
|
+
constructor(http: HttpClient, noRetryPolicy: RetryPolicy);
|
|
291
327
|
/**
|
|
292
328
|
* **This is NOT how you submit audio for music recognition.** For
|
|
293
329
|
* recognition, use `audd.recognize()` (or `audd.recognizeEnterprise()` for
|
|
@@ -299,6 +335,11 @@ declare class CustomCatalog {
|
|
|
299
335
|
* Calling this again with the same `audioId` re-fingerprints that slot.
|
|
300
336
|
* There is no public list/delete endpoint; track `audioId` ↔ song
|
|
301
337
|
* mappings on your side.
|
|
338
|
+
*
|
|
339
|
+
* **No automatic retry.** Custom-catalog upload is metered, and a transport
|
|
340
|
+
* failure could otherwise cause a silent re-upload that double-charges. Any
|
|
341
|
+
* 5xx or pre-upload connection error surfaces as a clean exception — the
|
|
342
|
+
* caller decides whether to retry.
|
|
302
343
|
*/
|
|
303
344
|
add(opts: CustomCatalogAddOptions): Promise<void>;
|
|
304
345
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -38,11 +38,15 @@ type Source = string | URL | Blob | Uint8Array;
|
|
|
38
38
|
* - RECOGNITION — `recognize`, `recognizeEnterprise`, `advanced.findLyrics`:
|
|
39
39
|
* retry on pre-upload connection failures + 5xx.
|
|
40
40
|
* DO NOT retry on read-timeout-after-upload (cost protection).
|
|
41
|
-
* - MUTATING — `streams.add`, `streams.delete`, etc
|
|
41
|
+
* - MUTATING — `streams.add`, `streams.delete`, etc.:
|
|
42
42
|
* retry only on pre-upload connection failures. DO NOT retry
|
|
43
43
|
* 5xx (the side effect may have happened).
|
|
44
|
+
* - NONE — `customCatalog.add`: never retry. Custom-catalog upload is
|
|
45
|
+
* metered; auto-retry on transport failure could double-charge
|
|
46
|
+
* for the same audio fingerprinting. Surface a clean error and
|
|
47
|
+
* let the caller decide.
|
|
44
48
|
*/
|
|
45
|
-
type RetryClass = "read" | "recognition" | "mutating";
|
|
49
|
+
type RetryClass = "read" | "recognition" | "mutating" | "none";
|
|
46
50
|
interface RetryPolicy {
|
|
47
51
|
retryClass: RetryClass;
|
|
48
52
|
maxAttempts: number;
|
|
@@ -228,6 +232,19 @@ interface LongpollOptions {
|
|
|
228
232
|
timeout?: number;
|
|
229
233
|
/** Bypass the default-on `getCallbackUrl` preflight. */
|
|
230
234
|
skipCallbackCheck?: boolean;
|
|
235
|
+
/**
|
|
236
|
+
* Radio id to subscribe to — the SDK derives the 9-char category locally
|
|
237
|
+
* from `(api_token, radio_id)`. Mutually exclusive with `category`. Only
|
|
238
|
+
* meaningful on the object-form call site (`longpoll({ radioId: 42 })`).
|
|
239
|
+
*/
|
|
240
|
+
radioId?: number;
|
|
241
|
+
/**
|
|
242
|
+
* Pre-derived 9-char longpoll category. Mutually exclusive with `radioId`.
|
|
243
|
+
* Only meaningful on the object-form call site
|
|
244
|
+
* (`longpoll({ category: "abc123def" })`); the positional string form
|
|
245
|
+
* `longpoll("abc123def")` is the more common way to pass a category.
|
|
246
|
+
*/
|
|
247
|
+
category?: string;
|
|
231
248
|
}
|
|
232
249
|
declare class Streams {
|
|
233
250
|
private readonly http;
|
|
@@ -266,6 +283,17 @@ declare class Streams {
|
|
|
266
283
|
/**
|
|
267
284
|
* Long-poll the AudD subscription endpoint.
|
|
268
285
|
*
|
|
286
|
+
* Two call shapes:
|
|
287
|
+
*
|
|
288
|
+
* - **Common case** — pass an options object with `radioId`; the SDK
|
|
289
|
+
* derives the 9-char category locally from `(api_token, radio_id)`:
|
|
290
|
+
* `longpoll({ radioId: 42 })`.
|
|
291
|
+
* - **Tokenless / pre-derived category** — pass the category as a positional
|
|
292
|
+
* string (`longpoll("abc123def")`) or via the object form
|
|
293
|
+
* (`longpoll({ category: "abc123def" })`). Useful when the category was
|
|
294
|
+
* shared with you (e.g. a browser/mobile client running without the
|
|
295
|
+
* api_token).
|
|
296
|
+
*
|
|
269
297
|
* Returns a {@link LongpollPoll} handle with three async-iterables —
|
|
270
298
|
* `matches`, `notifications`, `errors` — that are filled by a background
|
|
271
299
|
* loop. Iterate them independently or in parallel via `Promise.all([...])`.
|
|
@@ -275,8 +303,16 @@ declare class Streams {
|
|
|
275
303
|
* callback URL, and the preflight surfaces that misconfiguration as an
|
|
276
304
|
* actionable {@link AudDInvalidRequestError}. Pass `skipCallbackCheck: true`
|
|
277
305
|
* to bypass.
|
|
306
|
+
*
|
|
307
|
+
* Throws {@link AudDInvalidRequestError} if the object form supplies both
|
|
308
|
+
* `radioId` and `category`, or neither.
|
|
278
309
|
*/
|
|
279
310
|
longpoll(category: string, opts?: LongpollOptions): Promise<LongpollPoll>;
|
|
311
|
+
longpoll(opts: LongpollOptions & ({
|
|
312
|
+
radioId: number;
|
|
313
|
+
} | {
|
|
314
|
+
category: string;
|
|
315
|
+
})): Promise<LongpollPoll>;
|
|
280
316
|
private preflightCallbackUrl;
|
|
281
317
|
}
|
|
282
318
|
|
|
@@ -286,8 +322,8 @@ interface CustomCatalogAddOptions {
|
|
|
286
322
|
}
|
|
287
323
|
declare class CustomCatalog {
|
|
288
324
|
private readonly http;
|
|
289
|
-
private readonly
|
|
290
|
-
constructor(http: HttpClient,
|
|
325
|
+
private readonly noRetryPolicy;
|
|
326
|
+
constructor(http: HttpClient, noRetryPolicy: RetryPolicy);
|
|
291
327
|
/**
|
|
292
328
|
* **This is NOT how you submit audio for music recognition.** For
|
|
293
329
|
* recognition, use `audd.recognize()` (or `audd.recognizeEnterprise()` for
|
|
@@ -299,6 +335,11 @@ declare class CustomCatalog {
|
|
|
299
335
|
* Calling this again with the same `audioId` re-fingerprints that slot.
|
|
300
336
|
* There is no public list/delete endpoint; track `audioId` ↔ song
|
|
301
337
|
* mappings on your side.
|
|
338
|
+
*
|
|
339
|
+
* **No automatic retry.** Custom-catalog upload is metered, and a transport
|
|
340
|
+
* failure could otherwise cause a silent re-upload that double-charges. Any
|
|
341
|
+
* 5xx or pre-upload connection error surfaces as a clean exception — the
|
|
342
|
+
* caller decides whether to retry.
|
|
302
343
|
*/
|
|
303
344
|
add(opts: CustomCatalogAddOptions): Promise<void>;
|
|
304
345
|
}
|
package/dist/index.js
CHANGED
|
@@ -662,6 +662,8 @@ function shouldRetryResponse(resp, retryClass) {
|
|
|
662
662
|
return s >= HTTP_SERVER_ERROR_FLOOR;
|
|
663
663
|
case "mutating":
|
|
664
664
|
return false;
|
|
665
|
+
case "none":
|
|
666
|
+
return false;
|
|
665
667
|
}
|
|
666
668
|
}
|
|
667
669
|
function shouldRetryError(err, retryClass) {
|
|
@@ -672,6 +674,8 @@ function shouldRetryError(err, retryClass) {
|
|
|
672
674
|
return isPreUploadConnectionError(err);
|
|
673
675
|
case "mutating":
|
|
674
676
|
return isPreUploadConnectionError(err);
|
|
677
|
+
case "none":
|
|
678
|
+
return false;
|
|
675
679
|
}
|
|
676
680
|
}
|
|
677
681
|
function sleep(ms) {
|
|
@@ -1147,30 +1151,42 @@ var Streams = class {
|
|
|
1147
1151
|
parseCallback(body) {
|
|
1148
1152
|
return parseCallback(body);
|
|
1149
1153
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1154
|
+
async longpoll(arg1, opts = {}) {
|
|
1155
|
+
let category;
|
|
1156
|
+
let effectiveOpts;
|
|
1157
|
+
if (typeof arg1 === "string") {
|
|
1158
|
+
category = arg1;
|
|
1159
|
+
effectiveOpts = opts;
|
|
1160
|
+
} else {
|
|
1161
|
+
effectiveOpts = arg1;
|
|
1162
|
+
const hasRadioId = arg1.radioId !== void 0;
|
|
1163
|
+
const hasCategory = arg1.category !== void 0;
|
|
1164
|
+
if (hasRadioId && hasCategory) {
|
|
1165
|
+
throw new AudDInvalidRequestError({
|
|
1166
|
+
errorCode: 0,
|
|
1167
|
+
message: "longpoll(): pass exactly one of `radioId` or `category` \u2014 got both.",
|
|
1168
|
+
httpStatus: 0
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
if (!hasRadioId && !hasCategory) {
|
|
1172
|
+
throw new AudDInvalidRequestError({
|
|
1173
|
+
errorCode: 0,
|
|
1174
|
+
message: "longpoll(): pass exactly one of `radioId` or `category` \u2014 got neither.",
|
|
1175
|
+
httpStatus: 0
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
category = hasRadioId ? this.deriveLongpollCategory(arg1.radioId) : arg1.category;
|
|
1179
|
+
}
|
|
1180
|
+
if (effectiveOpts.skipCallbackCheck !== true) {
|
|
1165
1181
|
await this.preflightCallbackUrl();
|
|
1166
1182
|
}
|
|
1167
|
-
const timeoutSec =
|
|
1183
|
+
const timeoutSec = effectiveOpts.timeout ?? 50;
|
|
1168
1184
|
const httpClient = this.http;
|
|
1169
1185
|
const readPolicy = this.readPolicy;
|
|
1170
1186
|
return startLongpoll({
|
|
1171
1187
|
category,
|
|
1172
1188
|
timeout: timeoutSec,
|
|
1173
|
-
sinceTime:
|
|
1189
|
+
sinceTime: effectiveOpts.sinceTime,
|
|
1174
1190
|
fetchOnce: (params, signal) => runRetried(
|
|
1175
1191
|
() => httpClient.get(`${API_BASE}/longpoll/`, params, { signal }),
|
|
1176
1192
|
readPolicy
|
|
@@ -1232,12 +1248,12 @@ async function runRetried2(fn, policy) {
|
|
|
1232
1248
|
}
|
|
1233
1249
|
}
|
|
1234
1250
|
var CustomCatalog = class {
|
|
1235
|
-
constructor(http,
|
|
1251
|
+
constructor(http, noRetryPolicy) {
|
|
1236
1252
|
this.http = http;
|
|
1237
|
-
this.
|
|
1253
|
+
this.noRetryPolicy = noRetryPolicy;
|
|
1238
1254
|
}
|
|
1239
1255
|
http;
|
|
1240
|
-
|
|
1256
|
+
noRetryPolicy;
|
|
1241
1257
|
/**
|
|
1242
1258
|
* **This is NOT how you submit audio for music recognition.** For
|
|
1243
1259
|
* recognition, use `audd.recognize()` (or `audd.recognizeEnterprise()` for
|
|
@@ -1249,6 +1265,11 @@ var CustomCatalog = class {
|
|
|
1249
1265
|
* Calling this again with the same `audioId` re-fingerprints that slot.
|
|
1250
1266
|
* There is no public list/delete endpoint; track `audioId` ↔ song
|
|
1251
1267
|
* mappings on your side.
|
|
1268
|
+
*
|
|
1269
|
+
* **No automatic retry.** Custom-catalog upload is metered, and a transport
|
|
1270
|
+
* failure could otherwise cause a silent re-upload that double-charges. Any
|
|
1271
|
+
* 5xx or pre-upload connection error surfaces as a clean exception — the
|
|
1272
|
+
* caller decides whether to retry.
|
|
1252
1273
|
*/
|
|
1253
1274
|
async add(opts) {
|
|
1254
1275
|
const reopen = prepareSource(opts.source);
|
|
@@ -1257,7 +1278,7 @@ var CustomCatalog = class {
|
|
|
1257
1278
|
const prepared = await reopen();
|
|
1258
1279
|
const fields = { ...prepared.fields, audio_id: audioId };
|
|
1259
1280
|
return this.http.postForm(UPLOAD_URL, fields);
|
|
1260
|
-
}, this.
|
|
1281
|
+
}, this.noRetryPolicy);
|
|
1261
1282
|
decodeSuccess2(resp.jsonBody, resp.httpStatus, resp.requestId);
|
|
1262
1283
|
}
|
|
1263
1284
|
};
|
|
@@ -1501,7 +1522,7 @@ var AudD = class {
|
|
|
1501
1522
|
/** Sub-namespace for the private fingerprint catalog. NOT for recognition. */
|
|
1502
1523
|
get customCatalog() {
|
|
1503
1524
|
if (this._customCatalog === void 0) {
|
|
1504
|
-
this._customCatalog = new CustomCatalog(this._http, this.policyFor("
|
|
1525
|
+
this._customCatalog = new CustomCatalog(this._http, this.policyFor("none"));
|
|
1505
1526
|
}
|
|
1506
1527
|
return this._customCatalog;
|
|
1507
1528
|
}
|