itd-api 0.0.8 → 0.0.9
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 +79 -15
- package/dist/{chunk-ATCZ4T2K.cjs → chunk-HTF2MOM4.cjs} +517 -130
- package/dist/chunk-HTF2MOM4.cjs.map +1 -0
- package/dist/{chunk-JIYN33FG.js → chunk-MYAU2WJU.js} +507 -131
- package/dist/chunk-MYAU2WJU.js.map +1 -0
- package/dist/index.cjs +133 -89
- package/dist/index.d.cts +4206 -1
- package/dist/index.d.ts +4206 -1
- package/dist/index.js +1 -1
- package/dist/node.cjs +143 -95
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +13 -9
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-ATCZ4T2K.cjs.map +0 -1
- package/dist/chunk-JIYN33FG.js.map +0 -1
- package/dist/index-Duh31Wnx.d.cts +0 -3933
- package/dist/index-Duh31Wnx.d.ts +0 -3933
|
@@ -614,6 +614,20 @@ var RealtimeStatus = Object.freeze({
|
|
|
614
614
|
Error: "error",
|
|
615
615
|
Disconnected: "disconnected"
|
|
616
616
|
});
|
|
617
|
+
var ServiceState = Object.freeze({
|
|
618
|
+
/** Работает штатно. */
|
|
619
|
+
Operational: "operational",
|
|
620
|
+
/** Работает с деградацией. */
|
|
621
|
+
Degraded: "degraded",
|
|
622
|
+
/** Недоступен. */
|
|
623
|
+
Downtime: "downtime"
|
|
624
|
+
});
|
|
625
|
+
var IncidentKind = Object.freeze({
|
|
626
|
+
/** Недоступен. */
|
|
627
|
+
Down: "down",
|
|
628
|
+
/** Деградация. */
|
|
629
|
+
Degraded: "deg"
|
|
630
|
+
});
|
|
617
631
|
var AccessType = Object.freeze({
|
|
618
632
|
/** Никто. */
|
|
619
633
|
Nobody: "nobody",
|
|
@@ -1283,8 +1297,18 @@ function hasLocalStorage() {
|
|
|
1283
1297
|
|
|
1284
1298
|
// src/core/auth.ts
|
|
1285
1299
|
var AUTH_PATHS = {
|
|
1300
|
+
signUp: "/api/v1/auth/sign-up",
|
|
1286
1301
|
signIn: "/api/v1/auth/sign-in",
|
|
1287
|
-
|
|
1302
|
+
verifyOtp: "/api/v1/auth/verify-otp",
|
|
1303
|
+
resendOtp: "/api/v1/auth/resend-otp",
|
|
1304
|
+
refresh: "/api/v1/auth/refresh",
|
|
1305
|
+
logout: "/api/v1/auth/logout",
|
|
1306
|
+
forgotPassword: "/api/v1/auth/forgot-password",
|
|
1307
|
+
resetPassword: "/api/v1/auth/reset-password",
|
|
1308
|
+
changePassword: "/api/v1/auth/change-password",
|
|
1309
|
+
sessions: "/api/v1/auth/sessions",
|
|
1310
|
+
/** Префикс внешнего входа: к нему дописывается имя провайдера. */
|
|
1311
|
+
oauthLogin: "/api/v1/auth/login"
|
|
1288
1312
|
};
|
|
1289
1313
|
var TURNSTILE_SITE_KEY = "0x4AAAAAACHhxczw6fJGwPBg";
|
|
1290
1314
|
var DEVICE_ID_HEADER = "X-Device-Id";
|
|
@@ -1356,7 +1380,7 @@ var AuthManager = class {
|
|
|
1356
1380
|
/** То же самое, но без чтения хранилища — для вызовов, где сессия уже загружена. */
|
|
1357
1381
|
#hasRefreshSession() {
|
|
1358
1382
|
if (!this.#config.useCookieJar) return true;
|
|
1359
|
-
if (this.#jar.has(AUTH_FLAG_COOKIE)) return true;
|
|
1383
|
+
if (this.#jar.has(AUTH_FLAG_COOKIE, this.#config.baseUrl)) return true;
|
|
1360
1384
|
return Boolean(this.#session?.refreshToken);
|
|
1361
1385
|
}
|
|
1362
1386
|
/** Заголовки авторизации для очередного запроса. Пустой объект, если токена нет. */
|
|
@@ -1461,12 +1485,14 @@ var AuthManager = class {
|
|
|
1461
1485
|
async getSession() {
|
|
1462
1486
|
return this.#loadSession();
|
|
1463
1487
|
}
|
|
1464
|
-
/** Заменяет сессию целиком. */
|
|
1488
|
+
/** Заменяет сессию и связанные с ней cookie целиком. */
|
|
1465
1489
|
async setSession(session) {
|
|
1490
|
+
this.#jar.clear();
|
|
1466
1491
|
this.#jar.deserialize(session.cookies);
|
|
1467
|
-
this.#deviceId
|
|
1468
|
-
|
|
1492
|
+
if (session.deviceId) this.#deviceId = session.deviceId;
|
|
1493
|
+
this.#session = session;
|
|
1469
1494
|
this.#seedRefreshCookie();
|
|
1495
|
+
await this.#saveSession(session);
|
|
1470
1496
|
}
|
|
1471
1497
|
/**
|
|
1472
1498
|
* Забывает сессию и cookie. Сетевой запрос не выполняется.
|
|
@@ -1630,7 +1656,7 @@ var AuthManager = class {
|
|
|
1630
1656
|
}
|
|
1631
1657
|
if (credentials.turnstileToken) return credentials.turnstileToken;
|
|
1632
1658
|
throw new ItdConfigError(
|
|
1633
|
-
"\u0412\u0445\u043E\u0434 \u043F\u043E email \u0438 \u043F\u0430\u0440\u043E\u043B\u044E \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0442\u043E\u043A\u0435\u043D \u043A\u0430\u043F\u0447\u0438 Cloudflare Turnstile: \u0431\u0435\u0437 \u043D\u0435\u0433\u043E \u0441\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 422. \u041F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 auth.getTurnstileToken (\u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A \u0441\u0432\u0435\u0436\u0435\u0433\u043E \u0442\u043E\u043A\u0435\u043D\u0430) \u043B\u0438\u0431\u043E \u0440\u0430\u0437\u043E\u0432\u044B\u0439 auth.turnstileToken. \u041A\u043B\u044E\u0447 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u2014 TURNSTILE_SITE_KEY. \u0412 Node \u0442\u043E\u043A\u0435\u043D \u0443\u043C\u0435\u0435\u0442 \u0434\u043E\u0431\u044B\u0432\u0430\u0442\u044C \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u044B\u0439 \u043F\u0430\u043A\u0435\u0442: npm i itd-api
|
|
1659
|
+
"\u0412\u0445\u043E\u0434 \u043F\u043E email \u0438 \u043F\u0430\u0440\u043E\u043B\u044E \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0442\u043E\u043A\u0435\u043D \u043A\u0430\u043F\u0447\u0438 Cloudflare Turnstile: \u0431\u0435\u0437 \u043D\u0435\u0433\u043E \u0441\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 422. \u041F\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 auth.getTurnstileToken (\u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A \u0441\u0432\u0435\u0436\u0435\u0433\u043E \u0442\u043E\u043A\u0435\u043D\u0430) \u043B\u0438\u0431\u043E \u0440\u0430\u0437\u043E\u0432\u044B\u0439 auth.turnstileToken. \u041A\u043B\u044E\u0447 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u2014 TURNSTILE_SITE_KEY. \u0412 Node \u0442\u043E\u043A\u0435\u043D \u0443\u043C\u0435\u0435\u0442 \u0434\u043E\u0431\u044B\u0432\u0430\u0442\u044C \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u044B\u0439 \u043F\u0430\u043A\u0435\u0442: npm i @itd-api/turnstile, \u0437\u0430\u0442\u0435\u043C getTurnstileToken: createTurnstileSolver()."
|
|
1634
1660
|
);
|
|
1635
1661
|
}
|
|
1636
1662
|
async #performSignIn(credentials) {
|
|
@@ -1675,6 +1701,7 @@ var MemoryTokenStorage = class {
|
|
|
1675
1701
|
var LocalStorageTokenStorage = class {
|
|
1676
1702
|
#key;
|
|
1677
1703
|
#fallback = new MemoryTokenStorage();
|
|
1704
|
+
/** Доступен ли `localStorage` для дальнейших операций. */
|
|
1678
1705
|
#available;
|
|
1679
1706
|
/** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */
|
|
1680
1707
|
constructor(key = "itd-api:session") {
|
|
@@ -1693,26 +1720,31 @@ var LocalStorageTokenStorage = class {
|
|
|
1693
1720
|
}
|
|
1694
1721
|
}
|
|
1695
1722
|
set(session) {
|
|
1696
|
-
if (
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
this.#fallback.set(session);
|
|
1723
|
+
if (this.#available) {
|
|
1724
|
+
try {
|
|
1725
|
+
globalThis.localStorage.setItem(this.#key, JSON.stringify(session));
|
|
1726
|
+
return;
|
|
1727
|
+
} catch {
|
|
1728
|
+
this.#degrade();
|
|
1729
|
+
}
|
|
1704
1730
|
}
|
|
1731
|
+
this.#fallback.set(session);
|
|
1705
1732
|
}
|
|
1706
1733
|
clear() {
|
|
1707
|
-
if (
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
this.#fallback.clear();
|
|
1734
|
+
if (this.#available) {
|
|
1735
|
+
try {
|
|
1736
|
+
globalThis.localStorage.removeItem(this.#key);
|
|
1737
|
+
return;
|
|
1738
|
+
} catch {
|
|
1739
|
+
this.#degrade();
|
|
1740
|
+
}
|
|
1715
1741
|
}
|
|
1742
|
+
this.#fallback.clear();
|
|
1743
|
+
}
|
|
1744
|
+
/** Переводит хранилище в память без переноса прежнего значения. */
|
|
1745
|
+
#degrade() {
|
|
1746
|
+
this.#available = false;
|
|
1747
|
+
this.#fallback.clear();
|
|
1716
1748
|
}
|
|
1717
1749
|
};
|
|
1718
1750
|
function createTokenStorage(handlers) {
|
|
@@ -1768,10 +1800,15 @@ function normalizeBaseUrl(baseUrl) {
|
|
|
1768
1800
|
}
|
|
1769
1801
|
|
|
1770
1802
|
// src/core/version.ts
|
|
1771
|
-
var LIBRARY_VERSION = "0.0.
|
|
1803
|
+
var LIBRARY_VERSION = "0.0.9";
|
|
1772
1804
|
|
|
1773
1805
|
// src/core/config.ts
|
|
1774
1806
|
var DEFAULT_BASE_URL = "https://xn--d1ah4a.com";
|
|
1807
|
+
var DEFAULT_STATUS_BASE_URL = "https://xn--80a7abcbg.xn--d1ah4a.com";
|
|
1808
|
+
var STATUS_SERVICE = "status";
|
|
1809
|
+
var BUILT_IN_SERVICES = Object.freeze([
|
|
1810
|
+
Object.freeze({ name: STATUS_SERVICE, baseUrl: DEFAULT_STATUS_BASE_URL, auth: false })
|
|
1811
|
+
]);
|
|
1775
1812
|
var DEFAULT_TIMEOUT = 3e4;
|
|
1776
1813
|
var DEFAULT_USER_AGENT = `Mozilla/5.0 (compatible; itd-api/${LIBRARY_VERSION}; +https://github.com/KiowDev/itd-api)`;
|
|
1777
1814
|
var DEFAULT_RATE_LIMIT_DELAYS = Object.freeze([1e3, 5e3, 3e4, 6e4, 9e4]);
|
|
@@ -1884,6 +1921,12 @@ function validateAuth(auth) {
|
|
|
1884
1921
|
"auth \u043D\u0435 \u0440\u0430\u0441\u043F\u043E\u0437\u043D\u0430\u043D. \u041E\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u0441 accessToken \u043B\u0438\u0431\u043E \u043E\u0431\u044A\u0435\u043A\u0442 { accessToken }, { email, password } \u0438\u043B\u0438 { getToken }"
|
|
1885
1922
|
);
|
|
1886
1923
|
}
|
|
1924
|
+
function resolveServices(services) {
|
|
1925
|
+
if (!services) return [];
|
|
1926
|
+
return Object.entries(services).map(
|
|
1927
|
+
([name, value]) => typeof value === "string" ? { name, baseUrl: value } : { ...value, name }
|
|
1928
|
+
);
|
|
1929
|
+
}
|
|
1887
1930
|
function resolveConfig(options = {}) {
|
|
1888
1931
|
const mode = options.mode ?? RuntimeMode.Auto;
|
|
1889
1932
|
if (!Object.values(RuntimeMode).includes(mode)) {
|
|
@@ -1897,6 +1940,7 @@ function resolveConfig(options = {}) {
|
|
|
1897
1940
|
}
|
|
1898
1941
|
return {
|
|
1899
1942
|
baseUrl: normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL),
|
|
1943
|
+
services: resolveServices(options.services),
|
|
1900
1944
|
auth: validateAuth(options.auth),
|
|
1901
1945
|
storage: options.storage ?? new MemoryTokenStorage(),
|
|
1902
1946
|
autoRefresh: options.autoRefresh ?? true,
|
|
@@ -2003,7 +2047,7 @@ function sleep(ms) {
|
|
|
2003
2047
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2004
2048
|
}
|
|
2005
2049
|
function createQueueMiddleware(schedule) {
|
|
2006
|
-
return (request, next) => request.skipQueue ? next(request) : schedule(() => next(request));
|
|
2050
|
+
return (request, next) => request.skipQueue ? next(request) : schedule(request, () => next(request));
|
|
2007
2051
|
}
|
|
2008
2052
|
function createPluginsMiddleware(plugins) {
|
|
2009
2053
|
return (request, next) => {
|
|
@@ -2011,6 +2055,18 @@ function createPluginsMiddleware(plugins) {
|
|
|
2011
2055
|
return plugins.run(request, next);
|
|
2012
2056
|
};
|
|
2013
2057
|
}
|
|
2058
|
+
function createServicesMiddleware(registry) {
|
|
2059
|
+
return async (request, next) => {
|
|
2060
|
+
if (request.service === void 0) return next(request);
|
|
2061
|
+
const service = registry.require(request.service);
|
|
2062
|
+
let prepared = request.baseUrl === void 0 ? { ...request, baseUrl: service.baseUrl } : request;
|
|
2063
|
+
if (service.headers) prepared = withLayerHeaders(prepared, service.headers);
|
|
2064
|
+
if (service.auth === false && prepared.skipAuth === void 0) {
|
|
2065
|
+
prepared = { ...prepared, skipAuth: true };
|
|
2066
|
+
}
|
|
2067
|
+
return next(prepared);
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2014
2070
|
async function applyAuth(request, deps) {
|
|
2015
2071
|
if (request.skipAuth) return request;
|
|
2016
2072
|
const headers = await deps.getAuthHeaders();
|
|
@@ -2040,11 +2096,11 @@ function resolveBackoff(retry, global) {
|
|
|
2040
2096
|
}
|
|
2041
2097
|
function createRetryMiddleware(deps) {
|
|
2042
2098
|
const globalScheduler = deps.retry ? createRetryScheduler(deps.retry) : void 0;
|
|
2043
|
-
const nextDelay = (error, attempt, method, backoff) => {
|
|
2099
|
+
const nextDelay = (error, attempt, request, method, backoff) => {
|
|
2044
2100
|
if (isItdRateLimitError(error)) {
|
|
2045
2101
|
const wait = error.retryAfter ?? deps.rateLimitDelays[attempt - 1];
|
|
2046
2102
|
if (wait === void 0) return void 0;
|
|
2047
|
-
deps.pauseQueue?.(wait);
|
|
2103
|
+
deps.pauseQueue?.(wait, request);
|
|
2048
2104
|
deps.logger?.debug(`\u043B\u0438\u043C\u0438\u0442 \u0447\u0430\u0441\u0442\u043E\u0442\u044B, \u043F\u043E\u043F\u044B\u0442\u043A\u0430 ${attempt + 1} \u0447\u0435\u0440\u0435\u0437 ${wait} \u043C\u0441`);
|
|
2049
2105
|
return wait;
|
|
2050
2106
|
}
|
|
@@ -2057,13 +2113,14 @@ function createRetryMiddleware(deps) {
|
|
|
2057
2113
|
try {
|
|
2058
2114
|
return await next({ ...request, attempt });
|
|
2059
2115
|
} catch (error) {
|
|
2060
|
-
const delay = nextDelay(error, attempt, method, backoff);
|
|
2116
|
+
const delay = nextDelay(error, attempt, request, method, backoff);
|
|
2061
2117
|
if (delay === void 0) throw error;
|
|
2062
2118
|
await deps.hooks.onRetry?.({
|
|
2063
2119
|
method,
|
|
2064
2120
|
path: request.path,
|
|
2065
2121
|
url: deps.buildUrl(request),
|
|
2066
|
-
|
|
2122
|
+
// Умолчания транспорта добавляются после слоя повторов и сюда не входят.
|
|
2123
|
+
headers: new Headers({ ...request.layerHeaders, ...request.headers }),
|
|
2067
2124
|
attempt,
|
|
2068
2125
|
error,
|
|
2069
2126
|
delay
|
|
@@ -2086,6 +2143,8 @@ var RESERVED_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
|
2086
2143
|
"retry",
|
|
2087
2144
|
"method",
|
|
2088
2145
|
"path",
|
|
2146
|
+
"service",
|
|
2147
|
+
"baseUrl",
|
|
2089
2148
|
"query",
|
|
2090
2149
|
"body",
|
|
2091
2150
|
"skipAuth",
|
|
@@ -2253,6 +2312,107 @@ var RequestQueue = class {
|
|
|
2253
2312
|
this.#drain();
|
|
2254
2313
|
}
|
|
2255
2314
|
};
|
|
2315
|
+
var RequestQueuePool = class {
|
|
2316
|
+
#options;
|
|
2317
|
+
#main;
|
|
2318
|
+
/** Очереди сервисов заводятся при первом запросе — обычно не нужна ни одна. */
|
|
2319
|
+
#byService = /* @__PURE__ */ new Map();
|
|
2320
|
+
constructor(options) {
|
|
2321
|
+
this.#options = options;
|
|
2322
|
+
this.#main = new RequestQueue(options);
|
|
2323
|
+
}
|
|
2324
|
+
/** Очередь хоста. */
|
|
2325
|
+
for(service) {
|
|
2326
|
+
if (service === void 0) return this.#main;
|
|
2327
|
+
let queue = this.#byService.get(service);
|
|
2328
|
+
if (!queue) {
|
|
2329
|
+
queue = new RequestQueue(this.#options);
|
|
2330
|
+
this.#byService.set(service, queue);
|
|
2331
|
+
}
|
|
2332
|
+
return queue;
|
|
2333
|
+
}
|
|
2334
|
+
/** Останавливает все очереди. */
|
|
2335
|
+
stop() {
|
|
2336
|
+
this.#main.stop();
|
|
2337
|
+
for (const queue of this.#byService.values()) queue.stop();
|
|
2338
|
+
}
|
|
2339
|
+
};
|
|
2340
|
+
|
|
2341
|
+
// src/core/services.ts
|
|
2342
|
+
function hostOf(url) {
|
|
2343
|
+
try {
|
|
2344
|
+
return new URL(url).hostname.toLowerCase();
|
|
2345
|
+
} catch {
|
|
2346
|
+
return "";
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
function isSameSite(primaryHost, host) {
|
|
2350
|
+
if (!primaryHost || !host) return false;
|
|
2351
|
+
return host === primaryHost || host.endsWith(`.${primaryHost}`);
|
|
2352
|
+
}
|
|
2353
|
+
var ServiceRegistry = class {
|
|
2354
|
+
#services = /* @__PURE__ */ new Map();
|
|
2355
|
+
/** Хост основного API. */
|
|
2356
|
+
#primaryHost;
|
|
2357
|
+
/** @param primaryBaseUrl базовый URL клиента */
|
|
2358
|
+
constructor(primaryBaseUrl) {
|
|
2359
|
+
this.#primaryHost = primaryBaseUrl ? hostOf(primaryBaseUrl) : "";
|
|
2360
|
+
}
|
|
2361
|
+
/**
|
|
2362
|
+
* Регистрирует сервис. Имя очищается от краевых пробелов, базовый URL приводится
|
|
2363
|
+
* к каноничному виду, а незаданный `auth` выводится из хоста.
|
|
2364
|
+
*
|
|
2365
|
+
* @throws {ItdConfigError} если имя пустое, имя занято или `baseUrl` не абсолютный URL
|
|
2366
|
+
*/
|
|
2367
|
+
define(definition) {
|
|
2368
|
+
const raw = definition?.name;
|
|
2369
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
2370
|
+
throw new ItdConfigError("\u0423 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435\u043F\u0443\u0441\u0442\u043E\u0435 \u0438\u043C\u044F");
|
|
2371
|
+
}
|
|
2372
|
+
const name = raw.trim();
|
|
2373
|
+
if (this.#services.has(name)) {
|
|
2374
|
+
throw new ItdConfigError(`\u0421\u0435\u0440\u0432\u0438\u0441 \xAB${name}\xBB \u0443\u0436\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0437\u0430\u043C\u0435\u043D\u0451\u043D`);
|
|
2375
|
+
}
|
|
2376
|
+
const baseUrl = normalizeBaseUrl(definition.baseUrl);
|
|
2377
|
+
this.#services.set(name, {
|
|
2378
|
+
...definition,
|
|
2379
|
+
name,
|
|
2380
|
+
baseUrl,
|
|
2381
|
+
auth: definition.auth ?? isSameSite(this.#primaryHost, hostOf(baseUrl))
|
|
2382
|
+
});
|
|
2383
|
+
}
|
|
2384
|
+
/** Определение сервиса либо `undefined`, если такого нет. */
|
|
2385
|
+
get(name) {
|
|
2386
|
+
return this.#services.get(name);
|
|
2387
|
+
}
|
|
2388
|
+
/** Зарегистрирован ли сервис с таким именем. */
|
|
2389
|
+
has(name) {
|
|
2390
|
+
return this.#services.has(name);
|
|
2391
|
+
}
|
|
2392
|
+
/**
|
|
2393
|
+
* Определение сервиса.
|
|
2394
|
+
*
|
|
2395
|
+
* @throws {ItdConfigError} если сервис не зарегистрирован
|
|
2396
|
+
*/
|
|
2397
|
+
require(name) {
|
|
2398
|
+
const service = this.#services.get(name);
|
|
2399
|
+
if (!service) {
|
|
2400
|
+
const known = [...this.#services.keys()];
|
|
2401
|
+
throw new ItdConfigError(
|
|
2402
|
+
`\u0421\u0435\u0440\u0432\u0438\u0441 \xAB${name}\xBB \u043D\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D. ` + (known.length > 0 ? `\u0418\u0437\u0432\u0435\u0441\u0442\u043D\u044B: ${known.join(", ")}` : "\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0435\u0433\u043E \u0447\u0435\u0440\u0435\u0437 itd.defineService() \u0438\u043B\u0438 \u043E\u043F\u0446\u0438\u044E services")
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2405
|
+
return service;
|
|
2406
|
+
}
|
|
2407
|
+
/**
|
|
2408
|
+
* Базовый URL сервиса.
|
|
2409
|
+
*
|
|
2410
|
+
* @throws {ItdConfigError} если сервис не зарегистрирован
|
|
2411
|
+
*/
|
|
2412
|
+
resolveBaseUrl(name) {
|
|
2413
|
+
return this.require(name).baseUrl;
|
|
2414
|
+
}
|
|
2415
|
+
};
|
|
2256
2416
|
|
|
2257
2417
|
// src/core/redact.ts
|
|
2258
2418
|
var SECRET_HEADERS = /* @__PURE__ */ new Set(["authorization", "cookie", "set-cookie", "x-api-key"]);
|
|
@@ -2530,6 +2690,29 @@ async function readBody(response) {
|
|
|
2530
2690
|
const text = await response.text();
|
|
2531
2691
|
return text === "" ? void 0 : text;
|
|
2532
2692
|
}
|
|
2693
|
+
function createAbortError() {
|
|
2694
|
+
const error = new Error("\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430");
|
|
2695
|
+
error.name = "AbortError";
|
|
2696
|
+
return error;
|
|
2697
|
+
}
|
|
2698
|
+
function abortable(promise, signal) {
|
|
2699
|
+
if (signal.aborted) {
|
|
2700
|
+
return Promise.race([
|
|
2701
|
+
promise,
|
|
2702
|
+
new Promise((_resolve, reject) => {
|
|
2703
|
+
setTimeout(() => reject(createAbortError()), 0);
|
|
2704
|
+
})
|
|
2705
|
+
]);
|
|
2706
|
+
}
|
|
2707
|
+
let onAbort;
|
|
2708
|
+
const interrupted = new Promise((_resolve, reject) => {
|
|
2709
|
+
onAbort = () => reject(createAbortError());
|
|
2710
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2711
|
+
});
|
|
2712
|
+
return Promise.race([promise, interrupted]).finally(() => {
|
|
2713
|
+
if (onAbort) signal.removeEventListener("abort", onAbort);
|
|
2714
|
+
});
|
|
2715
|
+
}
|
|
2533
2716
|
function createAbortBundle(userSignal, timeout) {
|
|
2534
2717
|
const controller = new AbortController();
|
|
2535
2718
|
let timedOut = false;
|
|
@@ -2593,70 +2776,104 @@ var Transport = class {
|
|
|
2593
2776
|
headers: redactHeaders(headers),
|
|
2594
2777
|
body: redactBody(request.body)
|
|
2595
2778
|
});
|
|
2596
|
-
let response;
|
|
2597
2779
|
try {
|
|
2598
|
-
response
|
|
2780
|
+
let response;
|
|
2781
|
+
try {
|
|
2782
|
+
response = await this.#config.fetch(url, {
|
|
2783
|
+
method,
|
|
2784
|
+
headers,
|
|
2785
|
+
signal: abort.signal,
|
|
2786
|
+
...body !== void 0 ? { body } : {},
|
|
2787
|
+
...this.#config.sendCredentials ? { credentials: "include" } : {}
|
|
2788
|
+
});
|
|
2789
|
+
} catch (error) {
|
|
2790
|
+
const duration2 = Date.now() - startedAt;
|
|
2791
|
+
const failure = this.#toTransportError(error, abort, request, method, timeout);
|
|
2792
|
+
await this.#config.hooks.onError?.({ ...context, duration: duration2, error: failure });
|
|
2793
|
+
this.#config.logger?.warn(
|
|
2794
|
+
`\xD7 ${method} ${request.path} (${duration2} \u043C\u0441): ${failure.message}`
|
|
2795
|
+
);
|
|
2796
|
+
throw failure;
|
|
2797
|
+
}
|
|
2798
|
+
if (this.#deps.onRateLimit) {
|
|
2799
|
+
const { limit, remaining } = readRateLimit(response.headers);
|
|
2800
|
+
this.#deps.onRateLimit(limit, remaining, request);
|
|
2801
|
+
}
|
|
2802
|
+
if (this.#config.useCookieJar) this.#deps.cookies?.setFromResponse(url, response);
|
|
2803
|
+
if (response.ok) {
|
|
2804
|
+
await this.#config.hooks.onResponse?.({
|
|
2805
|
+
...context,
|
|
2806
|
+
status: response.status,
|
|
2807
|
+
duration: Date.now() - startedAt,
|
|
2808
|
+
response
|
|
2809
|
+
});
|
|
2810
|
+
}
|
|
2811
|
+
const payload = await this.#readBodyOrFail(
|
|
2812
|
+
response,
|
|
2813
|
+
context,
|
|
2814
|
+
request,
|
|
2599
2815
|
method,
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2816
|
+
abort,
|
|
2817
|
+
timeout
|
|
2818
|
+
);
|
|
2819
|
+
const duration = Date.now() - startedAt;
|
|
2820
|
+
if (!response.ok) {
|
|
2821
|
+
const error = createApiError({
|
|
2822
|
+
method,
|
|
2823
|
+
path: request.path,
|
|
2824
|
+
status: response.status,
|
|
2825
|
+
statusText: response.statusText,
|
|
2826
|
+
headers: response.headers,
|
|
2827
|
+
response,
|
|
2828
|
+
body: payload
|
|
2829
|
+
});
|
|
2830
|
+
await this.#config.hooks.onError?.({ ...context, duration, error });
|
|
2831
|
+
this.#config.logger?.warn(
|
|
2832
|
+
`\u2190 ${response.status} ${method} ${request.path} (${duration} \u043C\u0441): ${error.message}`
|
|
2833
|
+
);
|
|
2834
|
+
throw error;
|
|
2835
|
+
}
|
|
2836
|
+
this.#config.logger?.debug(`\u2190 ${response.status} ${method} ${request.path} (${duration} \u043C\u0441)`);
|
|
2837
|
+
return request.raw ? payload : unwrapData(payload);
|
|
2611
2838
|
} finally {
|
|
2612
2839
|
abort.cleanup();
|
|
2613
2840
|
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
response,
|
|
2629
|
-
body: payload
|
|
2841
|
+
};
|
|
2842
|
+
/** Читает тело и преобразует ошибку чтения в транспортную ошибку библиотеки. */
|
|
2843
|
+
async #readBodyOrFail(response, context, request, method, abort, timeout) {
|
|
2844
|
+
const startedAt = Date.now();
|
|
2845
|
+
try {
|
|
2846
|
+
return await abortable(readBody(response), abort.signal);
|
|
2847
|
+
} catch (error) {
|
|
2848
|
+
await response.body?.cancel().catch(() => {
|
|
2849
|
+
});
|
|
2850
|
+
const failure = this.#toTransportError(error, abort, request, method, timeout);
|
|
2851
|
+
await this.#config.hooks.onError?.({
|
|
2852
|
+
...context,
|
|
2853
|
+
duration: Date.now() - startedAt,
|
|
2854
|
+
error: failure
|
|
2630
2855
|
});
|
|
2631
|
-
await this.#config.hooks.onError?.({ ...context, duration, error });
|
|
2632
2856
|
this.#config.logger?.warn(
|
|
2633
|
-
`\
|
|
2857
|
+
`\xD7 ${method} ${request.path}: \u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C \u0442\u0435\u043B\u043E \u043E\u0442\u0432\u0435\u0442\u0430 \u2014 ${failure.message}`
|
|
2634
2858
|
);
|
|
2635
|
-
throw
|
|
2859
|
+
throw failure;
|
|
2636
2860
|
}
|
|
2637
|
-
await this.#config.hooks.onResponse?.({
|
|
2638
|
-
...context,
|
|
2639
|
-
status: response.status,
|
|
2640
|
-
duration,
|
|
2641
|
-
response
|
|
2642
|
-
});
|
|
2643
|
-
this.#config.logger?.debug(`\u2190 ${response.status} ${method} ${request.path} (${duration} \u043C\u0441)`);
|
|
2644
|
-
return request.raw ? payload : unwrapData(payload);
|
|
2645
|
-
};
|
|
2646
|
-
/** Итоговый URL со строкой запроса. Нужен и слою повторов — для хука `onRetry`. */
|
|
2647
|
-
buildUrl(request) {
|
|
2648
|
-
return joinUrl(this.#config.baseUrl, request.path) + buildQuery(request.query);
|
|
2649
2861
|
}
|
|
2650
2862
|
/**
|
|
2651
|
-
*
|
|
2863
|
+
* Итоговый URL со строкой запроса. Нужен и слою повторов — для хука `onRetry`.
|
|
2652
2864
|
*
|
|
2653
|
-
*
|
|
2654
|
-
* что добавили слои конвейера (авторизация), и только в самом конце — заголовки
|
|
2655
|
-
* конкретного вызова. Так пользователь может переопределить что угодно.
|
|
2865
|
+
* Хост берётся из самого запроса, если он там задан: у сервисов платформы свои домены.
|
|
2656
2866
|
*/
|
|
2657
|
-
|
|
2867
|
+
buildUrl(request) {
|
|
2868
|
+
const base = request.baseUrl ?? this.#config.baseUrl;
|
|
2869
|
+
return joinUrl(base, request.path) + buildQuery(request.query);
|
|
2870
|
+
}
|
|
2871
|
+
/**
|
|
2872
|
+
* Собирает общие заголовки клиента: `User-Agent`, идентификатор устройства,
|
|
2873
|
+
* заголовки конфигурации и cookie для указанного адреса.
|
|
2874
|
+
*/
|
|
2875
|
+
async platformHeaders(url) {
|
|
2658
2876
|
const headers = new Headers();
|
|
2659
|
-
headers.set("Accept", "application/json");
|
|
2660
2877
|
headers.set("X-Requested-With", "XMLHttpRequest");
|
|
2661
2878
|
if (this.#config.userAgent) setHeader(headers, "User-Agent", this.#config.userAgent);
|
|
2662
2879
|
if (this.#deps.getDeviceId) {
|
|
@@ -2664,12 +2881,21 @@ var Transport = class {
|
|
|
2664
2881
|
}
|
|
2665
2882
|
for (const [name, value] of Object.entries(this.#config.headers))
|
|
2666
2883
|
setHeader(headers, name, value);
|
|
2667
|
-
for (const [name, value] of Object.entries(request.layerHeaders ?? {}))
|
|
2668
|
-
setHeader(headers, name, value);
|
|
2669
2884
|
if (this.#config.useCookieJar && this.#deps.cookies) {
|
|
2670
2885
|
const cookie = this.#deps.cookies.getHeader(url);
|
|
2671
2886
|
if (cookie) setHeader(headers, "Cookie", cookie);
|
|
2672
2887
|
}
|
|
2888
|
+
return headers;
|
|
2889
|
+
}
|
|
2890
|
+
/**
|
|
2891
|
+
* Дополняет общие заголовки значением `Accept`, заголовками конвейера и вызова.
|
|
2892
|
+
* Заголовки вызова применяются последними.
|
|
2893
|
+
*/
|
|
2894
|
+
async #buildHeaders(request, url) {
|
|
2895
|
+
const headers = await this.platformHeaders(url);
|
|
2896
|
+
if (!headers.has("Accept")) headers.set("Accept", "application/json");
|
|
2897
|
+
for (const [name, value] of Object.entries(request.layerHeaders ?? {}))
|
|
2898
|
+
setHeader(headers, name, value);
|
|
2673
2899
|
for (const [name, value] of Object.entries(request.headers ?? {})) {
|
|
2674
2900
|
setHeader(headers, name, value);
|
|
2675
2901
|
}
|
|
@@ -2796,14 +3022,15 @@ var PollTransport = class {
|
|
|
2796
3022
|
while (!context.signal.aborted) {
|
|
2797
3023
|
const token = await context.getToken();
|
|
2798
3024
|
if (!token) throw new UnauthorizedStreamError();
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2801
|
-
|
|
3025
|
+
const url = `${joinUrl(context.baseUrl, "/api/notifications/")}?limit=${this.#limit}&offset=0`;
|
|
3026
|
+
const headers = await context.baseHeaders(url);
|
|
3027
|
+
headers.set("Accept", "application/json");
|
|
3028
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
3029
|
+
const response = await context.fetch(url, {
|
|
3030
|
+
method: "GET",
|
|
3031
|
+
headers,
|
|
3032
|
+
signal: context.signal
|
|
2802
3033
|
});
|
|
2803
|
-
const response = await context.fetch(
|
|
2804
|
-
`${joinUrl(context.baseUrl, "/api/notifications/")}?limit=${this.#limit}&offset=0`,
|
|
2805
|
-
{ method: "GET", headers, signal: context.signal }
|
|
2806
|
-
);
|
|
2807
3034
|
if (response.status === 401) throw new UnauthorizedStreamError();
|
|
2808
3035
|
if (!response.ok) throw new Error(`\u041E\u043F\u0440\u043E\u0441 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0439 \u0432\u0435\u0440\u043D\u0443\u043B \u0441\u0442\u0430\u0442\u0443\u0441 ${response.status}`);
|
|
2809
3036
|
const body = await response.json();
|
|
@@ -3059,13 +3286,13 @@ var SseTransport = class {
|
|
|
3059
3286
|
async connect(context) {
|
|
3060
3287
|
const token = await context.getToken();
|
|
3061
3288
|
if (!token) throw new UnauthorizedStreamError();
|
|
3062
|
-
const
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3289
|
+
const url = joinUrl(context.baseUrl, STREAM_PATH);
|
|
3290
|
+
const headers = await context.baseHeaders(url);
|
|
3291
|
+
headers.set("Accept", "text/event-stream");
|
|
3292
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
3293
|
+
headers.set("Cache-Control", "no-cache");
|
|
3067
3294
|
if (this.#lastEventId) headers.set("Last-Event-ID", this.#lastEventId);
|
|
3068
|
-
const response = await context.fetch(
|
|
3295
|
+
const response = await context.fetch(url, {
|
|
3069
3296
|
method: "GET",
|
|
3070
3297
|
headers,
|
|
3071
3298
|
signal: context.signal
|
|
@@ -3126,6 +3353,38 @@ var RealtimeTransportKind = Object.freeze({
|
|
|
3126
3353
|
/** Периодический опрос REST. */
|
|
3127
3354
|
Poll: "poll"
|
|
3128
3355
|
});
|
|
3356
|
+
function validateRealtimeOptions(options) {
|
|
3357
|
+
const positiveInteger = (value, name) => {
|
|
3358
|
+
if (value === void 0) return;
|
|
3359
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
3360
|
+
throw new ItdConfigError(
|
|
3361
|
+
`realtime.${name} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0446\u0435\u043B\u044B\u043C \u043D\u0435\u043E\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043B\u044C\u043D\u044B\u043C \u0447\u0438\u0441\u043B\u043E\u043C, \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E: ${value}`
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
};
|
|
3365
|
+
const duration = (value, name, min) => {
|
|
3366
|
+
if (value === void 0) return;
|
|
3367
|
+
if (!Number.isFinite(value) || value < min) {
|
|
3368
|
+
throw new ItdConfigError(
|
|
3369
|
+
`realtime.${name} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0447\u0438\u0441\u043B\u043E\u043C \u043D\u0435 \u043C\u0435\u043D\u044C\u0448\u0435 ${min}, \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E: ${value}`
|
|
3370
|
+
);
|
|
3371
|
+
}
|
|
3372
|
+
};
|
|
3373
|
+
positiveInteger(options.maxAttempts, "maxAttempts");
|
|
3374
|
+
duration(options.pollInterval, "pollInterval", 1);
|
|
3375
|
+
duration(options.idleTimeout, "idleTimeout", 0);
|
|
3376
|
+
if (options.jitter !== void 0 && !(options.jitter >= 0 && options.jitter <= 1)) {
|
|
3377
|
+
throw new ItdConfigError(
|
|
3378
|
+
`realtime.jitter \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0432 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D\u0435 0\u20261, \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E: ${options.jitter}`
|
|
3379
|
+
);
|
|
3380
|
+
}
|
|
3381
|
+
if (options.backoff !== void 0) {
|
|
3382
|
+
if (!Array.isArray(options.backoff) || options.backoff.length === 0) {
|
|
3383
|
+
throw new ItdConfigError("realtime.backoff \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043D\u0435\u043F\u0443\u0441\u0442\u044B\u043C \u0441\u043F\u0438\u0441\u043A\u043E\u043C \u043F\u0430\u0443\u0437");
|
|
3384
|
+
}
|
|
3385
|
+
for (const delay of options.backoff) duration(delay, "backoff", 0);
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3129
3388
|
var ItdRealtime = class {
|
|
3130
3389
|
#deps;
|
|
3131
3390
|
#options;
|
|
@@ -3147,6 +3406,7 @@ var ItdRealtime = class {
|
|
|
3147
3406
|
#timer;
|
|
3148
3407
|
#detachEnvironment;
|
|
3149
3408
|
constructor(deps, options = {}) {
|
|
3409
|
+
validateRealtimeOptions(options);
|
|
3150
3410
|
this.#deps = deps;
|
|
3151
3411
|
this.#options = options;
|
|
3152
3412
|
this.#maxAttempts = options.maxAttempts ?? MAX_RECONNECT_ATTEMPTS;
|
|
@@ -3227,6 +3487,7 @@ var ItdRealtime = class {
|
|
|
3227
3487
|
}
|
|
3228
3488
|
/** Запускает попытку подключения; повторы планирует сам. */
|
|
3229
3489
|
#run() {
|
|
3490
|
+
if (!this.#wanted) return;
|
|
3230
3491
|
this.#controller?.abort();
|
|
3231
3492
|
const controller = new AbortController();
|
|
3232
3493
|
this.#controller = controller;
|
|
@@ -3234,6 +3495,7 @@ var ItdRealtime = class {
|
|
|
3234
3495
|
void this.#transport.connect({
|
|
3235
3496
|
baseUrl: this.#deps.baseUrl,
|
|
3236
3497
|
fetch: this.#deps.fetch,
|
|
3498
|
+
baseHeaders: this.#deps.baseHeaders,
|
|
3237
3499
|
getToken: this.#deps.getToken,
|
|
3238
3500
|
signal: controller.signal,
|
|
3239
3501
|
onOpen: () => {
|
|
@@ -3284,17 +3546,17 @@ var ItdRealtime = class {
|
|
|
3284
3546
|
async #refreshAndReconnect(error) {
|
|
3285
3547
|
this.#setStatus(RealtimeStatus.Error);
|
|
3286
3548
|
const refreshed = await this.#deps.refresh().catch(() => false);
|
|
3549
|
+
if (!this.#wanted) return;
|
|
3287
3550
|
if (!refreshed) {
|
|
3288
|
-
this.#
|
|
3289
|
-
this.#emitter.emit("giveup", void 0);
|
|
3551
|
+
this.#giveUp(error);
|
|
3290
3552
|
return;
|
|
3291
3553
|
}
|
|
3292
3554
|
this.#scheduleReconnect(error);
|
|
3293
3555
|
}
|
|
3294
3556
|
#scheduleReconnect(error) {
|
|
3557
|
+
if (!this.#wanted) return;
|
|
3295
3558
|
if (this.#attempt >= this.#maxAttempts) {
|
|
3296
|
-
this.#
|
|
3297
|
-
this.#emitter.emit("giveup", void 0);
|
|
3559
|
+
this.#giveUp(error);
|
|
3298
3560
|
return;
|
|
3299
3561
|
}
|
|
3300
3562
|
const delay = reconnectDelay(this.#attempt, this.#options);
|
|
@@ -3306,6 +3568,15 @@ var ItdRealtime = class {
|
|
|
3306
3568
|
this.#run();
|
|
3307
3569
|
}, delay);
|
|
3308
3570
|
}
|
|
3571
|
+
/** Завершает автоматические попытки переподключения. */
|
|
3572
|
+
#giveUp(error) {
|
|
3573
|
+
this.#wanted = false;
|
|
3574
|
+
this.#attempt = 0;
|
|
3575
|
+
this.#detachEnvironment?.();
|
|
3576
|
+
this.#detachEnvironment = void 0;
|
|
3577
|
+
this.#emitter.emit("error", { error, willReconnect: false });
|
|
3578
|
+
this.#emitter.emit("giveup", void 0);
|
|
3579
|
+
}
|
|
3309
3580
|
/**
|
|
3310
3581
|
* Подписывается на события среды.
|
|
3311
3582
|
*
|
|
@@ -3353,6 +3624,9 @@ var PaginationMode = Object.freeze({
|
|
|
3353
3624
|
/** Следующая страница запрашивается смещением от начала списка. */
|
|
3354
3625
|
Offset: "offset"
|
|
3355
3626
|
});
|
|
3627
|
+
function mapPage(page, map) {
|
|
3628
|
+
return { ...page, items: page.items.map(map) };
|
|
3629
|
+
}
|
|
3356
3630
|
function readItems(body, fields) {
|
|
3357
3631
|
if (Array.isArray(body)) return body;
|
|
3358
3632
|
for (const field of fields) {
|
|
@@ -3629,7 +3903,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3629
3903
|
async signUp(credentials, options = {}) {
|
|
3630
3904
|
const body = await this.http.request({
|
|
3631
3905
|
method: "POST",
|
|
3632
|
-
path:
|
|
3906
|
+
path: AUTH_PATHS.signUp,
|
|
3633
3907
|
body: credentials,
|
|
3634
3908
|
skipAuth: true,
|
|
3635
3909
|
skipAuthRefresh: true,
|
|
@@ -3654,7 +3928,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3654
3928
|
async signIn(credentials, options = {}) {
|
|
3655
3929
|
const body = await this.http.request({
|
|
3656
3930
|
method: "POST",
|
|
3657
|
-
path:
|
|
3931
|
+
path: AUTH_PATHS.signIn,
|
|
3658
3932
|
body: credentials,
|
|
3659
3933
|
skipAuth: true,
|
|
3660
3934
|
skipAuthRefresh: true,
|
|
@@ -3675,7 +3949,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3675
3949
|
async verifyOtp(input, options = {}) {
|
|
3676
3950
|
const body = await this.http.request({
|
|
3677
3951
|
method: "POST",
|
|
3678
|
-
path:
|
|
3952
|
+
path: AUTH_PATHS.verifyOtp,
|
|
3679
3953
|
body: input,
|
|
3680
3954
|
skipAuth: true,
|
|
3681
3955
|
skipAuthRefresh: true,
|
|
@@ -3692,7 +3966,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3692
3966
|
resendOtp(input, options = {}) {
|
|
3693
3967
|
return this.http.request({
|
|
3694
3968
|
method: "POST",
|
|
3695
|
-
path:
|
|
3969
|
+
path: AUTH_PATHS.resendOtp,
|
|
3696
3970
|
body: input,
|
|
3697
3971
|
skipAuth: true,
|
|
3698
3972
|
skipAuthRefresh: true,
|
|
@@ -3769,7 +4043,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3769
4043
|
async logout(options = {}) {
|
|
3770
4044
|
await this.http.request({
|
|
3771
4045
|
method: "POST",
|
|
3772
|
-
path:
|
|
4046
|
+
path: AUTH_PATHS.logout,
|
|
3773
4047
|
skipAuthRefresh: true,
|
|
3774
4048
|
...this.requestOptions(options)
|
|
3775
4049
|
});
|
|
@@ -3799,7 +4073,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3799
4073
|
async forgotPassword(input, options = {}) {
|
|
3800
4074
|
const body = await this.http.request({
|
|
3801
4075
|
method: "POST",
|
|
3802
|
-
path:
|
|
4076
|
+
path: AUTH_PATHS.forgotPassword,
|
|
3803
4077
|
body: input,
|
|
3804
4078
|
skipAuth: true,
|
|
3805
4079
|
skipAuthRefresh: true,
|
|
@@ -3820,7 +4094,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3820
4094
|
resetPassword(input, options = {}) {
|
|
3821
4095
|
return this.http.request({
|
|
3822
4096
|
method: "POST",
|
|
3823
|
-
path:
|
|
4097
|
+
path: AUTH_PATHS.resetPassword,
|
|
3824
4098
|
body: input,
|
|
3825
4099
|
skipAuth: true,
|
|
3826
4100
|
skipAuthRefresh: true,
|
|
@@ -3858,14 +4132,17 @@ var AuthResource = class extends BaseResource {
|
|
|
3858
4132
|
* Меняет пароль. Требует действующей сессии.
|
|
3859
4133
|
*
|
|
3860
4134
|
* При неверном текущем пароле сервер отвечает `ACCOUNT_CURRENT_PASSWORD_INCORRECT`.
|
|
4135
|
+
*
|
|
4136
|
+
* @example
|
|
4137
|
+
* ```ts
|
|
4138
|
+
* await itd.auth.changePassword({ currentPassword, newPassword });
|
|
4139
|
+
* ```
|
|
3861
4140
|
*/
|
|
3862
4141
|
changePassword(input, options = {}) {
|
|
3863
4142
|
return this.http.request({
|
|
3864
4143
|
method: "POST",
|
|
3865
|
-
path:
|
|
3866
|
-
|
|
3867
|
-
// не проверить, а лишнее поле он игнорирует.
|
|
3868
|
-
body: { ...input, currentPassword: input.oldPassword },
|
|
4144
|
+
path: AUTH_PATHS.changePassword,
|
|
4145
|
+
body: { currentPassword: input.currentPassword, newPassword: input.newPassword },
|
|
3869
4146
|
...this.requestOptions(options)
|
|
3870
4147
|
});
|
|
3871
4148
|
}
|
|
@@ -3881,13 +4158,13 @@ var AuthResource = class extends BaseResource {
|
|
|
3881
4158
|
* ```
|
|
3882
4159
|
*/
|
|
3883
4160
|
oauthUrl(provider) {
|
|
3884
|
-
return joinUrl(this.http.baseUrl,
|
|
4161
|
+
return joinUrl(this.http.baseUrl, `${AUTH_PATHS.oauthLogin}/${provider}`);
|
|
3885
4162
|
}
|
|
3886
4163
|
/** Загружает список активных сессий. У текущей поле `isCurrent` равно `true`. */
|
|
3887
4164
|
async sessions(options = {}) {
|
|
3888
4165
|
const body = await this.http.request({
|
|
3889
4166
|
method: "GET",
|
|
3890
|
-
path:
|
|
4167
|
+
path: AUTH_PATHS.sessions,
|
|
3891
4168
|
...this.requestOptions(options)
|
|
3892
4169
|
});
|
|
3893
4170
|
return pickArray(body, "sessions");
|
|
@@ -3896,7 +4173,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3896
4173
|
revokeSession(sessionId, options = {}) {
|
|
3897
4174
|
return this.http.request({
|
|
3898
4175
|
method: "DELETE",
|
|
3899
|
-
path:
|
|
4176
|
+
path: `${AUTH_PATHS.sessions}/${encodeURIComponent(sessionId)}`,
|
|
3900
4177
|
...this.requestOptions(options)
|
|
3901
4178
|
});
|
|
3902
4179
|
}
|
|
@@ -3904,7 +4181,7 @@ var AuthResource = class extends BaseResource {
|
|
|
3904
4181
|
revokeOtherSessions(options = {}) {
|
|
3905
4182
|
return this.http.request({
|
|
3906
4183
|
method: "DELETE",
|
|
3907
|
-
path:
|
|
4184
|
+
path: AUTH_PATHS.sessions,
|
|
3908
4185
|
...this.requestOptions(options)
|
|
3909
4186
|
});
|
|
3910
4187
|
}
|
|
@@ -4376,7 +4653,25 @@ var NotificationsResource = class extends BaseResource {
|
|
|
4376
4653
|
}
|
|
4377
4654
|
};
|
|
4378
4655
|
|
|
4656
|
+
// src/core/time.ts
|
|
4657
|
+
var NAIVE_STAMP = /^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
|
|
4658
|
+
function utcStampToIso(value) {
|
|
4659
|
+
const match = typeof value === "string" ? NAIVE_STAMP.exec(value) : null;
|
|
4660
|
+
if (!match) return value;
|
|
4661
|
+
const iso = `${match[1]}T${match[2]}Z`;
|
|
4662
|
+
return Number.isFinite(Date.parse(iso)) ? iso : value;
|
|
4663
|
+
}
|
|
4664
|
+
|
|
4379
4665
|
// src/resources/platform.ts
|
|
4666
|
+
function normalizeStatus(body) {
|
|
4667
|
+
if (!isRecord(body) || !Array.isArray(body.services)) return body;
|
|
4668
|
+
return {
|
|
4669
|
+
...body,
|
|
4670
|
+
services: body.services.map(
|
|
4671
|
+
(service) => typeof service?.last_checked === "string" ? { ...service, last_checked: utcStampToIso(service.last_checked) } : service
|
|
4672
|
+
)
|
|
4673
|
+
};
|
|
4674
|
+
}
|
|
4380
4675
|
var PlatformResource = class extends BaseResource {
|
|
4381
4676
|
/** Загружает журнал изменений. */
|
|
4382
4677
|
async changelog(options = {}) {
|
|
@@ -4404,6 +4699,31 @@ var PlatformResource = class extends BaseResource {
|
|
|
4404
4699
|
...this.requestOptions(options)
|
|
4405
4700
|
});
|
|
4406
4701
|
}
|
|
4702
|
+
/**
|
|
4703
|
+
* Загружает состояние сервисов платформы за последние 90 суток.
|
|
4704
|
+
*
|
|
4705
|
+
* Идёт на хост `статус.итд.com` без авторизации. Ответ кэшируется сервером на минуту.
|
|
4706
|
+
* История по суткам приходит разреженной, ровный массив даёт `statusDays`.
|
|
4707
|
+
*
|
|
4708
|
+
* @example
|
|
4709
|
+
* ```ts
|
|
4710
|
+
* const status = await itd.platform.status();
|
|
4711
|
+
*
|
|
4712
|
+
* if (status.overall_status !== 'operational') {
|
|
4713
|
+
* const broken = status.services.filter((s) => s.current_status !== 'operational');
|
|
4714
|
+
* console.log('лежит:', broken.map((s) => s.name).join(', '));
|
|
4715
|
+
* }
|
|
4716
|
+
* ```
|
|
4717
|
+
*/
|
|
4718
|
+
async status(options = {}) {
|
|
4719
|
+
const body = await this.http.request({
|
|
4720
|
+
method: "GET",
|
|
4721
|
+
service: STATUS_SERVICE,
|
|
4722
|
+
path: "/api/status",
|
|
4723
|
+
...this.requestOptions(options)
|
|
4724
|
+
});
|
|
4725
|
+
return normalizeStatus(body);
|
|
4726
|
+
}
|
|
4407
4727
|
};
|
|
4408
4728
|
|
|
4409
4729
|
// src/resources/posts.ts
|
|
@@ -5168,13 +5488,15 @@ var VerificationResource = class extends BaseResource {
|
|
|
5168
5488
|
};
|
|
5169
5489
|
|
|
5170
5490
|
// src/client.ts
|
|
5171
|
-
var ItdClient = class {
|
|
5491
|
+
var ItdClient = class _ItdClient {
|
|
5172
5492
|
#config;
|
|
5173
5493
|
#http;
|
|
5494
|
+
#transport;
|
|
5174
5495
|
#authManager;
|
|
5175
5496
|
#jar;
|
|
5176
|
-
#
|
|
5497
|
+
#queues;
|
|
5177
5498
|
#plugins = new PluginRegistry();
|
|
5499
|
+
#services;
|
|
5178
5500
|
/** Порождённые потоки уведомлений — чтобы `close()` мог закрыть их разом. */
|
|
5179
5501
|
#streams = /* @__PURE__ */ new Set();
|
|
5180
5502
|
/** Авторизация, сессии и пароли. */
|
|
@@ -5211,19 +5533,23 @@ var ItdClient = class {
|
|
|
5211
5533
|
const config = resolveConfig(options);
|
|
5212
5534
|
this.#config = config;
|
|
5213
5535
|
this.#jar = new CookieJar();
|
|
5214
|
-
|
|
5215
|
-
this.#
|
|
5536
|
+
this.#services = new ServiceRegistry(config.baseUrl);
|
|
5537
|
+
for (const service of BUILT_IN_SERVICES) this.#services.define(service);
|
|
5538
|
+
for (const service of config.services) this.#services.define(service);
|
|
5539
|
+
const queues = config.rateLimit ? new RequestQueuePool(config.rateLimit) : void 0;
|
|
5540
|
+
this.#queues = queues;
|
|
5216
5541
|
let authManager;
|
|
5217
5542
|
const transport = new Transport(config, {
|
|
5218
5543
|
cookies: config.useCookieJar ? this.#jar : void 0,
|
|
5219
5544
|
getDeviceId: () => authManager.getDeviceId(),
|
|
5220
|
-
onRateLimit:
|
|
5545
|
+
onRateLimit: queues && config.rateLimit?.respectHeaders ? (limit, remaining, request) => this.#throttleByHeaders(limit, remaining, request) : void 0
|
|
5221
5546
|
});
|
|
5547
|
+
this.#transport = transport;
|
|
5222
5548
|
const pluginsLayer = createPluginsMiddleware(this.#plugins);
|
|
5223
5549
|
const retriesLayer = createRetryMiddleware({
|
|
5224
5550
|
retry: config.retry,
|
|
5225
5551
|
rateLimitDelays: config.rateLimit?.retryDelays ?? [],
|
|
5226
|
-
pauseQueue:
|
|
5552
|
+
pauseQueue: queues ? (ms, request) => queues.for(request.service).pause(ms) : void 0,
|
|
5227
5553
|
hooks: config.hooks,
|
|
5228
5554
|
logger: config.logger,
|
|
5229
5555
|
buildUrl: (request) => transport.buildUrl(request)
|
|
@@ -5241,8 +5567,13 @@ var ItdClient = class {
|
|
|
5241
5567
|
authManager = new AuthManager(config, authHandler, this.#jar);
|
|
5242
5568
|
this.#authManager = authManager;
|
|
5243
5569
|
const middlewares = [];
|
|
5244
|
-
if (
|
|
5570
|
+
if (queues) {
|
|
5571
|
+
middlewares.push(
|
|
5572
|
+
createQueueMiddleware((request, task) => queues.for(request.service).schedule(task))
|
|
5573
|
+
);
|
|
5574
|
+
}
|
|
5245
5575
|
middlewares.push(pluginsLayer);
|
|
5576
|
+
middlewares.push(createServicesMiddleware(this.#services));
|
|
5246
5577
|
middlewares.push(retriesLayer);
|
|
5247
5578
|
middlewares.push(
|
|
5248
5579
|
createAuthMiddleware({
|
|
@@ -5300,7 +5631,7 @@ var ItdClient = class {
|
|
|
5300
5631
|
*
|
|
5301
5632
|
* @example
|
|
5302
5633
|
* ```ts
|
|
5303
|
-
* import { crypt } from 'itd-api
|
|
5634
|
+
* import { crypt } from '@itd-api/crypto';
|
|
5304
5635
|
*
|
|
5305
5636
|
* itd.use(crypt());
|
|
5306
5637
|
* await itd.posts.create({ content: 'секрет' }, { encrypt: 'invis' });
|
|
@@ -5310,6 +5641,41 @@ var ItdClient = class {
|
|
|
5310
5641
|
this.#plugins.add(plugin, { baseUrl: this.#config.baseUrl, logger: this.#config.logger });
|
|
5311
5642
|
return this;
|
|
5312
5643
|
}
|
|
5644
|
+
/**
|
|
5645
|
+
* Регистрирует сервис платформы — домен, отличный от основного.
|
|
5646
|
+
*
|
|
5647
|
+
* Запросы с `{ service: 'имя' }` уходят на его хост с его заголовками. То же самое умеет
|
|
5648
|
+
* опция `services` конструктора. Занятое имя не переопределяется — ни своё, ни встроенное:
|
|
5649
|
+
* разовому запросу хост задаётся полем `baseUrl`.
|
|
5650
|
+
*
|
|
5651
|
+
* Заголовок авторизации по умолчанию уходит только своим — домену клиента и его
|
|
5652
|
+
* поддоменам. Стороннему хосту токен нужно разрешить явно: `auth: true`.
|
|
5653
|
+
*
|
|
5654
|
+
* @throws {ItdConfigError} если определение неверно или имя уже занято
|
|
5655
|
+
*
|
|
5656
|
+
* @example Сервис платформы на поддомене — токен уходит сам
|
|
5657
|
+
* ```ts
|
|
5658
|
+
* itd.defineService({
|
|
5659
|
+
* name: 'pb',
|
|
5660
|
+
* baseUrl: 'https://pbapi.xn--d1ah4a.com',
|
|
5661
|
+
* headers: { Referer: 'https://pixel.xn--d1ah4a.com/' },
|
|
5662
|
+
* });
|
|
5663
|
+
*
|
|
5664
|
+
* await itd.request({ method: 'GET', service: 'pb', path: '/api/pixel-info' });
|
|
5665
|
+
* ```
|
|
5666
|
+
*/
|
|
5667
|
+
defineService(definition) {
|
|
5668
|
+
this.#services.define(definition);
|
|
5669
|
+
return this;
|
|
5670
|
+
}
|
|
5671
|
+
/**
|
|
5672
|
+
* Базовый URL зарегистрированного сервиса.
|
|
5673
|
+
*
|
|
5674
|
+
* @throws {ItdConfigError} если сервис не зарегистрирован
|
|
5675
|
+
*/
|
|
5676
|
+
serviceBaseUrl(name) {
|
|
5677
|
+
return this.#services.resolveBaseUrl(name);
|
|
5678
|
+
}
|
|
5313
5679
|
/**
|
|
5314
5680
|
* Подписывается на события авторизации.
|
|
5315
5681
|
*
|
|
@@ -5351,6 +5717,7 @@ var ItdClient = class {
|
|
|
5351
5717
|
{
|
|
5352
5718
|
baseUrl: this.#config.baseUrl,
|
|
5353
5719
|
fetch: this.#config.fetch,
|
|
5720
|
+
baseHeaders: (url) => this.#transport.platformHeaders(url),
|
|
5354
5721
|
getToken: () => this.#authManager.getAccessToken(),
|
|
5355
5722
|
refresh: () => this.#authManager.onUnauthorized(),
|
|
5356
5723
|
fetchUnreadCount: () => this.notifications.count(),
|
|
@@ -5379,12 +5746,19 @@ var ItdClient = class {
|
|
|
5379
5746
|
async close() {
|
|
5380
5747
|
for (const stream of this.#streams) stream.disconnect();
|
|
5381
5748
|
this.#streams.clear();
|
|
5382
|
-
this.#
|
|
5749
|
+
this.#queues?.stop();
|
|
5383
5750
|
}
|
|
5384
5751
|
/** Позволяет использовать клиент с `await using`. */
|
|
5385
5752
|
[Symbol.asyncDispose]() {
|
|
5386
5753
|
return this.close();
|
|
5387
5754
|
}
|
|
5755
|
+
static {
|
|
5756
|
+
if (typeof Symbol.asyncDispose !== "symbol") {
|
|
5757
|
+
const prototype = _ItdClient.prototype;
|
|
5758
|
+
prototype[/* @__PURE__ */ Symbol.for("Symbol.asyncDispose")] = prototype.undefined;
|
|
5759
|
+
delete prototype.undefined;
|
|
5760
|
+
}
|
|
5761
|
+
}
|
|
5388
5762
|
/** Текущая сессия целиком — чтобы сохранить её самостоятельно. */
|
|
5389
5763
|
getSession() {
|
|
5390
5764
|
return this.#authManager.getSession();
|
|
@@ -5404,21 +5778,16 @@ var ItdClient = class {
|
|
|
5404
5778
|
* Смысл этой паузы прежде всего в том, чтобы при работе в несколько потоков остальные
|
|
5405
5779
|
* запросы не улетели в стену все разом.
|
|
5406
5780
|
*/
|
|
5407
|
-
#throttleByHeaders(limit, remaining) {
|
|
5781
|
+
#throttleByHeaders(limit, remaining, request) {
|
|
5408
5782
|
if (remaining === void 0 || remaining > 0) return;
|
|
5409
5783
|
const first = this.#config.rateLimit?.retryDelays[0];
|
|
5410
5784
|
if (first === void 0) return;
|
|
5411
|
-
this.#
|
|
5785
|
+
this.#queues?.for(request.service).pause(first);
|
|
5412
5786
|
this.#config.logger?.debug(
|
|
5413
5787
|
`\u043B\u0438\u043C\u0438\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0441\u0447\u0435\u0440\u043F\u0430\u043D (${remaining} \u0438\u0437 ${limit ?? "?"}), \u043E\u0447\u0435\u0440\u0435\u0434\u044C \u0436\u0434\u0451\u0442 ${first} \u043C\u0441`
|
|
5414
5788
|
);
|
|
5415
5789
|
}
|
|
5416
5790
|
};
|
|
5417
|
-
if (typeof Symbol.asyncDispose !== "symbol") {
|
|
5418
|
-
const prototype = ItdClient.prototype;
|
|
5419
|
-
prototype[/* @__PURE__ */ Symbol.for("Symbol.asyncDispose")] = prototype.undefined;
|
|
5420
|
-
delete prototype.undefined;
|
|
5421
|
-
}
|
|
5422
5791
|
function createClient(options = {}) {
|
|
5423
5792
|
return new ItdClient(options);
|
|
5424
5793
|
}
|
|
@@ -5524,12 +5893,19 @@ function resolveNotificationUrl(notification) {
|
|
|
5524
5893
|
function isMyProfile(profile) {
|
|
5525
5894
|
return "subscription" in profile;
|
|
5526
5895
|
}
|
|
5896
|
+
var STATUS_WINDOW_DAYS = 90;
|
|
5527
5897
|
function toDate(value) {
|
|
5528
5898
|
if (!value) return null;
|
|
5529
5899
|
const date = new Date(value);
|
|
5530
5900
|
return Number.isFinite(date.getTime()) ? date : null;
|
|
5531
5901
|
}
|
|
5902
|
+
function statusDays(service) {
|
|
5903
|
+
return Array.from(
|
|
5904
|
+
{ length: STATUS_WINDOW_DAYS },
|
|
5905
|
+
(_, index) => service.days[String(index)] ?? null
|
|
5906
|
+
);
|
|
5907
|
+
}
|
|
5532
5908
|
|
|
5533
|
-
export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AUTH_FLAG_COOKIE, AUTH_PATHS, AccessType, AttachmentType, CommentSort, DEFAULT_BASE_URL, DEFAULT_TIMEOUT, DEFAULT_USER_AGENT, DEVICE_ID_HEADER, DetectedRuntime, FeedTab, IMAGE_MIME_TYPES, InteractionType, ItdAbortError, ItdApiError, ItdApiErrorKind, ItdAuthError, ItdClient, ItdConfigError, ItdConflictError, ItdError, ItdErrorCode, ItdErrorKind, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdPhoneVerificationError, ItdRateLimitError, ItdRealtime, ItdServerError, ItdTimeoutError, ItdValidationError, LIBRARY_VERSION, LikesVisibility, LocalStorageTokenStorage, MAX_RECONNECT_ATTEMPTS, MemoryTokenStorage, NOTIFICATION_TYPE_ALIASES, NotificationType, OAuthProvider, PaginationMode, Paginator, RECONNECT_BACKOFF, RECONNECT_JITTER, REFRESH_COOKIE, REFRESH_COOKIE_PATH, RealtimeStatus, RealtimeTransportKind, ReportReason, ReportTargetType, RuntimeMode, STREAM_PATH, SignInStatus, SpanType, TURNSTILE_SITE_KEY, UnauthorizedStreamError, VIDEO_MIME_TYPES, ViewReason, ViewSource, WallAccess, canonicalNotificationType, comment, createClient, createTokenStorage, formatNotificationText, isBuilder, isItdApiError, isItdAuthError, isItdConflictError, isItdError, isItdForbiddenError, isItdNotFoundError, isItdPhoneVerificationError, isItdRateLimitError, isItdServerError, isItdValidationError, isKnownNotificationType, isMyProfile, normalizeNotification, poll, post, readNotificationEvent, readUnreadCountEvent, report, resolveNotificationUrl, toDate };
|
|
5534
|
-
//# sourceMappingURL=chunk-
|
|
5535
|
-
//# sourceMappingURL=chunk-
|
|
5909
|
+
export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AUTH_FLAG_COOKIE, AUTH_PATHS, AccessType, AttachmentType, BUILT_IN_SERVICES, CommentSort, DEFAULT_BASE_URL, DEFAULT_STATUS_BASE_URL, DEFAULT_TIMEOUT, DEFAULT_UPLOAD_TIMEOUT, DEFAULT_USER_AGENT, DEVICE_ID_HEADER, DetectedRuntime, FeedTab, IMAGE_MIME_TYPES, IncidentKind, InteractionType, ItdAbortError, ItdApiError, ItdApiErrorKind, ItdAuthError, ItdClient, ItdConfigError, ItdConflictError, ItdError, ItdErrorCode, ItdErrorKind, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdPhoneVerificationError, ItdRateLimitError, ItdRealtime, ItdServerError, ItdTimeoutError, ItdValidationError, LIBRARY_VERSION, LikesVisibility, LocalStorageTokenStorage, MAX_RECONNECT_ATTEMPTS, MemoryTokenStorage, NOTIFICATION_TYPE_ALIASES, NotificationType, OAuthProvider, PaginationMode, Paginator, RECONNECT_BACKOFF, RECONNECT_JITTER, REFRESH_COOKIE, REFRESH_COOKIE_PATH, REQUEST_OPTION_KEYS, RealtimeStatus, RealtimeTransportKind, ReportReason, ReportTargetType, RuntimeMode, STATUS_SERVICE, STREAM_PATH, ServiceRegistry, ServiceState, SignInStatus, SpanType, TURNSTILE_SITE_KEY, UnauthorizedStreamError, VIDEO_MIME_TYPES, ViewReason, ViewSource, WallAccess, canonicalNotificationType, comment, createClient, createTokenStorage, formatNotificationText, isBuilder, isItdApiError, isItdAuthError, isItdConflictError, isItdError, isItdForbiddenError, isItdNotFoundError, isItdPhoneVerificationError, isItdRateLimitError, isItdServerError, isItdValidationError, isKnownNotificationType, isMyProfile, mapPage, normalizeNotification, poll, post, readNotificationEvent, readUnreadCountEvent, report, resolveNotificationUrl, statusDays, toDate, utcStampToIso };
|
|
5910
|
+
//# sourceMappingURL=chunk-MYAU2WJU.js.map
|
|
5911
|
+
//# sourceMappingURL=chunk-MYAU2WJU.js.map
|