itd-api 0.9.0 → 0.9.2
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 +4 -4
- package/dist/events/index.cjs +3 -4
- package/dist/events/index.d.cts +3 -3
- package/dist/events/index.d.ts +3 -3
- package/dist/events/index.js +4 -4
- package/dist/index.cjs +198 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -65
- package/dist/index.d.ts +11 -65
- package/dist/index.js +199 -39
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +3 -3
- package/dist/node/index.js +3 -3
- package/dist/rest/index.cjs +4 -5
- package/dist/rest/index.d.cts +3 -3
- package/dist/rest/index.d.ts +3 -3
- package/dist/rest/index.js +5 -5
- package/dist/shared/{events-CqtkP65d.d.ts → events-BCn5LRnT.d.cts} +3 -5
- package/dist/shared/{events-C5wnTXPT.js → events-BIBO2Jif.js} +4 -4
- package/dist/shared/{events-C5wnTXPT.js.map → events-BIBO2Jif.js.map} +1 -1
- package/dist/shared/{events-FZfnEez0.cjs → events-BsRm_Fba.cjs} +3 -9
- package/dist/shared/{events-FZfnEez0.cjs.map → events-BsRm_Fba.cjs.map} +1 -1
- package/dist/shared/{events-DGAWlCaI.d.cts → events-t1uGgpkf.d.ts} +3 -5
- package/dist/shared/{multi-storage-SoW05uzO.js → multi-storage-C3Ngtop1.js} +13 -8
- package/dist/shared/multi-storage-C3Ngtop1.js.map +1 -0
- package/dist/shared/{multi-storage-CDKLa956.cjs → multi-storage-s-fPtjoy.cjs} +13 -8
- package/dist/shared/multi-storage-s-fPtjoy.cjs.map +1 -0
- package/dist/shared/{options-DOJYtoti.cjs → options-DjEtbVaf.cjs} +2 -2
- package/dist/shared/{options-DOJYtoti.cjs.map → options-DjEtbVaf.cjs.map} +1 -1
- package/dist/shared/{options-DhgGg7Ms.js → options-i4LrKfqx.js} +2 -2
- package/dist/shared/{options-DhgGg7Ms.js.map → options-i4LrKfqx.js.map} +1 -1
- package/dist/shared/{redact-Ba5iSVYZ.js → redact-DJV0XM3n.js} +40 -15
- package/dist/shared/redact-DJV0XM3n.js.map +1 -0
- package/dist/shared/{redact-BP00URmQ.cjs → redact-lAmck1Z6.cjs} +45 -14
- package/dist/shared/redact-lAmck1Z6.cjs.map +1 -0
- package/dist/shared/{render-hiWFh2s4.js → render--ZXmYEf-.js} +131 -100
- package/dist/shared/render--ZXmYEf-.js.map +1 -0
- package/dist/shared/{render-B4qis7Sb.d.ts → render-BdnBV-aT.d.ts} +112 -16
- package/dist/shared/{render-DDwy2Ame.d.cts → render-DA83gS0f.d.cts} +112 -16
- package/dist/shared/{render-Dqi8Owqk.cjs → render-DqVzx68r.cjs} +129 -104
- package/dist/shared/render-DqVzx68r.cjs.map +1 -0
- package/dist/shared/{storage-QNVxzpDB.cjs → storage-CZJZoaz9.cjs} +4 -2
- package/dist/shared/storage-CZJZoaz9.cjs.map +1 -0
- package/dist/shared/{storage-CfHKzVHf.js → storage-DiDe0PZM.js} +4 -2
- package/dist/shared/storage-DiDe0PZM.js.map +1 -0
- package/dist/shared/{url-XBsMdAcv.d.ts → url-Dbj6V6fk.d.cts} +21 -5
- package/dist/shared/{url-XBsMdAcv.d.cts → url-Dbj6V6fk.d.ts} +21 -5
- package/dist/shared/{url-Bsb3xE5U.cjs → url-Doc0XXW_.cjs} +274 -86
- package/dist/shared/url-Doc0XXW_.cjs.map +1 -0
- package/dist/shared/{url-DP33mp3s.js → url-i2f-X1hX.js} +274 -86
- package/dist/shared/url-i2f-X1hX.js.map +1 -0
- package/dist/web/index.cjs +1 -1
- package/dist/web/index.js +1 -1
- package/package.json +4 -4
- package/dist/shared/multi-storage-CDKLa956.cjs.map +0 -1
- package/dist/shared/multi-storage-SoW05uzO.js.map +0 -1
- package/dist/shared/redact-BP00URmQ.cjs.map +0 -1
- package/dist/shared/redact-Ba5iSVYZ.js.map +0 -1
- package/dist/shared/render-Dqi8Owqk.cjs.map +0 -1
- package/dist/shared/render-hiWFh2s4.js.map +0 -1
- package/dist/shared/storage-CfHKzVHf.js.map +0 -1
- package/dist/shared/storage-QNVxzpDB.cjs.map +0 -1
- package/dist/shared/url-Bsb3xE5U.cjs.map +0 -1
- package/dist/shared/url-DP33mp3s.js.map +0 -1
|
@@ -274,16 +274,20 @@ function parseNameValuePair(nameValuePairStr) {
|
|
|
274
274
|
}
|
|
275
275
|
function parseSetCookie(input, options) {
|
|
276
276
|
options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;
|
|
277
|
-
if (!input)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
277
|
+
if (!input) {
|
|
278
|
+
if (!options.map) return [];
|
|
279
|
+
else return createNullObj();
|
|
280
|
+
}
|
|
281
|
+
if (input.headers) {
|
|
282
|
+
if (typeof input.headers.getSetCookie === "function") input = input.headers.getSetCookie();
|
|
283
|
+
else if (input.headers["set-cookie"]) input = input.headers["set-cookie"];
|
|
284
|
+
else {
|
|
285
|
+
var sch = input.headers[Object.keys(input.headers).find(function(key) {
|
|
286
|
+
return key.toLowerCase() === "set-cookie";
|
|
287
|
+
})];
|
|
288
|
+
if (!sch && input.headers.cookie && !options.silent) console.warn("Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning.");
|
|
289
|
+
input = sch;
|
|
290
|
+
}
|
|
287
291
|
}
|
|
288
292
|
var split = options.split;
|
|
289
293
|
var isArray = Array.isArray(input);
|
|
@@ -364,6 +368,16 @@ const REFRESH_COOKIE = "refresh_token";
|
|
|
364
368
|
const REFRESH_COOKIE_PATH = "/api/v1/auth";
|
|
365
369
|
/** Разделитель origin и содержимого cookie при сериализации. В origin пробелов не бывает. */
|
|
366
370
|
const SERIALIZED_SEPARATOR = " ";
|
|
371
|
+
const COOKIE_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
372
|
+
/** Проверяет одну запись, созданную {@link CookieJar.serialize}. @internal */
|
|
373
|
+
function isSerializedCookieEntry(entry) {
|
|
374
|
+
const separatorAt = entry.indexOf(SERIALIZED_SEPARATOR);
|
|
375
|
+
if (separatorAt <= 0) return false;
|
|
376
|
+
const origin = entry.slice(0, separatorAt);
|
|
377
|
+
if (originOf(origin) !== origin) return false;
|
|
378
|
+
const parsed = parseSetCookie([entry.slice(separatorAt + 1)]);
|
|
379
|
+
return parsed.length === 1 && COOKIE_NAME.test(parsed[0]?.name ?? "");
|
|
380
|
+
}
|
|
367
381
|
/** Дата в миллисекунды. Некорректная дата считается отсутствующей, а не `NaN`. */
|
|
368
382
|
function toTimestamp(date) {
|
|
369
383
|
if (!date) return void 0;
|
|
@@ -398,8 +412,20 @@ function pathMatches(cookiePath, requestPath) {
|
|
|
398
412
|
* Реализована практическая часть RFC 6265: origin, путь, срок жизни, флаг `Secure`.
|
|
399
413
|
* Доменные cookie для поддоменов намеренно не поддерживаются — API работает с одного хоста.
|
|
400
414
|
*/
|
|
401
|
-
var CookieJar = class {
|
|
415
|
+
var CookieJar = class CookieJar {
|
|
402
416
|
#byOrigin = /* @__PURE__ */ new Map();
|
|
417
|
+
/** Независимая копия для auth-flow, который ещё не получил право на commit. */
|
|
418
|
+
clone() {
|
|
419
|
+
const copy = new CookieJar();
|
|
420
|
+
copy.deserialize(this.serialize());
|
|
421
|
+
return copy;
|
|
422
|
+
}
|
|
423
|
+
/** Атомарно с точки зрения синхронных читателей заменяет содержимое снимком другого jar. */
|
|
424
|
+
replaceWith(source) {
|
|
425
|
+
const entries = source.serialize();
|
|
426
|
+
this.clear();
|
|
427
|
+
this.deserialize(entries);
|
|
428
|
+
}
|
|
403
429
|
/**
|
|
404
430
|
* Забирает `Set-Cookie` из ответа.
|
|
405
431
|
*
|
|
@@ -501,11 +527,10 @@ var CookieJar = class {
|
|
|
501
527
|
deserialize(entries) {
|
|
502
528
|
if (!entries) return;
|
|
503
529
|
for (const entry of entries) {
|
|
530
|
+
if (!isSerializedCookieEntry(entry)) continue;
|
|
504
531
|
const separatorAt = entry.indexOf(SERIALIZED_SEPARATOR);
|
|
505
|
-
if (separatorAt <= 0) continue;
|
|
506
532
|
const origin = entry.slice(0, separatorAt);
|
|
507
533
|
const setCookie = entry.slice(separatorAt + 1);
|
|
508
|
-
if (!originOf(origin)) continue;
|
|
509
534
|
this.setFromStrings(origin, [setCookie]);
|
|
510
535
|
}
|
|
511
536
|
}
|
|
@@ -725,6 +750,12 @@ Object.defineProperty(exports, "isSameSite", {
|
|
|
725
750
|
return isSameSite;
|
|
726
751
|
}
|
|
727
752
|
});
|
|
753
|
+
Object.defineProperty(exports, "isSerializedCookieEntry", {
|
|
754
|
+
enumerable: true,
|
|
755
|
+
get: function() {
|
|
756
|
+
return isSerializedCookieEntry;
|
|
757
|
+
}
|
|
758
|
+
});
|
|
728
759
|
Object.defineProperty(exports, "joinUrl", {
|
|
729
760
|
enumerable: true,
|
|
730
761
|
get: function() {
|
|
@@ -798,4 +829,4 @@ Object.defineProperty(exports, "supportsStreamingBody", {
|
|
|
798
829
|
}
|
|
799
830
|
});
|
|
800
831
|
|
|
801
|
-
//# sourceMappingURL=redact-
|
|
832
|
+
//# sourceMappingURL=redact-lAmck1Z6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact-lAmck1Z6.cjs","names":["ItdConfigError","ItdConfigError","#byOrigin","#matching"],"sources":["../../src/core/runtime.ts","../../src/core/url.ts","../../node_modules/set-cookie-parser/lib/set-cookie.js","../../src/core/cookies.ts","../../src/core/redact.ts"],"sourcesContent":["import { ItdConfigError } from './errors.js';\n\n/**\n * Как библиотека обращается с cookie.\n *\n * - `browser` — cookie ведёт браузер, запросы уходят с `credentials: 'include'`;\n * - `server` — cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную;\n * - `auto` — определяется по среде исполнения (значение по умолчанию).\n */\nexport const RuntimeMode = Object.freeze({\n /** Определяется по среде исполнения. Значение по умолчанию. */\n Auto: 'auto',\n /** Cookie ведёт браузер, запросы уходят с `credentials: 'include'`. */\n Browser: 'browser',\n /** Cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную. */\n Server: 'server',\n} as const);\nexport type RuntimeMode = (typeof RuntimeMode)[keyof typeof RuntimeMode];\n\n/** Распознанная среда исполнения. */\nexport const DetectedRuntime = Object.freeze({\n Browser: 'browser',\n /** Есть `window`, но нет `document`; cookie ведёт нативный сетевой слой. */\n ReactNative: 'react-native',\n Server: 'server',\n} as const);\nexport type DetectedRuntime = (typeof DetectedRuntime)[keyof typeof DetectedRuntime];\n\n/**\n * Определяет среду исполнения.\n *\n * React Native выделен отдельно намеренно: там есть `window`, но нет `document`, а cookie\n * хранит нативный сетевой слой (`NSHTTPCookieStorage` / `OkHttp`). Свой jar в этой среде\n * привёл бы к отправке cookie дважды.\n */\nexport function detectRuntime(): DetectedRuntime {\n const nav = (globalThis as { navigator?: { product?: string } }).navigator;\n if (nav?.product === 'ReactNative') return DetectedRuntime.ReactNative;\n\n if (typeof document !== 'undefined') return DetectedRuntime.Browser;\n\n return DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли вести собственный cookie-jar.\n *\n * Только в серверных средах: в браузере `Set-Cookie` из JS не читается и не нужен,\n * в React Native cookie ведёт нативный слой.\n */\nexport function shouldUseCookieJar(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return false;\n if (mode === RuntimeMode.Server) return true;\n return detectRuntime() === DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли отправлять запросы с `credentials: 'include'`.\n *\n * Только в браузере: именно так refresh-cookie попадает в запрос `POST /api/v1/auth/refresh`.\n * Требует настроенного CORS на стороне итд.com — если его нет, укажите свой прокси в `baseUrl`.\n */\nexport function shouldSendCredentials(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return true;\n if (mode === RuntimeMode.Server) return false;\n return detectRuntime() === DetectedRuntime.Browser;\n}\n\n/**\n * Возвращает реализацию `fetch`.\n *\n * @param custom реализация из конфигурации клиента, если пользователь её передал\n * @throws {ItdConfigError} если `fetch` недоступен — например, на Node ниже 18\n */\nexport function resolveFetch(custom?: typeof fetch): typeof fetch {\n if (custom !== undefined) {\n if (typeof custom !== 'function') {\n throw new ItdConfigError('fetch должен быть функцией');\n }\n return custom;\n }\n\n if (typeof globalThis.fetch === 'function') {\n // Привязка к globalThis обязательна: в некоторых средах несвязанный fetch бросает\n // «Illegal invocation».\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new ItdConfigError(\n 'В этой среде нет глобального fetch. Обновитесь до Node 18+ либо передайте свою ' +\n 'реализацию через опцию fetch.',\n );\n}\n\n/**\n * Проверки бинарных типов, безопасные в любой среде.\n *\n * Обычный `instanceof` здесь недостаточен: конструктора может не быть вовсе, и тогда\n * проверка падает с `ReferenceError`, а не возвращает `false`. `Blob` есть в Node с 18.0,\n * но `File` стал глобальным только в Node 20 — при заявленной поддержке Node 18 голый\n * `instanceof File` ронял бы любую загрузку.\n */\nexport function isBlob(value: unknown): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob;\n}\n\n/** @see {@link isBlob} */\nexport function isFile(value: unknown): value is File {\n return typeof File !== 'undefined' && value instanceof File;\n}\n\n/** Доступно ли потоковое чтение тела ответа — от этого зависит, сработает ли SSE. */\nexport function supportsStreamingBody(): boolean {\n return typeof ReadableStream !== 'undefined' && typeof TextDecoder !== 'undefined';\n}\n\n/**\n * Создаёт идентификатор устройства для заголовка `X-Device-Id` — UUID v4.\n *\n * `crypto.randomUUID` есть в Node 19+, браузерах и Deno, но отсутствует в Node 18 вне\n * защищённого контекста, поэтому предусмотрен запасной путь.\n */\nexport function createDeviceId(): string {\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n\n if (typeof webCrypto?.randomUUID === 'function') return webCrypto.randomUUID();\n\n // Форма UUID v4 собирается вручную: серверу важна стабильность значения, а не его энтропия.\n const bytes = new Uint8Array(16);\n if (typeof webCrypto?.getRandomValues === 'function') webCrypto.getRandomValues(bytes);\n else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20, 32),\n ].join('-');\n}\n","import { ItdConfigError } from './errors.js';\n\n/** Значение параметра запроса. `undefined` и `null` в строку не попадают. */\nexport type QueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | readonly (string | number | boolean)[];\n\n/** Параметры строки запроса. */\nexport type QueryParams = Record<string, QueryValue>;\n\n/**\n * Собирает строку запроса.\n *\n * Правила:\n * - `undefined` и `null` пропускаются целиком — не нужно чистить объект перед вызовом;\n * - `boolean` превращается в `true` / `false`;\n * - массив повторяет ключ (`ids=1&ids=2`).\n *\n * @returns строка вида `?a=1&b=2` либо пустая строка, если параметров нет\n *\n * @example\n * ```ts\n * buildQuery({ tab: 'popular', limit: 20, cursor: undefined });\n * // '?tab=popular&limit=20'\n * ```\n */\nexport function buildQuery(params?: QueryParams): string {\n if (!params) return '';\n\n const search = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item === undefined || item === null) continue;\n search.append(key, String(item));\n }\n continue;\n }\n\n search.append(key, String(value));\n }\n\n const query = search.toString();\n return query ? `?${query}` : '';\n}\n\n/**\n * Кодирует значение для подстановки в путь.\n *\n * Нужно для сегментов, которые могут содержать что угодно, — прежде всего хэштегов\n * в `/api/hashtags/{tag}/posts`.\n *\n * @throws {ItdConfigError} если значение пустое\n */\nexport function encodePathSegment(value: string, name = 'параметр пути'): string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new ItdConfigError(\n `${name} должен быть непустой строкой, получено: ${JSON.stringify(value)}`,\n );\n }\n return encodeURIComponent(value);\n}\n\n/** Хост из URL в нижнем регистре. Пустая строка, если разобрать не удалось. */\nexport function hostOf(url: string): string {\n try {\n return new URL(url).hostname.toLowerCase();\n } catch {\n return '';\n }\n}\n\n/** Origin из URL — схема, хост и порт. Пустая строка, если разобрать не удалось. */\nexport function originOf(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return '';\n }\n}\n\n/** Тот же хост либо его поддомен. Принимает хосты, а не адреса. */\nexport function isSameSite(primaryHost: string, host: string): boolean {\n if (!primaryHost || !host) return false;\n return host === primaryHost || host.endsWith(`.${primaryHost}`);\n}\n\n/**\n * Склеивает базовый URL и путь.\n *\n * Завершающий слэш пути сохраняется: он значим для `/api/notifications/`\n * и `/api/v1/subscription/`, без него сервер отвечает ошибкой.\n *\n * @example\n * ```ts\n * joinUrl('https://xn--d1ah4a.com/', '/api/notifications/');\n * // 'https://xn--d1ah4a.com/api/notifications/'\n * ```\n */\nexport function joinUrl(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n const suffix = path.startsWith('/') ? path : `/${path}`;\n return `${base}${suffix}`;\n}\n\n/** Приводит базовый URL к каноничному виду и проверяет, что он вообще похож на URL. */\nexport function normalizeBaseUrl(baseUrl: string): string {\n if (typeof baseUrl !== 'string' || baseUrl.trim() === '') {\n throw new ItdConfigError(\n `baseUrl должен быть непустой строкой с абсолютным URL, получено: ${JSON.stringify(baseUrl)}`,\n );\n }\n\n let parsed: URL;\n try {\n parsed = new URL(baseUrl);\n } catch {\n throw new ItdConfigError(\n `baseUrl должен быть абсолютным URL, получено: ${JSON.stringify(baseUrl)}`,\n );\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new ItdConfigError(\n `baseUrl должен использовать http или https, получено: ${parsed.protocol}`,\n );\n }\n\n if (parsed.username || parsed.password || parsed.search || parsed.hash) {\n throw new ItdConfigError(\n 'baseUrl не должен содержать логин, пароль, query-параметры или fragment',\n );\n }\n\n return parsed.origin + (parsed.pathname === '/' ? '' : parsed.pathname.replace(/\\/$/, ''));\n}\n","var defaultParseOptions = {\n decodeValues: true,\n map: false,\n silent: false,\n split: \"auto\", // auto = split strings but not arrays\n};\n\nfunction isForbiddenKey(key) {\n return typeof key !== \"string\" || key in {};\n}\n\nfunction createNullObj() {\n return Object.create(null);\n}\n\nfunction isNonEmptyString(str) {\n return typeof str === \"string\" && !!str.trim();\n}\n\nfunction parseString(setCookieValue, options) {\n var parts = setCookieValue.split(\";\").filter(isNonEmptyString);\n\n var nameValuePairStr = parts.shift();\n if (!nameValuePairStr) {\n return null;\n }\n var parsed = parseNameValuePair(nameValuePairStr);\n var name = parsed.name;\n var value = parsed.value;\n\n options = options\n ? Object.assign({}, defaultParseOptions, options)\n : defaultParseOptions;\n\n if (isForbiddenKey(name)) {\n return null;\n }\n\n try {\n value = options.decodeValues ? decodeURIComponent(value) : value; // decode cookie value\n } catch (e) {\n console.error(\n \"set-cookie-parser: failed to decode cookie value. Set options.decodeValues=false to disable decoding.\",\n e\n );\n }\n\n var cookie = createNullObj();\n cookie.name = name;\n cookie.value = value;\n\n parts.forEach(function (part) {\n var sides = part.split(\"=\");\n var key = sides.shift().trim().toLowerCase();\n if (isForbiddenKey(key)) {\n return;\n }\n var value = sides.join(\"=\").trim();\n if (key === \"expires\") {\n cookie.expires = new Date(value);\n } else if (key === \"max-age\") {\n var n = parseInt(value, 10);\n if (!Number.isNaN(n)) cookie.maxAge = n;\n } else if (key === \"secure\") {\n cookie.secure = true;\n } else if (key === \"httponly\") {\n cookie.httpOnly = true;\n } else if (key === \"samesite\") {\n cookie.sameSite = value;\n } else if (key === \"partitioned\") {\n cookie.partitioned = true;\n } else if (key) {\n cookie[key] = value;\n }\n });\n\n return cookie;\n}\n\nfunction parseNameValuePair(nameValuePairStr) {\n // Parses name-value-pair according to rfc6265bis draft\n\n var name = \"\";\n var value = \"\";\n var nameValueArr = nameValuePairStr.split(\"=\");\n if (nameValueArr.length > 1) {\n name = nameValueArr.shift();\n value = nameValueArr.join(\"=\"); // everything after the first =, joined by a \"=\" if there was more than one part\n } else {\n value = nameValuePairStr;\n }\n\n return { name: name, value: value };\n}\n\nfunction parseSetCookie(input, options) {\n options = options\n ? Object.assign({}, defaultParseOptions, options)\n : defaultParseOptions;\n\n if (!input) {\n if (!options.map) {\n return [];\n } else {\n return createNullObj();\n }\n }\n\n if (input.headers) {\n if (typeof input.headers.getSetCookie === \"function\") {\n // for fetch responses - they combine headers of the same type in the headers array,\n // but getSetCookie returns an uncombined array\n input = input.headers.getSetCookie();\n } else if (input.headers[\"set-cookie\"]) {\n // fast-path for node.js (which automatically normalizes header names to lower-case)\n input = input.headers[\"set-cookie\"];\n } else {\n // slow-path for other environments - see #25\n var sch =\n input.headers[\n Object.keys(input.headers).find(function (key) {\n return key.toLowerCase() === \"set-cookie\";\n })\n ];\n // warn if called on a request-like object with a cookie header rather than a set-cookie header - see #34, 36\n if (!sch && input.headers.cookie && !options.silent) {\n console.warn(\n \"Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning.\"\n );\n }\n input = sch;\n }\n }\n\n var split = options.split;\n var isArray = Array.isArray(input);\n\n if (split === \"auto\") {\n split = !isArray;\n }\n\n if (!isArray) {\n input = [input];\n }\n\n input = input.filter(isNonEmptyString);\n\n if (split) {\n input = input.map(splitCookiesString).flat();\n }\n\n if (!options.map) {\n return input\n .map(function (str) {\n return parseString(str, options);\n })\n .filter(Boolean);\n } else {\n var cookies = createNullObj();\n return input.reduce(function (cookies, str) {\n var cookie = parseString(str, options);\n if (cookie && !isForbiddenKey(cookie.name)) {\n cookies[cookie.name] = cookie;\n }\n return cookies;\n }, cookies);\n }\n}\n\n/*\n Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas\n that are within a single set-cookie field-value, such as in the Expires portion.\n\n This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2\n Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128\n React Native's fetch does this for *every* header, including set-cookie.\n\n Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25\n Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation\n*/\nfunction splitCookiesString(cookiesString) {\n if (Array.isArray(cookiesString)) {\n return cookiesString;\n }\n if (typeof cookiesString !== \"string\") {\n return [];\n }\n\n var cookiesStrings = [];\n var pos = 0;\n var start;\n var ch;\n var lastComma;\n var nextStart;\n var cookiesSeparatorFound;\n\n function skipWhitespace() {\n while (pos < cookiesString.length && /\\s/.test(cookiesString.charAt(pos))) {\n pos += 1;\n }\n return pos < cookiesString.length;\n }\n\n function notSpecialChar() {\n ch = cookiesString.charAt(pos);\n\n return ch !== \"=\" && ch !== \";\" && ch !== \",\";\n }\n\n while (pos < cookiesString.length) {\n start = pos;\n cookiesSeparatorFound = false;\n\n while (skipWhitespace()) {\n ch = cookiesString.charAt(pos);\n if (ch === \",\") {\n // ',' is a cookie separator if we have later first '=', not ';' or ','\n lastComma = pos;\n pos += 1;\n\n skipWhitespace();\n nextStart = pos;\n\n while (pos < cookiesString.length && notSpecialChar()) {\n pos += 1;\n }\n\n // currently special character\n if (pos < cookiesString.length && cookiesString.charAt(pos) === \"=\") {\n // we found cookies separator\n cookiesSeparatorFound = true;\n // pos is inside the next cookie, so back up and return it.\n pos = nextStart;\n cookiesStrings.push(cookiesString.substring(start, lastComma));\n start = pos;\n } else {\n // in param ',' or param separator ';',\n // we continue from that comma\n pos = lastComma + 1;\n }\n } else {\n pos += 1;\n }\n }\n\n if (!cookiesSeparatorFound || pos >= cookiesString.length) {\n cookiesStrings.push(cookiesString.substring(start, cookiesString.length));\n }\n }\n\n return cookiesStrings;\n}\n\n// named export for CJS\nparseSetCookie.parseSetCookie = parseSetCookie;\n// for backwards compatibility\nparseSetCookie.parse = parseSetCookie;\nparseSetCookie.parseString = parseString;\nparseSetCookie.splitCookiesString = splitCookiesString;\n\n// EXPORTS\n// (this section is replaced by build-cjs.js)\n\n// named export for ESM\nexport { parseSetCookie };\n// for backwards compatibility\nexport default parseSetCookie;\nexport { parseSetCookie as parse, parseString, splitCookiesString };\n","import { parse as parseSetCookie, splitCookiesString } from 'set-cookie-parser';\nimport { originOf } from './url.js';\n\n/** Cookie, сохранённая в jar. */\ninterface StoredCookie {\n name: string;\n value: string;\n path: string;\n /** Момент истечения, мс с начала эпохи. `undefined` — сессионная cookie. */\n expires: number | undefined;\n secure: boolean;\n}\n\n/** Имя cookie-флага «есть refresh-сессия». Ставится сайтом итд.com рядом с refresh-токеном. */\nexport const AUTH_FLAG_COOKIE = 'is_auth';\n\n/**\n * Имя cookie с refresh-токеном.\n *\n * `POST /api/v1/auth/refresh` читает токен **только отсюда** — тело запроса сервер игнорирует.\n * Cookie помечена `HttpOnly`, поэтому в браузере её не прочитать и не выставить; вне браузера\n * она проходит через jar, и туда же кладётся токен, переданный строкой.\n */\nexport const REFRESH_COOKIE = 'refresh_token';\n\n/** Путь, которым сервер ограничивает {@link REFRESH_COOKIE}. */\nexport const REFRESH_COOKIE_PATH = '/api/v1/auth';\n\n/** Разделитель origin и содержимого cookie при сериализации. В origin пробелов не бывает. */\nconst SERIALIZED_SEPARATOR = ' ';\nconst COOKIE_NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\n/** Проверяет одну запись, созданную {@link CookieJar.serialize}. @internal */\nexport function isSerializedCookieEntry(entry: string): boolean {\n const separatorAt = entry.indexOf(SERIALIZED_SEPARATOR);\n if (separatorAt <= 0) return false;\n\n const origin = entry.slice(0, separatorAt);\n if (originOf(origin) !== origin) return false;\n\n const parsed = parseSetCookie([entry.slice(separatorAt + 1)]);\n return parsed.length === 1 && COOKIE_NAME.test(parsed[0]?.name ?? '');\n}\n\n/** Дата в миллисекунды. Некорректная дата считается отсутствующей, а не `NaN`. */\nfunction toTimestamp(date: Date | undefined): number | undefined {\n if (!date) return undefined;\n const time = date.getTime();\n return Number.isFinite(time) ? time : undefined;\n}\n\nfunction pathOf(url: string): string {\n try {\n return new URL(url).pathname || '/';\n } catch {\n return '/';\n }\n}\n\n/**\n * Подходит ли путь cookie запросу.\n *\n * Правило из RFC 6265: путь cookie должен быть префиксом пути запроса, причём граница\n * должна проходить по сегменту — `/api` не подходит запросу `/apiary`.\n */\nfunction pathMatches(cookiePath: string, requestPath: string): boolean {\n if (cookiePath === '/' || cookiePath === requestPath) return true;\n if (!requestPath.startsWith(cookiePath)) return false;\n return cookiePath.endsWith('/') || requestPath[cookiePath.length] === '/';\n}\n\n/**\n * Минимальное хранилище cookie для сред без своего.\n *\n * Refresh-токен итд.com приходит в `Set-Cookie`, а `fetch` вне браузера cookie не хранит —\n * без jar сессию не продлить. В браузере и React Native не используется: там cookie ведёт\n * сама среда.\n *\n * Реализована практическая часть RFC 6265: origin, путь, срок жизни, флаг `Secure`.\n * Доменные cookie для поддоменов намеренно не поддерживаются — API работает с одного хоста.\n */\nexport class CookieJar {\n readonly #byOrigin = new Map<string, Map<string, StoredCookie>>();\n\n /** Независимая копия для auth-flow, который ещё не получил право на commit. */\n clone(): CookieJar {\n const copy = new CookieJar();\n copy.deserialize(this.serialize());\n return copy;\n }\n\n /** Атомарно с точки зрения синхронных читателей заменяет содержимое снимком другого jar. */\n replaceWith(source: CookieJar): void {\n const entries = source.serialize();\n this.clear();\n this.deserialize(entries);\n }\n\n /**\n * Забирает `Set-Cookie` из ответа.\n *\n * Использует `Headers.getSetCookie()`, где он есть (Node 20+, undici). В остальных средах\n * заголовки склеены в одну строку, и её нельзя резать по запятой напрямую: запятая есть\n * внутри `Expires=Wed, 09 Jun 2027 …`. Разделением занимается `set-cookie-parser`.\n */\n setFromResponse(url: string, response: Response): void {\n const headers = response.headers as Headers & { getSetCookie?: () => string[] };\n\n const raw =\n typeof headers.getSetCookie === 'function'\n ? headers.getSetCookie()\n : splitCookiesString(headers.get('set-cookie') ?? '');\n\n if (raw.length > 0) this.setFromStrings(url, raw);\n }\n\n /**\n * Кладёт cookie напрямую, минуя `Set-Cookie`.\n *\n * Нужно ровно в одном случае: пользователь передал refresh-токен строкой, а сервер читает\n * его только из cookie. Значение не кодируется — оно уходит в заголовок как есть.\n */\n set(url: string, name: string, value: string, path = '/'): void {\n this.setFromStrings(url, [`${name}=${value}; Path=${path}`]);\n }\n\n /** Сохраняет cookie из готовых строк `Set-Cookie`. */\n setFromStrings(url: string, setCookieStrings: string[]): void {\n const origin = originOf(url);\n if (!origin) return;\n\n const jar = this.#byOrigin.get(origin) ?? new Map<string, StoredCookie>();\n\n for (const parsed of parseSetCookie(setCookieStrings)) {\n // Битую дату (её легко получить, если заголовки склеены неправильно) считаем\n // отсутствующей: сессионная cookie лучше, чем cookie со сроком NaN, которая\n // не истекает и одновременно нигде не находится.\n const expires = toTimestamp(parsed.expires);\n const maxAgeExpires =\n typeof parsed.maxAge === 'number' && Number.isFinite(parsed.maxAge)\n ? Date.now() + parsed.maxAge * 1000\n : undefined;\n\n // Max-Age приоритетнее Expires — так требует RFC 6265.\n const expiresAt = maxAgeExpires ?? expires;\n\n // Удаление cookie сервером: срок в прошлом либо Max-Age=0.\n if (expiresAt !== undefined && expiresAt <= Date.now()) {\n jar.delete(parsed.name);\n continue;\n }\n\n jar.set(parsed.name, {\n name: parsed.name,\n value: parsed.value,\n path: parsed.path ?? '/',\n expires: expiresAt,\n secure: parsed.secure ?? false,\n });\n }\n\n this.#byOrigin.set(origin, jar);\n }\n\n /**\n * Собирает значение заголовка `Cookie` для запроса.\n *\n * @returns строка вида `a=1; b=2` либо `undefined`, если подходящих cookie нет\n */\n getHeader(url: string): string | undefined {\n const cookies = this.#matching(url);\n if (cookies.length === 0) return undefined;\n return cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');\n }\n\n /**\n * Значение действующей cookie.\n *\n * Нужно, чтобы забрать обновлённый refresh-токен: сервер ротирует его при каждом\n * продлении сессии, и сохранять надо именно новое значение.\n *\n * @param url если указан, учитываются origin, путь и флаг `Secure`\n */\n getValue(name: string, url?: string): string | undefined {\n if (url) return this.#matching(url).find((cookie) => cookie.name === name)?.value;\n\n const now = Date.now();\n for (const jar of this.#byOrigin.values()) {\n const cookie = jar.get(name);\n if (cookie && (cookie.expires === undefined || cookie.expires > now)) return cookie.value;\n }\n return undefined;\n }\n\n /**\n * Есть ли действующая cookie с таким именем.\n *\n * Используется для проверки флага {@link AUTH_FLAG_COOKIE} перед запросом обновления\n * токена: у анонима refresh-сессии нет, и дёргать API незачем.\n */\n has(name: string, url?: string): boolean {\n if (url) return this.#matching(url).some((cookie) => cookie.name === name);\n\n const now = Date.now();\n for (const jar of this.#byOrigin.values()) {\n const cookie = jar.get(name);\n if (cookie && (cookie.expires === undefined || cookie.expires > now)) return true;\n }\n return false;\n }\n\n /** Сохраняет содержимое jar для записи в {@link TokenStorage}. */\n serialize(): string[] {\n const result: string[] = [];\n const now = Date.now();\n\n for (const [origin, jar] of this.#byOrigin) {\n for (const cookie of jar.values()) {\n if (cookie.expires !== undefined && cookie.expires <= now) continue;\n\n const parts = [`${cookie.name}=${cookie.value}`, `Path=${cookie.path}`];\n if (cookie.expires !== undefined) {\n parts.push(`Expires=${new Date(cookie.expires).toUTCString()}`);\n }\n if (cookie.secure) parts.push('Secure');\n\n result.push(`${origin}${SERIALIZED_SEPARATOR}${parts.join('; ')}`);\n }\n }\n\n return result;\n }\n\n /** Восстанавливает jar из результата {@link serialize}. Некорректные записи молча пропускаются. */\n deserialize(entries: readonly string[] | undefined): void {\n if (!entries) return;\n\n for (const entry of entries) {\n if (!isSerializedCookieEntry(entry)) continue;\n const separatorAt = entry.indexOf(SERIALIZED_SEPARATOR);\n\n const origin = entry.slice(0, separatorAt);\n const setCookie = entry.slice(separatorAt + 1);\n\n this.setFromStrings(origin, [setCookie]);\n }\n }\n\n /** Удаляет все cookie. */\n clear(): void {\n this.#byOrigin.clear();\n }\n\n /** Действующие cookie, подходящие запросу: тот же origin, подходящий путь, не истёкшие. */\n #matching(url: string): StoredCookie[] {\n const origin = originOf(url);\n const jar = this.#byOrigin.get(origin);\n if (!jar) return [];\n\n const isSecureRequest = origin.startsWith('https:');\n const requestPath = pathOf(url);\n const now = Date.now();\n const result: StoredCookie[] = [];\n\n for (const cookie of jar.values()) {\n if (cookie.expires !== undefined && cookie.expires <= now) {\n jar.delete(cookie.name);\n continue;\n }\n if (cookie.secure && !isSecureRequest) continue;\n if (!pathMatches(cookie.path, requestPath)) continue;\n\n result.push(cookie);\n }\n\n return result;\n }\n}\n","import { isBlob } from './runtime.js';\n\n/** Заголовки, значение которых нельзя писать в лог целиком. */\nconst SECRET_HEADERS = new Set([\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-order-token',\n]);\n\n/** Поля тела запроса, значение которых нельзя писать в лог. */\nconst SECRET_FIELDS = new Set([\n 'password',\n 'oldpassword',\n 'newpassword',\n 'accesstoken',\n 'refreshtoken',\n 'currentpassword',\n 'flowtoken',\n 'token',\n 'turnstiletoken',\n 'otp',\n 'pass',\n 'email',\n 'phone',\n 'address',\n 'orderaccesstoken',\n]);\n\n/** Query-параметры, содержащие секреты. */\nconst SECRET_QUERY_PARAMS = new Set(['token', 'access_token', 'c']);\n\n/**\n * Прячет середину секрета, оставляя концы для сопоставления.\n *\n * @example\n * ```ts\n * maskSecret('eyJhbGciOiJIUzI1NiJ9.abc'); // 'eyJh…(24)…abc'\n * ```\n */\nexport function maskSecret(value: string): string {\n if (value.length <= 8) return '…';\n return `${value.slice(0, 4)}…(${value.length})…${value.slice(-3)}`;\n}\n\n/** Маскирует секретные query-параметры URL перед записью в логи и ошибки. */\nexport function redactUrl(url: string): string {\n try {\n const parsed = new URL(url);\n const entries = [...parsed.searchParams.entries()];\n parsed.search = '';\n for (const [name, value] of entries) {\n parsed.searchParams.append(\n name,\n SECRET_QUERY_PARAMS.has(name.toLowerCase()) ? maskSecret(value) : value,\n );\n }\n return parsed.toString();\n } catch {\n return url.replace(/([?&](?:token|access_token|c)=)[^&#]*/gi, '$1[скрыто]');\n }\n}\n\n/** Маскирует подписанные адреса внутри произвольного диагностического текста. */\nexport function redactUrlsInText(text: string): string {\n return text.replace(/https?:\\/\\/[^\\s\"'<>]+/gi, (url) => redactUrl(url));\n}\n\n/**\n * Создаёт безопасную причину ошибки для публичной цепочки `cause`.\n *\n * Чужие объекты не сохраняются: их поля и пользовательские методы нельзя надёжно\n * сериализовать без риска вывести секрет. Для Error и строк остаются тип и сообщение,\n * но все встреченные в сообщении HTTP(S)-адреса проходят маскирование.\n */\nexport function redactErrorCause(error: unknown): Error | undefined {\n const message =\n error instanceof Error ? error.message : typeof error === 'string' ? error : undefined;\n if (message === undefined) return undefined;\n\n const safeMessage = redactUrlsInText(message);\n const safe = error instanceof TypeError ? new TypeError(safeMessage) : new Error(safeMessage);\n if (error instanceof Error && !(error instanceof TypeError)) safe.name = error.name;\n return safe;\n}\n\n/**\n * Готовит заголовки к записи в лог.\n *\n * `Authorization` и `Cookie` маскируются: логи часто уезжают в системы сбора,\n * и токен доступа в них попадать не должен.\n */\nexport function redactHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n\n headers.forEach((value, name) => {\n if (SECRET_HEADERS.has(name.toLowerCase())) {\n // У Authorization маскируем только сам токен, схему («Bearer») оставляем видимой.\n const spaceAt = value.indexOf(' ');\n result[name] =\n spaceAt > 0\n ? `${value.slice(0, spaceAt)} ${maskSecret(value.slice(spaceAt + 1))}`\n : maskSecret(value);\n return;\n }\n result[name] = value;\n });\n\n return result;\n}\n\n/**\n * Готовит тело запроса к записи в лог: пароли, токены и коды OTP заменяются заглушкой.\n *\n * Обходит вложенные объекты и массивы. `FormData` и бинарные тела не раскрываются вовсе.\n */\nexport function redactBody(body: unknown): unknown {\n if (body === null || body === undefined) return body;\n\n if (typeof FormData !== 'undefined' && body instanceof FormData) return '[FormData]';\n if (isBlob(body)) return '[Blob]';\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return '[binary]';\n\n if (Array.isArray(body)) return body.map(redactBody);\n\n if (typeof body === 'object') {\n const result: Record<string, unknown> = {};\n const entries = Object.entries(body);\n const containsEmail = entries.some(([key]) => key.toLowerCase() === 'email');\n for (const [key, value] of entries) {\n const normalized = key.toLowerCase();\n const secret = SECRET_FIELDS.has(normalized) || (normalized === 'code' && containsEmail);\n result[key] = secret ? '[скрыто]' : redactBody(value);\n }\n return result;\n }\n\n return body;\n}\n"],"x_google_ignoreList":[2],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { B as isRecord, C as ReportReason, E as SpanType, G as pickString, H as pickBoolean, J as identityResult, K as RetrySafety, M as defineBuiltInOperation, U as pickNumber, V as pickArray, W as pickObject, X as mergeService, Y as voidResult, c as normalizeNotification, ct as createDeadline, nt as STATUS_SERVICE, o as passthroughOperation, q as defineOperation, s as voidOperation, tt as DEFAULT_STATUS_BASE_URL, w as ReportTargetType, y as InteractionType } from "./url-
|
|
1
|
+
import { B as isRecord, C as ReportReason, E as SpanType, G as pickString, H as pickBoolean, J as identityResult, K as RetrySafety, M as defineBuiltInOperation, U as pickNumber, V as pickArray, W as pickObject, X as mergeService, Y as voidResult, c as normalizeNotification, ct as createDeadline, nt as STATUS_SERVICE, o as passthroughOperation, q as defineOperation, s as voidOperation, tt as DEFAULT_STATUS_BASE_URL, w as ReportTargetType, y as InteractionType } from "./url-i2f-X1hX.js";
|
|
2
2
|
import { _ as ItdStateError, a as ItdConfigError, b as isItdApiError, l as ItdFileError, s as ItdError, t as ItdAbortError, u as ItdFileErrorReason } from "./errors-GI10kZxk.js";
|
|
3
|
-
import { a as redactUrl, b as
|
|
4
|
-
import { a as fileTooLarge, c as FileTransferMode, i as isReadableByteStream, n as boundedFileStream, o as optionalBytes, r as isBoundedFileStream, s as DEFAULT_URL_FILE_MAX_BYTES, t as resolveFileStreamOptions } from "./options-
|
|
5
|
-
import { r as createKeyValueStore
|
|
3
|
+
import { a as redactUrl, b as isBlob, f as encodePathSegment, r as redactErrorCause, x as isFile, y as createDeviceId } from "./redact-DJV0XM3n.js";
|
|
4
|
+
import { a as fileTooLarge, c as FileTransferMode, i as isReadableByteStream, n as boundedFileStream, o as optionalBytes, r as isBoundedFileStream, s as DEFAULT_URL_FILE_MAX_BYTES, t as resolveFileStreamOptions } from "./options-i4LrKfqx.js";
|
|
5
|
+
import { r as createKeyValueStore } from "./key-value-store-Bt2PSMxY.js";
|
|
6
6
|
//#region src/core/feature-catalog.ts
|
|
7
7
|
/**
|
|
8
8
|
* Изменяемый слой над каталогом конкретного API.
|
|
@@ -370,6 +370,22 @@ function createFileResolver(fetchImplementation) {
|
|
|
370
370
|
}
|
|
371
371
|
//#endregion
|
|
372
372
|
//#region src/core/features.ts
|
|
373
|
+
var FeatureInstallationTransaction = class {
|
|
374
|
+
#cleanup = [];
|
|
375
|
+
add(cleanup) {
|
|
376
|
+
this.#cleanup.push(cleanup);
|
|
377
|
+
}
|
|
378
|
+
snapshot() {
|
|
379
|
+
return [...this.#cleanup];
|
|
380
|
+
}
|
|
381
|
+
rollback(reportError) {
|
|
382
|
+
for (let index = this.#cleanup.length - 1; index >= 0; index -= 1) try {
|
|
383
|
+
this.#cleanup[index]?.();
|
|
384
|
+
} catch (error) {
|
|
385
|
+
reportError(error);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
373
389
|
function requireName(value, kind) {
|
|
374
390
|
if (typeof value !== "string" || value.trim() === "") throw new ItdConfigError(`${kind} должен иметь непустое имя`);
|
|
375
391
|
return value.trim();
|
|
@@ -385,6 +401,21 @@ function validateBucket(owner, localName, bucket) {
|
|
|
385
401
|
if (bucket.concurrency !== void 0 && (!Number.isInteger(bucket.concurrency) || bucket.concurrency < 1)) throw new ItdConfigError(`feature «${owner}»: concurrency бакета «${localName}» должен быть целым числом от 1`);
|
|
386
402
|
if (bucket.rps !== void 0 && (!Number.isFinite(bucket.rps) || bucket.rps <= 0)) throw new ItdConfigError(`feature «${owner}»: rps бакета «${localName}» должен быть положительным числом`);
|
|
387
403
|
}
|
|
404
|
+
function validateFeatureDefinition(feature, isInstalled) {
|
|
405
|
+
if (typeof feature !== "object" || feature === null) throw new ItdConfigError("feature должен быть объектом");
|
|
406
|
+
const name = requireFeatureName(feature.name);
|
|
407
|
+
if (isInstalled(name)) throw new ItdConfigError(`feature «${name}» уже установлен`);
|
|
408
|
+
if (typeof feature.setup !== "function") throw new ItdConfigError(`feature «${name}» должен предоставлять setup()`);
|
|
409
|
+
if (typeof feature.operations !== "object" || feature.operations === null || Array.isArray(feature.operations)) throw new ItdConfigError(`feature «${name}» должен объявлять operations`);
|
|
410
|
+
if (feature.services !== void 0 && !Array.isArray(feature.services)) throw new ItdConfigError(`feature «${name}»: services должен быть массивом`);
|
|
411
|
+
if (feature.buckets !== void 0 && (typeof feature.buckets !== "object" || feature.buckets === null || Array.isArray(feature.buckets))) throw new ItdConfigError(`feature «${name}»: buckets должен быть объектом`);
|
|
412
|
+
return name;
|
|
413
|
+
}
|
|
414
|
+
function validateFeatureInstallation(name, installation) {
|
|
415
|
+
if (typeof installation !== "object" || installation === null || !("api" in installation)) throw new ItdConfigError(`setup() feature «${name}» должен вернуть объект с полем api`);
|
|
416
|
+
if (installation.close !== void 0 && typeof installation.close !== "function") throw new ItdConfigError(`feature «${name}»: close должен быть функцией`);
|
|
417
|
+
if (installation.dispose !== void 0 && typeof installation.dispose !== "function") throw new ItdConfigError(`feature «${name}»: dispose должен быть функцией`);
|
|
418
|
+
}
|
|
388
419
|
/** Реестр подключаемых модулей клиента. @internal */
|
|
389
420
|
var FeatureRegistry = class {
|
|
390
421
|
#deps;
|
|
@@ -394,20 +425,89 @@ var FeatureRegistry = class {
|
|
|
394
425
|
constructor(deps) {
|
|
395
426
|
this.#deps = deps;
|
|
396
427
|
}
|
|
397
|
-
|
|
398
|
-
this.#deps.assertActive("установить feature");
|
|
399
|
-
if (this.#disposed) throw new ItdStateError("Реестр feature уже освобождён");
|
|
400
|
-
if (typeof feature !== "object" || feature === null) throw new ItdConfigError("feature должен быть объектом");
|
|
401
|
-
const name = requireFeatureName(feature.name);
|
|
402
|
-
if (this.#features.has(name)) throw new ItdConfigError(`feature «${name}» уже установлен`);
|
|
403
|
-
if (typeof feature.setup !== "function") throw new ItdConfigError(`feature «${name}» должен предоставлять setup()`);
|
|
404
|
-
if (typeof feature.operations !== "object" || feature.operations === null || Array.isArray(feature.operations)) throw new ItdConfigError(`feature «${name}» должен объявлять operations`);
|
|
405
|
-
if (feature.services !== void 0 && !Array.isArray(feature.services)) throw new ItdConfigError(`feature «${name}»: services должен быть массивом`);
|
|
406
|
-
if (feature.buckets !== void 0 && (typeof feature.buckets !== "object" || feature.buckets === null || Array.isArray(feature.buckets))) throw new ItdConfigError(`feature «${name}»: buckets должен быть объектом`);
|
|
407
|
-
const rollback = [];
|
|
428
|
+
#registerServices(featureName, definitions, transaction) {
|
|
408
429
|
const services = /* @__PURE__ */ new Set();
|
|
430
|
+
for (const service of definitions) {
|
|
431
|
+
const serviceName = requireName(service?.name, `Сервис feature «${featureName}»`);
|
|
432
|
+
const owner = this.#serviceOwners.get(serviceName);
|
|
433
|
+
if (owner !== void 0) throw new ItdConfigError(`feature «${featureName}»: сервис «${serviceName}» уже принадлежит feature «${owner}»`);
|
|
434
|
+
if (services.has(serviceName)) throw new ItdConfigError(`feature «${featureName}»: сервис «${serviceName}» объявлен повторно`);
|
|
435
|
+
if (!this.#deps.services.has(serviceName)) {
|
|
436
|
+
this.#deps.services.define(service);
|
|
437
|
+
transaction.add(() => void this.#deps.services.delete(serviceName));
|
|
438
|
+
} else {
|
|
439
|
+
const override = this.#deps.serviceOverrides.find((candidate) => candidate.name.trim() === serviceName);
|
|
440
|
+
if (override) {
|
|
441
|
+
const previous = this.#deps.services.replace(mergeService(service, override));
|
|
442
|
+
transaction.add(() => void this.#deps.services.replace(previous));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
this.#serviceOwners.set(serviceName, featureName);
|
|
446
|
+
transaction.add(() => {
|
|
447
|
+
if (this.#serviceOwners.get(serviceName) === featureName) this.#serviceOwners.delete(serviceName);
|
|
448
|
+
});
|
|
449
|
+
services.add(serviceName);
|
|
450
|
+
}
|
|
451
|
+
return services;
|
|
452
|
+
}
|
|
453
|
+
#registerBuckets(featureName, definitions, transaction) {
|
|
409
454
|
const bucketNames = /* @__PURE__ */ new Map();
|
|
455
|
+
for (const [rawLocalName, bucket] of Object.entries(definitions)) {
|
|
456
|
+
const localName = requireName(rawLocalName, `Бакет feature «${featureName}»`);
|
|
457
|
+
validateBucket(featureName, localName, bucket);
|
|
458
|
+
const globalName = `feature:${featureName}/${localName}`;
|
|
459
|
+
transaction.add(this.#deps.catalog.registerBucket(featureName, globalName, bucket));
|
|
460
|
+
const unregisterQueue = this.#deps.registerBucket(globalName, bucket);
|
|
461
|
+
if (unregisterQueue) transaction.add(unregisterQueue);
|
|
462
|
+
bucketNames.set(localName, globalName);
|
|
463
|
+
}
|
|
464
|
+
return bucketNames;
|
|
465
|
+
}
|
|
466
|
+
#registerOperations(featureName, definitions, services, bucketNames, transaction) {
|
|
410
467
|
const operations = /* @__PURE__ */ new Map();
|
|
468
|
+
for (const [rawLocalName, definition] of Object.entries(definitions)) {
|
|
469
|
+
const localName = requireName(rawLocalName, `Операция feature «${featureName}»`);
|
|
470
|
+
if (typeof definition !== "object" || definition === null) throw new ItdConfigError(`feature «${featureName}»: операция «${localName}» должна быть объектом`);
|
|
471
|
+
if (![
|
|
472
|
+
"GET",
|
|
473
|
+
"POST",
|
|
474
|
+
"PUT",
|
|
475
|
+
"PATCH",
|
|
476
|
+
"DELETE"
|
|
477
|
+
].includes(definition.method)) throw new ItdConfigError(`feature «${featureName}»: операция «${localName}» содержит неизвестный HTTP-метод`);
|
|
478
|
+
if (!Object.values(RetrySafety).includes(definition.retrySafety)) throw new ItdConfigError(`feature «${featureName}»: операция «${localName}» содержит неизвестную retrySafety`);
|
|
479
|
+
if (definition.service !== void 0 && typeof definition.service !== "string") throw new ItdConfigError(`feature «${featureName}»: service операции «${localName}» должен быть строкой`);
|
|
480
|
+
if (definition.bucket !== void 0 && typeof definition.bucket !== "string") throw new ItdConfigError(`feature «${featureName}»: bucket операции «${localName}» должен быть строкой`);
|
|
481
|
+
if (definition.read !== void 0 && typeof definition.read !== "function") throw new ItdConfigError(`feature «${featureName}»: read операции «${localName}» должна быть функцией`);
|
|
482
|
+
if (definition.annotations !== void 0 && (typeof definition.annotations !== "object" || definition.annotations === null || Array.isArray(definition.annotations))) throw new ItdConfigError(`feature «${featureName}»: annotations операции «${localName}» должны быть объектом`);
|
|
483
|
+
if (definition.service !== void 0 && !services.has(definition.service)) throw new ItdConfigError(`feature «${featureName}»: операция «${localName}» ссылается на необъявленный сервис «${definition.service}»`);
|
|
484
|
+
const bucket = definition.bucket === void 0 ? this.#deps.catalog.defaultBucket : bucketNames.get(definition.bucket);
|
|
485
|
+
if (bucket === void 0) throw new ItdConfigError(`feature «${featureName}»: операция «${localName}» ссылается на необъявленный бакет «${definition.bucket}»`);
|
|
486
|
+
const operationId = `${featureName}.${localName}`;
|
|
487
|
+
const contract = defineOperation(operationId, {
|
|
488
|
+
method: definition.method,
|
|
489
|
+
retrySafety: definition.retrySafety,
|
|
490
|
+
bucket,
|
|
491
|
+
...definition.annotations === void 0 ? {} : { annotations: definition.annotations }
|
|
492
|
+
}, definition.read ?? identityResult);
|
|
493
|
+
transaction.add(this.#deps.catalog.registerOperation(featureName, operationId, {
|
|
494
|
+
method: contract.method,
|
|
495
|
+
retrySafety: contract.retrySafety,
|
|
496
|
+
bucket,
|
|
497
|
+
...contract.annotations === void 0 ? {} : { annotations: contract.annotations }
|
|
498
|
+
}));
|
|
499
|
+
operations.set(localName, {
|
|
500
|
+
contract,
|
|
501
|
+
service: definition.service
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
return operations;
|
|
505
|
+
}
|
|
506
|
+
install(feature) {
|
|
507
|
+
this.#deps.assertActive("установить feature");
|
|
508
|
+
if (this.#disposed) throw new ItdStateError("Реестр feature уже освобождён");
|
|
509
|
+
const name = validateFeatureDefinition(feature, (candidate) => this.#features.has(candidate));
|
|
510
|
+
const transaction = new FeatureInstallationTransaction();
|
|
411
511
|
const controller = new AbortController();
|
|
412
512
|
let committed = false;
|
|
413
513
|
const reportRollbackError = (message, error) => {
|
|
@@ -416,74 +516,9 @@ var FeatureRegistry = class {
|
|
|
416
516
|
} catch {}
|
|
417
517
|
};
|
|
418
518
|
try {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (owner !== void 0) throw new ItdConfigError(`feature «${name}»: сервис «${serviceName}» уже принадлежит feature «${owner}»`);
|
|
423
|
-
if (services.has(serviceName)) throw new ItdConfigError(`feature «${name}»: сервис «${serviceName}» объявлен повторно`);
|
|
424
|
-
if (!this.#deps.services.has(serviceName)) {
|
|
425
|
-
this.#deps.services.define(service);
|
|
426
|
-
rollback.push(() => void this.#deps.services.delete(serviceName));
|
|
427
|
-
} else {
|
|
428
|
-
const override = this.#deps.serviceOverrides.find((candidate) => candidate.name.trim() === serviceName);
|
|
429
|
-
if (override) {
|
|
430
|
-
const previous = this.#deps.services.replace(mergeService(service, override));
|
|
431
|
-
rollback.push(() => void this.#deps.services.replace(previous));
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
this.#serviceOwners.set(serviceName, name);
|
|
435
|
-
rollback.push(() => {
|
|
436
|
-
if (this.#serviceOwners.get(serviceName) === name) this.#serviceOwners.delete(serviceName);
|
|
437
|
-
});
|
|
438
|
-
services.add(serviceName);
|
|
439
|
-
}
|
|
440
|
-
for (const [rawLocalName, bucket] of Object.entries(feature.buckets ?? {})) {
|
|
441
|
-
const localName = requireName(rawLocalName, `Бакет feature «${name}»`);
|
|
442
|
-
validateBucket(name, localName, bucket);
|
|
443
|
-
const globalName = `feature:${name}/${localName}`;
|
|
444
|
-
const unregisterCatalog = this.#deps.catalog.registerBucket(name, globalName, bucket);
|
|
445
|
-
rollback.push(unregisterCatalog);
|
|
446
|
-
const unregisterQueue = this.#deps.registerBucket(globalName, bucket);
|
|
447
|
-
if (unregisterQueue) rollback.push(unregisterQueue);
|
|
448
|
-
bucketNames.set(localName, globalName);
|
|
449
|
-
}
|
|
450
|
-
for (const [rawLocalName, definition] of Object.entries(feature.operations)) {
|
|
451
|
-
const localName = requireName(rawLocalName, `Операция feature «${name}»`);
|
|
452
|
-
if (typeof definition !== "object" || definition === null) throw new ItdConfigError(`feature «${name}»: операция «${localName}» должна быть объектом`);
|
|
453
|
-
if (![
|
|
454
|
-
"GET",
|
|
455
|
-
"POST",
|
|
456
|
-
"PUT",
|
|
457
|
-
"PATCH",
|
|
458
|
-
"DELETE"
|
|
459
|
-
].includes(definition.method)) throw new ItdConfigError(`feature «${name}»: операция «${localName}» содержит неизвестный HTTP-метод`);
|
|
460
|
-
if (!Object.values(RetrySafety).includes(definition.retrySafety)) throw new ItdConfigError(`feature «${name}»: операция «${localName}» содержит неизвестную retrySafety`);
|
|
461
|
-
if (definition.service !== void 0 && typeof definition.service !== "string") throw new ItdConfigError(`feature «${name}»: service операции «${localName}» должен быть строкой`);
|
|
462
|
-
if (definition.bucket !== void 0 && typeof definition.bucket !== "string") throw new ItdConfigError(`feature «${name}»: bucket операции «${localName}» должен быть строкой`);
|
|
463
|
-
if (definition.read !== void 0 && typeof definition.read !== "function") throw new ItdConfigError(`feature «${name}»: read операции «${localName}» должна быть функцией`);
|
|
464
|
-
if (definition.annotations !== void 0 && (typeof definition.annotations !== "object" || definition.annotations === null || Array.isArray(definition.annotations))) throw new ItdConfigError(`feature «${name}»: annotations операции «${localName}» должны быть объектом`);
|
|
465
|
-
if (definition.service !== void 0 && !services.has(definition.service)) throw new ItdConfigError(`feature «${name}»: операция «${localName}» ссылается на необъявленный сервис «${definition.service}»`);
|
|
466
|
-
const bucket = definition.bucket === void 0 ? this.#deps.catalog.defaultBucket : bucketNames.get(definition.bucket);
|
|
467
|
-
if (bucket === void 0) throw new ItdConfigError(`feature «${name}»: операция «${localName}» ссылается на необъявленный бакет «${definition.bucket}»`);
|
|
468
|
-
const operationId = `${name}.${localName}`;
|
|
469
|
-
const contract = defineOperation(operationId, {
|
|
470
|
-
method: definition.method,
|
|
471
|
-
retrySafety: definition.retrySafety,
|
|
472
|
-
bucket,
|
|
473
|
-
...definition.annotations === void 0 ? {} : { annotations: definition.annotations }
|
|
474
|
-
}, definition.read ?? identityResult);
|
|
475
|
-
const unregister = this.#deps.catalog.registerOperation(name, operationId, {
|
|
476
|
-
method: contract.method,
|
|
477
|
-
retrySafety: contract.retrySafety,
|
|
478
|
-
bucket,
|
|
479
|
-
...contract.annotations === void 0 ? {} : { annotations: contract.annotations }
|
|
480
|
-
});
|
|
481
|
-
rollback.push(unregister);
|
|
482
|
-
operations.set(localName, {
|
|
483
|
-
contract,
|
|
484
|
-
service: definition.service
|
|
485
|
-
});
|
|
486
|
-
}
|
|
519
|
+
const services = this.#registerServices(name, feature.services ?? [], transaction);
|
|
520
|
+
const bucketNames = this.#registerBuckets(name, feature.buckets ?? {}, transaction);
|
|
521
|
+
const operations = this.#registerOperations(name, feature.operations, services, bucketNames, transaction);
|
|
487
522
|
const context = Object.freeze({
|
|
488
523
|
featureName: name,
|
|
489
524
|
baseUrl: this.#deps.baseUrl,
|
|
@@ -538,7 +573,7 @@ var FeatureRegistry = class {
|
|
|
538
573
|
registered = false;
|
|
539
574
|
unregister();
|
|
540
575
|
};
|
|
541
|
-
if (!committed)
|
|
576
|
+
if (!committed) transaction.add(() => {
|
|
542
577
|
if (!registered) return;
|
|
543
578
|
if (committed) {
|
|
544
579
|
release();
|
|
@@ -563,21 +598,21 @@ var FeatureRegistry = class {
|
|
|
563
598
|
}
|
|
564
599
|
});
|
|
565
600
|
const installation = feature.setup(context);
|
|
566
|
-
|
|
567
|
-
if (installation.close !== void 0 && typeof installation.close !== "function") throw new ItdConfigError(`feature «${name}»: close должен быть функцией`);
|
|
568
|
-
if (installation.dispose !== void 0 && typeof installation.dispose !== "function") throw new ItdConfigError(`feature «${name}»: dispose должен быть функцией`);
|
|
601
|
+
validateFeatureInstallation(name, installation);
|
|
569
602
|
this.#features.set(name, {
|
|
570
603
|
name,
|
|
571
604
|
controller,
|
|
572
605
|
close: installation.close,
|
|
573
606
|
dispose: installation.dispose,
|
|
574
|
-
cleanup:
|
|
607
|
+
cleanup: transaction.snapshot()
|
|
575
608
|
});
|
|
576
609
|
committed = true;
|
|
577
610
|
return installation.api;
|
|
578
611
|
} catch (error) {
|
|
579
612
|
controller.abort(new ItdAbortError(`Установка feature «${name}» отменена`));
|
|
580
|
-
|
|
613
|
+
transaction.rollback((rollbackError) => {
|
|
614
|
+
reportRollbackError(`Не удалось полностью откатить feature «${name}»`, rollbackError);
|
|
615
|
+
});
|
|
581
616
|
throw error;
|
|
582
617
|
}
|
|
583
618
|
}
|
|
@@ -1461,7 +1496,7 @@ function resolveComment(input, allowReplyTo = false) {
|
|
|
1461
1496
|
const COMMENTS_REPLIES = pageOperation("comments.replies", (body) => readPagedPage(body, "replies"));
|
|
1462
1497
|
const COMMENTS_REPLY = passthroughOperation("comments.reply");
|
|
1463
1498
|
const COMMENTS_UPDATE = passthroughOperation("comments.update");
|
|
1464
|
-
const COMMENTS_RESTORE =
|
|
1499
|
+
const COMMENTS_RESTORE = voidOperation("comments.restore");
|
|
1465
1500
|
const COMMENTS_LIKE = passthroughOperation("comments.like");
|
|
1466
1501
|
const COMMENTS_UNLIKE = passthroughOperation("comments.unlike");
|
|
1467
1502
|
const COMMENTS_REMOVE = voidOperation("comments.remove");
|
|
@@ -1544,7 +1579,7 @@ var CommentsResource = class extends BaseResource {
|
|
|
1544
1579
|
}
|
|
1545
1580
|
/** Восстанавливает удалённый комментарий. */
|
|
1546
1581
|
restore(commentId, options = {}) {
|
|
1547
|
-
return this.
|
|
1582
|
+
return this.voidOperation(COMMENTS_RESTORE, {
|
|
1548
1583
|
path: `/api/comments/${encodePathSegment(commentId, "commentId")}/restore`,
|
|
1549
1584
|
...options
|
|
1550
1585
|
});
|
|
@@ -3056,7 +3091,7 @@ const POSTS_STATS = defineBuiltInOperation("posts.stats", (body) => pickArray(bo
|
|
|
3056
3091
|
const POSTS_CREATE = passthroughOperation("posts.create");
|
|
3057
3092
|
const POSTS_GET = passthroughOperation("posts.get");
|
|
3058
3093
|
const POSTS_UPDATE = passthroughOperation("posts.update");
|
|
3059
|
-
const POSTS_RESTORE =
|
|
3094
|
+
const POSTS_RESTORE = voidOperation("posts.restore");
|
|
3060
3095
|
const POSTS_LIKE = passthroughOperation("posts.like");
|
|
3061
3096
|
const POSTS_UNLIKE = passthroughOperation("posts.unlike");
|
|
3062
3097
|
const POSTS_REPOST = passthroughOperation("posts.repost");
|
|
@@ -3213,7 +3248,7 @@ var PostsResource = class extends BaseResource {
|
|
|
3213
3248
|
}
|
|
3214
3249
|
/** Восстанавливает удалённый пост. */
|
|
3215
3250
|
restore(postId, options = {}) {
|
|
3216
|
-
return this.
|
|
3251
|
+
return this.voidOperation(POSTS_RESTORE, {
|
|
3217
3252
|
path: `/api/posts/${encodePathSegment(postId, "postId")}/restore`,
|
|
3218
3253
|
...options
|
|
3219
3254
|
});
|
|
@@ -4684,10 +4719,6 @@ function createShopOrderAccessStorage(store, options = {}) {
|
|
|
4684
4719
|
clear: () => backend.delete(key)
|
|
4685
4720
|
};
|
|
4686
4721
|
}
|
|
4687
|
-
/** Создаёт независимое хранилище доступа к заказам в памяти. */
|
|
4688
|
-
function createMemoryShopOrderAccessStorage() {
|
|
4689
|
-
return createShopOrderAccessStorage(new MemoryKeyValueStore());
|
|
4690
|
-
}
|
|
4691
4722
|
//#endregion
|
|
4692
4723
|
//#region src/shop/feature.ts
|
|
4693
4724
|
const Operation = Object.freeze({
|
|
@@ -4742,7 +4773,7 @@ function createShopFeature(options = {}) {
|
|
|
4742
4773
|
}
|
|
4743
4774
|
},
|
|
4744
4775
|
setup(context) {
|
|
4745
|
-
const storage = options.storage ??
|
|
4776
|
+
const storage = options.storage ?? new MemoryShopOrderAccessStorage();
|
|
4746
4777
|
let pendingEmail = null;
|
|
4747
4778
|
const readSession = async () => {
|
|
4748
4779
|
const session = await storage.get();
|
|
@@ -5032,6 +5063,6 @@ function renderSpans(content, spans = [], options = {}) {
|
|
|
5032
5063
|
return result;
|
|
5033
5064
|
}
|
|
5034
5065
|
//#endregion
|
|
5035
|
-
export {
|
|
5066
|
+
export { utcStampToIso as A, AUDIO_MIME_TYPES as C, isBuilder as D, comment as E, mapPage as F, createFeatureHost as I, ExtensibleOperationCatalog as L, BaseResource as M, PaginationMode as N, createStatusFeature as O, Paginator as P, ALLOWED_MIME_TYPES as S, VIDEO_MIME_TYPES as T, poll as _, createShopOrderAccessStorage as a, parseHtml as b, ShopOrderStatus as c, isMyProfile as d, fromStream as f, post as g, report as h, MemoryShopOrderAccessStorage as i, NotificationsResource as j, toDate as k, ShopProductCategory as l, createResources as m, renderSpans as n, statusDays as o, fromUrl as p, createShopFeature as r, ShopConsentKind as s, SpanRenderFormat as t, ShopProductStatus as u, autoSpans as v, IMAGE_MIME_TYPES as w, parseMarkdown as x, markup as y };
|
|
5036
5067
|
|
|
5037
|
-
//# sourceMappingURL=render
|
|
5068
|
+
//# sourceMappingURL=render--ZXmYEf-.js.map
|