itd-api 0.7.0 → 0.7.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 (90) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +540 -9806
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +280 -4981
  5. package/dist/index.d.ts +280 -4981
  6. package/dist/index.js +407 -9673
  7. package/dist/index.js.map +1 -1
  8. package/dist/{node.cjs → node/index.cjs} +16 -14
  9. package/dist/node/index.cjs.map +1 -0
  10. package/dist/{node.d.cts → node/index.d.cts} +4 -3
  11. package/dist/{node.d.ts → node/index.d.ts} +4 -3
  12. package/dist/{node.js → node/index.js} +5 -3
  13. package/dist/node/index.js.map +1 -0
  14. package/dist/realtime/index.cjs +165 -0
  15. package/dist/realtime/index.cjs.map +1 -0
  16. package/dist/realtime/index.d.cts +51 -0
  17. package/dist/realtime/index.d.ts +51 -0
  18. package/dist/realtime/index.js +120 -0
  19. package/dist/realtime/index.js.map +1 -0
  20. package/dist/rest/index.cjs +398 -0
  21. package/dist/rest/index.cjs.map +1 -0
  22. package/dist/rest/index.d.cts +146 -0
  23. package/dist/rest/index.d.ts +146 -0
  24. package/dist/rest/index.js +302 -0
  25. package/dist/rest/index.js.map +1 -0
  26. package/dist/shared/auth-provider-CG8oCQ9F.cjs +108 -0
  27. package/dist/shared/auth-provider-CG8oCQ9F.cjs.map +1 -0
  28. package/dist/shared/auth-provider-mYqxsSVa.js +91 -0
  29. package/dist/shared/auth-provider-mYqxsSVa.js.map +1 -0
  30. package/dist/shared/contracts-BoT7msmq.d.cts +84 -0
  31. package/dist/shared/contracts-BoT7msmq.d.ts +84 -0
  32. package/dist/{multi-storage-Bf84xiO8.cjs → shared/cookies-DZwFq6kr.cjs} +98 -429
  33. package/dist/shared/cookies-DZwFq6kr.cjs.map +1 -0
  34. package/dist/{multi-storage-BUZaLAPO.js → shared/cookies-tX2sNwxb.js} +99 -352
  35. package/dist/shared/cookies-tX2sNwxb.js.map +1 -0
  36. package/dist/{storage-IHdXw52v.js → shared/errors-Bhrd2fJd.js} +2 -229
  37. package/dist/shared/errors-Bhrd2fJd.js.map +1 -0
  38. package/dist/{storage-DnzZPS_9.cjs → shared/errors-DfU8M5eS.cjs} +1 -288
  39. package/dist/shared/errors-DfU8M5eS.cjs.map +1 -0
  40. package/dist/shared/multi-storage--yTEqiod.cjs +150 -0
  41. package/dist/shared/multi-storage--yTEqiod.cjs.map +1 -0
  42. package/dist/shared/multi-storage-CjAPB5Kq.d.cts +72 -0
  43. package/dist/shared/multi-storage-CkvTUC5m.js +121 -0
  44. package/dist/shared/multi-storage-CkvTUC5m.js.map +1 -0
  45. package/dist/shared/multi-storage-DccjD7Ww.d.ts +72 -0
  46. package/dist/shared/options-Dg5N3r1V.cjs +189 -0
  47. package/dist/shared/options-Dg5N3r1V.cjs.map +1 -0
  48. package/dist/shared/options-DtATYdLr.js +142 -0
  49. package/dist/shared/options-DtATYdLr.js.map +1 -0
  50. package/dist/shared/render-C6HRPs10.js +4289 -0
  51. package/dist/shared/render-C6HRPs10.js.map +1 -0
  52. package/dist/shared/render-CgwKdOzu.d.ts +2311 -0
  53. package/dist/shared/render-DO0F5YSm.d.cts +2311 -0
  54. package/dist/shared/render-mcuELiYi.cjs +4462 -0
  55. package/dist/shared/render-mcuELiYi.cjs.map +1 -0
  56. package/dist/shared/storage-BPJR_k4-.cjs +290 -0
  57. package/dist/shared/storage-BPJR_k4-.cjs.map +1 -0
  58. package/dist/{storage-BqMxs76Y.d.ts → shared/storage-C_eICCep.d.cts} +2 -2
  59. package/dist/{storage-BqMxs76Y.d.cts → shared/storage-C_eICCep.d.ts} +2 -2
  60. package/dist/shared/storage-D86edNCB.js +231 -0
  61. package/dist/shared/storage-D86edNCB.js.map +1 -0
  62. package/dist/shared/url-BaMCQpYH.cjs +4084 -0
  63. package/dist/shared/url-BaMCQpYH.cjs.map +1 -0
  64. package/dist/shared/url-DTfZ2toq.d.cts +2081 -0
  65. package/dist/shared/url-DTfZ2toq.d.ts +2081 -0
  66. package/dist/shared/url-IU0xN9wX.js +3713 -0
  67. package/dist/shared/url-IU0xN9wX.js.map +1 -0
  68. package/dist/shared/websocket-BLR8eVJV.js +1874 -0
  69. package/dist/shared/websocket-BLR8eVJV.js.map +1 -0
  70. package/dist/shared/websocket-C_eI4H2o.cjs +1945 -0
  71. package/dist/shared/websocket-C_eI4H2o.cjs.map +1 -0
  72. package/dist/shared/websocket-DF7XIMiX.d.cts +562 -0
  73. package/dist/shared/websocket-DYKBr8HF.d.ts +562 -0
  74. package/dist/{web.cjs → web/index.cjs} +4 -3
  75. package/dist/web/index.cjs.map +1 -0
  76. package/dist/{web.d.cts → web/index.d.cts} +2 -2
  77. package/dist/{web.d.ts → web/index.d.ts} +2 -2
  78. package/dist/{web.js → web/index.js} +3 -2
  79. package/dist/web/index.js.map +1 -0
  80. package/package.json +40 -12
  81. package/dist/multi-storage-BUZaLAPO.js.map +0 -1
  82. package/dist/multi-storage-BUoEoW8f.d.cts +0 -154
  83. package/dist/multi-storage-Bf84xiO8.cjs.map +0 -1
  84. package/dist/multi-storage-CQSlI_kn.d.ts +0 -154
  85. package/dist/node.cjs.map +0 -1
  86. package/dist/node.js.map +0 -1
  87. package/dist/storage-DnzZPS_9.cjs.map +0 -1
  88. package/dist/storage-IHdXw52v.js.map +0 -1
  89. package/dist/web.cjs.map +0 -1
  90. package/dist/web.js.map +0 -1
@@ -0,0 +1,120 @@
1
+ import { L as pickNumber, N as createClientRuntime, T as ITD_CATALOG, Z as LIBRARY_VERSION, _ as RealtimeStatus, ct as installAsyncDisposeFallback, g as NotificationType, n as formatNotificationText, o as canonicalNotificationType, q as DEFAULT_BASE_URL, r as normalizeNotification, s as isKnownNotificationType, st as systemClock, t as resolveNotificationUrl, tt as RuntimeMode } from "../shared/url-IU0xN9wX.js";
2
+ import { A as isItdStateError, C as isItdError, O as isItdRateLimitError, _ as ItdStateError, a as ItdConfigError, b as isItdApiError, c as ItdErrorKind, d as ItdForbiddenError, f as ItdNetworkError, g as ItdServerError, h as ItdRateLimitError, i as ItdAuthError, n as ItdApiError, p as ItdNotFoundError, r as ItdApiErrorKind, s as ItdError, t as ItdAbortError, v as ItdTimeoutError, x as isItdAuthError, y as ItdValidationError } from "../shared/errors-Bhrd2fJd.js";
3
+ import { a as RealtimeTransportKind, c as RealtimeUpdateType, i as ItdRealtime, l as UnauthorizedStreamError, n as RealtimeComposer, o as setRealtimeConnectGuard, r as RealtimeRouter, s as RealtimeUpdateOrigin, t as WebSocketTransport, u as runRealtimeMiddleware } from "../shared/websocket-BLR8eVJV.js";
4
+ import { n as bearerToken, r as tokenProvider, t as anonymousAuth } from "../shared/auth-provider-mYqxsSVa.js";
5
+ //#region src/realtime/client.ts
6
+ /**
7
+ * Поток уведомлений с собственным конвейером запросов.
8
+ *
9
+ * Тот же {@link ItdRealtime}, что отдаёт `itd.realtime()`, но собранный без полного клиента:
10
+ * ресурсы, билдеры и сессия сюда не входят. Нужен приложениям, которым от API нужны только
11
+ * события, — виджетам, счётчикам непрочитанного, фоновым слушателям.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { createRealtimeClient } from 'itd-api/realtime';
16
+ *
17
+ * await using stream = createRealtimeClient({ auth: token });
18
+ * stream.on('notification', ({ notification }) => console.log(notification.type));
19
+ * await stream.connect();
20
+ * ```
21
+ */
22
+ var ItdRealtimeClient = class ItdRealtimeClient extends ItdRealtime {
23
+ #runtime;
24
+ /** Общий результат терминальной очистки для идемпотентных повторных вызовов. */
25
+ #disposePromise;
26
+ #disposed = false;
27
+ constructor(options = {}) {
28
+ const runtime = createClientRuntime(options, {
29
+ catalog: ITD_CATALOG,
30
+ auth: () => resolveAuthProvider(options.auth)
31
+ });
32
+ super(realtimeDeps(runtime), options);
33
+ this.#runtime = runtime;
34
+ setRealtimeConnectGuard(this, () => {
35
+ if (!this.#disposed) return;
36
+ throw new ItdStateError("Поток уже окончательно освобождён через dispose(); нельзя подключить его снова. Создайте новый");
37
+ });
38
+ }
39
+ /**
40
+ * Окончательно освобождает поток и его конвейер: отключает соединение, дожидается
41
+ * обработчиков и останавливает очередь запросов.
42
+ *
43
+ * Повторные вызовы возвращают тот же результат очистки.
44
+ */
45
+ dispose() {
46
+ if (this.#disposePromise) return this.#disposePromise;
47
+ this.#disposed = true;
48
+ this.#disposePromise = this.#dispose();
49
+ return this.#disposePromise;
50
+ }
51
+ async #dispose() {
52
+ const errors = [];
53
+ this.disconnect();
54
+ try {
55
+ await this.drain();
56
+ } catch (error) {
57
+ errors.push(error);
58
+ }
59
+ try {
60
+ this.#runtime.close();
61
+ await this.#runtime.dispose();
62
+ } catch (error) {
63
+ errors.push(error);
64
+ }
65
+ if (errors.length > 0) throw new AggregateError(errors, "Не удалось освободить поток");
66
+ }
67
+ /** Позволяет использовать поток с `await using`. */
68
+ [Symbol.asyncDispose]() {
69
+ return this.dispose();
70
+ }
71
+ static {
72
+ installAsyncDisposeFallback(ItdRealtimeClient);
73
+ }
74
+ };
75
+ /** Приводит опцию `auth` к провайдеру конвейера. */
76
+ function resolveAuthProvider(auth) {
77
+ if (auth === void 0) return anonymousAuth();
78
+ return typeof auth === "string" ? bearerToken(auth) : auth;
79
+ }
80
+ /**
81
+ * Связывает поток с собранным конвейером.
82
+ *
83
+ * Начальный счётчик непрочитанных берётся той же операцией, что и при опросе
84
+ * (`realtime.poll.unread`): ресурс уведомлений потоку для этого не нужен.
85
+ */
86
+ function realtimeDeps(runtime) {
87
+ const request = ({ operationId, path, query, signal }) => runtime.http.operation(operationId, {
88
+ path,
89
+ query,
90
+ signal
91
+ });
92
+ return {
93
+ baseUrl: runtime.config.baseUrl,
94
+ fetch: runtime.config.fetch,
95
+ clock: runtime.config.clock,
96
+ logger: runtime.config.logger,
97
+ request,
98
+ baseHeaders: (url) => runtime.platformHeaders(url),
99
+ getToken: () => runtime.auth.token(),
100
+ refresh: () => runtime.auth.recover(),
101
+ fetchUnreadCount: async () => {
102
+ const payload = await request({
103
+ operationId: "realtime.poll.unread",
104
+ path: "/api/notifications/count"
105
+ });
106
+ return pickNumber(payload, "count", 0);
107
+ }
108
+ };
109
+ }
110
+ /**
111
+ * Создаёт поток уведомлений с собственным конвейером. Равнозначно конструктору
112
+ * {@link ItdRealtimeClient}.
113
+ */
114
+ function createRealtimeClient(options = {}) {
115
+ return new ItdRealtimeClient(options);
116
+ }
117
+ //#endregion
118
+ export { DEFAULT_BASE_URL, ItdAbortError, ItdApiError, ItdApiErrorKind, ItdAuthError, ItdConfigError, ItdError, ItdErrorKind, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdRateLimitError, ItdRealtime, ItdRealtimeClient, ItdServerError, ItdStateError, ItdTimeoutError, ItdValidationError, LIBRARY_VERSION, NotificationType, RealtimeComposer, RealtimeRouter, RealtimeStatus, RealtimeTransportKind, RealtimeUpdateOrigin, RealtimeUpdateType, RuntimeMode, UnauthorizedStreamError, WebSocketTransport, anonymousAuth, bearerToken, canonicalNotificationType, createRealtimeClient, formatNotificationText, isItdApiError, isItdAuthError, isItdError, isItdRateLimitError, isItdStateError, isKnownNotificationType, normalizeNotification, resolveNotificationUrl, runRealtimeMiddleware, systemClock, tokenProvider };
119
+
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["#runtime","#disposed","#disposePromise","#dispose"],"sources":["../../src/realtime/client.ts"],"sourcesContent":["import { installAsyncDisposeFallback } from '../core/async-dispose.js';\nimport { type AuthProvider, anonymousAuth, bearerToken } from '../core/auth-provider.js';\nimport { ItdStateError } from '../core/errors.js';\nimport { type ClientRuntime, createClientRuntime } from '../core/execution/client-runtime.js';\nimport type { RuntimeOptions } from '../core/options.js';\nimport { pickNumber } from '../core/unwrap.js';\nimport { ITD_CATALOG } from '../domain/catalog.js';\nimport {\n ItdRealtime,\n type RealtimeDeps,\n type RealtimeOptions,\n setRealtimeConnectGuard,\n} from './stream.js';\nimport type { RealtimeContext } from './updates.js';\n\n/** Опции конструктора {@link ItdRealtimeClient}. */\nexport interface RealtimeClientOptions<C extends RealtimeContext = RealtimeContext>\n extends RuntimeOptions,\n RealtimeOptions<C> {\n /**\n * Авторизация. Строка — сокращение для {@link bearerToken}.\n *\n * Без неё поток идёт анонимно. Токен считается готовым: продлевать его клиент не умеет,\n * а на отказ авторизации переподключение спрашивает токен заново. Сессия, которая входит\n * по паролю и продлевает себя сама, живёт в полном `ItdClient`.\n */\n auth?: string | AuthProvider | undefined;\n}\n\n/**\n * Поток уведомлений с собственным конвейером запросов.\n *\n * Тот же {@link ItdRealtime}, что отдаёт `itd.realtime()`, но собранный без полного клиента:\n * ресурсы, билдеры и сессия сюда не входят. Нужен приложениям, которым от API нужны только\n * события, — виджетам, счётчикам непрочитанного, фоновым слушателям.\n *\n * @example\n * ```ts\n * import { createRealtimeClient } from 'itd-api/realtime';\n *\n * await using stream = createRealtimeClient({ auth: token });\n * stream.on('notification', ({ notification }) => console.log(notification.type));\n * await stream.connect();\n * ```\n */\nexport class ItdRealtimeClient<C extends RealtimeContext = RealtimeContext> extends ItdRealtime<C> {\n readonly #runtime: ClientRuntime;\n /** Общий результат терминальной очистки для идемпотентных повторных вызовов. */\n #disposePromise: Promise<void> | undefined;\n #disposed = false;\n\n constructor(options: RealtimeClientOptions<C> = {}) {\n const runtime = createClientRuntime(options, {\n catalog: ITD_CATALOG,\n auth: () => resolveAuthProvider(options.auth),\n });\n\n super(realtimeDeps(runtime), options);\n this.#runtime = runtime;\n\n setRealtimeConnectGuard<C>(this, () => {\n if (!this.#disposed) return;\n throw new ItdStateError(\n 'Поток уже окончательно освобождён через dispose(); нельзя подключить его снова. ' +\n 'Создайте новый',\n );\n });\n }\n\n /**\n * Окончательно освобождает поток и его конвейер: отключает соединение, дожидается\n * обработчиков и останавливает очередь запросов.\n *\n * Повторные вызовы возвращают тот же результат очистки.\n */\n dispose(): Promise<void> {\n if (this.#disposePromise) return this.#disposePromise;\n this.#disposed = true;\n this.#disposePromise = this.#dispose();\n return this.#disposePromise;\n }\n\n async #dispose(): Promise<void> {\n const errors: unknown[] = [];\n this.disconnect();\n try {\n await this.drain();\n } catch (error) {\n errors.push(error);\n }\n try {\n this.#runtime.close();\n await this.#runtime.dispose();\n } catch (error) {\n errors.push(error);\n }\n if (errors.length > 0) throw new AggregateError(errors, 'Не удалось освободить поток');\n }\n\n /** Позволяет использовать поток с `await using`. */\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n\n static {\n installAsyncDisposeFallback(ItdRealtimeClient);\n }\n}\n\n/** Приводит опцию `auth` к провайдеру конвейера. */\nfunction resolveAuthProvider(auth: RealtimeClientOptions['auth']): AuthProvider {\n if (auth === undefined) return anonymousAuth();\n return typeof auth === 'string' ? bearerToken(auth) : auth;\n}\n\n/**\n * Связывает поток с собранным конвейером.\n *\n * Начальный счётчик непрочитанных берётся той же операцией, что и при опросе\n * (`realtime.poll.unread`): ресурс уведомлений потоку для этого не нужен.\n */\nfunction realtimeDeps(runtime: ClientRuntime): RealtimeDeps {\n const request: NonNullable<RealtimeDeps['request']> = ({ operationId, path, query, signal }) =>\n runtime.http.operation(operationId, { path, query, signal });\n\n return {\n baseUrl: runtime.config.baseUrl,\n fetch: runtime.config.fetch,\n clock: runtime.config.clock,\n logger: runtime.config.logger,\n request,\n baseHeaders: (url) => runtime.platformHeaders(url),\n getToken: () => runtime.auth.token(),\n refresh: () => runtime.auth.recover(),\n fetchUnreadCount: async () => {\n const payload = await request({\n operationId: 'realtime.poll.unread',\n path: '/api/notifications/count',\n });\n return pickNumber(payload, 'count', 0);\n },\n };\n}\n\n/**\n * Создаёт поток уведомлений с собственным конвейером. Равнозначно конструктору\n * {@link ItdRealtimeClient}.\n */\nexport function createRealtimeClient<C extends RealtimeContext = RealtimeContext>(\n options: RealtimeClientOptions<C> = {},\n): ItdRealtimeClient<C> {\n return new ItdRealtimeClient<C>(options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,oBAAb,MAAa,0BAAuE,YAAe;CACjG;;CAEA;CACA,YAAY;CAEZ,YAAY,UAAoC,CAAC,GAAG;EAClD,MAAM,UAAU,oBAAoB,SAAS;GAC3C,SAAS;GACT,YAAY,oBAAoB,QAAQ,IAAI;EAC9C,CAAC;EAED,MAAM,aAAa,OAAO,GAAG,OAAO;EACpC,KAAKA,WAAW;EAEhB,wBAA2B,YAAY;GACrC,IAAI,CAAC,KAAKC,WAAW;GACrB,MAAM,IAAI,cACR,gGAEF;EACF,CAAC;CACH;;;;;;;CAQA,UAAyB;EACvB,IAAI,KAAKC,iBAAiB,OAAO,KAAKA;EACtC,KAAKD,YAAY;EACjB,KAAKC,kBAAkB,KAAKC,SAAS;EACrC,OAAO,KAAKD;CACd;CAEA,MAAMC,WAA0B;EAC9B,MAAM,SAAoB,CAAC;EAC3B,KAAK,WAAW;EAChB,IAAI;GACF,MAAM,KAAK,MAAM;EACnB,SAAS,OAAO;GACd,OAAO,KAAK,KAAK;EACnB;EACA,IAAI;GACF,KAAKH,SAAS,MAAM;GACpB,MAAM,KAAKA,SAAS,QAAQ;EAC9B,SAAS,OAAO;GACd,OAAO,KAAK,KAAK;EACnB;EACA,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,eAAe,QAAQ,6BAA6B;CACvF;;CAGA,CAAC,OAAO,gBAA+B;EACrC,OAAO,KAAK,QAAQ;CACtB;CAEA;EACE,4BAA4B,iBAAiB;CAC/C;AACF;;AAGA,SAAS,oBAAoB,MAAmD;CAC9E,IAAI,SAAS,KAAA,GAAW,OAAO,cAAc;CAC7C,OAAO,OAAO,SAAS,WAAW,YAAY,IAAI,IAAI;AACxD;;;;;;;AAQA,SAAS,aAAa,SAAsC;CAC1D,MAAM,WAAiD,EAAE,aAAa,MAAM,OAAO,aACjF,QAAQ,KAAK,UAAU,aAAa;EAAE;EAAM;EAAO;CAAO,CAAC;CAE7D,OAAO;EACL,SAAS,QAAQ,OAAO;EACxB,OAAO,QAAQ,OAAO;EACtB,OAAO,QAAQ,OAAO;EACtB,QAAQ,QAAQ,OAAO;EACvB;EACA,cAAc,QAAQ,QAAQ,gBAAgB,GAAG;EACjD,gBAAgB,QAAQ,KAAK,MAAM;EACnC,eAAe,QAAQ,KAAK,QAAQ;EACpC,kBAAkB,YAAY;GAC5B,MAAM,UAAU,MAAM,QAAQ;IAC5B,aAAa;IACb,MAAM;GACR,CAAC;GACD,OAAO,WAAW,SAAS,SAAS,CAAC;EACvC;CACF;AACF;;;;;AAMA,SAAgB,qBACd,UAAoC,CAAC,GACf;CACtB,OAAO,IAAI,kBAAqB,OAAO;AACzC"}
@@ -0,0 +1,398 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_url = require("../shared/url-BaMCQpYH.cjs");
3
+ const require_errors = require("../shared/errors-DfU8M5eS.cjs");
4
+ const require_render = require("../shared/render-mcuELiYi.cjs");
5
+ const require_options = require("../shared/options-Dg5N3r1V.cjs");
6
+ const require_auth_provider = require("../shared/auth-provider-CG8oCQ9F.cjs");
7
+ //#region src/rest/client.ts
8
+ /**
9
+ * Минимальный клиент REST API итд.com.
10
+ *
11
+ * Тот же конвейер запросов, что и у полного клиента, — с повторами, очередью, плагинами
12
+ * и типизированными ошибками, — но без сессии, потока событий и нескольких аккаунтов.
13
+ * Нужен там, где токен уже есть, а размер поставки важен: серверные интеграции, воркеры,
14
+ * браузерные приложения.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { createRestClient } from 'itd-api/rest';
19
+ *
20
+ * const api = createRestClient({ auth: process.env.ITD_TOKEN });
21
+ * const feed = await api.posts.list({ tab: 'popular' });
22
+ * ```
23
+ */
24
+ var ItdRestClient = class ItdRestClient {
25
+ #runtime;
26
+ #features;
27
+ #resources;
28
+ /** Общий результат терминальной очистки для идемпотентных повторных вызовов. */
29
+ #disposePromise;
30
+ #disposed = false;
31
+ /** Профили, подписки, блокировки, приватность. */
32
+ get users() {
33
+ return this.#resources.users;
34
+ }
35
+ /** Лента, публикация, реакции, репосты, комментарии к постам. */
36
+ get posts() {
37
+ return this.#resources.posts;
38
+ }
39
+ /** Ответы на комментарии и действия над ними. */
40
+ get comments() {
41
+ return this.#resources.comments;
42
+ }
43
+ /** Загрузка файлов и медиа. */
44
+ get files() {
45
+ return this.#resources.files;
46
+ }
47
+ /** Уведомления: список, счётчик, отметки о прочтении, настройки. */
48
+ get notifications() {
49
+ return this.#resources.notifications;
50
+ }
51
+ /** Хэштеги и посты по ним. */
52
+ get hashtags() {
53
+ return this.#resources.hashtags;
54
+ }
55
+ /** Глобальный поиск по пользователям и хэштегам. */
56
+ get search() {
57
+ return this.#resources.search;
58
+ }
59
+ /** Жалобы на контент и пользователей. */
60
+ get reports() {
61
+ return this.#resources.reports;
62
+ }
63
+ /** Верификация профиля. */
64
+ get verification() {
65
+ return this.#resources.verification;
66
+ }
67
+ /** Подписка и способы оплаты. */
68
+ get subscription() {
69
+ return this.#resources.subscription;
70
+ }
71
+ /** Сведения о платформе: версии приложений, изменения, анонсы, баннер события. */
72
+ get platform() {
73
+ return this.#resources.platform;
74
+ }
75
+ /** Телеметрия просмотров. */
76
+ get telemetry() {
77
+ return this.#resources.telemetry;
78
+ }
79
+ constructor(options = {}) {
80
+ const { auth, ...runtimeOptions } = options;
81
+ const catalog = new require_render.ExtensibleOperationCatalog(require_url.ITD_CATALOG);
82
+ this.#runtime = require_url.createClientRuntime(runtimeOptions, {
83
+ catalog,
84
+ assertActive: (action) => this.#assertActive(action),
85
+ auth: () => resolveAuthProvider(auth)
86
+ });
87
+ this.#features = new require_render.FeatureRegistry({
88
+ http: this.#runtime.http,
89
+ services: this.#runtime.services,
90
+ serviceOverrides: this.#runtime.config.services,
91
+ catalog,
92
+ baseUrl: this.#runtime.config.baseUrl,
93
+ clock: this.#runtime.config.clock,
94
+ logger: this.#runtime.config.logger,
95
+ assertActive: (action) => this.#assertActive(action),
96
+ registerBucket: (name, definition) => this.#runtime.registerRateLimitBucket(name, definition)
97
+ });
98
+ const status = this.#features.install(require_render.createStatusFeature());
99
+ this.#resources = require_render.createResources({
100
+ http: this.#runtime.http,
101
+ fetch: this.#runtime.config.fetch,
102
+ status
103
+ });
104
+ }
105
+ #assertActive(action) {
106
+ if (!this.#disposed) return;
107
+ throw new require_errors.ItdStateError(`Клиент уже окончательно освобождён через dispose(); нельзя ${action}. Создайте новый клиент`);
108
+ }
109
+ /** Базовый URL, к которому обращается клиент. */
110
+ get baseUrl() {
111
+ return this.#runtime.config.baseUrl;
112
+ }
113
+ /**
114
+ * Выполняет произвольный запрос к API.
115
+ *
116
+ * Запасной путь для случаев, когда нужного метода ещё нет или ответ сервера разошёлся
117
+ * с документацией. Проходит через ту же авторизацию, очередь и обработку ошибок.
118
+ *
119
+ * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
120
+ */
121
+ request(options) {
122
+ return this.#runtime.http.request({
123
+ ...options,
124
+ operationId: options.operationId ?? "raw"
125
+ });
126
+ }
127
+ /**
128
+ * Остаток серверных лимитов по бакетам, через которые уже проходили запросы.
129
+ *
130
+ * Пустой массив при `rateLimit: false`.
131
+ */
132
+ rateLimitState() {
133
+ return this.#runtime.rateLimitState();
134
+ }
135
+ /** Устанавливает REST feature поверх общего request pipeline клиента. */
136
+ install(feature) {
137
+ return this.#features.install(feature);
138
+ }
139
+ /** Устанавливает REST feature и публикует его API как readonly-свойство клиента. */
140
+ withFeature(key, feature) {
141
+ this.#assertActive("установить feature");
142
+ if (typeof key !== "string" || key.trim() === "" || key !== key.trim()) throw new require_errors.ItdConfigError("Свойство feature должно иметь непустое имя без краевых пробелов");
143
+ if (key === "then" || key in this) throw new require_errors.ItdConfigError(`Свойство клиента «${key}» уже занято или зарезервировано`);
144
+ if (!Object.isExtensible(this)) throw new require_errors.ItdConfigError("Нельзя опубликовать feature на нерасширяемом клиенте");
145
+ const api = this.install(feature);
146
+ Object.defineProperty(this, key, {
147
+ value: api,
148
+ enumerable: true,
149
+ configurable: false,
150
+ writable: false
151
+ });
152
+ return this;
153
+ }
154
+ /** Имена установленных feature в порядке установки. */
155
+ featureNames() {
156
+ return this.#features.names();
157
+ }
158
+ /** Установлен ли feature с таким именем. */
159
+ hasFeature(name) {
160
+ return this.#features.has(name);
161
+ }
162
+ /**
163
+ * Подключает плагин.
164
+ *
165
+ * Сессионная идентичность плагину не передаётся: у клиента с готовым токеном её нет.
166
+ * Плагинам, которые изолируют состояние по аккаунту, нужен полный `ItdClient`.
167
+ *
168
+ * @throws {ItdConfigError} если плагин задан неверно или уже подключён
169
+ * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
170
+ */
171
+ use(plugin) {
172
+ this.#assertActive("подключить плагин");
173
+ this.#runtime.plugins.add(plugin, {
174
+ baseUrl: this.#runtime.config.baseUrl,
175
+ logger: this.#runtime.config.logger
176
+ });
177
+ return this;
178
+ }
179
+ /**
180
+ * Отключает плагин и освобождает заведённые им ресурсы.
181
+ *
182
+ * @returns `false`, если такого плагина не было
183
+ * @throws {ItdConfigError} если от плагина зависит другой подключённый плагин
184
+ */
185
+ unuse(name) {
186
+ return this.#runtime.plugins.remove(name);
187
+ }
188
+ /** Имена подключённых плагинов в фактическом порядке выполнения обёрток. */
189
+ pluginNames() {
190
+ return this.#runtime.plugins.names();
191
+ }
192
+ /** Подключён ли плагин с таким именем. */
193
+ hasPlugin(name) {
194
+ return this.#runtime.plugins.has(name);
195
+ }
196
+ /**
197
+ * Регистрирует сервис платформы — домен, отличный от основного.
198
+ *
199
+ * @throws {ItdConfigError} если определение неверно или имя уже занято
200
+ * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
201
+ */
202
+ defineService(definition) {
203
+ this.#assertActive("зарегистрировать сервис");
204
+ this.#runtime.services.define(definition);
205
+ return this;
206
+ }
207
+ /**
208
+ * Отправляет открытые накопители {@link telemetry} и останавливает очередь запросов.
209
+ *
210
+ * После вызова клиентом можно пользоваться снова. Терминальное освобождение —
211
+ * это {@link dispose}.
212
+ */
213
+ async close() {
214
+ const errors = [];
215
+ try {
216
+ try {
217
+ await this.#features.close();
218
+ } catch (error) {
219
+ errors.push(error);
220
+ }
221
+ try {
222
+ await this.#resources.closeTelemetry(false);
223
+ } catch (error) {
224
+ errors.push(error);
225
+ }
226
+ } finally {
227
+ this.#runtime.close();
228
+ }
229
+ if (errors.length === 1) throw errors[0];
230
+ if (errors.length > 1) throw new AggregateError(errors, "Не удалось закрыть клиент");
231
+ }
232
+ /**
233
+ * Окончательно освобождает клиент: выполняет {@link close}, отменяет незавершённые
234
+ * запросы и отключает все плагины.
235
+ *
236
+ * Терминальное состояние устанавливается сразу при первом вызове; повторные вызовы
237
+ * возвращают тот же результат очистки.
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * await using api = createRestClient({ auth: token });
242
+ * ```
243
+ */
244
+ dispose() {
245
+ if (this.#disposePromise) return this.#disposePromise;
246
+ this.#disposed = true;
247
+ this.#disposePromise = this.#dispose();
248
+ return this.#disposePromise;
249
+ }
250
+ async #dispose() {
251
+ const errors = [];
252
+ this.#resources.prepareTelemetryClose();
253
+ try {
254
+ await this.#features.close();
255
+ } catch (error) {
256
+ errors.push(error);
257
+ }
258
+ try {
259
+ await this.#resources.closeTelemetry(true);
260
+ } catch (error) {
261
+ errors.push(error);
262
+ }
263
+ try {
264
+ await this.#features.dispose();
265
+ } catch (error) {
266
+ errors.push(error);
267
+ }
268
+ try {
269
+ this.#runtime.close();
270
+ await this.#runtime.dispose();
271
+ } catch (error) {
272
+ errors.push(error);
273
+ }
274
+ if (errors.length > 0) throw new AggregateError(errors, "Не удалось освободить клиент");
275
+ }
276
+ /** Позволяет использовать клиент с `await using`. */
277
+ [Symbol.asyncDispose]() {
278
+ return this.dispose();
279
+ }
280
+ static {
281
+ require_url.installAsyncDisposeFallback(ItdRestClient);
282
+ }
283
+ };
284
+ /** Приводит опцию `auth` к провайдеру конвейера. */
285
+ function resolveAuthProvider(auth) {
286
+ if (auth === void 0) return require_auth_provider.anonymousAuth();
287
+ return typeof auth === "string" ? require_auth_provider.bearerToken(auth) : auth;
288
+ }
289
+ /**
290
+ * Создаёт минимальный клиент REST API. Равнозначно конструктору {@link ItdRestClient}.
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * const api = createRestClient({ auth: token, rateLimit: { concurrency: 4 } });
295
+ * ```
296
+ */
297
+ function createRestClient(options = {}) {
298
+ return new ItdRestClient(options);
299
+ }
300
+ //#endregion
301
+ exports.ALLOWED_MIME_TYPES = require_render.ALLOWED_MIME_TYPES;
302
+ exports.AUDIO_MIME_TYPES = require_render.AUDIO_MIME_TYPES;
303
+ exports.AccessType = require_url.AccessType;
304
+ exports.AttachmentType = require_url.AttachmentType;
305
+ exports.BUCKET_LIMITS = require_url.BUCKET_LIMITS;
306
+ exports.CommentSort = require_url.CommentSort;
307
+ exports.DEFAULT_BASE_URL = require_url.DEFAULT_BASE_URL;
308
+ exports.DEFAULT_RATE_LIMIT_BUCKET = require_url.DEFAULT_RATE_LIMIT_BUCKET;
309
+ exports.FeedTab = require_url.FeedTab;
310
+ exports.FileTransferMode = require_options.FileTransferMode;
311
+ exports.IMAGE_MIME_TYPES = require_render.IMAGE_MIME_TYPES;
312
+ exports.IncidentKind = require_url.IncidentKind;
313
+ exports.InteractionType = require_url.InteractionType;
314
+ exports.ItdAbortError = require_errors.ItdAbortError;
315
+ exports.ItdApiError = require_errors.ItdApiError;
316
+ exports.ItdApiErrorKind = require_errors.ItdApiErrorKind;
317
+ exports.ItdAuthError = require_errors.ItdAuthError;
318
+ exports.ItdConfigError = require_errors.ItdConfigError;
319
+ exports.ItdConflictError = require_errors.ItdConflictError;
320
+ exports.ItdError = require_errors.ItdError;
321
+ exports.ItdErrorCode = require_url.ItdErrorCode;
322
+ exports.ItdErrorKind = require_errors.ItdErrorKind;
323
+ exports.ItdFileError = require_errors.ItdFileError;
324
+ exports.ItdFileErrorReason = require_errors.ItdFileErrorReason;
325
+ exports.ItdForbiddenError = require_errors.ItdForbiddenError;
326
+ exports.ItdNetworkError = require_errors.ItdNetworkError;
327
+ exports.ItdNotFoundError = require_errors.ItdNotFoundError;
328
+ exports.ItdPhoneVerificationError = require_errors.ItdPhoneVerificationError;
329
+ exports.ItdRateLimitError = require_errors.ItdRateLimitError;
330
+ exports.ItdRestClient = ItdRestClient;
331
+ exports.ItdServerError = require_errors.ItdServerError;
332
+ exports.ItdStateError = require_errors.ItdStateError;
333
+ exports.ItdTimeoutError = require_errors.ItdTimeoutError;
334
+ exports.ItdValidationError = require_errors.ItdValidationError;
335
+ exports.LIBRARY_VERSION = require_url.LIBRARY_VERSION;
336
+ exports.LikesVisibility = require_url.LikesVisibility;
337
+ exports.NotificationType = require_url.NotificationType;
338
+ exports.OPERATIONS = require_url.OPERATIONS;
339
+ exports.PaginationMode = require_render.PaginationMode;
340
+ exports.Paginator = require_render.Paginator;
341
+ exports.RateLimitPacing = require_url.RateLimitPacing;
342
+ exports.ReportReason = require_url.ReportReason;
343
+ exports.ReportTargetType = require_url.ReportTargetType;
344
+ exports.RetrySafety = require_url.RetrySafety;
345
+ exports.RuntimeMode = require_url.RuntimeMode;
346
+ exports.STATUS_SERVICE = require_url.STATUS_SERVICE;
347
+ exports.ServiceState = require_url.ServiceState;
348
+ exports.SpanRenderFormat = require_render.SpanRenderFormat;
349
+ exports.SpanType = require_url.SpanType;
350
+ exports.VIDEO_MIME_TYPES = require_render.VIDEO_MIME_TYPES;
351
+ exports.ViewReason = require_url.ViewReason;
352
+ exports.ViewSource = require_url.ViewSource;
353
+ exports.WallAccess = require_url.WallAccess;
354
+ exports.anonymousAuth = require_auth_provider.anonymousAuth;
355
+ exports.autoSpans = require_render.autoSpans;
356
+ exports.bearerToken = require_auth_provider.bearerToken;
357
+ exports.canonicalNotificationType = require_url.canonicalNotificationType;
358
+ exports.comment = require_render.comment;
359
+ exports.createRestClient = createRestClient;
360
+ exports.formatNotificationText = require_url.formatNotificationText;
361
+ exports.fromStream = require_render.fromStream;
362
+ exports.fromUrl = require_render.fromUrl;
363
+ exports.isBuilder = require_render.isBuilder;
364
+ exports.isBuiltInOperationId = require_url.isBuiltInOperationId;
365
+ exports.isItdApiError = require_errors.isItdApiError;
366
+ exports.isItdAuthError = require_errors.isItdAuthError;
367
+ exports.isItdConflictError = require_errors.isItdConflictError;
368
+ exports.isItdError = require_errors.isItdError;
369
+ exports.isItdFileError = require_errors.isItdFileError;
370
+ exports.isItdForbiddenError = require_errors.isItdForbiddenError;
371
+ exports.isItdNotFoundError = require_errors.isItdNotFoundError;
372
+ exports.isItdPhoneVerificationError = require_errors.isItdPhoneVerificationError;
373
+ exports.isItdRateLimitError = require_errors.isItdRateLimitError;
374
+ exports.isItdServerError = require_errors.isItdServerError;
375
+ exports.isItdStateError = require_errors.isItdStateError;
376
+ exports.isItdValidationError = require_errors.isItdValidationError;
377
+ exports.isKnownNotificationType = require_url.isKnownNotificationType;
378
+ exports.isMyProfile = require_render.isMyProfile;
379
+ exports.mapPage = require_render.mapPage;
380
+ exports.markup = require_render.markup;
381
+ exports.normalizeNotification = require_url.normalizeNotification;
382
+ exports.operationBucket = require_url.operationBucket;
383
+ exports.operationMethod = require_url.operationMethod;
384
+ exports.operationRetrySafety = require_url.operationRetrySafety;
385
+ exports.parseHtml = require_render.parseHtml;
386
+ exports.parseMarkdown = require_render.parseMarkdown;
387
+ exports.poll = require_render.poll;
388
+ exports.post = require_render.post;
389
+ exports.renderSpans = require_render.renderSpans;
390
+ exports.report = require_render.report;
391
+ exports.resolveNotificationUrl = require_url.resolveNotificationUrl;
392
+ exports.statusDays = require_render.statusDays;
393
+ exports.systemClock = require_url.systemClock;
394
+ exports.toDate = require_render.toDate;
395
+ exports.tokenProvider = require_auth_provider.tokenProvider;
396
+ exports.utcStampToIso = require_render.utcStampToIso;
397
+
398
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["#runtime","#features","#resources","ExtensibleOperationCatalog","ITD_CATALOG","createClientRuntime","#assertActive","FeatureRegistry","createStatusFeature","createResources","#disposed","ItdStateError","ItdConfigError","#disposePromise","#dispose","anonymousAuth","bearerToken"],"sources":["../../src/rest/client.ts"],"sourcesContent":["import { installAsyncDisposeFallback } from '../core/async-dispose.js';\nimport { type AuthProvider, anonymousAuth, bearerToken } from '../core/auth-provider.js';\nimport { ItdConfigError, ItdStateError } from '../core/errors.js';\nimport { type ClientRuntime, createClientRuntime } from '../core/execution/client-runtime.js';\nimport { ExtensibleOperationCatalog } from '../core/feature-catalog.js';\nimport { type ClientFeature, FeatureRegistry } from '../core/features.js';\nimport type { RawRequestOptions, RuntimeOptions } from '../core/options.js';\nimport type { ClientPlugin } from '../core/plugins/contracts.js';\nimport type { RateLimitBucketState } from '../core/scheduling/rate-limit.js';\nimport type { ServiceDefinition } from '../core/services.js';\nimport { ITD_CATALOG } from '../domain/catalog.js';\nimport type { CommentsResource } from '../resources/comments.js';\nimport type { FilesResource } from '../resources/files.js';\nimport type { HashtagsResource } from '../resources/hashtags.js';\nimport type { NotificationsResource } from '../resources/notifications.js';\nimport type { PlatformResource } from '../resources/platform.js';\nimport type { PostsResource } from '../resources/posts.js';\nimport type { ReportsResource } from '../resources/reports.js';\nimport type { SearchResource } from '../resources/search.js';\nimport { createStatusFeature } from '../resources/status.js';\nimport type { SubscriptionResource } from '../resources/subscription.js';\nimport type { TelemetryResource } from '../resources/telemetry.js';\nimport type { UsersResource } from '../resources/users.js';\nimport type { VerificationResource } from '../resources/verification.js';\nimport { createResources, type RestResources } from './resources.js';\n\n/** Опции конструктора {@link ItdRestClient}. */\nexport interface RestClientOptions extends RuntimeOptions {\n /**\n * Авторизация. Строка — сокращение для {@link bearerToken}.\n *\n * Без неё доступны только публичные эндпоинты. Токен здесь считается готовым: продлевать\n * его клиент не умеет и на `401` отвечает ошибкой. Сессия, которая входит по паролю\n * и продлевает себя сама, живёт в полном `ItdClient`.\n */\n auth?: string | AuthProvider | undefined;\n}\n\n/**\n * Минимальный клиент REST API итд.com.\n *\n * Тот же конвейер запросов, что и у полного клиента, — с повторами, очередью, плагинами\n * и типизированными ошибками, — но без сессии, потока событий и нескольких аккаунтов.\n * Нужен там, где токен уже есть, а размер поставки важен: серверные интеграции, воркеры,\n * браузерные приложения.\n *\n * @example\n * ```ts\n * import { createRestClient } from 'itd-api/rest';\n *\n * const api = createRestClient({ auth: process.env.ITD_TOKEN });\n * const feed = await api.posts.list({ tab: 'popular' });\n * ```\n */\nexport class ItdRestClient {\n readonly #runtime: ClientRuntime;\n readonly #features: FeatureRegistry;\n readonly #resources: RestResources;\n /** Общий результат терминальной очистки для идемпотентных повторных вызовов. */\n #disposePromise: Promise<void> | undefined;\n #disposed = false;\n\n /** Профили, подписки, блокировки, приватность. */\n get users(): UsersResource {\n return this.#resources.users;\n }\n\n /** Лента, публикация, реакции, репосты, комментарии к постам. */\n get posts(): PostsResource {\n return this.#resources.posts;\n }\n\n /** Ответы на комментарии и действия над ними. */\n get comments(): CommentsResource {\n return this.#resources.comments;\n }\n\n /** Загрузка файлов и медиа. */\n get files(): FilesResource {\n return this.#resources.files;\n }\n\n /** Уведомления: список, счётчик, отметки о прочтении, настройки. */\n get notifications(): NotificationsResource {\n return this.#resources.notifications;\n }\n\n /** Хэштеги и посты по ним. */\n get hashtags(): HashtagsResource {\n return this.#resources.hashtags;\n }\n\n /** Глобальный поиск по пользователям и хэштегам. */\n get search(): SearchResource {\n return this.#resources.search;\n }\n\n /** Жалобы на контент и пользователей. */\n get reports(): ReportsResource {\n return this.#resources.reports;\n }\n\n /** Верификация профиля. */\n get verification(): VerificationResource {\n return this.#resources.verification;\n }\n\n /** Подписка и способы оплаты. */\n get subscription(): SubscriptionResource {\n return this.#resources.subscription;\n }\n\n /** Сведения о платформе: версии приложений, изменения, анонсы, баннер события. */\n get platform(): PlatformResource {\n return this.#resources.platform;\n }\n\n /** Телеметрия просмотров. */\n get telemetry(): TelemetryResource {\n return this.#resources.telemetry;\n }\n\n constructor(options: RestClientOptions = {}) {\n const { auth, ...runtimeOptions } = options;\n const catalog = new ExtensibleOperationCatalog(ITD_CATALOG);\n\n this.#runtime = createClientRuntime(runtimeOptions, {\n catalog,\n assertActive: (action) => this.#assertActive(action),\n auth: () => resolveAuthProvider(auth),\n });\n this.#features = new FeatureRegistry({\n http: this.#runtime.http,\n services: this.#runtime.services,\n serviceOverrides: this.#runtime.config.services,\n catalog,\n baseUrl: this.#runtime.config.baseUrl,\n clock: this.#runtime.config.clock,\n logger: this.#runtime.config.logger,\n assertActive: (action) => this.#assertActive(action),\n registerBucket: (name, definition) => this.#runtime.registerRateLimitBucket(name, definition),\n });\n const status = this.#features.install(createStatusFeature());\n this.#resources = createResources({\n http: this.#runtime.http,\n fetch: this.#runtime.config.fetch,\n status,\n });\n }\n\n #assertActive(action: string): void {\n if (!this.#disposed) return;\n throw new ItdStateError(\n `Клиент уже окончательно освобождён через dispose(); нельзя ${action}. Создайте новый клиент`,\n );\n }\n\n /** Базовый URL, к которому обращается клиент. */\n get baseUrl(): string {\n return this.#runtime.config.baseUrl;\n }\n\n /**\n * Выполняет произвольный запрос к API.\n *\n * Запасной путь для случаев, когда нужного метода ещё нет или ответ сервера разошёлся\n * с документацией. Проходит через ту же авторизацию, очередь и обработку ошибок.\n *\n * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}\n */\n request<T = unknown>(options: RawRequestOptions): Promise<T> {\n return this.#runtime.http.request<T>({\n ...options,\n operationId: options.operationId ?? 'raw',\n });\n }\n\n /**\n * Остаток серверных лимитов по бакетам, через которые уже проходили запросы.\n *\n * Пустой массив при `rateLimit: false`.\n */\n rateLimitState(): RateLimitBucketState[] {\n return this.#runtime.rateLimitState();\n }\n\n /** Устанавливает REST feature поверх общего request pipeline клиента. */\n install<TApi>(feature: ClientFeature<TApi>): TApi {\n return this.#features.install(feature);\n }\n\n /** Устанавливает REST feature и публикует его API как readonly-свойство клиента. */\n withFeature<const K extends string, TApi>(\n key: K,\n feature: ClientFeature<TApi>,\n ): this & { readonly [P in K]: TApi } {\n this.#assertActive('установить feature');\n if (typeof key !== 'string' || key.trim() === '' || key !== key.trim()) {\n throw new ItdConfigError('Свойство feature должно иметь непустое имя без краевых пробелов');\n }\n if (key === 'then' || key in this) {\n throw new ItdConfigError(`Свойство клиента «${key}» уже занято или зарезервировано`);\n }\n if (!Object.isExtensible(this)) {\n throw new ItdConfigError('Нельзя опубликовать feature на нерасширяемом клиенте');\n }\n\n const api = this.install(feature);\n Object.defineProperty(this, key, {\n value: api,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n return this as this & { readonly [P in K]: TApi };\n }\n\n /** Имена установленных feature в порядке установки. */\n featureNames(): string[] {\n return this.#features.names();\n }\n\n /** Установлен ли feature с таким именем. */\n hasFeature(name: string): boolean {\n return this.#features.has(name);\n }\n\n /**\n * Подключает плагин.\n *\n * Сессионная идентичность плагину не передаётся: у клиента с готовым токеном её нет.\n * Плагинам, которые изолируют состояние по аккаунту, нужен полный `ItdClient`.\n *\n * @throws {ItdConfigError} если плагин задан неверно или уже подключён\n * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}\n */\n use(plugin: ClientPlugin): this {\n this.#assertActive('подключить плагин');\n this.#runtime.plugins.add(plugin, {\n baseUrl: this.#runtime.config.baseUrl,\n logger: this.#runtime.config.logger,\n });\n return this;\n }\n\n /**\n * Отключает плагин и освобождает заведённые им ресурсы.\n *\n * @returns `false`, если такого плагина не было\n * @throws {ItdConfigError} если от плагина зависит другой подключённый плагин\n */\n unuse(name: string): Promise<boolean> {\n return this.#runtime.plugins.remove(name);\n }\n\n /** Имена подключённых плагинов в фактическом порядке выполнения обёрток. */\n pluginNames(): string[] {\n return this.#runtime.plugins.names();\n }\n\n /** Подключён ли плагин с таким именем. */\n hasPlugin(name: string): boolean {\n return this.#runtime.plugins.has(name);\n }\n\n /**\n * Регистрирует сервис платформы — домен, отличный от основного.\n *\n * @throws {ItdConfigError} если определение неверно или имя уже занято\n * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}\n */\n defineService(definition: ServiceDefinition): this {\n this.#assertActive('зарегистрировать сервис');\n this.#runtime.services.define(definition);\n return this;\n }\n\n /**\n * Отправляет открытые накопители {@link telemetry} и останавливает очередь запросов.\n *\n * После вызова клиентом можно пользоваться снова. Терминальное освобождение —\n * это {@link dispose}.\n */\n async close(): Promise<void> {\n const errors: unknown[] = [];\n try {\n try {\n await this.#features.close();\n } catch (error) {\n errors.push(error);\n }\n try {\n await this.#resources.closeTelemetry(false);\n } catch (error) {\n errors.push(error);\n }\n } finally {\n this.#runtime.close();\n }\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1) throw new AggregateError(errors, 'Не удалось закрыть клиент');\n }\n\n /**\n * Окончательно освобождает клиент: выполняет {@link close}, отменяет незавершённые\n * запросы и отключает все плагины.\n *\n * Терминальное состояние устанавливается сразу при первом вызове; повторные вызовы\n * возвращают тот же результат очистки.\n *\n * @example\n * ```ts\n * await using api = createRestClient({ auth: token });\n * ```\n */\n dispose(): Promise<void> {\n if (this.#disposePromise) return this.#disposePromise;\n this.#disposed = true;\n this.#disposePromise = this.#dispose();\n return this.#disposePromise;\n }\n\n async #dispose(): Promise<void> {\n const errors: unknown[] = [];\n // Телеметрия уходит через ещё установленный plugin pipeline и мимо проверки состояния.\n this.#resources.prepareTelemetryClose();\n try {\n await this.#features.close();\n } catch (error) {\n errors.push(error);\n }\n try {\n await this.#resources.closeTelemetry(true);\n } catch (error) {\n errors.push(error);\n }\n try {\n await this.#features.dispose();\n } catch (error) {\n errors.push(error);\n }\n try {\n this.#runtime.close();\n await this.#runtime.dispose();\n } catch (error) {\n errors.push(error);\n }\n if (errors.length > 0) throw new AggregateError(errors, 'Не удалось освободить клиент');\n }\n\n /** Позволяет использовать клиент с `await using`. */\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n\n static {\n installAsyncDisposeFallback(ItdRestClient);\n }\n}\n\n/** Приводит опцию `auth` к провайдеру конвейера. */\nfunction resolveAuthProvider(auth: RestClientOptions['auth']): AuthProvider {\n if (auth === undefined) return anonymousAuth();\n return typeof auth === 'string' ? bearerToken(auth) : auth;\n}\n\n/**\n * Создаёт минимальный клиент REST API. Равнозначно конструктору {@link ItdRestClient}.\n *\n * @example\n * ```ts\n * const api = createRestClient({ auth: token, rateLimit: { concurrency: 4 } });\n * ```\n */\nexport function createRestClient(options: RestClientOptions = {}): ItdRestClient {\n return new ItdRestClient(options);\n}\n"],"mappings":"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"}