@audd/sdk 1.5.11 → 1.5.12

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.js CHANGED
@@ -3,7 +3,7 @@ import * as path from 'path';
3
3
  import { createHash } from 'crypto';
4
4
 
5
5
  // src/version.ts
6
- var VERSION = "1.5.8";
6
+ var VERSION = "1.5.12";
7
7
 
8
8
  // src/errors.ts
9
9
  var AudDError = class extends Error {
@@ -76,6 +76,16 @@ var AudDConnectionError = class extends AudDError {
76
76
  this.cause = cause;
77
77
  }
78
78
  };
79
+ var USER_ABORT_ERROR_NAME = "UserAbortError";
80
+ function userAbortError(cause) {
81
+ const err = new Error("Request was cancelled by the caller's AbortSignal");
82
+ err.name = USER_ABORT_ERROR_NAME;
83
+ err.cause = cause;
84
+ return err;
85
+ }
86
+ function isUserAbortError(err) {
87
+ return err !== null && typeof err === "object" && err.name === USER_ABORT_ERROR_NAME;
88
+ }
79
89
  var AudDSerializationError = class extends AudDError {
80
90
  name = "AudDSerializationError";
81
91
  rawText;
@@ -148,6 +158,55 @@ function raiseFromErrorResponse(body, opts) {
148
158
  throw new Cls(fields);
149
159
  }
150
160
 
161
+ // src/events.ts
162
+ function safeEmit(hook, event) {
163
+ if (hook === void 0) return;
164
+ try {
165
+ hook(event);
166
+ } catch {
167
+ }
168
+ }
169
+ async function emitAround(hook, method, url, fn) {
170
+ const startedAt = Date.now();
171
+ safeEmit(hook, {
172
+ kind: "request",
173
+ method,
174
+ url,
175
+ requestId: null,
176
+ httpStatus: null,
177
+ elapsedMs: null,
178
+ errorCode: null,
179
+ extras: {}
180
+ });
181
+ let resp;
182
+ try {
183
+ resp = await fn();
184
+ } catch (err) {
185
+ safeEmit(hook, {
186
+ kind: "exception",
187
+ method,
188
+ url,
189
+ requestId: null,
190
+ httpStatus: null,
191
+ elapsedMs: Date.now() - startedAt,
192
+ errorCode: null,
193
+ extras: { name: err instanceof Error ? err.name : String(err) }
194
+ });
195
+ throw err;
196
+ }
197
+ safeEmit(hook, {
198
+ kind: "response",
199
+ method,
200
+ url,
201
+ requestId: resp.requestId,
202
+ httpStatus: resp.httpStatus,
203
+ elapsedMs: Date.now() - startedAt,
204
+ errorCode: null,
205
+ extras: {}
206
+ });
207
+ return resp;
208
+ }
209
+
151
210
  // src/userAgent.ts
152
211
  function userAgent() {
153
212
  const node = typeof process !== "undefined" && process.version ? process.version.replace(/^v/, "") : "unknown";
@@ -225,6 +284,11 @@ var HttpClient = class {
225
284
  requestId: response.headers.get("x-request-id"),
226
285
  rawText: text
227
286
  };
287
+ } catch (err) {
288
+ if (userSignal?.aborted === true && err !== null && typeof err === "object" && err.name === "AbortError") {
289
+ throw userAbortError(err);
290
+ }
291
+ throw err;
228
292
  } finally {
229
293
  clearTimeout(timer);
230
294
  if (userSignal !== void 0) {
@@ -249,10 +313,8 @@ function asObject(raw) {
249
313
  }
250
314
  return void 0;
251
315
  }
252
- function requireObject(raw, what) {
253
- const o = asObject(raw);
254
- if (o === void 0) throw new TypeError(`${what}: expected object`);
255
- return o;
316
+ function asObjectLenient(raw) {
317
+ return asObject(raw) ?? {};
256
318
  }
257
319
  function asString(v) {
258
320
  return typeof v === "string" ? v : void 0;
@@ -356,7 +418,7 @@ var RECOGNITION_KEYS = [
356
418
  "musicbrainz"
357
419
  ];
358
420
  function parseRecognitionResult(raw) {
359
- const r = requireObject(raw, "RecognitionResult");
421
+ const r = asObjectLenient(raw);
360
422
  const timecode = asString(r.timecode);
361
423
  const audioId = asNumber(r.audio_id);
362
424
  const artist = asString(r.artist);
@@ -431,7 +493,7 @@ var ENTERPRISE_MATCH_KEYS = [
431
493
  "end_seconds"
432
494
  ];
433
495
  function parseEnterpriseMatch(raw) {
434
- const r = requireObject(raw, "EnterpriseMatch");
496
+ const r = asObjectLenient(raw);
435
497
  const score = asNumber(r.score);
436
498
  const timecode = asString(r.timecode);
437
499
  const songLink = asString(r.song_link);
@@ -481,8 +543,8 @@ function parseEnterpriseMatch(raw) {
481
543
  }
482
544
  var ENTERPRISE_CHUNK_KEYS = ["songs", "offset"];
483
545
  function parseEnterpriseChunkResult(raw) {
484
- const r = requireObject(raw, "EnterpriseChunkResult");
485
- const songsRaw = Array.isArray(r.songs) ? r.songs : [];
546
+ const r = asObjectLenient(raw);
547
+ const songsRaw = Array.isArray(r.songs) ? r.songs.filter((s) => asObject(s) !== void 0) : [];
486
548
  const offset = asString(r.offset);
487
549
  const base = parseOffsetToSeconds(r.offset);
488
550
  const songs = songsRaw.map((s) => {
@@ -502,7 +564,7 @@ function parseEnterpriseChunkResult(raw) {
502
564
  }
503
565
  var STREAM_KEYS = ["radio_id", "url", "stream_running", "longpoll_category"];
504
566
  function parseStream(raw) {
505
- const r = requireObject(raw, "Stream");
567
+ const r = asObjectLenient(raw);
506
568
  const radioId = asNumber(r.radio_id);
507
569
  const url = asString(r.url);
508
570
  const streamRunning = asBoolean(r.stream_running);
@@ -532,7 +594,7 @@ var STREAM_CALLBACK_SONG_KEYS = [
532
594
  "musicbrainz"
533
595
  ];
534
596
  function parseStreamCallbackSong(raw) {
535
- const r = requireObject(raw, "StreamCallbackSong");
597
+ const r = asObjectLenient(raw);
536
598
  const artist = asString(r.artist);
537
599
  const title = asString(r.title);
538
600
  const score = asNumber(r.score);
@@ -562,7 +624,7 @@ var STREAM_CALLBACK_MATCH_KEYS = [
562
624
  "results"
563
625
  ];
564
626
  function parseStreamCallbackMatch(raw) {
565
- const r = requireObject(raw, "StreamCallbackMatch");
627
+ const r = asObjectLenient(raw);
566
628
  const radioId = asNumber(r.radio_id);
567
629
  const resultsRaw = Array.isArray(r.results) ? r.results : [];
568
630
  const songs = resultsRaw.filter((x) => asObject(x) !== void 0).map(parseStreamCallbackSong);
@@ -584,7 +646,7 @@ var STREAM_CALLBACK_NOTIFICATION_KEYS = [
584
646
  "notification_message"
585
647
  ];
586
648
  function parseStreamCallbackNotification(raw) {
587
- const r = requireObject(raw, "StreamCallbackNotification");
649
+ const r = asObjectLenient(raw);
588
650
  const radioId = asNumber(r.radio_id);
589
651
  const code = asNumber(r.notification_code);
590
652
  const message = asString(r.notification_message);
@@ -608,7 +670,7 @@ var LYRICS_KEYS = [
608
670
  "media"
609
671
  ];
610
672
  function parseLyricsResult(raw) {
611
- const r = requireObject(raw, "LyricsResult");
673
+ const r = asObjectLenient(raw);
612
674
  const artist = asString(r.artist);
613
675
  const title = asString(r.title);
614
676
  return {
@@ -704,6 +766,22 @@ async function retry(fn, policy) {
704
766
  if (haveResp && lastResp !== void 0) return lastResp;
705
767
  throw lastError;
706
768
  }
769
+ async function runRetried(fn, policy) {
770
+ try {
771
+ return await retry(fn, policy);
772
+ } catch (err) {
773
+ if (isUserAbortError(err)) {
774
+ throw new AudDConnectionError("Request was cancelled by the caller's AbortSignal", err);
775
+ }
776
+ if (err instanceof TypeError) {
777
+ throw new AudDConnectionError(`Network error: ${err.message}`, err);
778
+ }
779
+ if (err !== null && typeof err === "object" && err.name === "AbortError") {
780
+ throw new AudDConnectionError("Request was aborted (timeout)", err);
781
+ }
782
+ throw err;
783
+ }
784
+ }
707
785
  function looksLikeUrl(s) {
708
786
  return s.startsWith("http://") || s.startsWith("https://");
709
787
  }
@@ -955,13 +1033,13 @@ function decodeOne(resp) {
955
1033
  );
956
1034
  }
957
1035
  const dict = body;
958
- if ("notification" in dict) {
1036
+ if (asObject(dict.notification) !== void 0) {
959
1037
  const notification = parseStreamCallbackNotification(dict.notification);
960
1038
  const t = dict["time"];
961
1039
  if (typeof t === "number") notification.time = t;
962
1040
  return { kind: "notification", notification };
963
1041
  }
964
- if ("result" in dict) {
1042
+ if (asObject(dict.result) !== void 0) {
965
1043
  return { kind: "match", match: parseStreamCallbackMatch(dict.result) };
966
1044
  }
967
1045
  return { kind: "keepalive" };
@@ -1040,6 +1118,7 @@ function startLongpoll(cfg) {
1040
1118
 
1041
1119
  // src/streams.ts
1042
1120
  var API_BASE = "https://api.audd.io";
1121
+ var LONGPOLL_TIMEOUT_MARGIN_SEC = 10;
1043
1122
  var NO_CALLBACK_ERROR_CODE = 19;
1044
1123
  var PREFLIGHT_NO_CALLBACK_HINT = "Longpoll won't deliver events because no callback URL is configured for this account. Set one first via streams.setCallbackUrl(...) \u2014 `https://audd.tech/empty/` is fine if you only want longpolling and don't need a real receiver. To skip this check, pass skipCallbackCheck: true.";
1045
1124
  function decodeSuccess(body, httpStatus, requestId) {
@@ -1064,34 +1143,26 @@ function decodeSuccess(body, httpStatus, requestId) {
1064
1143
  rawResponse: obj
1065
1144
  });
1066
1145
  }
1067
- async function runRetried(fn, policy) {
1068
- try {
1069
- return await retry(fn, policy);
1070
- } catch (err) {
1071
- if (err instanceof TypeError) {
1072
- throw new AudDConnectionError(`Network error: ${err.message}`, err);
1073
- }
1074
- if (err !== null && typeof err === "object" && err.name === "AbortError") {
1075
- throw new AudDConnectionError("Request was aborted (timeout)", err);
1076
- }
1077
- throw err;
1078
- }
1079
- }
1080
1146
  var Streams = class {
1081
- constructor(http, readPolicy, mutatingPolicy, apiToken) {
1147
+ constructor(http, readPolicy, mutatingPolicy, apiToken, onEvent) {
1082
1148
  this.http = http;
1083
1149
  this.readPolicy = readPolicy;
1084
1150
  this.mutatingPolicy = mutatingPolicy;
1085
1151
  this.apiToken = apiToken;
1152
+ this.onEvent = onEvent;
1086
1153
  }
1087
1154
  http;
1088
1155
  readPolicy;
1089
1156
  mutatingPolicy;
1090
1157
  apiToken;
1158
+ onEvent;
1091
1159
  async post(path2, fields, policy) {
1092
- const resp = await runRetried(
1093
- () => this.http.postForm(`${API_BASE}/${path2}/`, fields),
1094
- policy
1160
+ const url = `${API_BASE}/${path2}/`;
1161
+ const resp = await emitAround(
1162
+ this.onEvent,
1163
+ path2,
1164
+ url,
1165
+ () => runRetried(() => this.http.postForm(url, fields), policy)
1095
1166
  );
1096
1167
  return decodeSuccess(resp.jsonBody, resp.httpStatus, resp.requestId);
1097
1168
  }
@@ -1138,11 +1209,11 @@ var Streams = class {
1138
1209
  async list() {
1139
1210
  const result = await this.post("getStreams", {}, this.readPolicy);
1140
1211
  if (!Array.isArray(result)) return [];
1141
- return result.map(parseStream);
1212
+ return result.filter((x) => asObject(x) !== void 0).map(parseStream);
1142
1213
  }
1143
1214
  /** Compute the 9-char longpoll category locally — pure, no network. */
1144
1215
  deriveLongpollCategory(radioId) {
1145
- return deriveLongpollCategory(this.apiToken, radioId);
1216
+ return deriveLongpollCategory(this.apiToken(), radioId);
1146
1217
  }
1147
1218
  /**
1148
1219
  * Parse a callback POST body into `{ match, notification }`. Pass an
@@ -1184,13 +1255,21 @@ var Streams = class {
1184
1255
  const timeoutSec = effectiveOpts.timeout ?? 50;
1185
1256
  const httpClient = this.http;
1186
1257
  const readPolicy = this.readPolicy;
1258
+ const onEvent = this.onEvent;
1259
+ const longpollUrl = `${API_BASE}/longpoll/`;
1260
+ const timeoutMs = (timeoutSec + LONGPOLL_TIMEOUT_MARGIN_SEC) * 1e3;
1187
1261
  return startLongpoll({
1188
1262
  category,
1189
1263
  timeout: timeoutSec,
1190
1264
  sinceTime: effectiveOpts.sinceTime,
1191
- fetchOnce: (params, signal) => runRetried(
1192
- () => httpClient.get(`${API_BASE}/longpoll/`, params, { signal }),
1193
- readPolicy
1265
+ fetchOnce: (params, signal) => emitAround(
1266
+ onEvent,
1267
+ "longpoll",
1268
+ longpollUrl,
1269
+ () => runRetried(
1270
+ () => httpClient.get(longpollUrl, params, { signal, timeoutMs }),
1271
+ readPolicy
1272
+ )
1194
1273
  )
1195
1274
  });
1196
1275
  }
@@ -1235,26 +1314,15 @@ function decodeSuccess2(body, httpStatus, requestId) {
1235
1314
  });
1236
1315
  }
1237
1316
  }
1238
- async function runRetried2(fn, policy) {
1239
- try {
1240
- return await retry(fn, policy);
1241
- } catch (err) {
1242
- if (err instanceof TypeError) {
1243
- throw new AudDConnectionError(`Network error: ${err.message}`, err);
1244
- }
1245
- if (err !== null && typeof err === "object" && err.name === "AbortError") {
1246
- throw new AudDConnectionError("Request was aborted (timeout)", err);
1247
- }
1248
- throw err;
1249
- }
1250
- }
1251
1317
  var CustomCatalog = class {
1252
- constructor(http, noRetryPolicy) {
1318
+ constructor(http, noRetryPolicy, onEvent) {
1253
1319
  this.http = http;
1254
1320
  this.noRetryPolicy = noRetryPolicy;
1321
+ this.onEvent = onEvent;
1255
1322
  }
1256
1323
  http;
1257
1324
  noRetryPolicy;
1325
+ onEvent;
1258
1326
  /**
1259
1327
  * **This is NOT how you submit audio for music recognition.** For
1260
1328
  * recognition, use `audd.recognize()` (or `audd.recognizeEnterprise()` for
@@ -1275,42 +1343,36 @@ var CustomCatalog = class {
1275
1343
  async add(opts) {
1276
1344
  const reopen = prepareSource(opts.source);
1277
1345
  const audioId = String(opts.audioId);
1278
- const resp = await runRetried2(async () => {
1279
- const prepared = await reopen();
1280
- const fields = { ...prepared.fields, audio_id: audioId };
1281
- return this.http.postForm(UPLOAD_URL, fields);
1282
- }, this.noRetryPolicy);
1346
+ const resp = await emitAround(
1347
+ this.onEvent,
1348
+ "customCatalogAdd",
1349
+ UPLOAD_URL,
1350
+ () => runRetried(async () => {
1351
+ const prepared = await reopen();
1352
+ const fields = { ...prepared.fields, audio_id: audioId };
1353
+ return this.http.postForm(UPLOAD_URL, fields);
1354
+ }, this.noRetryPolicy)
1355
+ );
1283
1356
  decodeSuccess2(resp.jsonBody, resp.httpStatus, resp.requestId);
1284
1357
  }
1285
1358
  };
1286
1359
 
1287
1360
  // src/advanced.ts
1288
1361
  var API_BASE2 = "https://api.audd.io";
1289
- async function runRetried3(fn, policy) {
1290
- try {
1291
- return await retry(fn, policy);
1292
- } catch (err) {
1293
- if (err instanceof TypeError) {
1294
- throw new AudDConnectionError(`Network error: ${err.message}`, err);
1295
- }
1296
- if (err !== null && typeof err === "object" && err.name === "AbortError") {
1297
- throw new AudDConnectionError("Request was aborted (timeout)", err);
1298
- }
1299
- throw err;
1300
- }
1301
- }
1302
1362
  var Advanced = class {
1303
1363
  /**
1304
1364
  * @param recognitionPolicy The findLyrics endpoint is metered and shouldn't
1305
1365
  * double-bill on post-upload read timeout: Advanced uses RECOGNITION retry
1306
1366
  * policy, not READ.
1307
1367
  */
1308
- constructor(http, recognitionPolicy) {
1368
+ constructor(http, recognitionPolicy, onEvent) {
1309
1369
  this.http = http;
1310
1370
  this.recognitionPolicy = recognitionPolicy;
1371
+ this.onEvent = onEvent;
1311
1372
  }
1312
1373
  http;
1313
1374
  recognitionPolicy;
1375
+ onEvent;
1314
1376
  /** Find lyrics by free-text query. Returns a list of matches (possibly empty). */
1315
1377
  async findLyrics(query) {
1316
1378
  const body = await this.rawRequest("findLyrics", { q: query });
@@ -1334,9 +1396,12 @@ var Advanced = class {
1334
1396
  if (v === void 0) continue;
1335
1397
  fields[k] = String(v);
1336
1398
  }
1337
- const resp = await runRetried3(
1338
- () => this.http.postForm(`${API_BASE2}/${method}/`, fields),
1339
- this.recognitionPolicy
1399
+ const url = `${API_BASE2}/${method}/`;
1400
+ const resp = await emitAround(
1401
+ this.onEvent,
1402
+ method,
1403
+ url,
1404
+ () => runRetried(() => this.http.postForm(url, fields), this.recognitionPolicy)
1340
1405
  );
1341
1406
  const body = resp.jsonBody;
1342
1407
  if (typeof body !== "object" || body === null || Array.isArray(body)) {
@@ -1352,13 +1417,6 @@ var ENTERPRISE_BASE = "https://enterprise.audd.io";
1352
1417
  var DEPRECATED_PARAMS_CODE = 51;
1353
1418
  var HTTP_CLIENT_ERROR_FLOOR2 = 400;
1354
1419
  var TOKEN_ENV_VAR = "AUDD_API_TOKEN";
1355
- function safeEmit(hook, event) {
1356
- if (hook === void 0) return;
1357
- try {
1358
- hook(event);
1359
- } catch {
1360
- }
1361
- }
1362
1420
  function resolveToken(apiToken) {
1363
1421
  if (apiToken !== void 0 && apiToken !== "") return apiToken;
1364
1422
  const env = (typeof process !== "undefined" ? process.env[TOKEN_ENV_VAR] : void 0) ?? "";
@@ -1431,7 +1489,7 @@ function decodeOrRaise(resp) {
1431
1489
  function decodeRecognize(resp) {
1432
1490
  const body = decodeOrRaise(resp);
1433
1491
  const result = body["result"];
1434
- if (result == null) return null;
1492
+ if (asObject(result) === void 0) return null;
1435
1493
  return parseRecognitionResult(result);
1436
1494
  }
1437
1495
  function decodeEnterprise(resp) {
@@ -1440,24 +1498,12 @@ function decodeEnterprise(resp) {
1440
1498
  if (!Array.isArray(chunks)) return [];
1441
1499
  const out = [];
1442
1500
  for (const c of chunks) {
1501
+ if (asObject(c) === void 0) continue;
1443
1502
  const chunk = parseEnterpriseChunkResult(c);
1444
1503
  out.push(...chunk.songs);
1445
1504
  }
1446
1505
  return out;
1447
1506
  }
1448
- async function runRetried4(fn, policy) {
1449
- try {
1450
- return await retry(fn, policy);
1451
- } catch (err) {
1452
- if (err instanceof TypeError) {
1453
- throw new AudDConnectionError(`Network error: ${err.message}`, err);
1454
- }
1455
- if (err !== null && typeof err === "object" && err.name === "AbortError") {
1456
- throw new AudDConnectionError("Request was aborted (timeout)", err);
1457
- }
1458
- throw err;
1459
- }
1460
- }
1461
1507
  var AudD = class {
1462
1508
  _http;
1463
1509
  _enterpriseHttp;
@@ -1515,7 +1561,8 @@ var AudD = class {
1515
1561
  this._http,
1516
1562
  this.policyFor("read"),
1517
1563
  this.policyFor("mutating"),
1518
- this._apiToken
1564
+ () => this._apiToken,
1565
+ this._onEvent
1519
1566
  );
1520
1567
  }
1521
1568
  return this._streams;
@@ -1523,14 +1570,14 @@ var AudD = class {
1523
1570
  /** Sub-namespace for the private fingerprint catalog. NOT for recognition. */
1524
1571
  get customCatalog() {
1525
1572
  if (this._customCatalog === void 0) {
1526
- this._customCatalog = new CustomCatalog(this._http, this.policyFor("none"));
1573
+ this._customCatalog = new CustomCatalog(this._http, this.policyFor("none"), this._onEvent);
1527
1574
  }
1528
1575
  return this._customCatalog;
1529
1576
  }
1530
1577
  /** Lyrics search + raw-request escape hatch. */
1531
1578
  get advanced() {
1532
1579
  if (this._advanced === void 0) {
1533
- this._advanced = new Advanced(this._http, this.policyFor("recognition"));
1580
+ this._advanced = new Advanced(this._http, this.policyFor("recognition"), this._onEvent);
1534
1581
  }
1535
1582
  return this._advanced;
1536
1583
  }
@@ -1546,20 +1593,11 @@ var AudD = class {
1546
1593
  const market = opts.market;
1547
1594
  const policy = this.policyFor("recognition");
1548
1595
  const url = `${API_BASE3}/`;
1549
- const startedAt = Date.now();
1550
- safeEmit(this._onEvent, {
1551
- kind: "request",
1552
- method: "recognize",
1596
+ const resp = await emitAround(
1597
+ this._onEvent,
1598
+ "recognize",
1553
1599
  url,
1554
- requestId: null,
1555
- httpStatus: null,
1556
- elapsedMs: null,
1557
- errorCode: null,
1558
- extras: {}
1559
- });
1560
- let resp;
1561
- try {
1562
- resp = await runRetried4(async () => {
1600
+ () => runRetried(async () => {
1563
1601
  const prepared = await reopen();
1564
1602
  const fields = { ...prepared.fields };
1565
1603
  if (opts.extraParameters) Object.assign(fields, opts.extraParameters);
@@ -1569,30 +1607,8 @@ var AudD = class {
1569
1607
  ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
1570
1608
  ...opts.signal !== void 0 ? { signal: opts.signal } : {}
1571
1609
  });
1572
- }, policy);
1573
- } catch (err) {
1574
- safeEmit(this._onEvent, {
1575
- kind: "exception",
1576
- method: "recognize",
1577
- url,
1578
- requestId: null,
1579
- httpStatus: null,
1580
- elapsedMs: Date.now() - startedAt,
1581
- errorCode: null,
1582
- extras: { name: err instanceof Error ? err.name : String(err) }
1583
- });
1584
- throw err;
1585
- }
1586
- safeEmit(this._onEvent, {
1587
- kind: "response",
1588
- method: "recognize",
1589
- url,
1590
- requestId: resp.requestId,
1591
- httpStatus: resp.httpStatus,
1592
- elapsedMs: Date.now() - startedAt,
1593
- errorCode: null,
1594
- extras: {}
1595
- });
1610
+ }, policy)
1611
+ );
1596
1612
  return decodeRecognize(resp);
1597
1613
  }
1598
1614
  /**
@@ -1605,14 +1621,20 @@ var AudD = class {
1605
1621
  const reopen = prepareSource(source);
1606
1622
  const extra = buildEnterpriseFields(opts);
1607
1623
  const policy = this.policyFor("recognition");
1608
- const resp = await runRetried4(async () => {
1609
- const prepared = await reopen();
1610
- const fields = { ...prepared.fields, ...extra };
1611
- return this._enterpriseHttp.postForm(`${ENTERPRISE_BASE}/`, fields, {
1612
- ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
1613
- ...opts.signal !== void 0 ? { signal: opts.signal } : {}
1614
- });
1615
- }, policy);
1624
+ const url = `${ENTERPRISE_BASE}/`;
1625
+ const resp = await emitAround(
1626
+ this._onEvent,
1627
+ "recognizeEnterprise",
1628
+ url,
1629
+ () => runRetried(async () => {
1630
+ const prepared = await reopen();
1631
+ const fields = { ...prepared.fields, ...extra };
1632
+ return this._enterpriseHttp.postForm(url, fields, {
1633
+ ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
1634
+ ...opts.signal !== void 0 ? { signal: opts.signal } : {}
1635
+ });
1636
+ }, policy)
1637
+ );
1616
1638
  return decodeEnterprise(resp);
1617
1639
  }
1618
1640
  /** Release any underlying resources. (Currently a no-op for `fetch`-based transport.) */