itd-api 0.9.3 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/dist/events/index.cjs +2 -2
- package/dist/events/index.d.cts +2 -2
- package/dist/events/index.d.ts +2 -2
- package/dist/events/index.js +2 -2
- package/dist/index.cjs +405 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -29
- package/dist/index.d.ts +181 -29
- package/dist/index.js +401 -44
- package/dist/index.js.map +1 -1
- package/dist/rest/index.cjs +2 -2
- package/dist/rest/index.d.cts +2 -2
- package/dist/rest/index.d.ts +2 -2
- package/dist/rest/index.js +2 -2
- package/dist/shared/{events-BzjI6pn5.js → events-B0Wtn4cF.js} +3 -3
- package/dist/shared/{events-BzjI6pn5.js.map → events-B0Wtn4cF.js.map} +1 -1
- package/dist/shared/{events-C1FudmSe.cjs → events-BB791aPk.cjs} +8 -2
- package/dist/shared/{events-C1FudmSe.cjs.map → events-BB791aPk.cjs.map} +1 -1
- package/dist/shared/{events-BPxBF0gQ.d.cts → events-BNGjJVI3.d.cts} +2 -2
- package/dist/shared/{events-DnwfcLxS.d.ts → events-CJO6q93Z.d.ts} +2 -2
- package/dist/shared/{render-Omy1drH1.cjs → render-BimHjOhw.cjs} +2 -2
- package/dist/shared/{render-Omy1drH1.cjs.map → render-BimHjOhw.cjs.map} +1 -1
- package/dist/shared/{render-C1F_QWYD.d.cts → render-C1A57W-5.d.cts} +2 -2
- package/dist/shared/{render-CtOpp9Pm.js → render-CkhvH_yh.js} +2 -2
- package/dist/shared/{render-CtOpp9Pm.js.map → render-CkhvH_yh.js.map} +1 -1
- package/dist/shared/{render-uFW2kDxp.d.ts → render-DC5nvqcP.d.ts} +2 -2
- package/dist/shared/{url-3Ts6EEHQ.js → url-BA5hEwj2.js} +65 -3
- package/dist/shared/url-BA5hEwj2.js.map +1 -0
- package/dist/shared/{url-D6wsXm1T.cjs → url-CDVgMIq5.cjs} +100 -2
- package/dist/shared/url-CDVgMIq5.cjs.map +1 -0
- package/dist/shared/{url-DubjkRR9.d.ts → url-DkMueFAT.d.cts} +70 -3
- package/dist/shared/{url-DubjkRR9.d.cts → url-DkMueFAT.d.ts} +70 -3
- package/package.json +2 -1
- package/dist/shared/url-3Ts6EEHQ.js.map +0 -1
- package/dist/shared/url-D6wsXm1T.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as ViewReason, B as BUCKET_LIMITS, C as ItdErrorCode, D as ReportTargetType, E as ReportReason, F as defineBuiltInOperation, G as pickArray, H as createClientRuntime, I as isBuiltInOperationId, L as operationBucket, M as WallAccess, N as ITD_CATALOG, O as ServiceState, P as OPERATIONS, R as operationMethod, S as InteractionType, T as NotificationType, U as createApiError, V as DEFAULT_RATE_LIMIT_BUCKET, X as RetrySafety, Y as pickString, _ as CaptchaType, at as orderPluginDefinitions, b as FeedTab, c as normalizeNotification, ct as STATUS_SERVICE, d as canonicalNotificationType, dt as isRecord, et as createRequestAbortScope, f as isKnownNotificationType, ft as requireOptionalBoolean, g as CaptchaField, gt as installAsyncDisposeFallback, h as CaptchaChoice, ht as systemClock, it as assertPluginRemovable, j as ViewSource, k as SpanType, lt as resolveRateLimit, m as AttachmentType, n as formatNotificationText, o as passthroughOperation, ot as DEFAULT_BASE_URL, p as AccessType, pt as RateLimitPacing, rt as RequestQueuePool, s as voidOperation, t as resolveNotificationUrl, tt as requestAbortError, ut as LIBRARY_VERSION, v as CommentSort, w as LikesVisibility, x as IncidentKind, y as EventChannelStatus, z as operationRetrySafety } from "./shared/url-BA5hEwj2.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 { 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-
|
|
3
|
+
import { c as REFRESH_COOKIE, h as joinUrl, 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-CkhvH_yh.js";
|
|
5
5
|
import { c as FileTransferMode } from "./shared/options-i4LrKfqx.js";
|
|
6
|
-
import { _ as
|
|
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, m as EventChannel, n as EventRouter, o as EVENT_OPERATIONS, p as createParser, r as NotificationEventsClient, s as NotificationEvents, t as EventComposer, u as setNotificationEventsConnectGuard, v as reportListenerError } from "./shared/events-B0Wtn4cF.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
8
|
import { n as copySession, r as createTokenStorage, t as MemoryTokenStorage } from "./shared/storage-DiDe0PZM.js";
|
|
9
9
|
import { a as scopedTokenStorage, i as isRestorableSession, n as controlledTokenStorage, r as createMultiTokenStorage, t as MemoryMultiTokenStorage } from "./shared/multi-storage-C3Ngtop1.js";
|
|
@@ -31,12 +31,37 @@ const SignInStatus = Object.freeze({
|
|
|
31
31
|
Authenticated: "authenticated",
|
|
32
32
|
OtpRequired: "otp_required"
|
|
33
33
|
});
|
|
34
|
+
/**
|
|
35
|
+
* Поле тела запроса по умолчанию для известных провайдеров.
|
|
36
|
+
*
|
|
37
|
+
* Используется, когда провайдера не спрашивали. Ответ `captchaProvider()` важнее этой таблицы.
|
|
38
|
+
*/
|
|
39
|
+
const CAPTCHA_FIELDS = Object.freeze({
|
|
40
|
+
[CaptchaType.Itd]: CaptchaField.Itd,
|
|
41
|
+
[CaptchaType.Cloudflare]: CaptchaField.Cloudflare
|
|
42
|
+
});
|
|
43
|
+
/** Состояния, которые может вернуть проверка QR-входа. */
|
|
44
|
+
const QrLoginStatus = Object.freeze({
|
|
45
|
+
Pending: "pending",
|
|
46
|
+
Scanned: "scanned",
|
|
47
|
+
CaptchaRequired: "captcha_required",
|
|
48
|
+
Authorized: "authorized",
|
|
49
|
+
Rejected: "rejected"
|
|
50
|
+
});
|
|
51
|
+
/** Состояния, приходящие из потокового наблюдения за QR-входом. */
|
|
52
|
+
const QrLoginStreamStatus = Object.freeze({
|
|
53
|
+
Pending: "pending",
|
|
54
|
+
Scanned: "scanned",
|
|
55
|
+
Approved: "approved",
|
|
56
|
+
Rejected: "rejected"
|
|
57
|
+
});
|
|
34
58
|
function requireString(body, key, message) {
|
|
35
59
|
const value = pickString(body, key);
|
|
36
60
|
if (!value) throw new ItdConfigError(message);
|
|
37
61
|
return value;
|
|
38
62
|
}
|
|
39
63
|
const AUTH_CHECK = passthroughOperation("auth.check");
|
|
64
|
+
const AUTH_CAPTCHA_PROVIDER = passthroughOperation("auth.captchaProvider");
|
|
40
65
|
const AUTH_SIGN_UP = defineBuiltInOperation("auth.signUp", (body) => requireString(body, "flowToken", "Сервер не вернул flowToken при регистрации"));
|
|
41
66
|
const AUTH_SIGN_IN = defineBuiltInOperation("auth.signIn", (body) => {
|
|
42
67
|
const accessToken = pickString(body, "accessToken");
|
|
@@ -58,6 +83,84 @@ const AUTH_CHANGE_PASSWORD = voidOperation("auth.changePassword");
|
|
|
58
83
|
const AUTH_SESSIONS = defineBuiltInOperation("auth.sessions", (body) => pickArray(body, "sessions"));
|
|
59
84
|
const AUTH_REVOKE_SESSION = voidOperation("auth.revokeSession");
|
|
60
85
|
const AUTH_REVOKE_OTHER_SESSIONS = voidOperation("auth.revokeOtherSessions");
|
|
86
|
+
const AUTH_QR_START = passthroughOperation("auth.qrStart");
|
|
87
|
+
const AUTH_QR_CLAIM = passthroughOperation("auth.qrClaim");
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/session/captcha.ts
|
|
90
|
+
function requireCaptchaText(value, field) {
|
|
91
|
+
if (value !== void 0 && (typeof value !== "string" || value.trim() === "")) throw new ItdConfigError(`${field} должен быть непустой строкой`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Проверяет форму блока `auth.captcha`.
|
|
95
|
+
*
|
|
96
|
+
* Отсутствие источника токена ошибкой не считается: до входа по паролю дело может и не
|
|
97
|
+
* дойти. О нехватке сообщит {@link resolveCaptchaBody} в момент входа.
|
|
98
|
+
*
|
|
99
|
+
* @throws {ItdConfigError} при некорректных значениях
|
|
100
|
+
*/
|
|
101
|
+
function validateCaptchaOptions(captcha) {
|
|
102
|
+
if (captcha === void 0) return;
|
|
103
|
+
if (!isRecord(captcha)) throw new ItdConfigError("auth.captcha должен быть объектом");
|
|
104
|
+
const { type, token, getToken, field } = captcha;
|
|
105
|
+
requireCaptchaText(type, "auth.captcha.type");
|
|
106
|
+
requireCaptchaText(token, "auth.captcha.token");
|
|
107
|
+
requireCaptchaText(field, "auth.captcha.field");
|
|
108
|
+
if (getToken !== void 0 && typeof getToken !== "function") throw new ItdConfigError("auth.captcha.getToken должен быть функцией");
|
|
109
|
+
}
|
|
110
|
+
/** Разбирает ответ `GET /api/v1/auth/captcha/provider` для автоматического входа. */
|
|
111
|
+
function readCaptchaProvider(body) {
|
|
112
|
+
const config = isRecord(body) ? body : void 0;
|
|
113
|
+
const provider = config?.provider;
|
|
114
|
+
const field = config?.field;
|
|
115
|
+
if (typeof provider !== "string" || provider.trim() === "" || typeof field !== "string" || field.trim() === "") throw new ItdConfigError("Сервер вернул неподдерживаемую конфигурацию капчи");
|
|
116
|
+
return {
|
|
117
|
+
provider,
|
|
118
|
+
field
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** Куда класть токен: настройка, иначе умолчание провайдера. */
|
|
122
|
+
function resolveField(type, configured) {
|
|
123
|
+
const field = configured ?? CAPTCHA_FIELDS[type];
|
|
124
|
+
if (field) return field;
|
|
125
|
+
throw new ItdConfigError(`Неизвестно, в каком поле сервер ждёт токен капчи «${type}». Передайте auth.captcha.field либо оставьте auth.captcha.type = ${CaptchaChoice.Auto}, чтобы поле назвал сервер.`);
|
|
126
|
+
}
|
|
127
|
+
/** Спрашивает свежий токен, затем берёт разовый. */
|
|
128
|
+
async function resolveToken(captcha, type) {
|
|
129
|
+
const token = await captcha.getToken?.(type) || captcha.token;
|
|
130
|
+
if (token) return token;
|
|
131
|
+
throw new ItdConfigError(`Источник капчи не вернул токен для провайдера «${type}». Проверьте auth.captcha.getToken.`);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Готовит фрагмент тела запроса с токеном капчи.
|
|
135
|
+
*
|
|
136
|
+
* При `CaptchaChoice.Auto` провайдер спрашивается у сервера — тогда и тип виджета,
|
|
137
|
+
* и имя поля приходят оттуда. Явно названный тип решается без этого запроса.
|
|
138
|
+
*
|
|
139
|
+
* @param askProvider как спросить активного провайдера; вызывается, только если это нужно
|
|
140
|
+
* @throws {ItdConfigError} если капча не настроена или токен не получен
|
|
141
|
+
*/
|
|
142
|
+
async function resolveCaptchaBody(captcha, askProvider) {
|
|
143
|
+
if (!captcha?.token && !captcha?.getToken) throw new ItdConfigError("Вход по email и паролю требует токен капчи. Передайте auth.captcha.getToken — источник свежего токена — либо разовый auth.captcha.token. В Node токен получает пакет @itd-api/captcha.");
|
|
144
|
+
const choice = captcha.type ?? CaptchaChoice.Auto;
|
|
145
|
+
if (choice === CaptchaChoice.Auto) {
|
|
146
|
+
const { provider, field } = await askProvider();
|
|
147
|
+
return { [field]: await resolveToken(captcha, provider) };
|
|
148
|
+
}
|
|
149
|
+
return { [resolveField(choice, captcha.field)]: await resolveToken(captcha, choice) };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Готовит фрагмент тела для разового вызова с готовым доказательством.
|
|
153
|
+
*
|
|
154
|
+
* Поле берётся из самого доказательства либо из умолчания провайдера; запроса к серверу нет.
|
|
155
|
+
*
|
|
156
|
+
* @throws {ItdConfigError} если доказательство неполное
|
|
157
|
+
*/
|
|
158
|
+
function captchaBody(captcha) {
|
|
159
|
+
if (!isRecord(captcha)) throw new ItdConfigError("captcha должен быть объектом { type, token }");
|
|
160
|
+
if (typeof captcha.token !== "string" || captcha.token.trim() === "") throw new ItdConfigError("captcha.token должен быть непустой строкой");
|
|
161
|
+
if (typeof captcha.type !== "string" || captcha.type.trim() === "") throw new ItdConfigError("captcha.type должен быть непустой строкой");
|
|
162
|
+
return { [resolveField(captcha.type, captcha.field)]: captcha.token };
|
|
163
|
+
}
|
|
61
164
|
//#endregion
|
|
62
165
|
//#region src/session/jwt.ts
|
|
63
166
|
/**
|
|
@@ -130,11 +233,10 @@ function validateAuth(auth) {
|
|
|
130
233
|
return { ...auth };
|
|
131
234
|
}
|
|
132
235
|
if ("email" in auth || "password" in auth) {
|
|
133
|
-
const { email, password,
|
|
236
|
+
const { email, password, captcha } = auth;
|
|
134
237
|
if (typeof email !== "string" || email.trim() === "") throw new ItdConfigError("auth.email должен быть непустой строкой");
|
|
135
238
|
if (typeof password !== "string" || password === "") throw new ItdConfigError("auth.password должен быть непустой строкой");
|
|
136
|
-
|
|
137
|
-
if (turnstileToken !== void 0 && (typeof turnstileToken !== "string" || turnstileToken.trim() === "")) throw new ItdConfigError("auth.turnstileToken должен быть непустой строкой");
|
|
239
|
+
validateCaptchaOptions(captcha);
|
|
138
240
|
return { ...auth };
|
|
139
241
|
}
|
|
140
242
|
throw new ItdConfigError("auth не распознан. Ожидается строка с accessToken либо объект { accessToken }, { email, password } или { getToken }");
|
|
@@ -181,6 +283,7 @@ function createItdAuth(options, deps) {
|
|
|
181
283
|
}
|
|
182
284
|
/** Пути эндпоинтов авторизации. */
|
|
183
285
|
const AUTH_PATHS = {
|
|
286
|
+
captchaProvider: "/api/v1/auth/captcha/provider",
|
|
184
287
|
signUp: "/api/v1/auth/sign-up",
|
|
185
288
|
signIn: "/api/v1/auth/sign-in",
|
|
186
289
|
verifyOtp: "/api/v1/auth/verify-otp",
|
|
@@ -190,7 +293,10 @@ const AUTH_PATHS = {
|
|
|
190
293
|
forgotPassword: "/api/v1/auth/forgot-password",
|
|
191
294
|
resetPassword: "/api/v1/auth/reset-password",
|
|
192
295
|
changePassword: "/api/v1/auth/change-password",
|
|
193
|
-
sessions: "/api/v1/auth/sessions"
|
|
296
|
+
sessions: "/api/v1/auth/sessions",
|
|
297
|
+
qrStart: "/api/v1/auth/qr/start",
|
|
298
|
+
qrClaim: "/api/v1/auth/qr/claim",
|
|
299
|
+
qrStream: "/api/v1/auth/qr/stream"
|
|
194
300
|
};
|
|
195
301
|
/**
|
|
196
302
|
* Публичный ключ Cloudflare Turnstile платформы итд.com.
|
|
@@ -200,14 +306,15 @@ const AUTH_PATHS = {
|
|
|
200
306
|
*
|
|
201
307
|
* Ключ привязан к домену: на чужом origin Cloudflare отказывает виджету с кодом `110200`.
|
|
202
308
|
* Поэтому отрисовать его может только код, выполняемый на самом итд.com. Остальным
|
|
203
|
-
* подходит `@itd-api/
|
|
309
|
+
* подходит `@itd-api/captcha`, готовый токен из другого источника или вовсе вход
|
|
204
310
|
* без капчи — по сохранённой сессии либо по токенам, взятым в браузере.
|
|
205
311
|
*
|
|
206
312
|
* @example
|
|
207
313
|
* ```ts
|
|
208
314
|
* turnstile.render('#captcha', {
|
|
209
315
|
* sitekey: TURNSTILE_SITE_KEY,
|
|
210
|
-
* callback: (
|
|
316
|
+
* callback: (token) =>
|
|
317
|
+
* itd.auth.signIn({ email, password, captcha: { type: CaptchaType.Cloudflare, token } }),
|
|
211
318
|
* });
|
|
212
319
|
* ```
|
|
213
320
|
*/
|
|
@@ -625,6 +732,13 @@ var AuthManager = class {
|
|
|
625
732
|
}
|
|
626
733
|
/** Сохраняет токен, полученный извне, — например после подтверждения OTP. */
|
|
627
734
|
async setAccessToken(accessToken, expectedRevision = this.#authEpoch, cookies) {
|
|
735
|
+
return this.#storeAccessToken(accessToken, expectedRevision, cookies, false);
|
|
736
|
+
}
|
|
737
|
+
/** Атомарно принимает токен и cookie завершённого входа как новую сессию. @internal */
|
|
738
|
+
async commitAuthFlow(accessToken, cookies, expectedRevision = this.#authEpoch) {
|
|
739
|
+
return this.#storeAccessToken(accessToken, expectedRevision, cookies, true);
|
|
740
|
+
}
|
|
741
|
+
async #storeAccessToken(accessToken, expectedRevision, cookies, replaceSession) {
|
|
628
742
|
this.#assertActive();
|
|
629
743
|
if (typeof accessToken !== "string" || accessToken.trim() === "") throw new ItdConfigError("accessToken должен быть непустой строкой");
|
|
630
744
|
await this.#loadSession();
|
|
@@ -634,7 +748,7 @@ var AuthManager = class {
|
|
|
634
748
|
this.#invalidateInFlight();
|
|
635
749
|
this.#transitionAuth(accessToken);
|
|
636
750
|
const saved = this.#saveSession({
|
|
637
|
-
...this.#session ?? {},
|
|
751
|
+
...replaceSession ? {} : this.#session ?? {},
|
|
638
752
|
accessToken,
|
|
639
753
|
obtainedAt: this.#config.clock.now()
|
|
640
754
|
});
|
|
@@ -849,29 +963,23 @@ var AuthManager = class {
|
|
|
849
963
|
this.#signingIn = promise;
|
|
850
964
|
return promise;
|
|
851
965
|
}
|
|
852
|
-
/**
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if (credentials.getTurnstileToken) {
|
|
860
|
-
const token = await credentials.getTurnstileToken();
|
|
861
|
-
if (token) return token;
|
|
862
|
-
}
|
|
863
|
-
if (credentials.turnstileToken) return credentials.turnstileToken;
|
|
864
|
-
throw new ItdConfigError("Вход по email и паролю требует токен капчи Cloudflare Turnstile: без него сервер отвечает 422. Передайте auth.getTurnstileToken (источник свежего токена) либо разовый auth.turnstileToken. Ключ виджета — TURNSTILE_SITE_KEY. В Node токен умеет добывать отдельный пакет: npm i @itd-api/turnstile, затем getTurnstileToken: createTurnstileSolver().");
|
|
966
|
+
/** Спрашивает у сервера активного провайдера и поле, в котором он ждёт токен. */
|
|
967
|
+
async #resolveCaptchaProvider() {
|
|
968
|
+
return readCaptchaProvider(await this.#http.execute(AUTH_CAPTCHA_PROVIDER, {
|
|
969
|
+
path: AUTH_PATHS.captchaProvider,
|
|
970
|
+
skipAuth: true,
|
|
971
|
+
skipAuthRefresh: true
|
|
972
|
+
}));
|
|
865
973
|
}
|
|
866
974
|
async #performSignIn(credentials, revision) {
|
|
867
|
-
const
|
|
975
|
+
const captcha = await resolveCaptchaBody(credentials.captcha, () => this.#resolveCaptchaProvider());
|
|
868
976
|
const flowCookies = new CookieJar();
|
|
869
977
|
const result = await this.#http.execute(AUTH_SIGN_IN, {
|
|
870
978
|
path: AUTH_PATHS.signIn,
|
|
871
979
|
body: {
|
|
872
980
|
email: credentials.email,
|
|
873
981
|
password: credentials.password,
|
|
874
|
-
|
|
982
|
+
...captcha
|
|
875
983
|
},
|
|
876
984
|
skipAuth: true,
|
|
877
985
|
skipAuthRefresh: true,
|
|
@@ -895,6 +1003,125 @@ var AuthManager = class {
|
|
|
895
1003
|
}
|
|
896
1004
|
};
|
|
897
1005
|
//#endregion
|
|
1006
|
+
//#region src/session/qr-stream.ts
|
|
1007
|
+
const QR_STREAM_STATUSES = new Set(Object.values(QrLoginStreamStatus));
|
|
1008
|
+
function readQrLoginStreamEvent(data) {
|
|
1009
|
+
let value;
|
|
1010
|
+
try {
|
|
1011
|
+
value = JSON.parse(data);
|
|
1012
|
+
} catch {
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (!isRecord(value)) return void 0;
|
|
1016
|
+
const event = value;
|
|
1017
|
+
if (typeof event.status !== "string" || !QR_STREAM_STATUSES.has(event.status)) return;
|
|
1018
|
+
return {
|
|
1019
|
+
status: event.status,
|
|
1020
|
+
...typeof event.expiresIn === "number" && Number.isFinite(event.expiresIn) ? { expiresIn: event.expiresIn } : {}
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
/** Читает короткоживущий SSE-поток QR-входа и последовательно доставляет его события. */
|
|
1024
|
+
async function consumeQrLoginStream(body, onEvent, signal) {
|
|
1025
|
+
const reader = body.getReader();
|
|
1026
|
+
const decoder = new TextDecoder();
|
|
1027
|
+
let delivery = Promise.resolve();
|
|
1028
|
+
let completed = false;
|
|
1029
|
+
const cancel = () => {
|
|
1030
|
+
reader.cancel(signal?.reason).catch(() => {});
|
|
1031
|
+
};
|
|
1032
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
1033
|
+
const parser = createParser({ onEvent(message) {
|
|
1034
|
+
const event = readQrLoginStreamEvent(message.data);
|
|
1035
|
+
if (!event) return;
|
|
1036
|
+
delivery = delivery.then(() => onEvent(event));
|
|
1037
|
+
} });
|
|
1038
|
+
try {
|
|
1039
|
+
for (;;) {
|
|
1040
|
+
const { done, value } = await reader.read();
|
|
1041
|
+
if (done) break;
|
|
1042
|
+
parser.feed(decoder.decode(value, { stream: true }));
|
|
1043
|
+
await delivery;
|
|
1044
|
+
}
|
|
1045
|
+
parser.feed(decoder.decode());
|
|
1046
|
+
await delivery;
|
|
1047
|
+
if (signal?.aborted) throw signal.reason;
|
|
1048
|
+
completed = true;
|
|
1049
|
+
} finally {
|
|
1050
|
+
signal?.removeEventListener("abort", cancel);
|
|
1051
|
+
if (!completed) await reader.cancel().catch(() => {});
|
|
1052
|
+
reader.releaseLock?.();
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
/** Открывает изолированный HTTP/SSE-канал QR-входа. @internal */
|
|
1056
|
+
async function openQrLoginStream(connection, cookies, input, onEvent, signal) {
|
|
1057
|
+
connection.assertActive?.("открыть QR-поток");
|
|
1058
|
+
const path = AUTH_PATHS.qrStream;
|
|
1059
|
+
const method = "POST";
|
|
1060
|
+
const url = joinUrl(connection.baseUrl, path);
|
|
1061
|
+
const abort = createRequestAbortScope(signal, connection.signal, 0, connection.clock);
|
|
1062
|
+
try {
|
|
1063
|
+
const headers = await connection.baseHeaders(url);
|
|
1064
|
+
headers.delete("Authorization");
|
|
1065
|
+
headers.delete("Cookie");
|
|
1066
|
+
headers.set("Accept", "text/event-stream");
|
|
1067
|
+
headers.set("Content-Type", "application/json");
|
|
1068
|
+
const cookie = cookies.getHeader(url);
|
|
1069
|
+
if (cookie) headers.set("Cookie", cookie);
|
|
1070
|
+
let response;
|
|
1071
|
+
try {
|
|
1072
|
+
response = await connection.fetch(url, {
|
|
1073
|
+
method,
|
|
1074
|
+
headers,
|
|
1075
|
+
body: JSON.stringify(input),
|
|
1076
|
+
credentials: "include",
|
|
1077
|
+
signal: abort.signal
|
|
1078
|
+
});
|
|
1079
|
+
} catch (error) {
|
|
1080
|
+
const failure = new ItdNetworkError(`Не удалось открыть QR-поток: ${String(error)}`, {
|
|
1081
|
+
method,
|
|
1082
|
+
path,
|
|
1083
|
+
cause: error
|
|
1084
|
+
});
|
|
1085
|
+
throw requestAbortError(abort, {
|
|
1086
|
+
timeout: 0,
|
|
1087
|
+
method,
|
|
1088
|
+
path
|
|
1089
|
+
}, failure);
|
|
1090
|
+
}
|
|
1091
|
+
cookies.setFromResponse(response.url || url, response);
|
|
1092
|
+
if (!response.ok) {
|
|
1093
|
+
const text = await response.text();
|
|
1094
|
+
let body = text;
|
|
1095
|
+
try {
|
|
1096
|
+
body = JSON.parse(text);
|
|
1097
|
+
} catch {}
|
|
1098
|
+
throw createApiError({
|
|
1099
|
+
method,
|
|
1100
|
+
path,
|
|
1101
|
+
status: response.status,
|
|
1102
|
+
statusText: response.statusText,
|
|
1103
|
+
headers: response.headers,
|
|
1104
|
+
response,
|
|
1105
|
+
body,
|
|
1106
|
+
now: connection.clock.now()
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
if (!response.body) throw new ItdNetworkError("Сервер не вернул тело QR-потока", {
|
|
1110
|
+
method,
|
|
1111
|
+
path
|
|
1112
|
+
});
|
|
1113
|
+
await consumeQrLoginStream(response.body, onEvent, abort.signal);
|
|
1114
|
+
} catch (error) {
|
|
1115
|
+
throw requestAbortError(abort, {
|
|
1116
|
+
timeout: 0,
|
|
1117
|
+
method,
|
|
1118
|
+
path
|
|
1119
|
+
}, error);
|
|
1120
|
+
} finally {
|
|
1121
|
+
abort.cleanup();
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
//#endregion
|
|
898
1125
|
//#region src/resources/auth.ts
|
|
899
1126
|
/**
|
|
900
1127
|
* Результат входа.
|
|
@@ -909,9 +1136,35 @@ var AuthManager = class {
|
|
|
909
1136
|
*/
|
|
910
1137
|
var AuthResource = class extends BaseResource {
|
|
911
1138
|
#auth;
|
|
1139
|
+
#connection;
|
|
1140
|
+
#qrFlows = /* @__PURE__ */ new Map();
|
|
912
1141
|
constructor(http, deps) {
|
|
913
1142
|
super(http);
|
|
914
1143
|
this.#auth = deps.auth;
|
|
1144
|
+
this.#connection = deps.connection;
|
|
1145
|
+
}
|
|
1146
|
+
#pruneQrFlows() {
|
|
1147
|
+
const now = this.#connection.clock.now();
|
|
1148
|
+
for (const [qrId, flow] of this.#qrFlows) if (flow.expiresAt !== void 0 && flow.expiresAt <= now) this.#qrFlows.delete(qrId);
|
|
1149
|
+
}
|
|
1150
|
+
#qrFlow(qrId) {
|
|
1151
|
+
this.#pruneQrFlows();
|
|
1152
|
+
const existing = this.#qrFlows.get(qrId);
|
|
1153
|
+
if (existing) return existing;
|
|
1154
|
+
const flow = {
|
|
1155
|
+
cookies: this.#auth.createCookieFlow(false),
|
|
1156
|
+
expiresAt: void 0
|
|
1157
|
+
};
|
|
1158
|
+
this.#qrFlows.set(qrId, flow);
|
|
1159
|
+
return flow;
|
|
1160
|
+
}
|
|
1161
|
+
#touchQrFlow(flow, expiresIn) {
|
|
1162
|
+
if (typeof expiresIn !== "number" || !Number.isFinite(expiresIn)) return;
|
|
1163
|
+
const expiresAt = this.#connection.clock.now() + Math.max(0, expiresIn) * 1e3;
|
|
1164
|
+
flow.expiresAt = flow.expiresAt === void 0 ? expiresAt : Math.min(flow.expiresAt, expiresAt);
|
|
1165
|
+
}
|
|
1166
|
+
#forgetTerminalQrError(qrId, error) {
|
|
1167
|
+
if (isItdApiError(error) && error.hasCode("QR_EXPIRED", "QR_ALREADY_USED", "QR_TOKEN_MISMATCH")) this.#qrFlows.delete(qrId);
|
|
915
1168
|
}
|
|
916
1169
|
/**
|
|
917
1170
|
* Проверяет состояние авторизации и возвращает текущего пользователя.
|
|
@@ -925,14 +1178,106 @@ var AuthResource = class extends BaseResource {
|
|
|
925
1178
|
});
|
|
926
1179
|
}
|
|
927
1180
|
/**
|
|
1181
|
+
* Узнаёт активного провайдера капчи и поле токена.
|
|
1182
|
+
*
|
|
1183
|
+
* Сервер может переключить провайдера или переименовать поле без выпуска новой версии SDK.
|
|
1184
|
+
* Автоматическому входу этот вызов не нужен — клиент делает его сам.
|
|
1185
|
+
*/
|
|
1186
|
+
captchaProvider(options = {}) {
|
|
1187
|
+
return this.http.execute(AUTH_CAPTCHA_PROVIDER, {
|
|
1188
|
+
path: AUTH_PATHS.captchaProvider,
|
|
1189
|
+
skipAuth: true,
|
|
1190
|
+
skipAuthRefresh: true,
|
|
1191
|
+
...options
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
/** Создаёт короткоживущую сессию QR-входа. */
|
|
1195
|
+
async startQrLogin(options = {}) {
|
|
1196
|
+
const cookies = this.#auth.createCookieFlow(false);
|
|
1197
|
+
const result = await this.http.execute(AUTH_QR_START, {
|
|
1198
|
+
path: AUTH_PATHS.qrStart,
|
|
1199
|
+
skipAuth: true,
|
|
1200
|
+
skipAuthRefresh: true,
|
|
1201
|
+
cookieJar: cookies,
|
|
1202
|
+
...options
|
|
1203
|
+
});
|
|
1204
|
+
if (typeof result.qrId === "string" && result.qrId !== "") {
|
|
1205
|
+
const flow = {
|
|
1206
|
+
cookies,
|
|
1207
|
+
expiresAt: void 0
|
|
1208
|
+
};
|
|
1209
|
+
this.#touchQrFlow(flow, result.expiresIn);
|
|
1210
|
+
this.#qrFlows.set(result.qrId, flow);
|
|
1211
|
+
}
|
|
1212
|
+
return result;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Проверяет QR-сессию и завершает вход после подтверждения на другом устройстве.
|
|
1216
|
+
*
|
|
1217
|
+
* До подтверждения возвращает промежуточный статус. Если сервер потребовал капчу,
|
|
1218
|
+
* повторите вызов с `captcha` — тип берётся из {@link captchaProvider}.
|
|
1219
|
+
* Полученный `accessToken` автоматически сохраняется в клиенте.
|
|
1220
|
+
*/
|
|
1221
|
+
async claimQrLogin(input, options = {}) {
|
|
1222
|
+
const revision = this.#auth.revision();
|
|
1223
|
+
const flow = this.#qrFlow(input.qrId);
|
|
1224
|
+
try {
|
|
1225
|
+
const { captcha, ...rest } = input;
|
|
1226
|
+
const result = await this.http.execute(AUTH_QR_CLAIM, {
|
|
1227
|
+
path: AUTH_PATHS.qrClaim,
|
|
1228
|
+
body: {
|
|
1229
|
+
...rest,
|
|
1230
|
+
...captcha ? captchaBody(captcha) : {}
|
|
1231
|
+
},
|
|
1232
|
+
skipAuth: true,
|
|
1233
|
+
skipAuthRefresh: true,
|
|
1234
|
+
cookieJar: flow.cookies,
|
|
1235
|
+
...options
|
|
1236
|
+
});
|
|
1237
|
+
this.#touchQrFlow(flow, result.expiresIn);
|
|
1238
|
+
if (result.status === QrLoginStatus.Authorized) {
|
|
1239
|
+
await this.#auth.commitAuthFlow(result.accessToken, flow.cookies, revision);
|
|
1240
|
+
this.#qrFlows.delete(input.qrId);
|
|
1241
|
+
} else if (result.status === QrLoginStatus.Rejected) this.#qrFlows.delete(input.qrId);
|
|
1242
|
+
return result;
|
|
1243
|
+
} catch (error) {
|
|
1244
|
+
this.#forgetTerminalQrError(input.qrId, error);
|
|
1245
|
+
throw error;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Слушает состояния QR-входа до закрытия ответа или отмены `signal`.
|
|
1250
|
+
*
|
|
1251
|
+
* Событие `approved` означает, что подтверждение завершено: после него вызовите
|
|
1252
|
+
* {@link claimQrLogin}, чтобы получить и сохранить access token.
|
|
1253
|
+
*/
|
|
1254
|
+
async streamQrLogin(input, onEvent, options = {}) {
|
|
1255
|
+
if (typeof onEvent !== "function") throw new ItdConfigError("onEvent QR-потока должен быть функцией");
|
|
1256
|
+
const flow = this.#qrFlow(input.qrId);
|
|
1257
|
+
try {
|
|
1258
|
+
await openQrLoginStream(this.#connection, flow.cookies, input, async (event) => {
|
|
1259
|
+
this.#touchQrFlow(flow, event.expiresIn);
|
|
1260
|
+
if (event.status === QrLoginStreamStatus.Rejected) this.#qrFlows.delete(input.qrId);
|
|
1261
|
+
await onEvent(event);
|
|
1262
|
+
}, options.signal);
|
|
1263
|
+
} catch (error) {
|
|
1264
|
+
this.#forgetTerminalQrError(input.qrId, error);
|
|
1265
|
+
throw error;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
928
1269
|
* Регистрирует аккаунт и запускает подтверждение по коду.
|
|
929
1270
|
*
|
|
930
1271
|
* @returns `flowToken`, который нужно передать в {@link verifyOtp}
|
|
931
1272
|
*/
|
|
932
1273
|
signUp(credentials, options = {}) {
|
|
1274
|
+
const { captcha, ...rest } = credentials;
|
|
933
1275
|
return this.http.execute(AUTH_SIGN_UP, {
|
|
934
1276
|
path: AUTH_PATHS.signUp,
|
|
935
|
-
body:
|
|
1277
|
+
body: {
|
|
1278
|
+
...rest,
|
|
1279
|
+
...captchaBody(captcha)
|
|
1280
|
+
},
|
|
936
1281
|
skipAuth: true,
|
|
937
1282
|
skipAuthRefresh: true,
|
|
938
1283
|
...options
|
|
@@ -949,17 +1294,21 @@ var AuthResource = class extends BaseResource {
|
|
|
949
1294
|
* @param credentials email, пароль и обязательный токен капчи — см. {@link CaptchaCredentials}
|
|
950
1295
|
*/
|
|
951
1296
|
async signIn(credentials, options = {}) {
|
|
1297
|
+
const { captcha, ...rest } = credentials;
|
|
952
1298
|
const revision = this.#auth.revision();
|
|
953
1299
|
const cookies = this.#auth.createCookieFlow(false);
|
|
954
1300
|
const result = await this.http.execute(AUTH_SIGN_IN, {
|
|
955
1301
|
path: AUTH_PATHS.signIn,
|
|
956
|
-
body:
|
|
1302
|
+
body: {
|
|
1303
|
+
...rest,
|
|
1304
|
+
...captchaBody(captcha)
|
|
1305
|
+
},
|
|
957
1306
|
skipAuth: true,
|
|
958
1307
|
skipAuthRefresh: true,
|
|
959
1308
|
cookieJar: cookies,
|
|
960
1309
|
...options
|
|
961
1310
|
});
|
|
962
|
-
if (result.status === SignInStatus.Authenticated) await this.#auth.
|
|
1311
|
+
if (result.status === SignInStatus.Authenticated) await this.#auth.commitAuthFlow(result.accessToken, cookies, revision);
|
|
963
1312
|
else this.#auth.commitCookieFlow(cookies, revision);
|
|
964
1313
|
return result;
|
|
965
1314
|
}
|
|
@@ -979,7 +1328,7 @@ var AuthResource = class extends BaseResource {
|
|
|
979
1328
|
cookieJar: cookies,
|
|
980
1329
|
...options
|
|
981
1330
|
});
|
|
982
|
-
await this.#auth.
|
|
1331
|
+
await this.#auth.commitAuthFlow(accessToken, cookies, revision);
|
|
983
1332
|
return accessToken;
|
|
984
1333
|
}
|
|
985
1334
|
/** Отправляет код подтверждения повторно. */
|
|
@@ -1084,7 +1433,10 @@ var AuthResource = class extends BaseResource {
|
|
|
1084
1433
|
forgotPassword(input, options = {}) {
|
|
1085
1434
|
return this.http.execute(AUTH_FORGOT_PASSWORD, {
|
|
1086
1435
|
path: AUTH_PATHS.forgotPassword,
|
|
1087
|
-
body:
|
|
1436
|
+
body: {
|
|
1437
|
+
email: input.email,
|
|
1438
|
+
...captchaBody(input.captcha)
|
|
1439
|
+
},
|
|
1088
1440
|
skipAuth: true,
|
|
1089
1441
|
skipAuthRefresh: true,
|
|
1090
1442
|
...options
|
|
@@ -1115,23 +1467,21 @@ var AuthResource = class extends BaseResource {
|
|
|
1115
1467
|
* ```ts
|
|
1116
1468
|
* await itd.auth.resetPasswordWithOtp({
|
|
1117
1469
|
* email,
|
|
1118
|
-
*
|
|
1470
|
+
* captcha: { type: provider, token, field },
|
|
1119
1471
|
* newPassword,
|
|
1120
1472
|
* getOtp: () => rl.question('Код из письма: '),
|
|
1121
1473
|
* });
|
|
1122
1474
|
* ```
|
|
1123
1475
|
*/
|
|
1124
1476
|
async resetPasswordWithOtp(input, options = {}) {
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
}, options);
|
|
1129
|
-
const otp = await input.getOtp();
|
|
1477
|
+
const { getOtp, newPassword, ...request } = input;
|
|
1478
|
+
const flowToken = await this.forgotPassword(request, options);
|
|
1479
|
+
const otp = await getOtp();
|
|
1130
1480
|
await this.resetPassword({
|
|
1131
1481
|
email: input.email,
|
|
1132
1482
|
otp,
|
|
1133
1483
|
flowToken,
|
|
1134
|
-
newPassword
|
|
1484
|
+
newPassword
|
|
1135
1485
|
}, options);
|
|
1136
1486
|
}
|
|
1137
1487
|
/**
|
|
@@ -1220,8 +1570,8 @@ function createManagedClient(options, internals) {
|
|
|
1220
1570
|
* const itd = new ItdClient({
|
|
1221
1571
|
* // `auth` не обязателен: когда хранилище уже содержит сессию, токен берётся оттуда,
|
|
1222
1572
|
* // а истёкший продлевается сам. Здесь он нужен на первый запуск.
|
|
1223
|
-
* // Вход по паролю требует токена капчи — см.
|
|
1224
|
-
* auth: { email, password,
|
|
1573
|
+
* // Вход по паролю требует токена капчи — см. CaptchaOptions.
|
|
1574
|
+
* auth: { email, password, captcha: createCaptchaSolver() },
|
|
1225
1575
|
* storage: new FileTokenStorage('./.itd-session.json'),
|
|
1226
1576
|
* rateLimit: { concurrency: 4, rps: 8 },
|
|
1227
1577
|
* });
|
|
@@ -1242,7 +1592,10 @@ var ItdClient = class ItdClient {
|
|
|
1242
1592
|
#auth;
|
|
1243
1593
|
/** Авторизация, сессии и пароли. */
|
|
1244
1594
|
get auth() {
|
|
1245
|
-
this.#auth ??= new AuthResource(this.#runtime.http, {
|
|
1595
|
+
this.#auth ??= new AuthResource(this.#runtime.http, {
|
|
1596
|
+
auth: this.#runtime.auth,
|
|
1597
|
+
connection: this.#runtime.connection()
|
|
1598
|
+
});
|
|
1246
1599
|
return this.#auth;
|
|
1247
1600
|
}
|
|
1248
1601
|
/** Профили, подписки, блокировки, приватность. */
|
|
@@ -1739,7 +2092,9 @@ function assertAccountsActive(accounts, action) {
|
|
|
1739
2092
|
* await accounts.restore();
|
|
1740
2093
|
*
|
|
1741
2094
|
* if (!accounts.has('kiow')) {
|
|
1742
|
-
* accounts.addAccount('kiow', {
|
|
2095
|
+
* accounts.addAccount('kiow', {
|
|
2096
|
+
* auth: { email, password, captcha: createCaptchaSolver() },
|
|
2097
|
+
* });
|
|
1743
2098
|
* }
|
|
1744
2099
|
*
|
|
1745
2100
|
* await accounts.account('kiow').posts.create({ content: 'привет' });
|
|
@@ -1818,7 +2173,9 @@ var ItdAccounts = class ItdAccounts {
|
|
|
1818
2173
|
*
|
|
1819
2174
|
* @example
|
|
1820
2175
|
* ```ts
|
|
1821
|
-
* accounts.addAccount('bot', {
|
|
2176
|
+
* accounts.addAccount('bot', {
|
|
2177
|
+
* auth: { email, password, captcha: createCaptchaSolver() },
|
|
2178
|
+
* });
|
|
1822
2179
|
* accounts.addAccount('reader', { auth: '<accessToken>' });
|
|
1823
2180
|
* accounts.addAccount('через-прокси', { fetch: proxyFetch('socks5://…') });
|
|
1824
2181
|
* ```
|
|
@@ -2151,6 +2508,6 @@ function createAccounts(options = {}) {
|
|
|
2151
2508
|
return new ItdAccounts(options);
|
|
2152
2509
|
}
|
|
2153
2510
|
//#endregion
|
|
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 };
|
|
2511
|
+
export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AccessType, AttachmentType, BUCKET_LIMITS, CAPTCHA_FIELDS, CaptchaChoice, CaptchaField, CaptchaType, 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, QrLoginStatus, QrLoginStreamStatus, 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 };
|
|
2155
2512
|
|
|
2156
2513
|
//# sourceMappingURL=index.js.map
|