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.
Files changed (64) hide show
  1. package/README.md +4 -4
  2. package/dist/events/index.cjs +3 -4
  3. package/dist/events/index.d.cts +3 -3
  4. package/dist/events/index.d.ts +3 -3
  5. package/dist/events/index.js +4 -4
  6. package/dist/index.cjs +198 -39
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +11 -65
  9. package/dist/index.d.ts +11 -65
  10. package/dist/index.js +199 -39
  11. package/dist/index.js.map +1 -1
  12. package/dist/node/index.cjs +3 -3
  13. package/dist/node/index.js +3 -3
  14. package/dist/rest/index.cjs +4 -5
  15. package/dist/rest/index.d.cts +3 -3
  16. package/dist/rest/index.d.ts +3 -3
  17. package/dist/rest/index.js +5 -5
  18. package/dist/shared/{events-CqtkP65d.d.ts → events-BCn5LRnT.d.cts} +3 -5
  19. package/dist/shared/{events-C5wnTXPT.js → events-BIBO2Jif.js} +4 -4
  20. package/dist/shared/{events-C5wnTXPT.js.map → events-BIBO2Jif.js.map} +1 -1
  21. package/dist/shared/{events-FZfnEez0.cjs → events-BsRm_Fba.cjs} +3 -9
  22. package/dist/shared/{events-FZfnEez0.cjs.map → events-BsRm_Fba.cjs.map} +1 -1
  23. package/dist/shared/{events-DGAWlCaI.d.cts → events-t1uGgpkf.d.ts} +3 -5
  24. package/dist/shared/{multi-storage-SoW05uzO.js → multi-storage-C3Ngtop1.js} +13 -8
  25. package/dist/shared/multi-storage-C3Ngtop1.js.map +1 -0
  26. package/dist/shared/{multi-storage-CDKLa956.cjs → multi-storage-s-fPtjoy.cjs} +13 -8
  27. package/dist/shared/multi-storage-s-fPtjoy.cjs.map +1 -0
  28. package/dist/shared/{options-DOJYtoti.cjs → options-DjEtbVaf.cjs} +2 -2
  29. package/dist/shared/{options-DOJYtoti.cjs.map → options-DjEtbVaf.cjs.map} +1 -1
  30. package/dist/shared/{options-DhgGg7Ms.js → options-i4LrKfqx.js} +2 -2
  31. package/dist/shared/{options-DhgGg7Ms.js.map → options-i4LrKfqx.js.map} +1 -1
  32. package/dist/shared/{redact-Ba5iSVYZ.js → redact-DJV0XM3n.js} +40 -15
  33. package/dist/shared/redact-DJV0XM3n.js.map +1 -0
  34. package/dist/shared/{redact-BP00URmQ.cjs → redact-lAmck1Z6.cjs} +45 -14
  35. package/dist/shared/redact-lAmck1Z6.cjs.map +1 -0
  36. package/dist/shared/{render-hiWFh2s4.js → render--ZXmYEf-.js} +131 -100
  37. package/dist/shared/render--ZXmYEf-.js.map +1 -0
  38. package/dist/shared/{render-B4qis7Sb.d.ts → render-BdnBV-aT.d.ts} +112 -16
  39. package/dist/shared/{render-DDwy2Ame.d.cts → render-DA83gS0f.d.cts} +112 -16
  40. package/dist/shared/{render-Dqi8Owqk.cjs → render-DqVzx68r.cjs} +129 -104
  41. package/dist/shared/render-DqVzx68r.cjs.map +1 -0
  42. package/dist/shared/{storage-QNVxzpDB.cjs → storage-CZJZoaz9.cjs} +4 -2
  43. package/dist/shared/storage-CZJZoaz9.cjs.map +1 -0
  44. package/dist/shared/{storage-CfHKzVHf.js → storage-DiDe0PZM.js} +4 -2
  45. package/dist/shared/storage-DiDe0PZM.js.map +1 -0
  46. package/dist/shared/{url-XBsMdAcv.d.ts → url-Dbj6V6fk.d.cts} +21 -5
  47. package/dist/shared/{url-XBsMdAcv.d.cts → url-Dbj6V6fk.d.ts} +21 -5
  48. package/dist/shared/{url-Bsb3xE5U.cjs → url-Doc0XXW_.cjs} +274 -86
  49. package/dist/shared/url-Doc0XXW_.cjs.map +1 -0
  50. package/dist/shared/{url-DP33mp3s.js → url-i2f-X1hX.js} +274 -86
  51. package/dist/shared/url-i2f-X1hX.js.map +1 -0
  52. package/dist/web/index.cjs +1 -1
  53. package/dist/web/index.js +1 -1
  54. package/package.json +4 -4
  55. package/dist/shared/multi-storage-CDKLa956.cjs.map +0 -1
  56. package/dist/shared/multi-storage-SoW05uzO.js.map +0 -1
  57. package/dist/shared/redact-BP00URmQ.cjs.map +0 -1
  58. package/dist/shared/redact-Ba5iSVYZ.js.map +0 -1
  59. package/dist/shared/render-Dqi8Owqk.cjs.map +0 -1
  60. package/dist/shared/render-hiWFh2s4.js.map +0 -1
  61. package/dist/shared/storage-CfHKzVHf.js.map +0 -1
  62. package/dist/shared/storage-QNVxzpDB.cjs.map +0 -1
  63. package/dist/shared/url-Bsb3xE5U.cjs.map +0 -1
  64. 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) if (!options.map) return [];
278
- else return createNullObj();
279
- if (input.headers) if (typeof input.headers.getSetCookie === "function") input = input.headers.getSetCookie();
280
- else if (input.headers["set-cookie"]) input = input.headers["set-cookie"];
281
- else {
282
- var sch = input.headers[Object.keys(input.headers).find(function(key) {
283
- return key.toLowerCase() === "set-cookie";
284
- })];
285
- 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.");
286
- input = sch;
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-BP00URmQ.cjs.map
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-DP33mp3s.js";
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 isFile, d as encodePathSegment, r as redactErrorCause, v as createDeviceId, y as isBlob } from "./redact-Ba5iSVYZ.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-DhgGg7Ms.js";
5
- import { r as createKeyValueStore, t as MemoryKeyValueStore } from "./key-value-store-Bt2PSMxY.js";
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
- install(feature) {
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
- for (const service of feature.services ?? []) {
420
- const serviceName = requireName(service?.name, `Сервис feature «${name}»`);
421
- const owner = this.#serviceOwners.get(serviceName);
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) rollback.push(() => {
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
- if (typeof installation !== "object" || installation === null || !("api" in installation)) throw new ItdConfigError(`setup() feature «${name}» должен вернуть объект с полем api`);
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: [...rollback]
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
- for (const undo of rollback.reverse()) undo();
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 = passthroughOperation("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.http.execute(COMMENTS_RESTORE, {
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 = passthroughOperation("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.http.execute(POSTS_RESTORE, {
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 ?? createMemoryShopOrderAccessStorage();
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 { toDate as A, ALLOWED_MIME_TYPES as C, comment as D, VIDEO_MIME_TYPES as E, Paginator as F, mapPage as I, createFeatureHost as L, NotificationsResource as M, BaseResource as N, isBuilder as O, PaginationMode as P, ExtensibleOperationCatalog as R, parseMarkdown as S, IMAGE_MIME_TYPES as T, post as _, createMemoryShopOrderAccessStorage as a, markup as b, ShopConsentKind as c, ShopProductStatus as d, isMyProfile as f, report as g, createResources as h, MemoryShopOrderAccessStorage as i, utcStampToIso as j, createStatusFeature as k, ShopOrderStatus as l, fromUrl as m, renderSpans as n, createShopOrderAccessStorage as o, fromStream as p, createShopFeature as r, statusDays as s, SpanRenderFormat as t, ShopProductCategory as u, poll as v, AUDIO_MIME_TYPES as w, parseHtml as x, autoSpans as y };
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-hiWFh2s4.js.map
5068
+ //# sourceMappingURL=render--ZXmYEf-.js.map