itd-api 0.7.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +72 -27
  2. package/dist/events/index.cjs +53 -0
  3. package/dist/events/index.d.cts +3 -0
  4. package/dist/events/index.d.ts +3 -0
  5. package/dist/events/index.js +5 -0
  6. package/dist/index.cjs +234 -200
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +70 -64
  9. package/dist/index.d.ts +70 -64
  10. package/dist/index.js +202 -179
  11. package/dist/index.js.map +1 -1
  12. package/dist/node/index.cjs +6 -5
  13. package/dist/node/index.cjs.map +1 -1
  14. package/dist/node/index.d.cts +2 -2
  15. package/dist/node/index.d.ts +2 -2
  16. package/dist/node/index.js +5 -4
  17. package/dist/node/index.js.map +1 -1
  18. package/dist/rest/index.cjs +32 -26
  19. package/dist/rest/index.cjs.map +1 -1
  20. package/dist/rest/index.d.cts +9 -7
  21. package/dist/rest/index.d.ts +9 -7
  22. package/dist/rest/index.js +19 -21
  23. package/dist/rest/index.js.map +1 -1
  24. package/dist/shared/{errors-DfU8M5eS.cjs → errors-BmP3TKoW.cjs} +3 -3
  25. package/dist/shared/{errors-DfU8M5eS.cjs.map → errors-BmP3TKoW.cjs.map} +1 -1
  26. package/dist/shared/{errors-Bhrd2fJd.js → errors-GI10kZxk.js} +3 -3
  27. package/dist/shared/{errors-Bhrd2fJd.js.map → errors-GI10kZxk.js.map} +1 -1
  28. package/dist/shared/{websocket-BLR8eVJV.js → events-C5wnTXPT.js} +770 -490
  29. package/dist/shared/events-C5wnTXPT.js.map +1 -0
  30. package/dist/shared/events-CqtkP65d.d.ts +698 -0
  31. package/dist/shared/events-DGAWlCaI.d.cts +698 -0
  32. package/dist/shared/{websocket-C_eI4H2o.cjs → events-FZfnEez0.cjs} +834 -518
  33. package/dist/shared/events-FZfnEez0.cjs.map +1 -0
  34. package/dist/shared/{storage-BPJR_k4-.cjs → key-value-store-B5GYVEYZ.cjs} +2 -86
  35. package/dist/shared/key-value-store-B5GYVEYZ.cjs.map +1 -0
  36. package/dist/shared/{storage-D86edNCB.js → key-value-store-Bt2PSMxY.js} +3 -69
  37. package/dist/shared/key-value-store-Bt2PSMxY.js.map +1 -0
  38. package/dist/shared/key-value-store-COZaNHZS.d.cts +69 -0
  39. package/dist/shared/key-value-store-COZaNHZS.d.ts +69 -0
  40. package/dist/shared/{multi-storage-DccjD7Ww.d.ts → multi-storage-BEL7tcKn.d.cts} +3 -2
  41. package/dist/shared/{multi-storage--yTEqiod.cjs → multi-storage-CDKLa956.cjs} +11 -10
  42. package/dist/shared/{multi-storage--yTEqiod.cjs.map → multi-storage-CDKLa956.cjs.map} +1 -1
  43. package/dist/shared/{multi-storage-CjAPB5Kq.d.cts → multi-storage-LkljOSzA.d.ts} +3 -2
  44. package/dist/shared/{multi-storage-CkvTUC5m.js → multi-storage-SoW05uzO.js} +5 -4
  45. package/dist/shared/{multi-storage-CkvTUC5m.js.map → multi-storage-SoW05uzO.js.map} +1 -1
  46. package/dist/shared/{options-Dg5N3r1V.cjs → options-DOJYtoti.cjs} +8 -6
  47. package/dist/shared/options-DOJYtoti.cjs.map +1 -0
  48. package/dist/shared/{options-DtATYdLr.js → options-DhgGg7Ms.js} +8 -6
  49. package/dist/shared/options-DhgGg7Ms.js.map +1 -0
  50. package/dist/shared/{cookies-DZwFq6kr.cjs → redact-BP00URmQ.cjs} +312 -2
  51. package/dist/shared/redact-BP00URmQ.cjs.map +1 -0
  52. package/dist/shared/{cookies-tX2sNwxb.js → redact-Ba5iSVYZ.js} +235 -3
  53. package/dist/shared/redact-Ba5iSVYZ.js.map +1 -0
  54. package/dist/shared/{render-CgwKdOzu.d.ts → render-B4qis7Sb.d.ts} +775 -313
  55. package/dist/shared/{render-DO0F5YSm.d.cts → render-DDwy2Ame.d.cts} +775 -313
  56. package/dist/shared/{render-mcuELiYi.cjs → render-Dqi8Owqk.cjs} +1464 -662
  57. package/dist/shared/render-Dqi8Owqk.cjs.map +1 -0
  58. package/dist/shared/{render-C6HRPs10.js → render-hiWFh2s4.js} +1366 -618
  59. package/dist/shared/render-hiWFh2s4.js.map +1 -0
  60. package/dist/shared/storage-BQrtKon9.d.cts +86 -0
  61. package/dist/shared/storage-CTRGT5wF.d.ts +86 -0
  62. package/dist/shared/storage-CfHKzVHf.js +71 -0
  63. package/dist/shared/storage-CfHKzVHf.js.map +1 -0
  64. package/dist/shared/storage-QNVxzpDB.cjs +88 -0
  65. package/dist/shared/storage-QNVxzpDB.cjs.map +1 -0
  66. package/dist/shared/{url-BaMCQpYH.cjs → url-Bsb3xE5U.cjs} +577 -466
  67. package/dist/shared/url-Bsb3xE5U.cjs.map +1 -0
  68. package/dist/shared/{url-IU0xN9wX.js → url-DP33mp3s.js} +508 -409
  69. package/dist/shared/url-DP33mp3s.js.map +1 -0
  70. package/dist/shared/{url-DTfZ2toq.d.ts → url-XBsMdAcv.d.cts} +1313 -1200
  71. package/dist/shared/{url-DTfZ2toq.d.cts → url-XBsMdAcv.d.ts} +1313 -1200
  72. package/dist/web/index.cjs +5 -4
  73. package/dist/web/index.cjs.map +1 -1
  74. package/dist/web/index.d.cts +1 -1
  75. package/dist/web/index.d.ts +1 -1
  76. package/dist/web/index.js +3 -2
  77. package/dist/web/index.js.map +1 -1
  78. package/package.json +16 -15
  79. package/dist/realtime/index.cjs +0 -165
  80. package/dist/realtime/index.cjs.map +0 -1
  81. package/dist/realtime/index.d.cts +0 -51
  82. package/dist/realtime/index.d.ts +0 -51
  83. package/dist/realtime/index.js +0 -120
  84. package/dist/realtime/index.js.map +0 -1
  85. package/dist/shared/auth-provider-CG8oCQ9F.cjs +0 -108
  86. package/dist/shared/auth-provider-CG8oCQ9F.cjs.map +0 -1
  87. package/dist/shared/auth-provider-mYqxsSVa.js +0 -91
  88. package/dist/shared/auth-provider-mYqxsSVa.js.map +0 -1
  89. package/dist/shared/cookies-DZwFq6kr.cjs.map +0 -1
  90. package/dist/shared/cookies-tX2sNwxb.js.map +0 -1
  91. package/dist/shared/options-Dg5N3r1V.cjs.map +0 -1
  92. package/dist/shared/options-DtATYdLr.js.map +0 -1
  93. package/dist/shared/render-C6HRPs10.js.map +0 -1
  94. package/dist/shared/render-mcuELiYi.cjs.map +0 -1
  95. package/dist/shared/storage-BPJR_k4-.cjs.map +0 -1
  96. package/dist/shared/storage-C_eICCep.d.cts +0 -152
  97. package/dist/shared/storage-C_eICCep.d.ts +0 -152
  98. package/dist/shared/storage-D86edNCB.js.map +0 -1
  99. package/dist/shared/url-BaMCQpYH.cjs.map +0 -1
  100. package/dist/shared/url-IU0xN9wX.js.map +0 -1
  101. package/dist/shared/websocket-BLR8eVJV.js.map +0 -1
  102. package/dist/shared/websocket-C_eI4H2o.cjs.map +0 -1
  103. package/dist/shared/websocket-DF7XIMiX.d.cts +0 -562
  104. package/dist/shared/websocket-DYKBr8HF.d.ts +0 -562
@@ -0,0 +1,698 @@
1
+ import { Bt as ItdClock, Ft as QueryParams, Pt as RuntimeOptions, a as NotificationEvent, bt as Logger, ct as Unsubscribe, et as ClientConnection, mn as NotificationType, nt as AuthProvider, s as Notification, sn as EventChannelStatus, st as Listener, tt as AuthIdentity } from "./url-XBsMdAcv.cjs";
2
+ //#region src/events/transports/transport.d.ts
3
+ /** Идентификаторы операций транспорта уведомлений. */
4
+ type EventOperationId = 'events.notifications.poll.updates' | 'events.notifications.poll.unread';
5
+ /** Запрос транспорта к конвейеру клиента. */
6
+ interface EventRequestInput {
7
+ operationId: EventOperationId;
8
+ path: string;
9
+ query?: QueryParams | undefined;
10
+ /**
11
+ * Сигнал отмены текущей попытки соединения.
12
+ */
13
+ signal?: AbortSignal | undefined;
14
+ }
15
+ /**
16
+ * Запрос через очередь, авторизацию, повторы, плагины и обработчики клиента.
17
+ *
18
+ * Ответ приходит уже разобранным и без обёртки `{ data: … }`, а неудача — типизированной
19
+ * ошибкой библиотеки.
20
+ */
21
+ type EventRequest = (input: EventRequestInput) => Promise<unknown>;
22
+ /** Событие, пришедшее по каналу реального времени. */
23
+ interface EventTransportFrame {
24
+ /** Имя события: `notification`, `unread_count` и другие. */
25
+ name: string;
26
+ /** Полезная нагрузка, уже разобранная из JSON. */
27
+ data: unknown;
28
+ }
29
+ /** Что транспорт получает от клиента при подключении. */
30
+ interface EventTransportContext extends Pick<ClientConnection, 'baseUrl' | 'authorize' | 'fetch' | 'baseHeaders' | 'getToken'> {
31
+ /** Отмена подключения. */
32
+ signal: AbortSignal;
33
+ /** Сообщает о полученном событии. */
34
+ onEvent: (event: EventTransportFrame) => void;
35
+ /** Сообщает о разобранном, но некорректном сообщении. Соединение при этом живёт. */
36
+ onParseError: (error: unknown, raw: string) => void;
37
+ /** Вызывается, когда соединение установлено. */
38
+ onOpen: () => void;
39
+ }
40
+ /** Канал получения исходных событий в реальном времени. */
41
+ interface EventTransport {
42
+ /** Понятное имя для логов и диагностики. */
43
+ readonly name: string;
44
+ /**
45
+ * Держит соединение, пока оно живо.
46
+ *
47
+ * Должен завершиться, когда поток закрылся, и бросить исключение при ошибке.
48
+ * Отмена через `context.signal` должна приводить к `AbortError`.
49
+ */
50
+ connect(context: EventTransportContext): Promise<void>;
51
+ }
52
+ /** Ошибка, по которой видно, что сервер отверг авторизацию потока. */
53
+ declare class UnauthorizedStreamError extends Error {
54
+ constructor();
55
+ }
56
+ //#endregion
57
+ //#region src/events/updates.d.ts
58
+ /** Типы нормализованных обновлений потока. */
59
+ declare const NotificationUpdateType: Readonly<{
60
+ readonly Notification: "notification";
61
+ readonly UnreadCount: "unreadCount";
62
+ readonly Unknown: "unknown";
63
+ }>;
64
+ /** Источники нормализованных обновлений потока. */
65
+ declare const NotificationUpdateOrigin: Readonly<{
66
+ readonly Stream: "stream";
67
+ readonly Sync: "sync";
68
+ }>;
69
+ type NotificationUpdateOrigin = (typeof NotificationUpdateOrigin)[keyof typeof NotificationUpdateOrigin];
70
+ /** Уведомление с типом, суженным фильтром потока. */
71
+ type NotificationOfType<T extends NotificationType> = Omit<Notification, 'type'> & {
72
+ type: T;
73
+ };
74
+ /** Конверт уведомления с типом, суженным фильтром потока. */
75
+ type NotificationEventOfType<T extends NotificationType> = Omit<NotificationEvent, 'notification'> & {
76
+ notification: NotificationOfType<T>;
77
+ };
78
+ /** Нормализованное уведомление из потока. */
79
+ interface NotificationUpdate<T extends NotificationType = NotificationType> {
80
+ readonly type: typeof NotificationUpdateType.Notification;
81
+ readonly data: NotificationEventOfType<T>;
82
+ }
83
+ /** Актуальное число непрочитанных уведомлений. */
84
+ interface UnreadCountUpdate {
85
+ readonly type: typeof NotificationUpdateType.UnreadCount;
86
+ readonly data: number;
87
+ }
88
+ /** Неизвестное библиотеке событие потока. */
89
+ interface UnknownNotificationUpdate {
90
+ readonly type: typeof NotificationUpdateType.Unknown;
91
+ readonly name: string;
92
+ readonly data: unknown;
93
+ }
94
+ /** Данные, проходящие через промежуточные обработчики потока. */
95
+ type NotificationEventsUpdate = NotificationUpdate | UnreadCountUpdate | UnknownNotificationUpdate;
96
+ /** Тип нормализованного обновления потока. */
97
+ type NotificationUpdateType = NotificationEventsUpdate['type'];
98
+ /** Обновление потока указанного типа. */
99
+ type NotificationUpdateOfType<T extends NotificationUpdateType> = Extract<NotificationEventsUpdate, {
100
+ type: T;
101
+ }>;
102
+ /**
103
+ * Общая форма контекста обработки: то, что есть у любого потока независимо от домена.
104
+ *
105
+ * Контекст — обычный объектный литерал, а не класс с геттерами и не `Object.freeze`:
106
+ * плагины-флейворы присваивают в него свои поля (`ctx.session = …`), а `@itd-api/hydrate`
107
+ * подменяет `update` и `stream` через `Object.defineProperty`.
108
+ *
109
+ * @typeParam U нормализованное обновление домена
110
+ * @typeParam S поток, который его получил
111
+ */
112
+ interface EventContext<U = unknown, S = unknown, O = unknown> {
113
+ /** Нормализованные данные обновления. */
114
+ readonly update: U;
115
+ /** Поток, который получил обновление. */
116
+ readonly stream: S;
117
+ /** Исходный кадр транспорта. Для начальной REST-синхронизации равен `undefined`. */
118
+ readonly raw: EventTransportFrame | undefined;
119
+ /** Откуда получены данные. */
120
+ readonly origin: O;
121
+ }
122
+ /** Контекст обработки одного обновления потока уведомлений. */
123
+ type NotificationEventContext<U extends NotificationEventsUpdate = NotificationEventsUpdate> = EventContext<U, NotificationEvents, NotificationUpdateOrigin>;
124
+ /** Контекст уведомления с типом, суженным фильтром. */
125
+ type NotificationContext<T extends NotificationType = NotificationType> = NotificationEventContext<NotificationUpdate<T>>;
126
+ /** Условия отбора уведомлений. Все указанные поля объединяются через логическое И. */
127
+ interface NotificationEventFilter<T extends NotificationType = NotificationType> {
128
+ /** Один или несколько канонических типов уведомления. */
129
+ type?: T | readonly T[];
130
+ /** Идентификатор хотя бы одного участника уведомления. */
131
+ actorId?: string;
132
+ /** Идентификатор объекта события. */
133
+ entityId?: string | null;
134
+ /** Идентификатор родительского объекта. */
135
+ parentEntityId?: string | null;
136
+ /** Дополнительная проверка после сопоставления полей. */
137
+ predicate?: (context: NotificationContext<T>) => boolean;
138
+ }
139
+ /** Краткая или объектная форма фильтра уведомлений. */
140
+ type NotificationEventSelector<T extends NotificationType = NotificationType> = T | readonly T[] | NotificationEventFilter<T>;
141
+ //#endregion
142
+ //#region src/events/middleware.d.ts
143
+ /** Продолжает цепочку промежуточных обработчиков потока. */
144
+ type EventNext = () => Promise<void>;
145
+ /** Обрабатывает обновление потока до его передачи подписчикам. */
146
+ type EventMiddleware<C extends EventContext = NotificationEventContext> = (context: C, next: EventNext) => void | Promise<void>;
147
+ /** Объект, предоставляющий снимок промежуточного обработчика потока. */
148
+ interface EventMiddlewareObject<C extends EventContext = NotificationEventContext> {
149
+ middleware(): EventMiddleware<C>;
150
+ }
151
+ /** Асинхронный обработчик нормализованного обновления потока. */
152
+ type EventHandler<C extends EventContext = NotificationEventContext> = (context: C) => unknown | Promise<unknown>;
153
+ /** Условие отбора контекста потока. */
154
+ type EventPredicate<C extends EventContext = NotificationEventContext> = (context: C) => boolean;
155
+ /** Проверка, сужающая тип контекста потока. */
156
+ type EventTypeGuard<C extends B, B extends EventContext = NotificationEventContext> = (context: B) => context is C;
157
+ /** Ключи, по которым обновления нельзя обрабатывать одновременно. */
158
+ type EventSequentializer<C extends EventContext = NotificationEventContext> = (context: C) => PropertyKey | readonly PropertyKey[] | undefined;
159
+ /** Выполняет промежуточные обработчики по порядку и запрещает повторный вызов `next()`. */
160
+ declare function runEventMiddleware<C extends EventContext>(middleware: readonly EventMiddleware<C>[], context: C, terminal: EventNext): Promise<void>;
161
+ //#endregion
162
+ //#region src/events/reconnect.d.ts
163
+ /** Настройки переподключения. */
164
+ interface ReconnectOptions {
165
+ /** Таблица пауз. Последнее значение действует для всех дальнейших попыток. */
166
+ backoff?: readonly number[];
167
+ /** Доля разброса, 0…1. */
168
+ jitter?: number;
169
+ /** Предел числа попыток. */
170
+ maxAttempts?: number;
171
+ }
172
+ //#endregion
173
+ //#region src/events/engine.d.ts
174
+ /** Зачем движок просит домен синхронизироваться. */
175
+ type EventSyncReason = 'initial' | 'reconnect';
176
+ /** Параметры постановки доменного события из REST или другого внешнего источника. */
177
+ interface EventEnqueueOptions<O = unknown> {
178
+ readonly origin: O;
179
+ readonly raw?: EventTransportFrame | undefined;
180
+ }
181
+ /** Контекст одной попытки подключения, теряющий актуальность после её завершения. */
182
+ interface EventSession<U, O = unknown> {
183
+ readonly signal: AbortSignal;
184
+ /** Завершается только после фактического `EventTransportContext.onOpen` этой попытки. */
185
+ readonly opened: Promise<void>;
186
+ /** Ставит нормализованное событие только пока эта попытка актуальна. */
187
+ enqueue(update: U, options: EventEnqueueOptions<O>): void;
188
+ }
189
+ /**
190
+ * События, которые движок рассылает сам.
191
+ *
192
+ * Ни одно из них не зависит от домена, поэтому они одинаковы у любого потока.
193
+ * Домен расширяет эту карту своими событиями.
194
+ */
195
+ interface EventChannelEvents<C extends EventContext = EventContext> {
196
+ /** Изменилось состояние соединения. */
197
+ status: EventChannelStatus;
198
+ /** Соединение оборвалось; будет предпринята попытка переподключения. */
199
+ error: {
200
+ error: unknown;
201
+ willReconnect: boolean;
202
+ };
203
+ /** Сообщение не удалось разобрать. Соединение при этом продолжает работать. */
204
+ parseError: {
205
+ error: unknown;
206
+ raw: string;
207
+ };
208
+ /** Запланировано переподключение. */
209
+ reconnect: {
210
+ attempt: number;
211
+ delay: number;
212
+ };
213
+ /** Попытки исчерпаны — соединение восстановится только ручным `connect()`. */
214
+ giveup: undefined;
215
+ /** Любой исходный кадр транспорта. Отправляется до нормализации и обработчиков. */
216
+ message: EventTransportFrame;
217
+ /** Промежуточный обработчик потока завершился исключением. */
218
+ middlewareError: {
219
+ error: unknown;
220
+ context: C;
221
+ };
222
+ /** Обработчик обновления завершился исключением. */
223
+ handlerError: {
224
+ error: unknown;
225
+ context: C;
226
+ };
227
+ }
228
+ /**
229
+ * Что движок получает от домена.
230
+ *
231
+ * @typeParam U нормализованное обновление домена
232
+ * @typeParam C контекст обработки, который домен собирает вокруг обновления
233
+ *
234
+ */
235
+ interface EventChannelDeps<U, C extends EventContext<U, unknown, O>, O = unknown> {
236
+ connection: ClientConnection;
237
+ clock?: ItdClock | undefined;
238
+ logger?: Logger | undefined;
239
+ transport: EventTransport;
240
+ /** Источник, который домен назначает нормализованным кадрам транспорта. */
241
+ streamOrigin: O;
242
+ /**
243
+ * Доменная обработка сырого кадра до нормализации. `true` — кадр поглощён и дальше
244
+ * не идёт. Нужна там, где кадр не является обновлением: у уведомлений так приходит
245
+ * `connected`.
246
+ */
247
+ handleFrame?: ((event: EventTransportFrame) => boolean) | undefined;
248
+ /** Превращает кадр в доменное обновление; `undefined` — кадр игнорируется. */
249
+ readUpdate: (event: EventTransportFrame) => U | undefined;
250
+ /**
251
+ * Ключ коалесцирования: ожидающее обновление с тем же ключом заменяется новым.
252
+ * `undefined` — обновление не коалесцируется.
253
+ */
254
+ coalesceKey?: ((update: U) => PropertyKey | undefined) | undefined;
255
+ /** Собирает контекст. Точка, куда домен добавляет свои поля и действия. */
256
+ createContext: (update: U, raw: EventTransportFrame | undefined, origin: O) => C;
257
+ /** Доставляет обновление доменным подписчикам после цепочки обработчиков. */
258
+ deliver: (update: U) => void;
259
+ /** Проверяет, можно ли запустить канал. */
260
+ connectGuard?: (() => void) | undefined;
261
+ /** Подготовка одной попытки соединения. */
262
+ initialize?: ((reason: EventSyncReason, session: EventSession<U, O>) => Promise<void>) | undefined;
263
+ /** Открывает транспорт до подготовки и накапливает выбранные кадры до её завершения. */
264
+ openBeforeInitialize?: boolean | undefined;
265
+ /** Ошибка подготовки отклоняет первый `connect()`. */
266
+ initializationRequired?: boolean | undefined;
267
+ /** Выбирает кадры, которые нужно накопить до завершения подготовки. По умолчанию все. */
268
+ bufferFrame?: ((event: EventTransportFrame) => boolean) | undefined;
269
+ }
270
+ /** Настройки движка: переподключение, параллелизм и реакция на среду. */
271
+ interface EventChannelOptions<C extends EventContext = EventContext> extends ReconnectOptions {
272
+ /** Максимальное число одновременно обрабатываемых обновлений. По умолчанию 1. */
273
+ concurrency?: number | undefined;
274
+ /** Возвращает ключи обновлений, которые нельзя обрабатывать одновременно. */
275
+ sequentialize?: EventSequentializer<C> | undefined;
276
+ /** Переподключаться, когда вкладка снова становится видимой. По умолчанию `true`. */
277
+ reconnectOnVisible?: boolean | undefined;
278
+ /** Переподключаться при восстановлении сети. По умолчанию `true`. */
279
+ reconnectOnOnline?: boolean | undefined;
280
+ }
281
+ /** Проверяет настройки общей механики потока. */
282
+ declare function resolveEventChannelOptions<C extends EventContext>(options?: EventChannelOptions<C>): Readonly<EventChannelOptions<C>>;
283
+ /**
284
+ * Общая механика потока событий: соединение, переподключение с задержкой, обновление
285
+ * токена, реакция на среду, статусы и очередь обработчиков.
286
+ *
287
+ * Ничего не знает о домене: что считать обновлением, как собрать контекст и кому его
288
+ * доставить, решают {@link EventChannelDeps}. Поэтому один и тот же движок несёт
289
+ * и поток уведомлений, и любой другой.
290
+ *
291
+ */
292
+ declare class EventChannel<U, C extends EventContext<U, unknown, O>, E extends EventChannelEvents<C> = EventChannelEvents<C>, O = unknown> {
293
+ #private;
294
+ constructor(deps: EventChannelDeps<U, C, O>, options?: EventChannelOptions<C>);
295
+ /** Текущее состояние соединения. */
296
+ get status(): EventChannelStatus;
297
+ /** Имя используемого транспорта. */
298
+ get transport(): string;
299
+ /** Подписывается на событие потока. @returns функция отписки */
300
+ on<K extends keyof E>(event: K, listener: Listener<E[K]>): Unsubscribe;
301
+ /** Подписывается на одно срабатывание события потока. */
302
+ once<K extends keyof E>(event: K, listener: Listener<E[K]>): Unsubscribe;
303
+ /** Рассылает доменное событие через общий эмиттер потока. */
304
+ emit<K extends keyof E>(event: K, payload: E[K]): void;
305
+ /** Снимает подписки на события. Обработчики обновлений и middleware остаются. */
306
+ removeAllListeners(): void;
307
+ /** Добавляет промежуточный обработчик. @returns функция его удаления */
308
+ use(middleware: EventMiddleware<C> | EventMiddlewareObject<C>): Unsubscribe;
309
+ /** Подписывает обработчик обновлений, подходящих под условие. */
310
+ onUpdate(predicate: EventPredicate<C>, handler: EventHandler<C>): Unsubscribe;
311
+ /**
312
+ * Поднимает соединение.
313
+ *
314
+ * Повторный вызов при уже живом соединении ничего не делает. Возвращает управление
315
+ * сразу после запуска: соединение живёт в фоне.
316
+ */
317
+ connect(): Promise<void>;
318
+ /** Закрывает соединение и отменяет запланированные попытки. */
319
+ disconnect(): void;
320
+ /**
321
+ * Ждёт обработчики и полное завершение уже остановленной сессии соединения.
322
+ *
323
+ * Работающий транспорт намеренно не блокирует `drain()`: сначала владелец вызывает
324
+ * {@link disconnect}, который синхронно отменяет сессию. После этого `drain()` ждёт
325
+ * завершения подготовки, транспорта и фонового обновления авторизации, включая их
326
+ * асинхронное освобождение ресурсов.
327
+ */
328
+ drain(): Promise<void>;
329
+ }
330
+ //#endregion
331
+ //#region src/events/stream.d.ts
332
+ /**
333
+ * События потока уведомлений.
334
+ *
335
+ * Общая часть — {@link EventChannelEvents}: статусы, ошибки и переподключение одинаковы
336
+ * у любого потока. Ниже — то, что есть только у уведомлений.
337
+ */
338
+ interface NotificationEventsMap<C extends NotificationEventContext = NotificationEventContext> extends EventChannelEvents<C> {
339
+ /** Пришло новое уведомление. */
340
+ notification: NotificationEvent;
341
+ /**
342
+ * Сервер подтвердил подключение и назвал получателя событий.
343
+ *
344
+ * Приходит первым кадром сразу после установки соединения.
345
+ */
346
+ ready: {
347
+ userId: string | undefined;
348
+ };
349
+ /**
350
+ * Получено актуальное число непрочитанных.
351
+ *
352
+ * При подключении клиент может запросить начальное значение через REST. Затем событие
353
+ * возникает, только если счётчик пришёл в потоке. В остальных случаях обновляйте его
354
+ * в приложении либо запрашивайте `itd.notifications.count()`.
355
+ */
356
+ unreadCount: number;
357
+ }
358
+ /** Способ получения событий. */
359
+ declare const NotificationEventsTransport: Readonly<{
360
+ /** Поток событий, если среда умеет читать тело по частям, иначе опрос. */
361
+ readonly Auto: "auto";
362
+ /** Поток `text/event-stream`. */
363
+ readonly Sse: "sse";
364
+ /** Периодический опрос REST. */
365
+ readonly Poll: "poll";
366
+ }>;
367
+ type NotificationEventsTransport = (typeof NotificationEventsTransport)[keyof typeof NotificationEventsTransport];
368
+ /** Настройки потока уведомлений. */
369
+ interface NotificationEventsOptions<C extends NotificationEventContext = NotificationEventContext> extends ReconnectOptions {
370
+ /**
371
+ * Транспорт. По умолчанию `auto`: поток событий, если среда умеет читать тело ответа
372
+ * по частям, иначе опрос.
373
+ *
374
+ * Можно передать и свою реализацию {@link EventTransport} — это пригодится, если
375
+ * у платформы появится WebSocket либо нужен нестандартный способ доставки.
376
+ */
377
+ transport?: NotificationEventsTransport | EventTransport;
378
+ /**
379
+ * Молчание сервера, после которого соединение считается мёртвым, мс. По умолчанию 90 000.
380
+ *
381
+ * Сервер не присылает keep-alive, поэтому без этой проверки оборванное соединение
382
+ * может незаметно «зависнуть».
383
+ */
384
+ idleTimeout?: number;
385
+ /**
386
+ * Сколько ждать ответа на запрос потока, прежде чем оборвать попытку, мс. По умолчанию
387
+ * 20 000. Защищает от зависания на установке соединения, когда {@link idleTimeout} ещё
388
+ * не действует. `0` отключает проверку. Только для потокового транспорта.
389
+ */
390
+ handshakeTimeout?: number;
391
+ /** Как часто опрашивать сервер, если используется запасной транспорт. */
392
+ pollInterval?: number;
393
+ /**
394
+ * Запрашивать число непрочитанных при подключении. По умолчанию `true`.
395
+ *
396
+ * Так поступает сайт итд.com: поток присылает только новые события, а начальное
397
+ * значение счётчика нужно получить отдельно.
398
+ */
399
+ syncCount?: boolean;
400
+ /**
401
+ * Переподключаться, когда вкладка снова становится видимой. По умолчанию `true`.
402
+ *
403
+ * Только в браузере. У сайта итд.com такой обработки нет, из-за чего вкладка,
404
+ * пролежавшая в фоне, может остаться без соединения.
405
+ */
406
+ reconnectOnVisible?: boolean;
407
+ /** Переподключаться при восстановлении сети. По умолчанию `true`. Только в браузере. */
408
+ reconnectOnOnline?: boolean;
409
+ /** Максимальное число одновременно обрабатываемых обновлений. По умолчанию 1. */
410
+ concurrency?: number;
411
+ /** Возвращает ключи обновлений, которые нельзя обрабатывать одновременно. */
412
+ sequentialize?: EventSequentializer<C>;
413
+ }
414
+ /** Что поток получает от клиента. */
415
+ interface NotificationEventsDeps {
416
+ connection: ClientConnection;
417
+ /** Конвейер клиента — см. {@link EventTransportContext.request}. */
418
+ request?: EventRequest | undefined;
419
+ clock?: ItdClock;
420
+ /** Идентификаторы аккаунта и сессии создавшего поток клиента. */
421
+ getAuthIdentity?: (() => AuthIdentity) | undefined;
422
+ /** Непрозрачная область авторизации создавшего поток клиента. */
423
+ getAuthScope?: (() => string) | undefined;
424
+ /** Загружает начальное число непрочитанных. */
425
+ fetchUnreadCount: (signal: AbortSignal) => Promise<number>;
426
+ /** Вызывается при явном закрытии потока. */
427
+ onClose?: (() => void) | undefined;
428
+ /** Вызывается при запуске ранее закрытого потока. */
429
+ onConnect?: (() => void) | undefined;
430
+ logger?: Logger | undefined;
431
+ }
432
+ /**
433
+ * Поток уведомлений в реальном времени.
434
+ *
435
+ * Доступен как стабильное свойство `itd.notifications.events`. Соединение поднимается методом {@link connect}
436
+ * и держится само: обрывы, обновление токена и повторные попытки библиотека берёт на себя.
437
+ *
438
+ * Параметр типа задаёт форму контекста: плагин может расширить её своими полями
439
+ * (`NotificationEvents<NotificationEventContext & SessionFlavor<S>>`) и типизировать обработчики.
440
+ *
441
+ * @example
442
+ * ```ts
443
+ * import { NotificationType } from 'itd-api';
444
+ *
445
+ * const stream = itd.notifications.events;
446
+ *
447
+ * stream.onNotification(NotificationType.PostComment, async ({ update }) => {
448
+ * await saveCommentNotification(update.data.notification);
449
+ * });
450
+ * stream.on('status', (status) => console.log('соединение:', status));
451
+ *
452
+ * await stream.connect();
453
+ * // …позже
454
+ * stream.disconnect();
455
+ * await stream.drain();
456
+ * ```
457
+ */
458
+ declare class NotificationEvents<C extends NotificationEventContext = NotificationEventContext> {
459
+ #private;
460
+ /** @internal */
461
+ constructor(deps: NotificationEventsDeps, options?: NotificationEventsOptions<C>);
462
+ /** Текущее состояние соединения. */
463
+ get status(): EventChannelStatus;
464
+ /** Имя используемого транспорта. */
465
+ get transport(): string;
466
+ /** Базовый URL клиента, создавшего поток. @internal */
467
+ get baseUrl(): string;
468
+ /** Идентификаторы аккаунта и сессии клиента, создавшего поток. @internal */
469
+ getAuthIdentity(): AuthIdentity | undefined;
470
+ /** Непрозрачная область авторизации создавшего поток клиента. @internal */
471
+ getAuthScope(): string | undefined;
472
+ /** Подписывается на событие потока. @returns функция отписки */
473
+ on<K extends keyof NotificationEventsMap<C>>(event: K, listener: Listener<NotificationEventsMap<C>[K]>): Unsubscribe;
474
+ /** Подписывается на одно срабатывание. */
475
+ once<K extends keyof NotificationEventsMap<C>>(event: K, listener: Listener<NotificationEventsMap<C>[K]>): Unsubscribe;
476
+ /**
477
+ * Добавляет промежуточный обработчик или объект, предоставляющий его через `middleware()`.
478
+ *
479
+ * Обработчики выполняются в порядке регистрации. Если `next()` не вызван, обновление не
480
+ * передаётся дальше по цепочке, асинхронным обработчикам и слушателям событий.
481
+ *
482
+ * @returns функция удаления обработчика
483
+ */
484
+ use(middleware: EventMiddleware<C> | EventMiddlewareObject<C>): Unsubscribe;
485
+ /** Подписывает асинхронный обработчик на все нормализованные обновления. */
486
+ onUpdate(handler: EventHandler<C>): Unsubscribe;
487
+ /** Подписывает асинхронный обработчик на обновление указанного типа. */
488
+ onUpdate<T extends NotificationUpdateType>(type: T, handler: EventHandler<C & NotificationEventContext<NotificationUpdateOfType<T>>>): Unsubscribe;
489
+ /** Подписывает асинхронный обработчик по функции сужения типа. */
490
+ onUpdate<N extends C>(guard: EventTypeGuard<N, C>, handler: EventHandler<N>): Unsubscribe;
491
+ /** Подписывает асинхронный обработчик по пользовательскому условию. */
492
+ onUpdate(predicate: EventPredicate<C>, handler: EventHandler<C>): Unsubscribe;
493
+ /** Подписывает асинхронный обработчик на уведомления, подходящие под фильтр. */
494
+ onNotification<T extends NotificationType>(selector: NotificationEventSelector<T>, handler: EventHandler<C & NotificationContext<T>>): Unsubscribe;
495
+ /** Подписывает асинхронный обработчик по функции сужения типа уведомления. */
496
+ onNotification<N extends C & NotificationContext>(guard: (context: C & NotificationContext) => context is N, handler: EventHandler<N>): Unsubscribe;
497
+ /** Подписывает асинхронный обработчик по пользовательскому условию. */
498
+ onNotification(predicate: (context: C & NotificationContext) => boolean, handler: EventHandler<C & NotificationContext>): Unsubscribe;
499
+ /**
500
+ * Поднимает соединение.
501
+ *
502
+ * Повторный вызов при уже живом соединении ничего не делает — это защита от двойного
503
+ * подключения при перерисовке интерфейса.
504
+ *
505
+ * Возвращает управление сразу после запуска: соединение живёт в фоне.
506
+ *
507
+ * @throws если создавший поток клиент уже освобождён
508
+ */
509
+ connect(): Promise<void>;
510
+ /** Закрывает соединение и отменяет запланированные попытки. */
511
+ disconnect(): void;
512
+ /** Ждёт завершения принятых обновлений и освобождения ресурсов остановленной сессии. */
513
+ drain(): Promise<void>;
514
+ /** Снимает подписки `on()` и `once()`. Остальные обработчики остаются. */
515
+ removeAllListeners(): void;
516
+ }
517
+ //#endregion
518
+ //#region src/events/client.d.ts
519
+ /** Опции конструктора {@link NotificationEventsClient}. */
520
+ interface NotificationEventsClientOptions<C extends NotificationEventContext = NotificationEventContext> extends RuntimeOptions, NotificationEventsOptions<C> {
521
+ /**
522
+ * Авторизация. Строка — сокращение для `bearerToken()`.
523
+ *
524
+ * Без неё поток идёт анонимно. Токен считается готовым: продлевать его клиент не умеет,
525
+ * а на отказ авторизации переподключение спрашивает токен заново. Сессия, которая входит
526
+ * по паролю и продлевает себя сама, живёт в полном `ItdClient`.
527
+ */
528
+ auth?: string | AuthProvider | undefined;
529
+ }
530
+ /**
531
+ * Поток уведомлений с собственным конвейером запросов.
532
+ *
533
+ * Тот же {@link NotificationEvents}, что доступен как `itd.notifications.events`, но собранный без полного клиента:
534
+ * ресурсы, билдеры и сессия сюда не входят. Нужен приложениям, которым от API нужны только
535
+ * события, — виджетам, счётчикам непрочитанного, фоновым слушателям.
536
+ *
537
+ * @example
538
+ * ```ts
539
+ * import { createNotificationEventsClient } from 'itd-api/events';
540
+ *
541
+ * await using stream = createNotificationEventsClient({ auth: token });
542
+ * stream.on('notification', ({ notification }) => console.log(notification.type));
543
+ * await stream.connect();
544
+ * ```
545
+ */
546
+ declare class NotificationEventsClient<C extends NotificationEventContext = NotificationEventContext> extends NotificationEvents<C> {
547
+ #private;
548
+ constructor(options?: NotificationEventsClientOptions<C>);
549
+ /**
550
+ * Окончательно освобождает поток и его конвейер: отключает соединение, дожидается
551
+ * обработчиков и останавливает очередь запросов.
552
+ *
553
+ * Повторные вызовы возвращают тот же результат очистки.
554
+ */
555
+ dispose(): Promise<void>;
556
+ /** Позволяет использовать поток с `await using`. */
557
+ [Symbol.asyncDispose](): Promise<void>;
558
+ }
559
+ /**
560
+ * Создаёт поток уведомлений с собственным конвейером. Равнозначно конструктору
561
+ * {@link NotificationEventsClient}.
562
+ */
563
+ declare function createNotificationEventsClient<C extends NotificationEventContext = NotificationEventContext>(options?: NotificationEventsClientOptions<C>): NotificationEventsClient<C>;
564
+ //#endregion
565
+ //#region src/events/router.d.ts
566
+ /** Выбирает маршрут обновления. `undefined` и `null` означают отсутствие маршрута. */
567
+ type EventRouteSelector<K extends PropertyKey, C extends EventContext = NotificationEventContext> = (context: C) => K | null | undefined | Promise<K | null | undefined>;
568
+ /**
569
+ * Направляет обновления потока в именованные цепочки промежуточных обработчиков.
570
+ *
571
+ * @example
572
+ * ```ts
573
+ * import { EventRouter, NotificationUpdateType } from 'itd-api/events';
574
+ *
575
+ * const router = new EventRouter((context) => context.update.type);
576
+ * router.route(NotificationUpdateType.Notification, async (context, next) => {
577
+ * if (context.update.type === NotificationUpdateType.Notification) {
578
+ * await handleNotification(context.update.data.notification);
579
+ * }
580
+ * await next();
581
+ * });
582
+ * stream.use(router);
583
+ * ```
584
+ */
585
+ declare class EventRouter<K extends PropertyKey = PropertyKey, C extends EventContext = NotificationEventContext> implements EventMiddlewareObject<C> {
586
+ #private;
587
+ constructor(selector: EventRouteSelector<K, C>);
588
+ /** Добавляет промежуточные обработчики к маршруту и возвращает функцию их удаления. */
589
+ route(key: K, ...middleware: readonly EventMiddleware<C>[]): Unsubscribe;
590
+ /** Добавляет промежуточные обработчики для обновлений без зарегистрированного маршрута. */
591
+ otherwise(...middleware: readonly EventMiddleware<C>[]): Unsubscribe;
592
+ /** Возвращает снимок маршрутов для `stream.use(router)` или ручной композиции. */
593
+ middleware(): EventMiddleware<C>;
594
+ }
595
+ //#endregion
596
+ //#region src/events/composer.d.ts
597
+ /** Функция или объект промежуточного обработчика для {@link EventComposer}. */
598
+ type EventMiddlewareLike<C extends EventContext = NotificationEventContext> = EventMiddleware<C> | EventMiddlewareObject<C>;
599
+ /** Один или несколько промежуточных обработчиков ветки. */
600
+ type EventMiddlewareGroup<C extends EventContext = NotificationEventContext> = EventMiddlewareLike<C> | readonly EventMiddlewareLike<C>[];
601
+ /** Синхронное или асинхронное условие ветвления. */
602
+ type EventFilter<C extends EventContext = NotificationEventContext> = (context: C) => boolean | Promise<boolean>;
603
+ /** Ошибка локальной ветки событий вместе с контекстом обрабатываемого обновления. */
604
+ interface EventErrorContext<C extends EventContext = NotificationEventContext> {
605
+ /** Исходное исключение обработчика. */
606
+ readonly error: unknown;
607
+ /** Контекст обновления, на котором завершилась ветка. */
608
+ readonly context: C;
609
+ }
610
+ /** Обработчик локальной границы ошибок. */
611
+ type EventErrorBoundary<C extends EventContext = NotificationEventContext> = (failure: EventErrorContext<C>, next: EventNext) => unknown | Promise<unknown>;
612
+ /** Именованные ветки для `EventComposer.route()`. */
613
+ type EventRouteTable<K extends string | symbol, C extends EventContext = NotificationEventContext> = Partial<Record<K, EventMiddlewareGroup<C>>>;
614
+ /**
615
+ * Собирает переиспользуемую цепочку обработчиков событий.
616
+ *
617
+ * Не открывает соединение. Готовый объект подключается через `stream.use(composer)`.
618
+ * Для каждого обновления используется текущий снимок вложенных обработчиков.
619
+ *
620
+ * @example
621
+ * ```ts
622
+ * const feature = new EventComposer<AppEventContext>();
623
+ * const safe = feature.errorBoundary(reportFeatureError);
624
+ * safe.filter(isPostUpdate).use(handlePost);
625
+ * stream.use(feature);
626
+ * ```
627
+ */
628
+ declare class EventComposer<C extends EventContext = NotificationEventContext> implements EventMiddlewareObject<C> {
629
+ #private;
630
+ constructor(...middleware: readonly EventMiddlewareLike<C>[]);
631
+ /** Добавляет промежуточные обработчики в конец цепочки. */
632
+ use(...middleware: readonly EventMiddlewareLike<C>[]): this;
633
+ /** Создаёт дочернюю ветку для контекста указанного типа. */
634
+ filter<N extends C>(predicate: EventTypeGuard<N, C>, ...middleware: readonly EventMiddlewareLike<N>[]): EventComposer<N>;
635
+ /** Создаёт дочернюю ветку по синхронному или асинхронному условию. */
636
+ filter(predicate: EventFilter<C>, ...middleware: readonly EventMiddlewareLike<C>[]): EventComposer<C>;
637
+ /**
638
+ * Направляет контекст в одну именованную ветку.
639
+ *
640
+ * Неизвестный ключ без запасной ветки передаёт обновление следующему обработчику. Для
641
+ * динамической регистрации и числовых ключей используйте {@link EventRouter} напрямую.
642
+ */
643
+ route<K extends string | symbol>(selector: EventRouteSelector<K, C>, routes: EventRouteTable<K, C>, fallback?: EventMiddlewareGroup<C>): this;
644
+ /**
645
+ * Создаёт дочернюю ветку с локальной границей ошибок.
646
+ *
647
+ * Перехватывает ошибки только из дочерней ветки. Вызов `next()` в обработчике ошибки
648
+ * продолжает внешнюю цепочку.
649
+ */
650
+ errorBoundary(handler: EventErrorBoundary<C>, ...middleware: readonly EventMiddlewareLike<C>[]): EventComposer<C>;
651
+ /** Возвращает промежуточный обработчик для `stream.use()` или вложенной цепочки. */
652
+ middleware(): EventMiddleware<C>;
653
+ }
654
+ //#endregion
655
+ //#region src/events/transports/websocket.d.ts
656
+ /** Дополнительные параметры конструктора, поддерживаемые Node-реализациями вроде `ws`. */
657
+ interface WebSocketImplementationOptions {
658
+ headers?: Record<string, string> | undefined;
659
+ handshakeTimeout?: number | undefined;
660
+ }
661
+ /** Конструктор WebSocket, который можно передать вместо глобальной реализации. */
662
+ interface WebSocketLike {
663
+ new (url: string | URL, protocols?: string | string[], options?: WebSocketImplementationOptions): unknown;
664
+ }
665
+ /** Определяет, был ли отказ до открытия сокета вызван недействительным токеном. */
666
+ type WebSocketOpenFailureClassifier = (error: unknown, signal: AbortSignal) => boolean | Promise<boolean>;
667
+ /** Настройки WebSocket-транспорта. */
668
+ interface WebSocketTransportOptions {
669
+ /** Путь апгрейда. По умолчанию `/api/ws`. */
670
+ path?: string | undefined;
671
+ /** Реализация WebSocket для сред без глобальной либо для передачи заголовков апгрейда. */
672
+ webSocketImpl?: WebSocketLike | undefined;
673
+ /** Способ передачи токена. `auto` выбирает заголовок при инъекции и query иначе. */
674
+ auth?: 'query' | 'header' | 'auto' | undefined;
675
+ /** Молчание открытого соединения до переподключения, мс. По умолчанию 90 000. */
676
+ idleTimeout?: number | undefined;
677
+ /** Период текстового `ping`, мс. По умолчанию 30 000. */
678
+ keepAlive?: number | undefined;
679
+ /** Максимальное время установки соединения, мс. По умолчанию 20 000. */
680
+ handshakeTimeout?: number | undefined;
681
+ /**
682
+ * Проверяет отказ до `open`, когда среда скрыла HTTP-статус WebSocket-upgrade.
683
+ * `true` преобразует отказ в {@link UnauthorizedStreamError}.
684
+ */
685
+ classifyOpenFailure?: WebSocketOpenFailureClassifier | undefined;
686
+ /** Часы транспорта. Обычно подменяются только в тестах. */
687
+ clock?: ItdClock | undefined;
688
+ }
689
+ /** Транспорт исходных событий поверх стандартного WebSocket. */
690
+ declare class WebSocketTransport implements EventTransport {
691
+ #private;
692
+ readonly name = "ws";
693
+ constructor(options?: WebSocketTransportOptions);
694
+ connect(context: EventTransportContext): Promise<void>;
695
+ }
696
+ //#endregion
697
+ export { EventTransport as $, ReconnectOptions as A, NotificationContext as B, EventChannelDeps as C, EventSession as D, EventEnqueueOptions as E, EventPredicate as F, NotificationEventsUpdate as G, NotificationEventFilter as H, EventSequentializer as I, NotificationUpdateOfType as J, NotificationOfType as K, EventTypeGuard as L, EventMiddleware as M, EventMiddlewareObject as N, EventSyncReason as O, EventNext as P, UnreadCountUpdate as Q, runEventMiddleware as R, EventChannel as S, EventChannelOptions as T, NotificationEventOfType as U, NotificationEventContext as V, NotificationEventSelector as W, NotificationUpdateType as X, NotificationUpdateOrigin as Y, UnknownNotificationUpdate as Z, createNotificationEventsClient as _, WebSocketTransportOptions as a, NotificationEventsOptions as b, EventErrorContext as c, EventMiddlewareLike as d, EventTransportContext as et, EventRouteTable as f, NotificationEventsClientOptions as g, NotificationEventsClient as h, WebSocketTransport as i, EventHandler as j, resolveEventChannelOptions as k, EventFilter as l, EventRouter as m, WebSocketLike as n, UnauthorizedStreamError as nt, EventComposer as o, EventRouteSelector as p, NotificationUpdate as q, WebSocketOpenFailureClassifier as r, EventErrorBoundary as s, WebSocketImplementationOptions as t, EventTransportFrame as tt, EventMiddlewareGroup as u, NotificationEvents as v, EventChannelEvents as w, NotificationEventsTransport as x, NotificationEventsMap as y, EventContext as z };
698
+ //# sourceMappingURL=events-DGAWlCaI.d.cts.map