itd-api 0.9.1 → 0.9.3

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.
Files changed (63) hide show
  1. package/dist/events/index.cjs +3 -4
  2. package/dist/events/index.d.cts +3 -3
  3. package/dist/events/index.d.ts +3 -3
  4. package/dist/events/index.js +4 -4
  5. package/dist/index.cjs +283 -90
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +16 -72
  8. package/dist/index.d.ts +16 -72
  9. package/dist/index.js +284 -90
  10. package/dist/index.js.map +1 -1
  11. package/dist/node/index.cjs +3 -3
  12. package/dist/node/index.js +3 -3
  13. package/dist/rest/index.cjs +4 -5
  14. package/dist/rest/index.d.cts +3 -3
  15. package/dist/rest/index.d.ts +3 -3
  16. package/dist/rest/index.js +5 -5
  17. package/dist/shared/{events-BDdJyH2p.d.ts → events-BPxBF0gQ.d.cts} +3 -5
  18. package/dist/shared/{events-D6y0Hxyz.js → events-BzjI6pn5.js} +4 -4
  19. package/dist/shared/{events-D6y0Hxyz.js.map → events-BzjI6pn5.js.map} +1 -1
  20. package/dist/shared/{events-BqFkwwTw.cjs → events-C1FudmSe.cjs} +3 -9
  21. package/dist/shared/{events-BqFkwwTw.cjs.map → events-C1FudmSe.cjs.map} +1 -1
  22. package/dist/shared/{events-BQyH5-S0.d.cts → events-DnwfcLxS.d.ts} +3 -5
  23. package/dist/shared/{multi-storage-SoW05uzO.js → multi-storage-C3Ngtop1.js} +13 -8
  24. package/dist/shared/multi-storage-C3Ngtop1.js.map +1 -0
  25. package/dist/shared/{multi-storage-CDKLa956.cjs → multi-storage-s-fPtjoy.cjs} +13 -8
  26. package/dist/shared/multi-storage-s-fPtjoy.cjs.map +1 -0
  27. package/dist/shared/{options-DOJYtoti.cjs → options-DjEtbVaf.cjs} +2 -2
  28. package/dist/shared/{options-DOJYtoti.cjs.map → options-DjEtbVaf.cjs.map} +1 -1
  29. package/dist/shared/{options-DhgGg7Ms.js → options-i4LrKfqx.js} +2 -2
  30. package/dist/shared/{options-DhgGg7Ms.js.map → options-i4LrKfqx.js.map} +1 -1
  31. package/dist/shared/{redact-Ba5iSVYZ.js → redact-DJV0XM3n.js} +40 -15
  32. package/dist/shared/redact-DJV0XM3n.js.map +1 -0
  33. package/dist/shared/{redact-BP00URmQ.cjs → redact-lAmck1Z6.cjs} +45 -14
  34. package/dist/shared/redact-lAmck1Z6.cjs.map +1 -0
  35. package/dist/shared/{render-BU1_wex8.d.cts → render-C1F_QWYD.d.cts} +82 -19
  36. package/dist/shared/{render-sb1VJhUA.js → render-CtOpp9Pm.js} +127 -124
  37. package/dist/shared/render-CtOpp9Pm.js.map +1 -0
  38. package/dist/shared/{render-DAEeCMk9.cjs → render-Omy1drH1.cjs} +125 -128
  39. package/dist/shared/render-Omy1drH1.cjs.map +1 -0
  40. package/dist/shared/{render-CZ_-F2Tl.d.ts → render-uFW2kDxp.d.ts} +82 -19
  41. package/dist/shared/{storage-QNVxzpDB.cjs → storage-CZJZoaz9.cjs} +4 -2
  42. package/dist/shared/storage-CZJZoaz9.cjs.map +1 -0
  43. package/dist/shared/{storage-CfHKzVHf.js → storage-DiDe0PZM.js} +4 -2
  44. package/dist/shared/storage-DiDe0PZM.js.map +1 -0
  45. package/dist/shared/{url-Dsr4c5r5.js → url-3Ts6EEHQ.js} +301 -96
  46. package/dist/shared/url-3Ts6EEHQ.js.map +1 -0
  47. package/dist/shared/{url-CzHqE-Fg.cjs → url-D6wsXm1T.cjs} +301 -96
  48. package/dist/shared/url-D6wsXm1T.cjs.map +1 -0
  49. package/dist/shared/{url-CZZcyPI0.d.cts → url-DubjkRR9.d.cts} +10 -16
  50. package/dist/shared/{url-CZZcyPI0.d.ts → url-DubjkRR9.d.ts} +10 -16
  51. package/dist/web/index.cjs +1 -1
  52. package/dist/web/index.js +1 -1
  53. package/package.json +5 -5
  54. package/dist/shared/multi-storage-CDKLa956.cjs.map +0 -1
  55. package/dist/shared/multi-storage-SoW05uzO.js.map +0 -1
  56. package/dist/shared/redact-BP00URmQ.cjs.map +0 -1
  57. package/dist/shared/redact-Ba5iSVYZ.js.map +0 -1
  58. package/dist/shared/render-DAEeCMk9.cjs.map +0 -1
  59. package/dist/shared/render-sb1VJhUA.js.map +0 -1
  60. package/dist/shared/storage-CfHKzVHf.js.map +0 -1
  61. package/dist/shared/storage-QNVxzpDB.cjs.map +0 -1
  62. package/dist/shared/url-CzHqE-Fg.cjs.map +0 -1
  63. package/dist/shared/url-Dsr4c5r5.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import { $ as orderPluginDefinitions, A as ITD_CATALOG, C as ReportReason, D as ViewReason, E as SpanType, F as operationMethod, G as pickString, I as operationRetrySafety, K as RetrySafety, L as BUCKET_LIMITS, M as defineBuiltInOperation, N as isBuiltInOperationId, O as ViewSource, P as operationBucket, Q as assertPluginRemovable, R as DEFAULT_RATE_LIMIT_BUCKET, S as NotificationType, T as ServiceState, V as pickArray, Z as RequestQueuePool, _ as FeedTab, at as isRecord, b as ItdErrorCode, c as normalizeNotification, d as canonicalNotificationType, et as DEFAULT_BASE_URL, f as isKnownNotificationType, g as EventChannelStatus, h as CommentSort, it as LIBRARY_VERSION, j as OPERATIONS, k as WallAccess, lt as systemClock, m as AttachmentType, n as formatNotificationText, nt as STATUS_SERVICE, o as passthroughOperation, ot as requireOptionalBoolean, p as AccessType, rt as resolveRateLimit, s as voidOperation, st as RateLimitPacing, t as resolveNotificationUrl, ut as installAsyncDisposeFallback, v as IncidentKind, w as ReportTargetType, x as LikesVisibility, y as InteractionType, z as createClientRuntime } from "./shared/url-Dsr4c5r5.js";
1
+ import { $ as orderPluginDefinitions, A as ITD_CATALOG, C as ReportReason, D as ViewReason, E as SpanType, F as operationMethod, G as pickString, I as operationRetrySafety, K as RetrySafety, L as BUCKET_LIMITS, M as defineBuiltInOperation, N as isBuiltInOperationId, O as ViewSource, P as operationBucket, Q as assertPluginRemovable, R as DEFAULT_RATE_LIMIT_BUCKET, S as NotificationType, T as ServiceState, V as pickArray, Z as RequestQueuePool, _ as FeedTab, at as isRecord, b as ItdErrorCode, c as normalizeNotification, d as canonicalNotificationType, et as DEFAULT_BASE_URL, f as isKnownNotificationType, g as EventChannelStatus, h as CommentSort, it as LIBRARY_VERSION, j as OPERATIONS, k as WallAccess, lt as systemClock, m as AttachmentType, n as formatNotificationText, nt as STATUS_SERVICE, o as passthroughOperation, ot as requireOptionalBoolean, p as AccessType, rt as resolveRateLimit, s as voidOperation, st as RateLimitPacing, t as resolveNotificationUrl, ut as installAsyncDisposeFallback, v as IncidentKind, w as ReportTargetType, x as LikesVisibility, y as InteractionType, z as createClientRuntime } from "./shared/url-3Ts6EEHQ.js";
2
2
  import { A as isItdStateError, C as isItdError, D as isItdPhoneVerificationError, E as isItdNotFoundError, O as isItdRateLimitError, S as isItdConflictError, T as isItdForbiddenError, _ as ItdStateError, a as ItdConfigError, b as isItdApiError, c as ItdErrorKind, d as ItdForbiddenError, f as ItdNetworkError, g as ItdServerError, h as ItdRateLimitError, i as ItdAuthError, j as isItdValidationError, k as isItdServerError, l as ItdFileError, m as ItdPhoneVerificationError, n as ItdApiError, o as ItdConflictError, p as ItdNotFoundError, r as ItdApiErrorKind, s as ItdError, t as ItdAbortError, u as ItdFileErrorReason, v as ItdTimeoutError, w as isItdFileError, x as isItdAuthError, y as ItdValidationError } from "./shared/errors-GI10kZxk.js";
3
- import { _ as RuntimeMode, c as REFRESH_COOKIE, l as REFRESH_COOKIE_PATH, v as createDeviceId } from "./shared/redact-Ba5iSVYZ.js";
4
- import { A as toDate, C as ALLOWED_MIME_TYPES, D as comment, E as VIDEO_MIME_TYPES, F as Paginator, I as mapPage, L as createFeatureHost, M as NotificationsResource, N as BaseResource, O as isBuilder, P as PaginationMode, R as ExtensibleOperationCatalog, S as parseMarkdown, T as IMAGE_MIME_TYPES, _ as post, a as createMemoryShopOrderAccessStorage, b as markup, c as ShopConsentKind, d as ShopProductStatus, f as isMyProfile, g as report, h as createResources, i as MemoryShopOrderAccessStorage, j as utcStampToIso, k as createStatusFeature, l as ShopOrderStatus, m as fromUrl, n as renderSpans, o as createShopOrderAccessStorage, p as fromStream, r as createShopFeature, s as statusDays, t as SpanRenderFormat, u as ShopProductCategory, v as poll, w as AUDIO_MIME_TYPES, x as parseHtml, y as autoSpans } from "./shared/render-sb1VJhUA.js";
5
- import { c as FileTransferMode } from "./shared/options-DhgGg7Ms.js";
6
- import { _ as Emitter, a as WebSocketTransport, c as NotificationEventsTransport, d as NotificationUpdateOrigin, f as NotificationUpdateType, g as runEventMiddleware, h as UnauthorizedStreamError, i as createNotificationEventsClient, l as resolveNotificationEventsOptions, n as EventRouter, o as EVENT_OPERATIONS, p as EventChannel, r as NotificationEventsClient, s as NotificationEvents, t as EventComposer, u as setNotificationEventsConnectGuard, v as reportListenerError } from "./shared/events-D6y0Hxyz.js";
3
+ import { c as REFRESH_COOKIE, l as REFRESH_COOKIE_PATH, s as CookieJar, u as isSerializedCookieEntry, v as RuntimeMode, y as createDeviceId } from "./shared/redact-DJV0XM3n.js";
4
+ import { A as utcStampToIso, C as AUDIO_MIME_TYPES, D as isBuilder, E as comment, F as mapPage, I as createFeatureHost, L as ExtensibleOperationCatalog, M as BaseResource, N as PaginationMode, O as createStatusFeature, P as Paginator, S as ALLOWED_MIME_TYPES, T as VIDEO_MIME_TYPES, _ as poll, a as createShopOrderAccessStorage, b as parseHtml, c as ShopOrderStatus, d as isMyProfile, f as fromStream, g as post, h as report, i as MemoryShopOrderAccessStorage, j as NotificationsResource, k as toDate, l as ShopProductCategory, m as createResources, n as renderSpans, o as statusDays, p as fromUrl, r as createShopFeature, s as ShopConsentKind, t as SpanRenderFormat, u as ShopProductStatus, v as autoSpans, w as IMAGE_MIME_TYPES, x as parseMarkdown, y as markup } from "./shared/render-CtOpp9Pm.js";
5
+ import { c as FileTransferMode } from "./shared/options-i4LrKfqx.js";
6
+ import { _ as reportListenerError, a as WebSocketTransport, c as NotificationEventsTransport, d as NotificationUpdateOrigin, f as NotificationUpdateType, g as Emitter, h as runEventMiddleware, i as createNotificationEventsClient, l as resolveNotificationEventsOptions, m as UnauthorizedStreamError, n as EventRouter, o as EVENT_OPERATIONS, p as EventChannel, r as NotificationEventsClient, s as NotificationEvents, t as EventComposer, u as setNotificationEventsConnectGuard } from "./shared/events-BzjI6pn5.js";
7
7
  import { a as isEnumerableKeyValueStore, i as createRecordKeyValueStore, o as withCodec, r as createKeyValueStore, s as withNamespace, t as MemoryKeyValueStore } from "./shared/key-value-store-Bt2PSMxY.js";
8
- import { n as copySession, r as createTokenStorage, t as MemoryTokenStorage } from "./shared/storage-CfHKzVHf.js";
9
- import { a as scopedTokenStorage, i as isRestorableSession, n as controlledTokenStorage, r as createMultiTokenStorage, t as MemoryMultiTokenStorage } from "./shared/multi-storage-SoW05uzO.js";
8
+ import { n as copySession, r as createTokenStorage, t as MemoryTokenStorage } from "./shared/storage-DiDe0PZM.js";
9
+ import { a as scopedTokenStorage, i as isRestorableSession, n as controlledTokenStorage, r as createMultiTokenStorage, t as MemoryMultiTokenStorage } from "./shared/multi-storage-C3Ngtop1.js";
10
10
  //#region src/notifications-api.ts
11
11
  var ClientNotifications = class extends NotificationsResource {
12
12
  #createEvents;
@@ -49,7 +49,7 @@ const AUTH_SIGN_IN = defineBuiltInOperation("auth.signIn", (body) => {
49
49
  };
50
50
  });
51
51
  const AUTH_VERIFY_OTP = defineBuiltInOperation("auth.verifyOtp", (body) => requireString(body, "accessToken", "Сервер не вернул accessToken после подтверждения кода"));
52
- const AUTH_REFRESH = defineBuiltInOperation("auth.refresh", (body) => pickString(body, "accessToken"));
52
+ const AUTH_REFRESH = defineBuiltInOperation("auth.refresh", (body) => requireString(body, "accessToken", "Сервер не вернул accessToken при обновлении сессии"));
53
53
  const AUTH_RESEND_OTP = voidOperation("auth.resendOtp");
54
54
  const AUTH_LOGOUT = voidOperation("auth.logout");
55
55
  const AUTH_FORGOT_PASSWORD = defineBuiltInOperation("auth.forgotPassword", (body) => requireString(body, "flowToken", "Сервер не вернул flowToken при запросе сброса пароля"));
@@ -74,38 +74,34 @@ function decodeBase64Url(segment) {
74
74
  const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
75
75
  return new TextDecoder().decode(bytes);
76
76
  }
77
- /**
78
- * Читает `sub` и `sid` из полезной нагрузки JWT.
79
- *
80
- * Подпись не проверяется — ключа для проверки у клиента нет. Прочитанные значения служат
81
- * лишь метками для разделения локального состояния и не дают доступа: его определяет сервер.
82
- */
83
- function readTokenIdentity(token) {
77
+ /** Читает полезную нагрузку JWT без проверки подписи. */
78
+ function readTokenPayload(token) {
84
79
  try {
85
80
  const payload = token.split(".")[1];
86
- if (!payload) return {};
81
+ if (!payload) return void 0;
87
82
  const parsed = JSON.parse(decodeBase64Url(payload));
88
- if (typeof parsed !== "object" || parsed === null) return {};
89
- const { sub, sid } = parsed;
90
- return {
91
- ...typeof sub === "string" && sub.length > 0 ? { subject: sub } : {},
92
- ...typeof sid === "string" && sid.length > 0 ? { sessionId: sid } : {}
93
- };
83
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return void 0;
84
+ return parsed;
94
85
  } catch {
95
- return {};
86
+ return;
96
87
  }
97
88
  }
98
- /**
99
- * Читает `sub` из полезной нагрузки JWT.
100
- *
101
- * @returns идентификатор владельца токена; `undefined`, если токен не JWT, повреждён
102
- * или поля `sub` в нём нет
103
- */
104
- function readTokenSubject(token) {
105
- return readTokenIdentity(token).subject;
89
+ /** Читает используемые клиентом поля JWT за один раз. */
90
+ function readTokenMetadata(token) {
91
+ const payload = readTokenPayload(token);
92
+ if (!payload) return {};
93
+ const { sub, sid, exp } = payload;
94
+ const expiresAt = typeof exp === "number" && Number.isFinite(exp) ? exp * 1e3 : void 0;
95
+ return {
96
+ ...typeof sub === "string" && sub.length > 0 ? { subject: sub } : {},
97
+ ...typeof sid === "string" && sid.length > 0 ? { sessionId: sid } : {},
98
+ ...expiresAt !== void 0 && Number.isFinite(expiresAt) ? { expiresAt } : {}
99
+ };
106
100
  }
107
101
  //#endregion
108
102
  //#region src/session/auth.ts
103
+ /** Запас до истечения токена на очередь и выполнение запроса. */
104
+ const ACCESS_TOKEN_REFRESH_LEEWAY_MS = 3e4;
109
105
  /**
110
106
  * Проверяет форму `auth` и сообщает о типичных ошибках понятным текстом.
111
107
  *
@@ -119,12 +115,18 @@ function validateAuth(auth) {
119
115
  return auth;
120
116
  }
121
117
  if (typeof auth !== "object" || auth === null) throw new ItdConfigError(`auth должен быть строкой с токеном или объектом, получено: ${typeof auth}`);
118
+ if ([
119
+ "getToken" in auth,
120
+ "accessToken" in auth || "refreshToken" in auth,
121
+ "email" in auth || "password" in auth
122
+ ].filter(Boolean).length > 1) throw new ItdConfigError("auth должен описывать ровно один способ авторизации: getToken, accessToken или email/password");
122
123
  if ("getToken" in auth) {
123
124
  if (typeof auth.getToken !== "function") throw new ItdConfigError("auth.getToken должен быть функцией");
124
125
  return { ...auth };
125
126
  }
126
127
  if ("accessToken" in auth) {
127
128
  if (typeof auth.accessToken !== "string" || auth.accessToken.trim() === "") throw new ItdConfigError("auth.accessToken должен быть непустой строкой");
129
+ if (auth.refreshToken !== void 0 && (typeof auth.refreshToken !== "string" || auth.refreshToken.trim() === "")) throw new ItdConfigError("auth.refreshToken должен быть непустой строкой");
128
130
  return { ...auth };
129
131
  }
130
132
  if ("email" in auth || "password" in auth) {
@@ -212,10 +214,67 @@ const AUTH_PATHS = {
212
214
  const TURNSTILE_SITE_KEY = "0x4AAAAAACHhxczw6fJGwPBg";
213
215
  /** Убирает поле, которое сохраняли промежуточные версии с поддержкой `getUserId()`. */
214
216
  function withoutLegacyUserId(session) {
215
- const clean = { ...session };
217
+ const clean = copySession(session);
216
218
  delete clean.userId;
217
219
  return clean;
218
220
  }
221
+ function normalizeSessionValue(value, source, mode = "strict", logger) {
222
+ const tolerant = mode === "stored";
223
+ if (!isRecord(value)) {
224
+ if (tolerant) {
225
+ logger?.warn(`${source} вернула не объект сессии; сохранённая запись пропущена`);
226
+ return null;
227
+ }
228
+ throw new ItdConfigError(`${source} должна быть объектом сессии`);
229
+ }
230
+ const record = value;
231
+ const normalized = { ...record };
232
+ delete normalized.userId;
233
+ const normalizeString = (field) => {
234
+ const item = record[field];
235
+ if (item === void 0) {
236
+ delete normalized[field];
237
+ return;
238
+ }
239
+ if (item !== void 0 && (typeof item !== "string" || item.trim() === "")) {
240
+ if (tolerant) {
241
+ logger?.warn(`${source}.${field} повреждена; поле сохранённой сессии пропущено`);
242
+ delete normalized[field];
243
+ return;
244
+ }
245
+ throw new ItdConfigError(`${source}.${field} должна быть непустой строкой`);
246
+ }
247
+ normalized[field] = item;
248
+ };
249
+ normalizeString("accessToken");
250
+ normalizeString("refreshToken");
251
+ normalizeString("deviceId");
252
+ if (record.obtainedAt === void 0) delete normalized.obtainedAt;
253
+ else if (typeof record.obtainedAt !== "number" || !Number.isFinite(record.obtainedAt)) {
254
+ if (!tolerant) throw new ItdConfigError(`${source}.obtainedAt должна быть конечным числом`);
255
+ else {
256
+ logger?.warn(`${source}.obtainedAt повреждена; поле сохранённой сессии пропущено`);
257
+ delete normalized.obtainedAt;
258
+ }
259
+ }
260
+ if (record.cookies === void 0) delete normalized.cookies;
261
+ else if (!Array.isArray(record.cookies)) {
262
+ if (tolerant) {
263
+ logger?.warn(`${source}.cookies повреждена; поле сохранённой сессии пропущено`);
264
+ delete normalized.cookies;
265
+ } else throw new ItdConfigError(`${source}.cookies должна быть массивом`);
266
+ } else {
267
+ const valid = record.cookies.filter((cookie) => typeof cookie === "string" && isSerializedCookieEntry(cookie));
268
+ if (valid.length > 0) normalized.cookies = valid;
269
+ else delete normalized.cookies;
270
+ }
271
+ return normalized;
272
+ }
273
+ function normalizeSession(value, source) {
274
+ const normalized = normalizeSessionValue(value, source);
275
+ if (!normalized) throw new ItdConfigError(`${source} должна быть объектом сессии`);
276
+ return normalized;
277
+ }
219
278
  let authScopeSequence = 0;
220
279
  function nextAuthScope() {
221
280
  authScopeSequence += 1;
@@ -242,7 +301,7 @@ var AuthManager = class {
242
301
  * старте читают хранилище один раз и не заводят каждый свой `deviceId`.
243
302
  */
244
303
  #loading = null;
245
- /** Общий промис обновления: к нему присоединяются все, кто получил 401. */
304
+ /** Текущее обновление: к нему присоединяются запросы той же ревизии. */
246
305
  #refreshing = null;
247
306
  /** Общий промис входа по логину и паролю. */
248
307
  #signingIn = null;
@@ -252,6 +311,7 @@ var AuthManager = class {
252
311
  #externalToken;
253
312
  /** Идентификаторы последнего токена внешнего источника для синхронных потребителей. */
254
313
  #externalIdentity;
314
+ #tokenMetadata;
255
315
  /**
256
316
  * Идентификатор устройства.
257
317
  *
@@ -265,11 +325,12 @@ var AuthManager = class {
265
325
  * Счётчик смен владельца авторизации.
266
326
  *
267
327
  * Растёт при каждой операции, которая заменяет или очищает сессию извне: `clear`,
268
- * `setSession`, `setAccessToken`, вход. `#performRefresh` снимает его значение перед
269
- * сетевым запросом и сверяет перед записью — иначе запоздавший ответ обновления мог бы
270
- * воскресить уже очищенную сессию поверх `signOut`.
328
+ * `setSession`, `setAccessToken`, вход. Refresh сверяет снимок до и после сетевого запроса.
271
329
  */
272
330
  #authEpoch = 0;
331
+ #externalReadGeneration = 0;
332
+ #disposed = false;
333
+ #persistence = Promise.resolve();
273
334
  constructor(config, http, jar, hooks = {}) {
274
335
  this.#config = config;
275
336
  this.#http = http;
@@ -279,15 +340,25 @@ var AuthManager = class {
279
340
  }
280
341
  /** Подписка на события авторизации. */
281
342
  get on() {
282
- return this.#emitter.on.bind(this.#emitter);
343
+ return ((...args) => {
344
+ this.#assertActive();
345
+ return this.#emitter.on(...args);
346
+ });
283
347
  }
284
348
  /** Подписка на одно срабатывание. */
285
349
  get once() {
286
- return this.#emitter.once.bind(this.#emitter);
350
+ return ((...args) => {
351
+ this.#assertActive();
352
+ return this.#emitter.once(...args);
353
+ });
287
354
  }
288
355
  /** Снимает служебные подписки при окончательном освобождении владельца. @internal */
289
356
  dispose() {
357
+ if (this.#disposed) return;
358
+ this.#disposed = true;
359
+ this.#externalReadGeneration += 1;
290
360
  this.#invalidateInFlight();
361
+ this.#tokenMetadata = void 0;
291
362
  this.#emitter.removeAllListeners();
292
363
  }
293
364
  /**
@@ -301,6 +372,7 @@ var AuthManager = class {
301
372
  }
302
373
  /** Загружает сессию и возвращает идентификаторы аккаунта и сессии для плагинов. */
303
374
  async getAuthIdentity() {
375
+ this.#assertActive();
304
376
  const session = await this.#loadSession();
305
377
  if (session?.accessToken) return this.#identityForToken(session.accessToken);
306
378
  const auth = this.#config.auth;
@@ -321,16 +393,57 @@ var AuthManager = class {
321
393
  /** Отмечает смену владельца авторизации — обесценивает результат идущего обновления. */
322
394
  #invalidateInFlight() {
323
395
  this.#authEpoch += 1;
396
+ this.#externalReadGeneration += 1;
397
+ }
398
+ /** Ревизия владельца сессии для условного commit внешнего auth-flow. @internal */
399
+ revision() {
400
+ this.#assertActive();
401
+ return this.#authEpoch;
402
+ }
403
+ /** Создаёт изолированный jar для сетевого auth-flow. @internal */
404
+ createCookieFlow(inherit = true) {
405
+ this.#assertActive();
406
+ return inherit ? this.#jar.clone() : new CookieJar();
407
+ }
408
+ /** Применяет cookies только если владелец сессии не сменился. @internal */
409
+ commitCookieFlow(cookies, expectedRevision) {
410
+ this.#assertActive();
411
+ if (this.#authEpoch !== expectedRevision) return false;
412
+ this.#jar.replaceWith(cookies);
413
+ return true;
414
+ }
415
+ #assertActive() {
416
+ if (this.#disposed) throw new ItdStateError("Менеджер авторизации уже освобождён");
417
+ }
418
+ #currentAccessToken() {
419
+ return this.#session?.accessToken ?? null;
324
420
  }
325
421
  #identityForToken(accessToken) {
326
- const token = accessToken ? readTokenIdentity(accessToken) : {};
422
+ const token = this.#metadataForToken(accessToken);
327
423
  return {
328
424
  ...token.subject ? { userId: token.subject } : {},
329
425
  ...token.sessionId ? { sessionId: token.sessionId } : {}
330
426
  };
331
427
  }
428
+ #metadataForToken(accessToken) {
429
+ if (!accessToken) {
430
+ this.#tokenMetadata = void 0;
431
+ return {};
432
+ }
433
+ if (this.#tokenMetadata?.accessToken === accessToken) return this.#tokenMetadata.value;
434
+ const value = readTokenMetadata(accessToken);
435
+ this.#tokenMetadata = {
436
+ accessToken,
437
+ value
438
+ };
439
+ return value;
440
+ }
332
441
  async #readExternalToken(getToken) {
442
+ this.#assertActive();
443
+ const generation = ++this.#externalReadGeneration;
333
444
  const token = await getToken() ?? null;
445
+ this.#assertActive();
446
+ if (generation !== this.#externalReadGeneration) return token;
334
447
  const current = this.#identityForToken(token ?? void 0);
335
448
  if (this.#externalToken !== void 0 && this.#externalToken !== token) {
336
449
  this.#rotateAuthScope();
@@ -361,6 +474,7 @@ var AuthManager = class {
361
474
  * ответ был бы `false` даже при полностью рабочей сохранённой сессии.
362
475
  */
363
476
  async hasRefreshSession() {
477
+ this.#assertActive();
364
478
  await this.#loadSession();
365
479
  return this.#hasRefreshSession();
366
480
  }
@@ -370,14 +484,33 @@ var AuthManager = class {
370
484
  if (this.#jar.has("is_auth", this.#config.baseUrl)) return true;
371
485
  return Boolean(this.#session?.refreshToken);
372
486
  }
373
- /**
374
- * Готовит состояние авторизации до входа запроса в очередь. Стадия `auth_preparation`.
375
- *
376
- * Загрузка хранилища, внешний источник токена и отложенный вход асинхронны, поэтому
377
- * обязаны завершиться до захвата слота очереди.
378
- */
487
+ /** Готовит внутреннюю сессию до retry исходного запроса. */
488
+ async preflight(allowRefresh) {
489
+ this.#assertActive();
490
+ let accessToken = (await this.#loadSession())?.accessToken;
491
+ if (!accessToken) {
492
+ const auth = this.#config.auth;
493
+ if (typeof auth === "object" && auth !== null && "email" in auth) accessToken = await this.#signInWithCredentials(auth) ?? void 0;
494
+ }
495
+ if (!accessToken || !allowRefresh || !this.#config.autoRefresh) return;
496
+ const expiresAt = this.#metadataForToken(accessToken).expiresAt;
497
+ if (expiresAt === void 0 || expiresAt > this.#config.clock.now() + ACCESS_TOKEN_REFRESH_LEEWAY_MS || !this.#hasRefreshSession()) return;
498
+ try {
499
+ await this.#refreshDeduplicated({
500
+ epoch: this.#authEpoch,
501
+ accessToken
502
+ });
503
+ } catch (error) {
504
+ this.#emitter.emit("authError", { error });
505
+ throw error;
506
+ }
507
+ }
508
+ /** Перед каждой попыткой перечитывает внешний источник токена. */
379
509
  async prepare() {
380
- await this.token();
510
+ this.#assertActive();
511
+ if ((await this.#loadSession())?.accessToken) return;
512
+ const auth = this.#config.auth;
513
+ if (typeof auth === "object" && auth !== null && "getToken" in auth) await this.#readExternalToken(() => auth.getToken());
381
514
  }
382
515
  /**
383
516
  * Заголовки уже подготовленной авторизации без чтения storage или вызова внешнего источника.
@@ -396,6 +529,7 @@ var AuthManager = class {
396
529
  * через `itd.auth.refresh()`, а библиотека просто пробрасывает {@link ItdAuthError}.
397
530
  */
398
531
  recover() {
532
+ this.#assertActive();
399
533
  return this.#config.autoRefresh ? this.onUnauthorized() : Promise.resolve(false);
400
534
  }
401
535
  /**
@@ -406,6 +540,7 @@ var AuthManager = class {
406
540
  * по новой сессии на каждый старт.
407
541
  */
408
542
  deviceId() {
543
+ this.#assertActive();
409
544
  if (this.#deviceId) return Promise.resolve(this.#deviceId);
410
545
  this.#deviceIdLoading ??= this.#resolveDeviceId().finally(() => {
411
546
  this.#deviceIdLoading = null;
@@ -413,9 +548,12 @@ var AuthManager = class {
413
548
  return this.#deviceIdLoading;
414
549
  }
415
550
  async #resolveDeviceId() {
551
+ const revision = this.#authEpoch;
416
552
  const session = await this.#loadSession();
553
+ this.#assertActive();
417
554
  const deviceId = this.#config.deviceId ?? session?.deviceId ?? createDeviceId();
418
555
  this.#deviceId = deviceId;
556
+ if (this.#authEpoch !== revision) return deviceId;
419
557
  if (session?.deviceId !== deviceId) await this.#saveSession({
420
558
  ...session ?? {},
421
559
  deviceId
@@ -429,6 +567,7 @@ var AuthManager = class {
429
567
  * и пароль, первый же запрос сам заведёт сессию.
430
568
  */
431
569
  async token() {
570
+ this.#assertActive();
432
571
  const session = await this.#loadSession();
433
572
  if (session?.accessToken) return session.accessToken;
434
573
  const auth = this.#config.auth;
@@ -443,6 +582,7 @@ var AuthManager = class {
443
582
  * @returns `true`, если токен обновлён и запрос имеет смысл повторить
444
583
  */
445
584
  async onUnauthorized() {
585
+ this.#assertActive();
446
586
  try {
447
587
  if (await this.#refreshDeduplicated() !== null) return true;
448
588
  this.#emitter.emit("authError", { error: this.#noRefreshSessionError() });
@@ -478,24 +618,33 @@ var AuthManager = class {
478
618
  * @throws {ItdAuthError} если обновить сессию не удалось
479
619
  */
480
620
  async refresh() {
621
+ this.#assertActive();
481
622
  const token = await this.#refreshDeduplicated();
482
623
  if (token === null) throw this.#noRefreshSessionError();
483
624
  return token;
484
625
  }
485
626
  /** Сохраняет токен, полученный извне, — например после подтверждения OTP. */
486
- async setAccessToken(accessToken) {
627
+ async setAccessToken(accessToken, expectedRevision = this.#authEpoch, cookies) {
628
+ this.#assertActive();
629
+ if (typeof accessToken !== "string" || accessToken.trim() === "") throw new ItdConfigError("accessToken должен быть непустой строкой");
487
630
  await this.#loadSession();
631
+ this.#assertActive();
632
+ if (this.#authEpoch !== expectedRevision) return false;
633
+ if (cookies) this.#jar.replaceWith(cookies);
488
634
  this.#invalidateInFlight();
489
635
  this.#transitionAuth(accessToken);
490
- await this.#saveSession({
636
+ const saved = this.#saveSession({
491
637
  ...this.#session ?? {},
492
638
  accessToken,
493
639
  obtainedAt: this.#config.clock.now()
494
640
  });
495
641
  this.#emitter.emit("tokens", { accessToken });
642
+ await saved;
643
+ return true;
496
644
  }
497
645
  /** Текущая сессия целиком. Полезно, чтобы сохранить её самому. */
498
646
  async getSession() {
647
+ this.#assertActive();
499
648
  const session = await this.#loadSession();
500
649
  return session ? copySession(session) : null;
501
650
  }
@@ -506,20 +655,24 @@ var AuthManager = class {
506
655
  * токена идентификатор прежнего владельца остаться не может.
507
656
  */
508
657
  async getUserId() {
658
+ this.#assertActive();
509
659
  const session = await this.#loadSession();
510
- return session?.accessToken ? readTokenSubject(session.accessToken) : void 0;
660
+ return session?.accessToken ? this.#identityForToken(session.accessToken).userId : void 0;
511
661
  }
512
662
  /** Заменяет сессию и связанные с ней cookie целиком. */
513
663
  async setSession(session) {
664
+ this.#assertActive();
665
+ const normalized = normalizeSession(session, "session");
514
666
  await this.#loadSession();
667
+ this.#assertActive();
515
668
  this.#invalidateInFlight();
516
- this.#transitionAuth(session.accessToken);
669
+ this.#transitionAuth(normalized.accessToken);
517
670
  this.#jar.clear();
518
- this.#jar.deserialize(session.cookies);
519
- if (session.deviceId) this.#deviceId = session.deviceId;
520
- this.#session = session;
671
+ this.#jar.deserialize(normalized.cookies);
672
+ if (normalized.deviceId) this.#deviceId = normalized.deviceId;
673
+ this.#session = normalized;
521
674
  this.#seedRefreshCookie();
522
- await this.#saveSession(session);
675
+ await this.#saveSession(normalized);
523
676
  }
524
677
  /**
525
678
  * Забывает сессию и cookie. Сетевой запрос не выполняется.
@@ -528,14 +681,19 @@ var AuthManager = class {
528
681
  * новую запись в списке сессий.
529
682
  */
530
683
  async clear() {
684
+ this.#assertActive();
531
685
  await this.#loadSession();
686
+ this.#assertActive();
532
687
  this.#invalidateInFlight();
533
688
  this.#transitionAuth(void 0);
534
- this.#session = null;
535
689
  this.#jar.clear();
536
- await this.#config.storage.clear();
537
- if (this.#deviceId) await this.#saveSession({ deviceId: this.#deviceId });
690
+ const retained = this.#deviceId ? { deviceId: this.#deviceId } : null;
691
+ this.#session = retained;
538
692
  this.#emitter.emit("signOut", void 0);
693
+ await this.#enqueuePersistence(async () => {
694
+ await this.#config.storage.clear();
695
+ if (retained) await this.#config.storage.set(copySession(retained));
696
+ });
539
697
  }
540
698
  #loadSession() {
541
699
  if (this.#session !== void 0) return Promise.resolve(this.#session);
@@ -546,7 +704,8 @@ var AuthManager = class {
546
704
  }
547
705
  async #performLoad() {
548
706
  const loaded = await this.#config.storage.get() ?? null;
549
- const stored = loaded ? withoutLegacyUserId(loaded) : null;
707
+ this.#assertActive();
708
+ const stored = loaded === null ? null : normalizeSessionValue(loaded, "storage.get()", "stored", this.#config.logger);
550
709
  if (stored?.cookies) this.#jar.deserialize(stored.cookies);
551
710
  const fromConfig = this.#sessionFromConfig(this.#config.auth);
552
711
  this.#session = stored && fromConfig ? {
@@ -568,7 +727,7 @@ var AuthManager = class {
568
727
  if (!this.#config.useCookieJar) return;
569
728
  const refreshToken = this.#session?.refreshToken;
570
729
  if (!refreshToken) return;
571
- if (this.#jar.has("refresh_token")) return;
730
+ if (this.#jar.has("refresh_token", this.#config.baseUrl + "/api/v1/auth")) return;
572
731
  this.#jar.set(this.#config.baseUrl, REFRESH_COOKIE, refreshToken, REFRESH_COOKIE_PATH);
573
732
  }
574
733
  #sessionFromConfig(auth) {
@@ -587,56 +746,76 @@ var AuthManager = class {
587
746
  async #saveSession(session) {
588
747
  const cookies = this.#config.useCookieJar ? this.#jar.serialize() : void 0;
589
748
  const deviceId = session.deviceId ?? this.#deviceId;
749
+ const { cookies: _staleCookies, ...withoutCookies } = copySession(session);
590
750
  const next = withoutLegacyUserId({
591
- ...session,
751
+ ...withoutCookies,
592
752
  ...cookies?.length ? { cookies } : {},
593
753
  ...deviceId ? { deviceId } : {}
594
754
  });
595
755
  this.#session = next;
596
- await this.#config.storage.set(next);
597
- }
598
- /**
599
- * Обновление с дедупликацией.
600
- *
601
- * Все, кто пришёл, пока обновление уже идёт, получают его результат, а не запускают своё.
602
- */
603
- #refreshDeduplicated() {
604
- if (this.#refreshing) return this.#refreshing;
605
- const promise = this.#performRefresh().finally(() => {
606
- this.#refreshing = null;
756
+ await this.#enqueuePersistence(() => this.#config.storage.set(copySession(next)));
757
+ }
758
+ #enqueuePersistence(operation) {
759
+ const pending = this.#persistence.then(operation, operation);
760
+ this.#persistence = pending.catch(() => {});
761
+ return pending;
762
+ }
763
+ /** Дедуплицирует refresh одной ревизии; следующая ждёт завершения предыдущей. */
764
+ #refreshDeduplicated(expectation = { epoch: this.#authEpoch }) {
765
+ const current = this.#refreshing;
766
+ if (current) {
767
+ if (current.epoch === expectation.epoch) return current.promise;
768
+ return current.promise.then(() => this.#refreshDeduplicated(expectation), () => this.#refreshDeduplicated(expectation));
769
+ }
770
+ const promise = this.#performRefresh(expectation).finally(() => {
771
+ if (this.#refreshing?.promise === promise) this.#refreshing = null;
607
772
  });
608
- this.#refreshing = promise;
773
+ this.#refreshing = {
774
+ epoch: expectation.epoch,
775
+ promise
776
+ };
609
777
  return promise;
610
778
  }
611
- async #performRefresh() {
779
+ #matchesRefreshExpectation(expectation) {
780
+ return this.#authEpoch === expectation.epoch && (expectation.accessToken === void 0 || this.#session?.accessToken === expectation.accessToken);
781
+ }
782
+ async #performRefresh(expectation) {
783
+ this.#assertActive();
612
784
  await this.#loadSession();
785
+ if (!this.#matchesRefreshExpectation(expectation)) return this.#currentAccessToken();
613
786
  if (!this.#hasRefreshSession()) return this.#reloginOrNull();
614
- const epoch = this.#authEpoch;
787
+ const flowCookies = this.#jar.clone();
615
788
  try {
616
789
  const accessToken = await this.#http.execute(AUTH_REFRESH, {
617
790
  path: AUTH_PATHS.refresh,
618
791
  skipAuth: true,
619
- skipAuthRefresh: true
792
+ skipAuthRefresh: true,
793
+ cookieJar: flowCookies
620
794
  });
621
- if (!accessToken) return this.#reloginOrNull();
622
- if (this.#authEpoch !== epoch) return this.#session?.accessToken ?? null;
795
+ if (!this.#matchesRefreshExpectation(expectation)) return this.#session?.accessToken ?? null;
796
+ this.#jar.replaceWith(flowCookies);
623
797
  const rotated = this.#jar.getValue(REFRESH_COOKIE, this.#config.baseUrl + REFRESH_COOKIE_PATH);
624
798
  this.#transitionAuth(accessToken, false);
625
- await this.#saveSession({
799
+ const saved = this.#saveSession({
626
800
  ...this.#session ?? {},
627
801
  accessToken,
628
802
  ...rotated ? { refreshToken: rotated } : {},
629
803
  obtainedAt: this.#config.clock.now()
630
804
  });
631
805
  this.#emitter.emit("tokens", { accessToken });
806
+ await saved;
807
+ if (this.#authEpoch !== expectation.epoch) return this.#currentAccessToken();
632
808
  return accessToken;
633
809
  } catch (error) {
634
- if (error instanceof ItdApiError) {
635
- if (this.#authEpoch !== epoch) return this.#session?.accessToken ?? null;
810
+ if (this.#authEpoch !== expectation.epoch) return this.#currentAccessToken();
811
+ if (error instanceof ItdAuthError) {
812
+ this.#invalidateInFlight();
813
+ const clearedRevision = this.#authEpoch;
636
814
  this.#transitionAuth(void 0);
637
815
  this.#session = null;
638
816
  this.#jar.clear();
639
- await this.#config.storage.clear();
817
+ await this.#enqueuePersistence(() => this.#config.storage.clear());
818
+ if (this.#authEpoch !== clearedRevision) return this.#currentAccessToken();
640
819
  const relogged = await this.#reloginOrNull();
641
820
  if (relogged !== null) return relogged;
642
821
  throw error;
@@ -650,7 +829,8 @@ var AuthManager = class {
650
829
  if (!this.#config.reloginOnRefreshFailure || !auth || typeof auth !== "object" || !("email" in auth)) return null;
651
830
  try {
652
831
  return await this.#signInWithCredentials(auth);
653
- } catch {
832
+ } catch (error) {
833
+ this.#config.logger?.warn("Автоматический повторный вход не удался", error);
654
834
  return null;
655
835
  }
656
836
  }
@@ -662,7 +842,8 @@ var AuthManager = class {
662
842
  */
663
843
  #signInWithCredentials(credentials) {
664
844
  if (this.#signingIn) return this.#signingIn;
665
- const promise = this.#performSignIn(credentials).finally(() => {
845
+ const revision = this.#authEpoch;
846
+ const promise = this.#performSignIn(credentials, revision).finally(() => {
666
847
  this.#signingIn = null;
667
848
  });
668
849
  this.#signingIn = promise;
@@ -682,8 +863,9 @@ var AuthManager = class {
682
863
  if (credentials.turnstileToken) return credentials.turnstileToken;
683
864
  throw new ItdConfigError("Вход по email и паролю требует токен капчи Cloudflare Turnstile: без него сервер отвечает 422. Передайте auth.getTurnstileToken (источник свежего токена) либо разовый auth.turnstileToken. Ключ виджета — TURNSTILE_SITE_KEY. В Node токен умеет добывать отдельный пакет: npm i @itd-api/turnstile, затем getTurnstileToken: createTurnstileSolver().");
684
865
  }
685
- async #performSignIn(credentials) {
866
+ async #performSignIn(credentials, revision) {
686
867
  const turnstileToken = await this.#resolveTurnstileToken(credentials);
868
+ const flowCookies = new CookieJar();
687
869
  const result = await this.#http.execute(AUTH_SIGN_IN, {
688
870
  path: AUTH_PATHS.signIn,
689
871
  body: {
@@ -692,18 +874,23 @@ var AuthManager = class {
692
874
  turnstileToken
693
875
  },
694
876
  skipAuth: true,
695
- skipAuthRefresh: true
877
+ skipAuthRefresh: true,
878
+ cookieJar: flowCookies
696
879
  });
697
880
  if (result.status !== SignInStatus.Authenticated) throw new ItdConfigError("Вход по email и паролю требует подтверждения кодом из письма. Автоматический вход невозможен: воспользуйтесь itd.auth.signInWithOtp() и передайте полученный accessToken в конфигурацию клиента.");
698
881
  const accessToken = result.accessToken;
882
+ this.#assertActive();
883
+ if (this.#authEpoch !== revision) return this.#session?.accessToken ?? null;
884
+ this.#jar.replaceWith(flowCookies);
699
885
  this.#invalidateInFlight();
700
886
  this.#transitionAuth(accessToken);
701
- await this.#saveSession({
887
+ const saved = this.#saveSession({
702
888
  accessToken,
703
889
  obtainedAt: this.#config.clock.now()
704
890
  });
705
891
  this.#emitter.emit("tokens", { accessToken });
706
892
  this.#emitter.emit("signIn", { accessToken });
893
+ await saved;
707
894
  return accessToken;
708
895
  }
709
896
  };
@@ -762,14 +949,18 @@ var AuthResource = class extends BaseResource {
762
949
  * @param credentials email, пароль и обязательный токен капчи — см. {@link CaptchaCredentials}
763
950
  */
764
951
  async signIn(credentials, options = {}) {
952
+ const revision = this.#auth.revision();
953
+ const cookies = this.#auth.createCookieFlow(false);
765
954
  const result = await this.http.execute(AUTH_SIGN_IN, {
766
955
  path: AUTH_PATHS.signIn,
767
956
  body: credentials,
768
957
  skipAuth: true,
769
958
  skipAuthRefresh: true,
959
+ cookieJar: cookies,
770
960
  ...options
771
961
  });
772
- if (result.status === SignInStatus.Authenticated) await this.#auth.setAccessToken(result.accessToken);
962
+ if (result.status === SignInStatus.Authenticated) await this.#auth.setAccessToken(result.accessToken, revision, cookies);
963
+ else this.#auth.commitCookieFlow(cookies, revision);
773
964
  return result;
774
965
  }
775
966
  /**
@@ -778,14 +969,17 @@ var AuthResource = class extends BaseResource {
778
969
  * Полученный токен сохраняется в клиенте автоматически.
779
970
  */
780
971
  async verifyOtp(input, options = {}) {
972
+ const revision = this.#auth.revision();
973
+ const cookies = this.#auth.createCookieFlow();
781
974
  const accessToken = await this.http.execute(AUTH_VERIFY_OTP, {
782
975
  path: AUTH_PATHS.verifyOtp,
783
976
  body: input,
784
977
  skipAuth: true,
785
978
  skipAuthRefresh: true,
979
+ cookieJar: cookies,
786
980
  ...options
787
981
  });
788
- await this.#auth.setAccessToken(accessToken);
982
+ await this.#auth.setAccessToken(accessToken, revision, cookies);
789
983
  return accessToken;
790
984
  }
791
985
  /** Отправляет код подтверждения повторно. */
@@ -1704,7 +1898,7 @@ var ItdAccounts = class ItdAccounts {
1704
1898
  })));
1705
1899
  const added = [];
1706
1900
  for (const { name, session } of sessions) {
1707
- if (!isRestorableSession(session)) continue;
1901
+ if (!isRestorableSession(session, this.#base.baseUrl ?? "https://xn--d1ah4a.com")) continue;
1708
1902
  if (this.#clients.has(name) || this.#removing.has(name)) continue;
1709
1903
  this.addAccount(name);
1710
1904
  added.push(name);
@@ -1957,6 +2151,6 @@ function createAccounts(options = {}) {
1957
2151
  return new ItdAccounts(options);
1958
2152
  }
1959
2153
  //#endregion
1960
- export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AccessType, AttachmentType, BUCKET_LIMITS, CommentSort, DEFAULT_BASE_URL, DEFAULT_RATE_LIMIT_BUCKET, EventChannel, EventChannelStatus, EventComposer, EventRouter, FeedTab, FileTransferMode, IMAGE_MIME_TYPES, IncidentKind, InteractionType, ItdAbortError, ItdAccounts, ItdApiError, ItdApiErrorKind, ItdAuthError, ItdClient, ItdConfigError, ItdConflictError, ItdError, ItdErrorCode, ItdErrorKind, ItdFileError, ItdFileErrorReason, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdPhoneVerificationError, ItdRateLimitError, ItdServerError, ItdStateError, ItdTimeoutError, ItdValidationError, LIBRARY_VERSION, LikesVisibility, MemoryKeyValueStore, MemoryMultiTokenStorage, MemoryShopOrderAccessStorage, MemoryTokenStorage, NotificationEvents, NotificationEventsClient, NotificationEventsTransport, NotificationType, NotificationUpdateOrigin, NotificationUpdateType, OPERATIONS, PaginationMode, Paginator, RateLimitPacing, ReportReason, ReportTargetType, RetrySafety, RuntimeMode, STATUS_SERVICE, ServiceState, ShopConsentKind, ShopOrderStatus, ShopProductCategory, ShopProductStatus, SignInStatus, SpanRenderFormat, SpanType, TURNSTILE_SITE_KEY, UnauthorizedStreamError, VIDEO_MIME_TYPES, ViewReason, ViewSource, WallAccess, WebSocketTransport, autoSpans, canonicalNotificationType, comment, createAccounts, createClient, createKeyValueStore, createMemoryShopOrderAccessStorage, createMultiTokenStorage, createNotificationEventsClient, createRecordKeyValueStore, createShopFeature, createShopOrderAccessStorage, createTokenStorage, formatNotificationText, fromStream, fromUrl, isBuilder, isBuiltInOperationId, isEnumerableKeyValueStore, isItdApiError, isItdAuthError, isItdConflictError, isItdError, isItdFileError, isItdForbiddenError, isItdNotFoundError, isItdPhoneVerificationError, isItdRateLimitError, isItdServerError, isItdStateError, isItdValidationError, isKnownNotificationType, isMyProfile, mapPage, markup, normalizeNotification, operationBucket, operationMethod, operationRetrySafety, parseHtml, parseMarkdown, poll, post, renderSpans, report, resolveNotificationUrl, runEventMiddleware, scopedTokenStorage, statusDays, systemClock, toDate, utcStampToIso, withCodec, withNamespace };
2154
+ export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AccessType, AttachmentType, BUCKET_LIMITS, CommentSort, DEFAULT_BASE_URL, DEFAULT_RATE_LIMIT_BUCKET, EventChannel, EventChannelStatus, EventComposer, EventRouter, FeedTab, FileTransferMode, IMAGE_MIME_TYPES, IncidentKind, InteractionType, ItdAbortError, ItdAccounts, ItdApiError, ItdApiErrorKind, ItdAuthError, ItdClient, ItdConfigError, ItdConflictError, ItdError, ItdErrorCode, ItdErrorKind, ItdFileError, ItdFileErrorReason, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdPhoneVerificationError, ItdRateLimitError, ItdServerError, ItdStateError, ItdTimeoutError, ItdValidationError, LIBRARY_VERSION, LikesVisibility, MemoryKeyValueStore, MemoryMultiTokenStorage, MemoryShopOrderAccessStorage, MemoryTokenStorage, NotificationEvents, NotificationEventsClient, NotificationEventsTransport, NotificationType, NotificationUpdateOrigin, NotificationUpdateType, OPERATIONS, PaginationMode, Paginator, RateLimitPacing, ReportReason, ReportTargetType, RetrySafety, RuntimeMode, STATUS_SERVICE, ServiceState, ShopConsentKind, ShopOrderStatus, ShopProductCategory, ShopProductStatus, SignInStatus, SpanRenderFormat, SpanType, TURNSTILE_SITE_KEY, UnauthorizedStreamError, VIDEO_MIME_TYPES, ViewReason, ViewSource, WallAccess, WebSocketTransport, autoSpans, canonicalNotificationType, comment, createAccounts, createClient, createKeyValueStore, createMultiTokenStorage, createNotificationEventsClient, createRecordKeyValueStore, createShopFeature, createShopOrderAccessStorage, createTokenStorage, formatNotificationText, fromStream, fromUrl, isBuilder, isBuiltInOperationId, isEnumerableKeyValueStore, isItdApiError, isItdAuthError, isItdConflictError, isItdError, isItdFileError, isItdForbiddenError, isItdNotFoundError, isItdPhoneVerificationError, isItdRateLimitError, isItdServerError, isItdStateError, isItdValidationError, isKnownNotificationType, isMyProfile, mapPage, markup, normalizeNotification, operationBucket, operationMethod, operationRetrySafety, parseHtml, parseMarkdown, poll, post, renderSpans, report, resolveNotificationUrl, runEventMiddleware, scopedTokenStorage, statusDays, systemClock, toDate, utcStampToIso, withCodec, withNamespace };
1961
2155
 
1962
2156
  //# sourceMappingURL=index.js.map