@audd/sdk 1.4.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.
@@ -0,0 +1,58 @@
1
+ import { F as FetchLike } from './http-y2YwjfAl.cjs';
2
+
3
+ /**
4
+ * Tokenless longpoll consumer for browser/widget/extension use cases.
5
+ *
6
+ * Carries no api_token. The category alone authorizes the subscription. The
7
+ * user/server who derived the category is responsible for ensuring a
8
+ * callback URL is set on their account (we can't preflight that without a
9
+ * token).
10
+ *
11
+ * Behavior:
12
+ * - HTTP non-2xx → throws `AudDServerError` (no silent infinite loop)
13
+ * - JSON decode failure on 2xx → throws `AudDSerializationError`
14
+ * - READ-class retries on 5xx + connection failures, configurable via
15
+ * `maxRetries` / `backoffFactorMs`
16
+ * - `[Symbol.asyncDispose]()` + manual `close()` for resource cleanup
17
+ *
18
+ * Imported from `audd/longpoll` (browser-safe sub-entry, NOT the main
19
+ * `audd` module — bundlers tree-shake the auth client out).
20
+ */
21
+
22
+ interface LongpollConsumerOptions {
23
+ /** Maximum retry attempts (default 3). */
24
+ maxRetries?: number;
25
+ /** Initial backoff in ms (default 500), jittered, exponential. */
26
+ backoffFactorMs?: number;
27
+ /** Custom fetch (e.g., for proxy/mTLS). */
28
+ fetch?: FetchLike;
29
+ }
30
+ interface IterateOptions {
31
+ sinceTime?: number;
32
+ /** Server-side timeout in seconds (default 50). */
33
+ timeout?: number;
34
+ }
35
+ /**
36
+ * Tokenless async longpoll consumer.
37
+ *
38
+ * ```ts
39
+ * import { LongpollConsumer } from 'audd/longpoll';
40
+ *
41
+ * const consumer = new LongpollConsumer("abc123def");
42
+ * for await (const event of consumer.iterate({ timeout: 30 })) {
43
+ * console.log(event);
44
+ * }
45
+ * ```
46
+ */
47
+ declare class LongpollConsumer {
48
+ readonly category: string;
49
+ private readonly fetchImpl;
50
+ private readonly policy;
51
+ constructor(category: string, opts?: LongpollConsumerOptions);
52
+ iterate(opts?: IterateOptions): AsyncIterable<Record<string, unknown>>;
53
+ /** Release any underlying resources. */
54
+ close(): void;
55
+ [Symbol.asyncDispose](): Promise<void>;
56
+ }
57
+
58
+ export { type IterateOptions, LongpollConsumer, type LongpollConsumerOptions };
@@ -0,0 +1,58 @@
1
+ import { F as FetchLike } from './http-y2YwjfAl.js';
2
+
3
+ /**
4
+ * Tokenless longpoll consumer for browser/widget/extension use cases.
5
+ *
6
+ * Carries no api_token. The category alone authorizes the subscription. The
7
+ * user/server who derived the category is responsible for ensuring a
8
+ * callback URL is set on their account (we can't preflight that without a
9
+ * token).
10
+ *
11
+ * Behavior:
12
+ * - HTTP non-2xx → throws `AudDServerError` (no silent infinite loop)
13
+ * - JSON decode failure on 2xx → throws `AudDSerializationError`
14
+ * - READ-class retries on 5xx + connection failures, configurable via
15
+ * `maxRetries` / `backoffFactorMs`
16
+ * - `[Symbol.asyncDispose]()` + manual `close()` for resource cleanup
17
+ *
18
+ * Imported from `audd/longpoll` (browser-safe sub-entry, NOT the main
19
+ * `audd` module — bundlers tree-shake the auth client out).
20
+ */
21
+
22
+ interface LongpollConsumerOptions {
23
+ /** Maximum retry attempts (default 3). */
24
+ maxRetries?: number;
25
+ /** Initial backoff in ms (default 500), jittered, exponential. */
26
+ backoffFactorMs?: number;
27
+ /** Custom fetch (e.g., for proxy/mTLS). */
28
+ fetch?: FetchLike;
29
+ }
30
+ interface IterateOptions {
31
+ sinceTime?: number;
32
+ /** Server-side timeout in seconds (default 50). */
33
+ timeout?: number;
34
+ }
35
+ /**
36
+ * Tokenless async longpoll consumer.
37
+ *
38
+ * ```ts
39
+ * import { LongpollConsumer } from 'audd/longpoll';
40
+ *
41
+ * const consumer = new LongpollConsumer("abc123def");
42
+ * for await (const event of consumer.iterate({ timeout: 30 })) {
43
+ * console.log(event);
44
+ * }
45
+ * ```
46
+ */
47
+ declare class LongpollConsumer {
48
+ readonly category: string;
49
+ private readonly fetchImpl;
50
+ private readonly policy;
51
+ constructor(category: string, opts?: LongpollConsumerOptions);
52
+ iterate(opts?: IterateOptions): AsyncIterable<Record<string, unknown>>;
53
+ /** Release any underlying resources. */
54
+ close(): void;
55
+ [Symbol.asyncDispose](): Promise<void>;
56
+ }
57
+
58
+ export { type IterateOptions, LongpollConsumer, type LongpollConsumerOptions };
@@ -0,0 +1,244 @@
1
+ // src/errors.ts
2
+ var AudDError = class extends Error {
3
+ name = "AudDError";
4
+ };
5
+ var AudDAPIError = class extends AudDError {
6
+ name = "AudDAPIError";
7
+ errorCode;
8
+ httpStatus;
9
+ requestId;
10
+ requestedParams;
11
+ requestMethod;
12
+ brandedMessage;
13
+ rawResponse;
14
+ /** Original `error_message` from the server. (`Error.message` may be overridden by subclasses.) */
15
+ serverMessage;
16
+ constructor(init) {
17
+ super(`[#${init.errorCode}] ${init.message}`);
18
+ this.errorCode = init.errorCode;
19
+ this.serverMessage = init.message;
20
+ this.httpStatus = init.httpStatus;
21
+ this.requestId = init.requestId ?? null;
22
+ this.requestedParams = init.requestedParams ?? {};
23
+ this.requestMethod = init.requestMethod ?? null;
24
+ this.brandedMessage = init.brandedMessage ?? null;
25
+ this.rawResponse = init.rawResponse ?? null;
26
+ }
27
+ };
28
+ var AudDServerError = class extends AudDAPIError {
29
+ name = "AudDServerError";
30
+ };
31
+ var AudDConnectionError = class extends AudDError {
32
+ name = "AudDConnectionError";
33
+ cause;
34
+ constructor(message, cause) {
35
+ super(message);
36
+ this.cause = cause;
37
+ }
38
+ };
39
+ var AudDSerializationError = class extends AudDError {
40
+ name = "AudDSerializationError";
41
+ rawText;
42
+ constructor(message, rawText = "") {
43
+ super(message);
44
+ this.rawText = rawText;
45
+ }
46
+ };
47
+
48
+ // src/retry.ts
49
+ var DEFAULT_BACKOFF_FACTOR_MS = 500;
50
+ var DEFAULT_BACKOFF_MAX_MS = 3e4;
51
+ var DEFAULT_MAX_ATTEMPTS = 3;
52
+ var HTTP_REQUEST_TIMEOUT = 408;
53
+ var HTTP_TOO_MANY_REQUESTS = 429;
54
+ var HTTP_SERVER_ERROR_FLOOR = 500;
55
+ function defaultPolicy(retryClass) {
56
+ return {
57
+ retryClass,
58
+ maxAttempts: DEFAULT_MAX_ATTEMPTS,
59
+ backoffFactorMs: DEFAULT_BACKOFF_FACTOR_MS,
60
+ backoffMaxMs: DEFAULT_BACKOFF_MAX_MS
61
+ };
62
+ }
63
+ function backoffDelayMs(attempt, policy) {
64
+ const base = Math.min(policy.backoffFactorMs * 2 ** attempt, policy.backoffMaxMs);
65
+ return base * (0.5 + Math.random());
66
+ }
67
+ function isAbortError(err) {
68
+ if (err === null || typeof err !== "object") return false;
69
+ const e = err;
70
+ return e.name === "AbortError";
71
+ }
72
+ function isPreUploadConnectionError(err) {
73
+ if (isAbortError(err)) return false;
74
+ return err instanceof TypeError;
75
+ }
76
+ function shouldRetryResponse(resp, retryClass) {
77
+ const s = resp.httpStatus;
78
+ switch (retryClass) {
79
+ case "read":
80
+ return s === HTTP_REQUEST_TIMEOUT || s === HTTP_TOO_MANY_REQUESTS || s >= HTTP_SERVER_ERROR_FLOOR;
81
+ case "recognition":
82
+ return s >= HTTP_SERVER_ERROR_FLOOR;
83
+ case "mutating":
84
+ return false;
85
+ }
86
+ }
87
+ function shouldRetryError(err, retryClass) {
88
+ switch (retryClass) {
89
+ case "read":
90
+ return isPreUploadConnectionError(err) || isAbortError(err);
91
+ case "recognition":
92
+ return isPreUploadConnectionError(err);
93
+ case "mutating":
94
+ return isPreUploadConnectionError(err);
95
+ }
96
+ }
97
+ function sleep(ms) {
98
+ return new Promise((resolve) => setTimeout(resolve, ms));
99
+ }
100
+ async function retry(fn, policy) {
101
+ let lastError;
102
+ let lastResp;
103
+ let haveResp = false;
104
+ for (let attempt = 0; attempt < policy.maxAttempts; attempt++) {
105
+ try {
106
+ const resp = await fn();
107
+ if (!shouldRetryResponse(resp, policy.retryClass)) return resp;
108
+ lastResp = resp;
109
+ haveResp = true;
110
+ lastError = void 0;
111
+ } catch (err) {
112
+ if (!shouldRetryError(err, policy.retryClass)) throw err;
113
+ lastError = err;
114
+ haveResp = false;
115
+ if (attempt + 1 >= policy.maxAttempts) throw err;
116
+ }
117
+ if (attempt + 1 >= policy.maxAttempts) break;
118
+ await sleep(backoffDelayMs(attempt, policy));
119
+ }
120
+ if (haveResp && lastResp !== void 0) return lastResp;
121
+ throw lastError;
122
+ }
123
+
124
+ // src/version.ts
125
+ var VERSION = "1.4.6";
126
+
127
+ // src/userAgent.ts
128
+ function userAgent() {
129
+ const node = typeof process !== "undefined" && process.version ? process.version.replace(/^v/, "") : "unknown";
130
+ const platform = typeof process !== "undefined" && process.platform ? process.platform : "browser";
131
+ return `audd-node/${VERSION} node/${node} (${platform})`;
132
+ }
133
+
134
+ // src/longpoll.ts
135
+ var LONGPOLL_URL = "https://api.audd.io/longpoll/";
136
+ var HTTP_CLIENT_ERROR_FLOOR = 400;
137
+ var DEFAULT_TIMEOUT_MS = 12e4;
138
+ function decode(jsonBody, httpStatus, rawText) {
139
+ if (httpStatus >= HTTP_CLIENT_ERROR_FLOOR) {
140
+ throw new AudDServerError({
141
+ errorCode: 0,
142
+ message: `Longpoll endpoint returned HTTP ${String(httpStatus)}`,
143
+ httpStatus,
144
+ requestId: null,
145
+ rawResponse: jsonBody ?? rawText
146
+ });
147
+ }
148
+ if (typeof jsonBody !== "object" || jsonBody === null || Array.isArray(jsonBody)) {
149
+ throw new AudDSerializationError("Longpoll response was not a JSON object", rawText);
150
+ }
151
+ return jsonBody;
152
+ }
153
+ var LongpollConsumer = class {
154
+ constructor(category, opts = {}) {
155
+ this.category = category;
156
+ this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
157
+ const base = defaultPolicy("read");
158
+ this.policy = {
159
+ ...base,
160
+ maxAttempts: opts.maxRetries ?? base.maxAttempts,
161
+ backoffFactorMs: opts.backoffFactorMs ?? base.backoffFactorMs
162
+ };
163
+ }
164
+ category;
165
+ fetchImpl;
166
+ policy;
167
+ iterate(opts = {}) {
168
+ const category = this.category;
169
+ const policy = this.policy;
170
+ const fetchImpl = this.fetchImpl;
171
+ const initialSince = opts.sinceTime;
172
+ const timeoutSec = opts.timeout ?? 50;
173
+ async function fetchOnce(curSince) {
174
+ const u = new URL(LONGPOLL_URL);
175
+ u.searchParams.set("category", category);
176
+ u.searchParams.set("timeout", String(timeoutSec));
177
+ if (curSince !== void 0) u.searchParams.set("since_time", String(curSince));
178
+ const controller = new AbortController();
179
+ const timer = setTimeout(() => {
180
+ controller.abort();
181
+ }, DEFAULT_TIMEOUT_MS);
182
+ try {
183
+ const response = await fetchImpl(u.toString(), {
184
+ method: "GET",
185
+ headers: { "User-Agent": userAgent() },
186
+ signal: controller.signal
187
+ });
188
+ const text = await response.text();
189
+ let json = null;
190
+ if (text !== "") {
191
+ try {
192
+ json = JSON.parse(text);
193
+ } catch {
194
+ json = null;
195
+ }
196
+ }
197
+ return {
198
+ jsonBody: json,
199
+ httpStatus: response.status,
200
+ requestId: response.headers.get("x-request-id"),
201
+ rawText: text
202
+ };
203
+ } finally {
204
+ clearTimeout(timer);
205
+ }
206
+ }
207
+ return {
208
+ [Symbol.asyncIterator]() {
209
+ let curSince = initialSince;
210
+ return {
211
+ async next() {
212
+ let resp;
213
+ try {
214
+ resp = await retry(() => fetchOnce(curSince), policy);
215
+ } catch (err) {
216
+ if (err instanceof TypeError) {
217
+ throw new AudDConnectionError(`Network error: ${err.message}`, err);
218
+ }
219
+ if (err !== null && typeof err === "object" && err.name === "AbortError") {
220
+ throw new AudDConnectionError("Request was aborted (timeout)", err);
221
+ }
222
+ throw err;
223
+ }
224
+ const body = decode(resp.jsonBody, resp.httpStatus, resp.rawText);
225
+ const ts = body["timestamp"];
226
+ if (typeof ts === "number") curSince = ts;
227
+ return { value: body, done: false };
228
+ }
229
+ };
230
+ }
231
+ };
232
+ }
233
+ /** Release any underlying resources. */
234
+ close() {
235
+ }
236
+ async [Symbol.asyncDispose]() {
237
+ this.close();
238
+ await Promise.resolve();
239
+ }
240
+ };
241
+
242
+ export { LongpollConsumer };
243
+ //# sourceMappingURL=longpoll.js.map
244
+ //# sourceMappingURL=longpoll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/retry.ts","../src/version.ts","../src/userAgent.ts","../src/longpoll.ts"],"names":[],"mappings":";AAiBO,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAM;AAAA,EAC1B,IAAA,GAAO,WAAA;AAClB,CAAA;AAGO,IAAM,YAAA,GAAN,cAA2B,SAAA,CAAU;AAAA,EACjC,IAAA,GAAO,cAAA;AAAA,EAChB,SAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA;AAAA,EAEA,aAAA;AAAA,EAEA,YAAY,IAAA,EAAwB;AAClC,IAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAS,CAAA,EAAA,EAAK,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA;AAC5C,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA;AACtB,IAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,OAAA;AAC1B,IAAA,IAAA,CAAK,aAAa,IAAA,CAAK,UAAA;AACvB,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,SAAA,IAAa,IAAA;AACnC,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA,CAAK,eAAA,IAAmB,EAAC;AAChD,IAAA,IAAA,CAAK,aAAA,GAAgB,KAAK,aAAA,IAAiB,IAAA;AAC3C,IAAA,IAAA,CAAK,cAAA,GAAiB,KAAK,cAAA,IAAkB,IAAA;AAC7C,IAAA,IAAA,CAAK,WAAA,GAAc,KAAK,WAAA,IAAe,IAAA;AAAA,EACzC;AACF,CAAA;AAmCO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA,EACvC,IAAA,GAAO,iBAAA;AAClB,CAAA;AAEO,IAAM,mBAAA,GAAN,cAAkC,SAAA,CAAU;AAAA,EACxC,IAAA,GAAO,qBAAA;AAAA,EACP,KAAA;AAAA,EACT,WAAA,CAAY,SAAiB,KAAA,EAAiB;AAC5C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AACF,CAAA;AAEO,IAAM,sBAAA,GAAN,cAAqC,SAAA,CAAU;AAAA,EAC3C,IAAA,GAAO,wBAAA;AAAA,EAChB,OAAA;AAAA,EACA,WAAA,CAAY,OAAA,EAAiB,OAAA,GAAU,EAAA,EAAI;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AACF,CAAA;;;AC7EO,IAAM,yBAAA,GAA4B,GAAA;AAClC,IAAM,sBAAA,GAAyB,GAAA;AAC/B,IAAM,oBAAA,GAAuB,CAAA;AAEpC,IAAM,oBAAA,GAAuB,GAAA;AAC7B,IAAM,sBAAA,GAAyB,GAAA;AAC/B,IAAM,uBAAA,GAA0B,GAAA;AAEzB,SAAS,cAAc,UAAA,EAAqC;AACjE,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,WAAA,EAAa,oBAAA;AAAA,IACb,eAAA,EAAiB,yBAAA;AAAA,IACjB,YAAA,EAAc;AAAA,GAChB;AACF;AAEA,SAAS,cAAA,CAAe,SAAiB,MAAA,EAA6B;AACpE,EAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,MAAA,CAAO,kBAAkB,CAAA,IAAK,OAAA,EAAS,OAAO,YAAY,CAAA;AAChF,EAAA,OAAO,IAAA,IAAQ,GAAA,GAAM,IAAA,CAAK,MAAA,EAAO,CAAA;AACnC;AAQA,SAAS,aAAa,GAAA,EAAuB;AAC3C,EAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,OAAO,GAAA,KAAQ,UAAU,OAAO,KAAA;AACpD,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,OAAO,EAAE,IAAA,KAAS,YAAA;AACpB;AAEA,SAAS,2BAA2B,GAAA,EAAuB;AACzD,EAAA,IAAI,YAAA,CAAa,GAAG,CAAA,EAAG,OAAO,KAAA;AAE9B,EAAA,OAAO,GAAA,YAAe,SAAA;AACxB;AAEA,SAAS,mBAAA,CAAoB,MAAoB,UAAA,EAAiC;AAChF,EAAA,MAAM,IAAI,IAAA,CAAK,UAAA;AACf,EAAA,QAAQ,UAAA;AAAY,IAClB,KAAK,MAAA;AACH,MAAA,OACE,CAAA,KAAM,oBAAA,IACN,CAAA,KAAM,sBAAA,IACN,CAAA,IAAK,uBAAA;AAAA,IAET,KAAK,aAAA;AACH,MAAA,OAAO,CAAA,IAAK,uBAAA;AAAA,IACd,KAAK,UAAA;AACH,MAAA,OAAO,KAAA;AAAA;AAEb;AAEA,SAAS,gBAAA,CAAiB,KAAc,UAAA,EAAiC;AACvE,EAAA,QAAQ,UAAA;AAAY,IAClB,KAAK,MAAA;AAGH,MAAA,OAAO,0BAAA,CAA2B,GAAG,CAAA,IAAK,YAAA,CAAa,GAAG,CAAA;AAAA,IAC5D,KAAK,aAAA;AAEH,MAAA,OAAO,2BAA2B,GAAG,CAAA;AAAA,IACvC,KAAK,UAAA;AAEH,MAAA,OAAO,2BAA2B,GAAG,CAAA;AAAA;AAE3C;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AAEA,eAAsB,KAAA,CACpB,IACA,MAAA,EACY;AACZ,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,GAAU,MAAA,CAAO,aAAa,OAAA,EAAA,EAAW;AAC7D,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,EAAA,EAAG;AACtB,MAAA,IAAI,CAAC,mBAAA,CAAoB,IAAA,EAAM,MAAA,CAAO,UAAU,GAAG,OAAO,IAAA;AAC1D,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,SAAA,GAAY,KAAA,CAAA;AAAA,IACd,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,CAAC,gBAAA,CAAiB,GAAA,EAAK,MAAA,CAAO,UAAU,GAAG,MAAM,GAAA;AACrD,MAAA,SAAA,GAAY,GAAA;AACZ,MAAA,QAAA,GAAW,KAAA;AACX,MAAA,IAAI,OAAA,GAAU,CAAA,IAAK,MAAA,CAAO,WAAA,EAAa,MAAM,GAAA;AAAA,IAC/C;AACA,IAAA,IAAI,OAAA,GAAU,CAAA,IAAK,MAAA,CAAO,WAAA,EAAa;AACvC,IAAA,MAAM,KAAA,CAAM,cAAA,CAAe,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EAC7C;AACA,EAAA,IAAI,QAAA,IAAY,QAAA,KAAa,MAAA,EAAW,OAAO,QAAA;AAC/C,EAAA,MAAM,SAAA;AACR;;;AC3HO,IAAM,OAAA,GAAU,OAAA;;;ACEhB,SAAS,SAAA,GAAoB;AAClC,EAAA,MAAM,IAAA,GACJ,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,OAAA,GACtC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA,GAChC,SAAA;AACN,EAAA,MAAM,WACJ,OAAO,OAAA,KAAY,eAAe,OAAA,CAAQ,QAAA,GAAW,QAAQ,QAAA,GAAW,SAAA;AAC1E,EAAA,OAAO,CAAA,UAAA,EAAa,OAAO,CAAA,MAAA,EAAS,IAAI,KAAK,QAAQ,CAAA,CAAA,CAAA;AACvD;;;ACkBA,IAAM,YAAA,GAAe,+BAAA;AACrB,IAAM,uBAAA,GAA0B,GAAA;AAChC,IAAM,kBAAA,GAAqB,IAAA;AAiB3B,SAAS,MAAA,CACP,QAAA,EACA,UAAA,EACA,OAAA,EACyB;AACzB,EAAA,IAAI,cAAc,uBAAA,EAAyB;AACzC,IAAA,MAAM,IAAI,eAAA,CAAgB;AAAA,MACxB,SAAA,EAAW,CAAA;AAAA,MACX,OAAA,EAAS,CAAA,gCAAA,EAAmC,MAAA,CAAO,UAAU,CAAC,CAAA,CAAA;AAAA,MAC9D,UAAA;AAAA,MACA,SAAA,EAAW,IAAA;AAAA,MACX,aAAa,QAAA,IAAY;AAAA,KAC1B,CAAA;AAAA,EACH;AACA,EAAA,IAAI,OAAO,aAAa,QAAA,IAAY,QAAA,KAAa,QAAQ,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAChF,IAAA,MAAM,IAAI,sBAAA,CAAuB,yCAAA,EAA2C,OAAO,CAAA;AAAA,EACrF;AACA,EAAA,OAAO,QAAA;AACT;AAcO,IAAM,mBAAN,MAAuB;AAAA,EAI5B,WAAA,CAA4B,QAAA,EAAkB,IAAA,GAAgC,EAAC,EAAG;AAAtD,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAC1B,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,KAAA,IAAW,UAAA,CAAW,KAAA,CAAoB,KAAK,UAAU,CAAA;AAC/E,IAAA,MAAM,IAAA,GAAO,cAAc,MAAM,CAAA;AACjC,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,GAAG,IAAA;AAAA,MACH,WAAA,EAAa,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,WAAA;AAAA,MACrC,eAAA,EAAiB,IAAA,CAAK,eAAA,IAAmB,IAAA,CAAK;AAAA,KAChD;AAAA,EACF;AAAA,EAR4B,QAAA;AAAA,EAHX,SAAA;AAAA,EACA,MAAA;AAAA,EAYjB,OAAA,CAAQ,IAAA,GAAuB,EAAC,EAA2C;AACzE,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AACtB,IAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AACpB,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,IAAA,MAAM,eAAe,IAAA,CAAK,SAAA;AAC1B,IAAA,MAAM,UAAA,GAAa,KAAK,OAAA,IAAW,EAAA;AAEnC,IAAA,eAAe,UAAU,QAAA,EAAqD;AAC5E,MAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,YAAY,CAAA;AAC9B,MAAA,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,QAAQ,CAAA;AACvC,MAAA,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,SAAA,EAAW,MAAA,CAAO,UAAU,CAAC,CAAA;AAChD,MAAA,IAAI,QAAA,KAAa,QAAW,CAAA,CAAE,YAAA,CAAa,IAAI,YAAA,EAAc,MAAA,CAAO,QAAQ,CAAC,CAAA;AAE7E,MAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,QAAA,UAAA,CAAW,KAAA,EAAM;AAAA,MACnB,GAAG,kBAAkB,CAAA;AACrB,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,SAAA,CAAU,CAAA,CAAE,UAAS,EAAG;AAAA,UAC7C,MAAA,EAAQ,KAAA;AAAA,UACR,OAAA,EAAS,EAAE,YAAA,EAAc,SAAA,EAAU,EAAE;AAAA,UACrC,QAAQ,UAAA,CAAW;AAAA,SACpB,CAAA;AACD,QAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,QAAA,IAAI,IAAA,GAAgB,IAAA;AACpB,QAAA,IAAI,SAAS,EAAA,EAAI;AACf,UAAA,IAAI;AACF,YAAA,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,UACxB,CAAA,CAAA,MAAQ;AACN,YAAA,IAAA,GAAO,IAAA;AAAA,UACT;AAAA,QACF;AACA,QAAA,OAAO;AAAA,UACL,QAAA,EAAU,IAAA;AAAA,UACV,YAAY,QAAA,CAAS,MAAA;AAAA,UACrB,SAAA,EAAW,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AAAA,UAC9C,OAAA,EAAS;AAAA,SACX;AAAA,MACF,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,CAAC,MAAA,CAAO,aAAa,CAAA,GAA4C;AAC/D,QAAA,IAAI,QAAA,GAAW,YAAA;AACf,QAAA,OAAO;AAAA,UACL,MAAM,IAAA,GAAyD;AAC7D,YAAA,IAAI,IAAA;AACJ,YAAA,IAAI;AACF,cAAA,IAAA,GAAO,MAAM,KAAA,CAAM,MAAM,SAAA,CAAU,QAAQ,GAAG,MAAM,CAAA;AAAA,YACtD,SAAS,GAAA,EAAK;AACZ,cAAA,IAAI,eAAe,SAAA,EAAW;AAC5B,gBAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,eAAA,EAAkB,GAAA,CAAI,OAAO,IAAI,GAAG,CAAA;AAAA,cACpE;AACA,cAAA,IACE,QAAQ,IAAA,IACR,OAAO,QAAQ,QAAA,IACd,GAAA,CAA0B,SAAS,YAAA,EACpC;AACA,gBAAA,MAAM,IAAI,mBAAA,CAAoB,+BAAA,EAAiC,GAAG,CAAA;AAAA,cACpE;AACA,cAAA,MAAM,GAAA;AAAA,YACR;AACA,YAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,UAAU,IAAA,CAAK,UAAA,EAAY,KAAK,OAAO,CAAA;AAChE,YAAA,MAAM,EAAA,GAAK,KAAK,WAAW,CAAA;AAC3B,YAAA,IAAI,OAAO,EAAA,KAAO,QAAA,EAAU,QAAA,GAAW,EAAA;AACvC,YAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,KAAA,EAAM;AAAA,UACpC;AAAA,SACF;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,GAAc;AAAA,EAEd;AAAA,EAEA,OAAO,MAAA,CAAO,YAAY,CAAA,GAAmB;AAC3C,IAAA,IAAA,CAAK,KAAA,EAAM;AACX,IAAA,MAAM,QAAQ,OAAA,EAAQ;AAAA,EACxB;AACF","file":"longpoll.js","sourcesContent":["/** Exception hierarchy for AudD API errors. */\n\nexport interface AudDApiErrorFields {\n errorCode: number;\n message: string;\n httpStatus: number;\n requestId: string | null;\n requestedParams: Record<string, unknown>;\n requestMethod: string | null;\n brandedMessage: string | null;\n rawResponse: unknown;\n}\n\nexport type AudDApiErrorInit = Partial<AudDApiErrorFields> &\n Pick<AudDApiErrorFields, \"errorCode\" | \"message\" | \"httpStatus\">;\n\n/** Base for everything thrown by this SDK. */\nexport class AudDError extends Error {\n override name = \"AudDError\";\n}\n\n/** Server returned `status: error`. Carries the AudD error code + the full echo. */\nexport class AudDAPIError extends AudDError {\n override name = \"AudDAPIError\";\n errorCode: number;\n httpStatus: number;\n requestId: string | null;\n requestedParams: Record<string, unknown>;\n requestMethod: string | null;\n brandedMessage: string | null;\n rawResponse: unknown;\n /** Original `error_message` from the server. (`Error.message` may be overridden by subclasses.) */\n serverMessage: string;\n\n constructor(init: AudDApiErrorInit) {\n super(`[#${init.errorCode}] ${init.message}`);\n this.errorCode = init.errorCode;\n this.serverMessage = init.message;\n this.httpStatus = init.httpStatus;\n this.requestId = init.requestId ?? null;\n this.requestedParams = init.requestedParams ?? {};\n this.requestMethod = init.requestMethod ?? null;\n this.brandedMessage = init.brandedMessage ?? null;\n this.rawResponse = init.rawResponse ?? null;\n }\n}\n\nexport class AudDAuthenticationError extends AudDAPIError {\n override name = \"AudDAuthenticationError\";\n}\nexport class AudDQuotaError extends AudDAPIError {\n override name = \"AudDQuotaError\";\n}\nexport class AudDSubscriptionError extends AudDAPIError {\n override name = \"AudDSubscriptionError\";\n}\nexport class AudDCustomCatalogAccessError extends AudDSubscriptionError {\n override name = \"AudDCustomCatalogAccessError\";\n}\nexport class AudDInvalidRequestError extends AudDAPIError {\n override name = \"AudDInvalidRequestError\";\n}\nexport class AudDInvalidAudioError extends AudDAPIError {\n override name = \"AudDInvalidAudioError\";\n}\nexport class AudDRateLimitError extends AudDAPIError {\n override name = \"AudDRateLimitError\";\n}\nexport class AudDStreamLimitError extends AudDAPIError {\n override name = \"AudDStreamLimitError\";\n}\nexport class AudDNotReleasedError extends AudDAPIError {\n override name = \"AudDNotReleasedError\";\n}\nexport class AudDBlockedError extends AudDAPIError {\n override name = \"AudDBlockedError\";\n}\nexport class AudDNeedsUpdateError extends AudDAPIError {\n override name = \"AudDNeedsUpdateError\";\n}\nexport class AudDServerError extends AudDAPIError {\n override name = \"AudDServerError\";\n}\n\nexport class AudDConnectionError extends AudDError {\n override name = \"AudDConnectionError\";\n override cause?: unknown;\n constructor(message: string, cause?: unknown) {\n super(message);\n this.cause = cause;\n }\n}\n\nexport class AudDSerializationError extends AudDError {\n override name = \"AudDSerializationError\";\n rawText: string;\n constructor(message: string, rawText = \"\") {\n super(message);\n this.rawText = rawText;\n }\n}\n\nexport type AudDAPIErrorCtor = new (init: AudDApiErrorInit) => AudDAPIError;\n\nconst CODE_MAP: Record<number, AudDAPIErrorCtor> = {\n 900: AudDAuthenticationError,\n 901: AudDAuthenticationError,\n 903: AudDAuthenticationError,\n 902: AudDQuotaError,\n 904: AudDSubscriptionError,\n 905: AudDSubscriptionError,\n 50: AudDInvalidRequestError,\n 51: AudDInvalidRequestError,\n 600: AudDInvalidRequestError,\n 601: AudDInvalidRequestError,\n 602: AudDInvalidRequestError,\n 700: AudDInvalidRequestError,\n 701: AudDInvalidRequestError,\n 702: AudDInvalidRequestError,\n 906: AudDInvalidRequestError,\n 300: AudDInvalidAudioError,\n 400: AudDInvalidAudioError,\n 500: AudDInvalidAudioError,\n 610: AudDStreamLimitError,\n 611: AudDRateLimitError,\n 907: AudDNotReleasedError,\n 19: AudDBlockedError,\n 31337: AudDBlockedError,\n 20: AudDNeedsUpdateError,\n 100: AudDServerError,\n 1000: AudDServerError,\n};\n\nexport function errorClassForCode(code: number): AudDAPIErrorCtor {\n return CODE_MAP[code] ?? AudDServerError;\n}\n\nfunction brandedMessageOf(result: unknown): string | null {\n if (typeof result !== \"object\" || result === null) return null;\n const r = result as { artist?: unknown; title?: unknown };\n const parts: string[] = [];\n if (typeof r.artist === \"string\" && r.artist.length > 0) parts.push(r.artist);\n if (typeof r.title === \"string\" && r.title.length > 0) parts.push(r.title);\n return parts.length === 0 ? null : parts.join(\" — \");\n}\n\nexport interface ServerErrorBody {\n error?: { error_code?: number | undefined; error_message?: string | undefined } | undefined;\n result?: unknown;\n request_params?: Record<string, unknown> | undefined;\n requested_params?: Record<string, unknown> | undefined;\n request_api_method?: string | undefined;\n}\n\nexport interface RaiseFromErrorOpts {\n httpStatus: number;\n requestId: string | null;\n customCatalogContext?: boolean;\n}\n\nconst CUSTOM_CATALOG_PREFIX =\n \"Adding songs to your custom catalog requires enterprise access that isn't enabled on your account.\\n\\n\" +\n \"Note: the custom-catalog endpoint is for adding songs to your private fingerprint database, not for music recognition. \" +\n \"If you intended to identify music, use recognize(...) (or recognizeEnterprise(...) for files longer than 25 seconds) instead.\\n\\n\" +\n \"To request custom-catalog access, contact api@audd.io.\\n\\n\";\n\nexport function raiseFromErrorResponse(body: ServerErrorBody, opts: RaiseFromErrorOpts): never {\n const code = body.error?.error_code ?? 0;\n const message = body.error?.error_message ?? \"\";\n const requestedParams = body.request_params ?? body.requested_params ?? {};\n const requestMethod = body.request_api_method ?? null;\n const branded = brandedMessageOf(body.result);\n\n const fields: AudDApiErrorFields = {\n errorCode: code,\n message,\n httpStatus: opts.httpStatus,\n requestId: opts.requestId,\n requestedParams,\n requestMethod,\n brandedMessage: branded,\n rawResponse: body,\n };\n\n const Cls = errorClassForCode(code);\n if (opts.customCatalogContext === true && Cls === AudDSubscriptionError) {\n const overridden = `${CUSTOM_CATALOG_PREFIX}[Server message: ${message}]`;\n throw new AudDCustomCatalogAccessError({ ...fields, message: overridden });\n }\n throw new Cls(fields);\n}\n","import type { HttpResponse } from \"./http.js\";\n\n/**\n * Cost-aware retry classes.\n *\n * - READ — idempotent reads (`streams.list`, `streams.getCallbackUrl`):\n * retry on 408/429/5xx + any connection error.\n * - RECOGNITION — `recognize`, `recognizeEnterprise`, `advanced.findLyrics`:\n * retry on pre-upload connection failures + 5xx.\n * DO NOT retry on read-timeout-after-upload (cost protection).\n * - MUTATING — `streams.add`, `streams.delete`, etc., `customCatalog.add`:\n * retry only on pre-upload connection failures. DO NOT retry\n * 5xx (the side effect may have happened).\n */\nexport type RetryClass = \"read\" | \"recognition\" | \"mutating\";\n\nexport interface RetryPolicy {\n retryClass: RetryClass;\n maxAttempts: number;\n backoffFactorMs: number;\n backoffMaxMs: number;\n}\n\nexport const DEFAULT_BACKOFF_FACTOR_MS = 500;\nexport const DEFAULT_BACKOFF_MAX_MS = 30_000;\nexport const DEFAULT_MAX_ATTEMPTS = 3;\n\nconst HTTP_REQUEST_TIMEOUT = 408;\nconst HTTP_TOO_MANY_REQUESTS = 429;\nconst HTTP_SERVER_ERROR_FLOOR = 500;\n\nexport function defaultPolicy(retryClass: RetryClass): RetryPolicy {\n return {\n retryClass,\n maxAttempts: DEFAULT_MAX_ATTEMPTS,\n backoffFactorMs: DEFAULT_BACKOFF_FACTOR_MS,\n backoffMaxMs: DEFAULT_BACKOFF_MAX_MS,\n };\n}\n\nfunction backoffDelayMs(attempt: number, policy: RetryPolicy): number {\n const base = Math.min(policy.backoffFactorMs * 2 ** attempt, policy.backoffMaxMs);\n return base * (0.5 + Math.random());\n}\n\n/**\n * `fetch()` raises `TypeError(\"fetch failed\")` when DNS/TCP/TLS failed before\n * the request body finished. AbortError (or DOMException/AbortError) means the\n * caller's AbortSignal fired — could be pre- or post-upload, treated as\n * post-upload conservatively for cost-protection.\n */\nfunction isAbortError(err: unknown): boolean {\n if (err === null || typeof err !== \"object\") return false;\n const e = err as { name?: unknown };\n return e.name === \"AbortError\";\n}\n\nfunction isPreUploadConnectionError(err: unknown): boolean {\n if (isAbortError(err)) return false;\n // Node fetch wraps DNS/TCP/TLS errors as TypeError. Browsers do too.\n return err instanceof TypeError;\n}\n\nfunction shouldRetryResponse(resp: HttpResponse, retryClass: RetryClass): boolean {\n const s = resp.httpStatus;\n switch (retryClass) {\n case \"read\":\n return (\n s === HTTP_REQUEST_TIMEOUT ||\n s === HTTP_TOO_MANY_REQUESTS ||\n s >= HTTP_SERVER_ERROR_FLOOR\n );\n case \"recognition\":\n return s >= HTTP_SERVER_ERROR_FLOOR;\n case \"mutating\":\n return false;\n }\n}\n\nfunction shouldRetryError(err: unknown, retryClass: RetryClass): boolean {\n switch (retryClass) {\n case \"read\":\n // Pre-upload connection errors and post-upload read timeouts are both\n // safe-ish: idempotent reads can be retried freely.\n return isPreUploadConnectionError(err) || isAbortError(err);\n case \"recognition\":\n // Pre-upload only — explicitly NOT post-upload AbortError (cost protection).\n return isPreUploadConnectionError(err);\n case \"mutating\":\n // Pre-upload only — server-side side-effect may have happened.\n return isPreUploadConnectionError(err);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function retry<T extends HttpResponse>(\n fn: () => Promise<T>,\n policy: RetryPolicy,\n): Promise<T> {\n let lastError: unknown;\n let lastResp: T | undefined;\n let haveResp = false;\n for (let attempt = 0; attempt < policy.maxAttempts; attempt++) {\n try {\n const resp = await fn();\n if (!shouldRetryResponse(resp, policy.retryClass)) return resp;\n lastResp = resp;\n haveResp = true;\n lastError = undefined;\n } catch (err) {\n if (!shouldRetryError(err, policy.retryClass)) throw err;\n lastError = err;\n haveResp = false;\n if (attempt + 1 >= policy.maxAttempts) throw err;\n }\n if (attempt + 1 >= policy.maxAttempts) break;\n await sleep(backoffDelayMs(attempt, policy));\n }\n if (haveResp && lastResp !== undefined) return lastResp;\n throw lastError;\n}\n","export const VERSION = \"1.4.6\";\n","import { VERSION } from \"./version.js\";\n\nexport function userAgent(): string {\n const node =\n typeof process !== \"undefined\" && process.version\n ? process.version.replace(/^v/, \"\")\n : \"unknown\";\n const platform =\n typeof process !== \"undefined\" && process.platform ? process.platform : \"browser\";\n return `audd-node/${VERSION} node/${node} (${platform})`;\n}\n","/**\n * Tokenless longpoll consumer for browser/widget/extension use cases.\n *\n * Carries no api_token. The category alone authorizes the subscription. The\n * user/server who derived the category is responsible for ensuring a\n * callback URL is set on their account (we can't preflight that without a\n * token).\n *\n * Behavior:\n * - HTTP non-2xx → throws `AudDServerError` (no silent infinite loop)\n * - JSON decode failure on 2xx → throws `AudDSerializationError`\n * - READ-class retries on 5xx + connection failures, configurable via\n * `maxRetries` / `backoffFactorMs`\n * - `[Symbol.asyncDispose]()` + manual `close()` for resource cleanup\n *\n * Imported from `audd/longpoll` (browser-safe sub-entry, NOT the main\n * `audd` module — bundlers tree-shake the auth client out).\n */\n\nimport {\n AudDConnectionError,\n AudDSerializationError,\n AudDServerError,\n} from \"./errors.js\";\nimport type { FetchLike, HttpResponse } from \"./http.js\";\nimport { defaultPolicy, retry, type RetryPolicy } from \"./retry.js\";\nimport { userAgent } from \"./userAgent.js\";\n\nconst LONGPOLL_URL = \"https://api.audd.io/longpoll/\";\nconst HTTP_CLIENT_ERROR_FLOOR = 400;\nconst DEFAULT_TIMEOUT_MS = 120_000;\n\nexport interface LongpollConsumerOptions {\n /** Maximum retry attempts (default 3). */\n maxRetries?: number;\n /** Initial backoff in ms (default 500), jittered, exponential. */\n backoffFactorMs?: number;\n /** Custom fetch (e.g., for proxy/mTLS). */\n fetch?: FetchLike;\n}\n\nexport interface IterateOptions {\n sinceTime?: number;\n /** Server-side timeout in seconds (default 50). */\n timeout?: number;\n}\n\nfunction decode(\n jsonBody: unknown,\n httpStatus: number,\n rawText: string,\n): Record<string, unknown> {\n if (httpStatus >= HTTP_CLIENT_ERROR_FLOOR) {\n throw new AudDServerError({\n errorCode: 0,\n message: `Longpoll endpoint returned HTTP ${String(httpStatus)}`,\n httpStatus,\n requestId: null,\n rawResponse: jsonBody ?? rawText,\n });\n }\n if (typeof jsonBody !== \"object\" || jsonBody === null || Array.isArray(jsonBody)) {\n throw new AudDSerializationError(\"Longpoll response was not a JSON object\", rawText);\n }\n return jsonBody as Record<string, unknown>;\n}\n\n/**\n * Tokenless async longpoll consumer.\n *\n * ```ts\n * import { LongpollConsumer } from 'audd/longpoll';\n *\n * const consumer = new LongpollConsumer(\"abc123def\");\n * for await (const event of consumer.iterate({ timeout: 30 })) {\n * console.log(event);\n * }\n * ```\n */\nexport class LongpollConsumer {\n private readonly fetchImpl: FetchLike;\n private readonly policy: RetryPolicy;\n\n constructor(public readonly category: string, opts: LongpollConsumerOptions = {}) {\n this.fetchImpl = opts.fetch ?? ((globalThis.fetch as FetchLike).bind(globalThis));\n const base = defaultPolicy(\"read\");\n this.policy = {\n ...base,\n maxAttempts: opts.maxRetries ?? base.maxAttempts,\n backoffFactorMs: opts.backoffFactorMs ?? base.backoffFactorMs,\n };\n }\n\n iterate(opts: IterateOptions = {}): AsyncIterable<Record<string, unknown>> {\n const category = this.category;\n const policy = this.policy;\n const fetchImpl = this.fetchImpl;\n const initialSince = opts.sinceTime;\n const timeoutSec = opts.timeout ?? 50;\n\n async function fetchOnce(curSince: number | undefined): Promise<HttpResponse> {\n const u = new URL(LONGPOLL_URL);\n u.searchParams.set(\"category\", category);\n u.searchParams.set(\"timeout\", String(timeoutSec));\n if (curSince !== undefined) u.searchParams.set(\"since_time\", String(curSince));\n\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort();\n }, DEFAULT_TIMEOUT_MS);\n try {\n const response = await fetchImpl(u.toString(), {\n method: \"GET\",\n headers: { \"User-Agent\": userAgent() },\n signal: controller.signal,\n });\n const text = await response.text();\n let json: unknown = null;\n if (text !== \"\") {\n try {\n json = JSON.parse(text);\n } catch {\n json = null;\n }\n }\n return {\n jsonBody: json,\n httpStatus: response.status,\n requestId: response.headers.get(\"x-request-id\"),\n rawText: text,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n return {\n [Symbol.asyncIterator](): AsyncIterator<Record<string, unknown>> {\n let curSince = initialSince;\n return {\n async next(): Promise<IteratorResult<Record<string, unknown>>> {\n let resp;\n try {\n resp = await retry(() => fetchOnce(curSince), policy);\n } catch (err) {\n if (err instanceof TypeError) {\n throw new AudDConnectionError(`Network error: ${err.message}`, err);\n }\n if (\n err !== null &&\n typeof err === \"object\" &&\n (err as { name?: string }).name === \"AbortError\"\n ) {\n throw new AudDConnectionError(\"Request was aborted (timeout)\", err);\n }\n throw err;\n }\n const body = decode(resp.jsonBody, resp.httpStatus, resp.rawText);\n const ts = body[\"timestamp\"];\n if (typeof ts === \"number\") curSince = ts;\n return { value: body, done: false };\n },\n };\n },\n };\n }\n\n /** Release any underlying resources. */\n close(): void {\n /* no persistent connections in fetch */\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n this.close();\n await Promise.resolve();\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@audd/sdk",
3
+ "version": "1.4.7",
4
+ "description": "Official TypeScript SDK for the AudD music recognition API.",
5
+ "license": "MIT",
6
+ "author": "AudD <api@audd.io>",
7
+ "repository": "github:AudDMusic/audd-node",
8
+ "homepage": "https://audd.io",
9
+ "bugs": "https://github.com/AudDMusic/audd-node/issues",
10
+ "keywords": [
11
+ "audd",
12
+ "music-recognition",
13
+ "audio",
14
+ "fingerprinting"
15
+ ],
16
+ "type": "module",
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.cjs"
25
+ },
26
+ "./longpoll": {
27
+ "types": "./dist/longpoll.d.ts",
28
+ "import": "./dist/longpoll.js",
29
+ "require": "./dist/longpoll.cjs"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "LICENSE",
37
+ "CHANGELOG.md"
38
+ ],
39
+ "engines": {
40
+ "node": ">=20"
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "test:integration": "vitest run --config vitest.integration.config.ts",
47
+ "lint": "eslint src test",
48
+ "typecheck": "tsc --noEmit",
49
+ "ci": "npm run lint && npm run typecheck && npm run test && npm run build"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.11.0",
53
+ "eslint": "^9.0.0",
54
+ "msw": "^2.4.0",
55
+ "prettier": "^3.3.0",
56
+ "tsup": "^8.2.0",
57
+ "typescript": "^5.4.0",
58
+ "typescript-eslint": "^8.0.0",
59
+ "vitest": "^2.0.0"
60
+ },
61
+ "publishConfig": {
62
+ "access": "public",
63
+ "provenance": true
64
+ }
65
+ }