itd-api 0.3.0 → 0.5.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.
- package/README.md +3 -2
- package/dist/index.cjs +3329 -1795
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1640 -1092
- package/dist/index.d.ts +1640 -1092
- package/dist/index.js +3249 -1730
- package/dist/index.js.map +1 -1
- package/dist/{multi-storage-CyMe404l.js → multi-storage-B0r0AInH.js} +151 -281
- package/dist/multi-storage-B0r0AInH.js.map +1 -0
- package/dist/{multi-storage-BhcA2Izn.d.ts → multi-storage-CLqmzq07.d.ts} +14 -54
- package/dist/{multi-storage-D1keK2Op.cjs → multi-storage-mBuCOVZY.cjs} +188 -294
- package/dist/multi-storage-mBuCOVZY.cjs.map +1 -0
- package/dist/{multi-storage-NDqzRQcD.d.cts → multi-storage-s_PcWPGH.d.cts} +14 -54
- package/dist/node.cjs +62 -53
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +19 -5
- package/dist/node.d.ts +19 -5
- package/dist/node.js +62 -54
- package/dist/node.js.map +1 -1
- package/dist/{storage-D9tfHx7Z.js → storage-DWrK3Z4M.js} +201 -18
- package/dist/storage-DWrK3Z4M.js.map +1 -0
- package/dist/storage-Doe3lpFQ.d.cts +152 -0
- package/dist/storage-Doe3lpFQ.d.ts +152 -0
- package/dist/{storage-ycBqLBRB.cjs → storage-dF8Tio5y.cjs} +254 -17
- package/dist/storage-dF8Tio5y.cjs.map +1 -0
- package/dist/web.cjs +143 -40
- package/dist/web.cjs.map +1 -1
- package/dist/web.d.cts +40 -3
- package/dist/web.d.ts +40 -3
- package/dist/web.js +141 -41
- package/dist/web.js.map +1 -1
- package/package.json +3 -3
- package/dist/multi-storage-CyMe404l.js.map +0 -1
- package/dist/multi-storage-D1keK2Op.cjs.map +0 -1
- package/dist/runtime-CFEsf-jD.cjs +0 -185
- package/dist/runtime-CFEsf-jD.cjs.map +0 -1
- package/dist/runtime-DHxDn8gf.js +0 -126
- package/dist/runtime-DHxDn8gf.js.map +0 -1
- package/dist/storage-BjNRlkbE.d.cts +0 -82
- package/dist/storage-BjNRlkbE.d.ts +0 -82
- package/dist/storage-D9tfHx7Z.js.map +0 -1
- package/dist/storage-ycBqLBRB.cjs.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as
|
|
1
|
+
import { _ as withNamespace, a as createTokenStorage, c as KeyValueStore, d as MemoryKeyValueStore, f as RecordKeyValueStoreSource, g as withCodec, h as isEnumerableKeyValueStore, i as TokenStorageAdapterOptions, l as KeyValueStoreKeys, m as createRecordKeyValueStore, n as MemoryTokenStorage, o as EnumerableKeyValueStore, p as createKeyValueStore, r as TokenStorage, s as KeyValueCodec, t as ItdSession, u as KeyValueStoreResult } from "./storage-Doe3lpFQ.js";
|
|
2
|
+
import { _ as UrlFile, a as scopedTokenStorage, c as FileContent, d as FileStreamContent, f as FileStreamOptions, g as StreamFile, h as LazyFile, i as createMultiTokenStorage, l as FileContext, m as FromStreamOptions, n as MultiTokenStorage, o as DEFAULT_FILE_STREAM_BUFFER_BYTES, p as FileTransferMode, r as MultiTokenStorageAdapterOptions, s as DEFAULT_URL_FILE_MAX_BYTES, t as MemoryMultiTokenStorage, u as FileInput, v as UrlFileOptions } from "./multi-storage-CLqmzq07.js";
|
|
3
3
|
//#region src/types/enums.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Перечисления API итд.com.
|
|
@@ -326,12 +326,12 @@ declare const ItdErrorCode: Readonly<{
|
|
|
326
326
|
}>;
|
|
327
327
|
type ItdErrorCode = Loose<(typeof ItdErrorCode)[keyof typeof ItdErrorCode]>;
|
|
328
328
|
//#endregion
|
|
329
|
-
//#region src/
|
|
329
|
+
//#region src/models/common.d.ts
|
|
330
330
|
/**
|
|
331
331
|
* Дата и время в формате ISO-8601, например `2026-07-21T14:30:00.000Z`.
|
|
332
332
|
*
|
|
333
333
|
* Библиотека не превращает такие поля в `Date`: строку проще сравнивать, логировать
|
|
334
|
-
* и передавать дальше без потерь. Для разбора есть
|
|
334
|
+
* и передавать дальше без потерь. Для разбора есть `toDate()`.
|
|
335
335
|
*/
|
|
336
336
|
type IsoDate = string;
|
|
337
337
|
/**
|
|
@@ -371,579 +371,6 @@ interface Span {
|
|
|
371
371
|
/** Идентификатор пользователя у некоторых ответов API с `mention`. */
|
|
372
372
|
id?: string;
|
|
373
373
|
}
|
|
374
|
-
/**
|
|
375
|
-
* Значок-«пин» в профиле — награда или отметка платформы.
|
|
376
|
-
*/
|
|
377
|
-
interface Pin {
|
|
378
|
-
/** Постоянный идентификатор, например `epepuy_202605_59`. */
|
|
379
|
-
slug: string;
|
|
380
|
-
/** Отображаемое название. */
|
|
381
|
-
name: string;
|
|
382
|
-
/** Описание, за что выдан. */
|
|
383
|
-
description: string;
|
|
384
|
-
/** Адрес изображения. */
|
|
385
|
-
url: string;
|
|
386
|
-
/** Когда выдан. Приходит только в списке своих пинов. */
|
|
387
|
-
grantedAt?: IsoDate;
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* Автор поста или комментария.
|
|
391
|
-
*
|
|
392
|
-
* Встречается внутри `post.author` и `comment.author`.
|
|
393
|
-
*/
|
|
394
|
-
interface Author {
|
|
395
|
-
id: UserId;
|
|
396
|
-
username: string;
|
|
397
|
-
displayName: string;
|
|
398
|
-
/**
|
|
399
|
-
* **Эмодзи, а не картинка.**
|
|
400
|
-
*
|
|
401
|
-
* На итд.com аватар — это символ клана (`🩵`, `🦎`), а не адрес изображения.
|
|
402
|
-
* Отрисовывать его нужно как текст.
|
|
403
|
-
*/
|
|
404
|
-
avatar: string;
|
|
405
|
-
/** Пройдена ли верификация. */
|
|
406
|
-
verified: boolean;
|
|
407
|
-
/** Активный значок профиля. Может отсутствовать. */
|
|
408
|
-
pin?: Pin | null;
|
|
409
|
-
/** Есть ли премиум-подписка (значок NUKSTA). */
|
|
410
|
-
hasNuksta?: boolean;
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* Участник события в уведомлении.
|
|
414
|
-
*
|
|
415
|
-
* Отличается от {@link Author} набором полей: вместо значков приходит связь с вами.
|
|
416
|
-
*/
|
|
417
|
-
interface Actor {
|
|
418
|
-
id: UserId;
|
|
419
|
-
username: string;
|
|
420
|
-
displayName: string;
|
|
421
|
-
/** Эмодзи-аватар, см. {@link Author.avatar}. */
|
|
422
|
-
avatar: string;
|
|
423
|
-
/** Подписаны ли вы на этого пользователя. */
|
|
424
|
-
isFollowing?: boolean;
|
|
425
|
-
/** Подписан ли он на вас. */
|
|
426
|
-
isFollowedBy?: boolean;
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Пользователь в списках.
|
|
430
|
-
*
|
|
431
|
-
* Набор полей зависит от эндпоинта: подписчики и подписки приносят `isFollowing`,
|
|
432
|
-
* поиск и рекомендации — `followersCount` и `hasNuksta`. Необязательные поля отражают
|
|
433
|
-
* это различие.
|
|
434
|
-
*/
|
|
435
|
-
interface UserSummary {
|
|
436
|
-
id: UserId;
|
|
437
|
-
username: string;
|
|
438
|
-
displayName: string;
|
|
439
|
-
/** Эмодзи-аватар, см. {@link Author.avatar}. */
|
|
440
|
-
avatar: string;
|
|
441
|
-
verified: boolean;
|
|
442
|
-
/** Подписаны ли вы. Приходит в списках подписчиков и подписок. */
|
|
443
|
-
isFollowing?: boolean;
|
|
444
|
-
/** Есть ли премиум. Приходит в поиске и рекомендациях. */
|
|
445
|
-
hasNuksta?: boolean;
|
|
446
|
-
/** Число подписчиков. Приходит в поиске и рекомендациях. */
|
|
447
|
-
followersCount?: number;
|
|
448
|
-
}
|
|
449
|
-
/** Поля профиля, общие для своего и чужого. */
|
|
450
|
-
interface ProfileBase {
|
|
451
|
-
id: UserId;
|
|
452
|
-
username: string;
|
|
453
|
-
displayName: string;
|
|
454
|
-
/** Эмодзи-аватар, см. {@link Author.avatar}. */
|
|
455
|
-
avatar: string;
|
|
456
|
-
/** URL изображения баннера либо `null`. */
|
|
457
|
-
banner: string | null;
|
|
458
|
-
/** Описание профиля. */
|
|
459
|
-
bio: string;
|
|
460
|
-
verified: boolean;
|
|
461
|
-
pin?: Pin | null;
|
|
462
|
-
/** Кто может писать на стену. */
|
|
463
|
-
wallAccess: WallAccess;
|
|
464
|
-
/** Кто видит реакции. */
|
|
465
|
-
likesVisibility: LikesVisibility;
|
|
466
|
-
followersCount: number;
|
|
467
|
-
followingCount: number;
|
|
468
|
-
postsCount: number;
|
|
469
|
-
createdAt: IsoDate;
|
|
470
|
-
}
|
|
471
|
-
/** Состояние подписки на премиум. */
|
|
472
|
-
interface SubscriptionState {
|
|
473
|
-
isActive: boolean;
|
|
474
|
-
expiresAt: IsoDate | null;
|
|
475
|
-
autoRenewal: boolean;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Свой профиль — ответ `GET /api/users/me`.
|
|
479
|
-
*
|
|
480
|
-
* Отличается от чужого наличием {@link subscription} и {@link isPhoneVerified}
|
|
481
|
-
* и отсутствием полей связи (`isFollowing`, `online`).
|
|
482
|
-
*/
|
|
483
|
-
interface MyProfile extends ProfileBase {
|
|
484
|
-
/** Закрыт ли профиль. */
|
|
485
|
-
isPrivate: boolean;
|
|
486
|
-
/** Подтверждён ли телефон. Без него часть действий недоступна. */
|
|
487
|
-
isPhoneVerified: boolean;
|
|
488
|
-
/** Своя премиум-подписка. */
|
|
489
|
-
subscription: SubscriptionState;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Состояние авторизации — ответ `GET /api/profile`.
|
|
493
|
-
*
|
|
494
|
-
* Endpoint доступен без сессии: в этом случае `authenticated` равен `false`,
|
|
495
|
-
* а `user` — `null`.
|
|
496
|
-
*/
|
|
497
|
-
interface AuthState {
|
|
498
|
-
/** Есть ли действующая сессия. */
|
|
499
|
-
authenticated: boolean;
|
|
500
|
-
/** Заблокирован ли текущий аккаунт. */
|
|
501
|
-
banned: boolean;
|
|
502
|
-
/** Текущий пользователь либо `null` без действующей сессии. */
|
|
503
|
-
user: MyProfile | null;
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Чужой профиль — ответ `GET /api/users/{id|username}`.
|
|
507
|
-
*
|
|
508
|
-
* Вместо своей подписки содержит связь с вами и присутствие.
|
|
509
|
-
*/
|
|
510
|
-
interface PublicProfile extends ProfileBase {
|
|
511
|
-
hasNuksta?: boolean;
|
|
512
|
-
/** Закреплённый пост, если он есть. */
|
|
513
|
-
pinnedPostId: string | null;
|
|
514
|
-
/** Подписаны ли вы на него. */
|
|
515
|
-
isFollowing: boolean;
|
|
516
|
-
/** Подписан ли он на вас. */
|
|
517
|
-
isFollowedBy: boolean;
|
|
518
|
-
/** Сейчас ли пользователь в сети. */
|
|
519
|
-
online: boolean;
|
|
520
|
-
/** Когда был в сети. `null`, если скрыто настройками приватности. */
|
|
521
|
-
lastSeen: IsoDate | null;
|
|
522
|
-
}
|
|
523
|
-
/** Профиль: свой либо чужой. Различаются функцией {@link isMyProfile}. */
|
|
524
|
-
type Profile = MyProfile | PublicProfile;
|
|
525
|
-
/**
|
|
526
|
-
* Свой ли это профиль.
|
|
527
|
-
*
|
|
528
|
-
* @example
|
|
529
|
-
* ```ts
|
|
530
|
-
* if (isMyProfile(profile)) console.log(profile.subscription.isActive);
|
|
531
|
-
* ```
|
|
532
|
-
*/
|
|
533
|
-
declare function isMyProfile(profile: Profile): profile is MyProfile;
|
|
534
|
-
/** Вложение поста или комментария. */
|
|
535
|
-
interface Attachment {
|
|
536
|
-
id: string;
|
|
537
|
-
type: AttachmentType;
|
|
538
|
-
/** Адрес файла на CDN. */
|
|
539
|
-
url: string;
|
|
540
|
-
/** Ширина изображения или видео в пикселях. */
|
|
541
|
-
width?: number;
|
|
542
|
-
/** Высота изображения или видео в пикселях. */
|
|
543
|
-
height?: number;
|
|
544
|
-
mimeType: string;
|
|
545
|
-
/** Исходное имя файла. Приходит не всегда. */
|
|
546
|
-
filename?: string;
|
|
547
|
-
/** Размер в байтах. Приходит не всегда. */
|
|
548
|
-
size?: number;
|
|
549
|
-
/** Длительность аудио или видео в секундах. */
|
|
550
|
-
duration?: number | null;
|
|
551
|
-
/** Порядковый номер во вложениях поста. */
|
|
552
|
-
order?: number;
|
|
553
|
-
}
|
|
554
|
-
/** Вариант ответа в опросе. */
|
|
555
|
-
interface PollOption {
|
|
556
|
-
id: string;
|
|
557
|
-
text: string;
|
|
558
|
-
/** Сколько голосов отдано за этот вариант. */
|
|
559
|
-
votesCount: number;
|
|
560
|
-
/** Порядковый номер варианта, начиная с нуля. */
|
|
561
|
-
position: number;
|
|
562
|
-
}
|
|
563
|
-
/** Опрос внутри поста. */
|
|
564
|
-
interface Poll {
|
|
565
|
-
id: string;
|
|
566
|
-
/** Пост, которому принадлежит опрос. */
|
|
567
|
-
postId: string;
|
|
568
|
-
question: string;
|
|
569
|
-
/** Можно ли выбрать несколько вариантов. */
|
|
570
|
-
multipleChoice: boolean;
|
|
571
|
-
options: PollOption[];
|
|
572
|
-
totalVotes: number;
|
|
573
|
-
/** Голосовали ли вы. */
|
|
574
|
-
hasVoted: boolean;
|
|
575
|
-
/** За что проголосовали вы. Пустой массив, если голоса не было. */
|
|
576
|
-
votedOptionIds: string[];
|
|
577
|
-
createdAt: IsoDate;
|
|
578
|
-
}
|
|
579
|
-
/** Пост ленты, стены или профиля. */
|
|
580
|
-
interface Post {
|
|
581
|
-
id: string;
|
|
582
|
-
content: string;
|
|
583
|
-
/** Разметка текста. Передаётся без изменений, см. {@link Span}. */
|
|
584
|
-
spans: Span[];
|
|
585
|
-
author: Author;
|
|
586
|
-
attachments: Attachment[];
|
|
587
|
-
likesCount: number;
|
|
588
|
-
commentsCount: number;
|
|
589
|
-
repostsCount: number;
|
|
590
|
-
viewsCount: number;
|
|
591
|
-
/** Чья это стена, если пост опубликован не у себя. */
|
|
592
|
-
wallRecipientId: UserId | null;
|
|
593
|
-
/** Владелец стены. Приходит не во всех ответах. */
|
|
594
|
-
wallRecipient?: Author | null;
|
|
595
|
-
/** Поставили ли вы реакцию. */
|
|
596
|
-
isLiked: boolean;
|
|
597
|
-
/** Делали ли вы репост. */
|
|
598
|
-
isReposted: boolean;
|
|
599
|
-
/** Засчитан ли просмотр. */
|
|
600
|
-
isViewed: boolean;
|
|
601
|
-
/** Ваш ли это пост. */
|
|
602
|
-
isOwner: boolean;
|
|
603
|
-
/** Исходный пост, если это репост. */
|
|
604
|
-
originalPost?: Post | null;
|
|
605
|
-
poll?: Poll | null;
|
|
606
|
-
/** Преобладающая реакция — эмодзи либо `null`. */
|
|
607
|
-
dominantEmoji?: string | null;
|
|
608
|
-
/** Когда пост отредактировали. `null`, если не редактировали. */
|
|
609
|
-
editedAt: IsoDate | null;
|
|
610
|
-
createdAt: IsoDate;
|
|
611
|
-
/**
|
|
612
|
-
* Служебная метка показа для телеметрии.
|
|
613
|
-
*
|
|
614
|
-
* Нужна только эндпоинтам `itd.telemetry.*`. В остальных случаях игнорируйте.
|
|
615
|
-
*/
|
|
616
|
-
vs?: string;
|
|
617
|
-
/**
|
|
618
|
-
* Топовые комментарии. Приходят только в ответе `GET /api/posts/{id}`.
|
|
619
|
-
*
|
|
620
|
-
* В списках постов поле отсутствует.
|
|
621
|
-
*/
|
|
622
|
-
comments?: Comment[];
|
|
623
|
-
}
|
|
624
|
-
/** На чей комментарий дан ответ. */
|
|
625
|
-
interface CommentReplyTo {
|
|
626
|
-
id: string;
|
|
627
|
-
username: string;
|
|
628
|
-
displayName: string;
|
|
629
|
-
}
|
|
630
|
-
/** Комментарий к посту или ответ на комментарий. */
|
|
631
|
-
interface Comment {
|
|
632
|
-
id: string;
|
|
633
|
-
/** Текст. У голосового комментария пустой. */
|
|
634
|
-
content: string;
|
|
635
|
-
/**
|
|
636
|
-
* Разметка текста, включая автоматически найденные сервером хэштеги и упоминания.
|
|
637
|
-
*
|
|
638
|
-
* Методы создания и редактирования комментария принимают только `content`, поэтому
|
|
639
|
-
* библиотека не отправляет ручные spans в этих операциях.
|
|
640
|
-
* Поле необязательно: отдельные ответы сервера могут его не содержать.
|
|
641
|
-
*/
|
|
642
|
-
spans?: Span[];
|
|
643
|
-
author: Author;
|
|
644
|
-
likesCount: number;
|
|
645
|
-
repliesCount: number;
|
|
646
|
-
isLiked: boolean;
|
|
647
|
-
createdAt: IsoDate;
|
|
648
|
-
/** Вложения. У голосового — одно аудио с `mimeType: 'audio/ogg'`. */
|
|
649
|
-
attachments?: Attachment[];
|
|
650
|
-
/** Вложенные ответы. В списках приходит превью, полный список — через `itd.comments.replies()`. */
|
|
651
|
-
replies?: Comment[];
|
|
652
|
-
/** Заполнено только у ответов. */
|
|
653
|
-
replyTo?: CommentReplyTo;
|
|
654
|
-
}
|
|
655
|
-
/**
|
|
656
|
-
* Уведомление в единой форме.
|
|
657
|
-
*
|
|
658
|
-
* REST-список и SSE-поток отдают уведомления по-разному — разные имена типов, разные имена
|
|
659
|
-
* полей, один участник против массива. Библиотека приводит оба вида к этой структуре,
|
|
660
|
-
* поэтому объекты из `itd.notifications.list()` и из потока можно складывать в один список.
|
|
661
|
-
*
|
|
662
|
-
* Исходные данные не теряются: сервeрное имя типа остаётся в {@link rawType},
|
|
663
|
-
* а весь необработанный объект — в {@link raw}.
|
|
664
|
-
*/
|
|
665
|
-
interface Notification {
|
|
666
|
-
id: string;
|
|
667
|
-
/** Канонический тип. Старые имена (`like`, `comment`) приведены к новым. */
|
|
668
|
-
type: NotificationType;
|
|
669
|
-
/** Имя типа в том виде, в каком его прислал сервер. */
|
|
670
|
-
rawType: string;
|
|
671
|
-
/** Объект события: пост, комментарий, пользователь. */
|
|
672
|
-
entityId: string | null;
|
|
673
|
-
/** Пост, которому принадлежит комментарий, если событие о комментарии. */
|
|
674
|
-
parentEntityId: string | null;
|
|
675
|
-
/** Прочитано ли уведомление. */
|
|
676
|
-
isRead: boolean;
|
|
677
|
-
/** Кто совершил действие. Для схлопнутых уведомлений — несколько человек. */
|
|
678
|
-
actors: Actor[];
|
|
679
|
-
/** Сколько участников схлопнуто в одно уведомление. Минимум 1. */
|
|
680
|
-
count: number;
|
|
681
|
-
/** Текст или заголовок объекта события. */
|
|
682
|
-
preview: string | null;
|
|
683
|
-
/** Ссылка перехода, предложенная сервером. Обычно точнее её `resolveNotificationUrl()`. */
|
|
684
|
-
clickUrl?: string;
|
|
685
|
-
createdAt: IsoDate;
|
|
686
|
-
/** Когда уведомление изменилось — например было прочитано. */
|
|
687
|
-
updatedAt: IsoDate;
|
|
688
|
-
/** Исходный объект как он пришёл от сервера. */
|
|
689
|
-
raw: unknown;
|
|
690
|
-
}
|
|
691
|
-
/** Настройки приватности профиля. */
|
|
692
|
-
interface PrivacySettings {
|
|
693
|
-
/** Закрыт ли профиль: подписка требует одобрения. */
|
|
694
|
-
isPrivate: boolean;
|
|
695
|
-
wallAccess: WallAccess;
|
|
696
|
-
likesVisibility: LikesVisibility;
|
|
697
|
-
/** Показывать ли время последнего посещения. */
|
|
698
|
-
showLastSeen: boolean;
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Настройки уведомлений.
|
|
702
|
-
*
|
|
703
|
-
* Сервер отдаёт плоский объект, но исторически знает два набора имён для одних и тех же
|
|
704
|
-
* настроек (`likes` и `reactions`, `comments` и `replies`). При сохранении библиотека
|
|
705
|
-
* отправляет оба, при чтении принимает любой.
|
|
706
|
-
*/
|
|
707
|
-
interface NotificationSettings {
|
|
708
|
-
/** Общий выключатель доставки. */
|
|
709
|
-
enabled: boolean;
|
|
710
|
-
/** Звук уведомления. */
|
|
711
|
-
sound: boolean;
|
|
712
|
-
/** Новые подписчики. */
|
|
713
|
-
follows: boolean;
|
|
714
|
-
/** Записи на вашей стене. */
|
|
715
|
-
wallPosts: boolean;
|
|
716
|
-
/** Реакции на ваши записи. */
|
|
717
|
-
likes: boolean;
|
|
718
|
-
/** Комментарии и ответы. */
|
|
719
|
-
comments: boolean;
|
|
720
|
-
/** Упоминания. */
|
|
721
|
-
mentions: boolean;
|
|
722
|
-
}
|
|
723
|
-
/** Активная сессия входа. */
|
|
724
|
-
interface Session {
|
|
725
|
-
id: string;
|
|
726
|
-
/** Та ли это сессия, из которой выполнен запрос. */
|
|
727
|
-
isCurrent: boolean;
|
|
728
|
-
createdAt: IsoDate;
|
|
729
|
-
lastUsedAt: IsoDate;
|
|
730
|
-
expiresAt: IsoDate;
|
|
731
|
-
ipAddress: string;
|
|
732
|
-
/** Код страны по IP, например `RU`. */
|
|
733
|
-
ipCountry: string | null;
|
|
734
|
-
ipCity: string | null;
|
|
735
|
-
deviceType: Loose<'desktop' | 'mobile'>;
|
|
736
|
-
osName: string | null;
|
|
737
|
-
osVersion: string | null;
|
|
738
|
-
/** Название браузера или приложения. */
|
|
739
|
-
clientName: string | null;
|
|
740
|
-
clientVersion: string | null;
|
|
741
|
-
deviceModel: string | null;
|
|
742
|
-
}
|
|
743
|
-
/** Состояние платной подписки и её цена. */
|
|
744
|
-
interface Subscription {
|
|
745
|
-
/** Активна ли подписка сейчас. */
|
|
746
|
-
active: boolean;
|
|
747
|
-
/** Включено ли автопродление. */
|
|
748
|
-
recurringEnabled: boolean;
|
|
749
|
-
/** Цена в рублях. */
|
|
750
|
-
price: number;
|
|
751
|
-
}
|
|
752
|
-
/** Сохранённый способ оплаты. */
|
|
753
|
-
interface PaymentMethod {
|
|
754
|
-
id: string;
|
|
755
|
-
/** Последние четыре цифры карты. */
|
|
756
|
-
last4?: string;
|
|
757
|
-
/** Платёжная система: `visa`, `mastercard`, `mir`. */
|
|
758
|
-
brand?: string;
|
|
759
|
-
/** Основной ли это способ оплаты. */
|
|
760
|
-
isDefault?: boolean;
|
|
761
|
-
expiresAt?: IsoDate | null;
|
|
762
|
-
}
|
|
763
|
-
/** Хэштег. */
|
|
764
|
-
interface Hashtag {
|
|
765
|
-
id: string;
|
|
766
|
-
/** Название без решётки. */
|
|
767
|
-
name: string;
|
|
768
|
-
/** Сколько постов с этим хэштегом. */
|
|
769
|
-
postsCount: number;
|
|
770
|
-
}
|
|
771
|
-
/** Клан в рейтинге. */
|
|
772
|
-
interface Clan {
|
|
773
|
-
/** Эмодзи клана — оно же аватар его участников. */
|
|
774
|
-
avatar: string;
|
|
775
|
-
memberCount: number;
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* Результат подписки на пользователя.
|
|
779
|
-
*
|
|
780
|
-
* @example
|
|
781
|
-
* ```ts
|
|
782
|
-
* const result = await itd.users.follow('nowkie');
|
|
783
|
-
* // { following: true, followersCount: 11 }
|
|
784
|
-
* ```
|
|
785
|
-
*/
|
|
786
|
-
interface FollowResult {
|
|
787
|
-
/** Подписка оформлена. У закрытого профиля отправляется заявка, и здесь будет `false`. */
|
|
788
|
-
following: boolean;
|
|
789
|
-
/** Сколько подписчиков стало у пользователя после действия. */
|
|
790
|
-
followersCount?: number;
|
|
791
|
-
/** Статус заявки, если профиль закрыт. */
|
|
792
|
-
status?: Loose<'following' | 'requested'>;
|
|
793
|
-
}
|
|
794
|
-
/** Запись журнала изменений платформы. */
|
|
795
|
-
interface ChangelogEntry {
|
|
796
|
-
version: string;
|
|
797
|
-
date: string;
|
|
798
|
-
changes: string[];
|
|
799
|
-
}
|
|
800
|
-
/** Кнопка в анонсе платформы. */
|
|
801
|
-
interface AnnouncementButton {
|
|
802
|
-
title: string;
|
|
803
|
-
/** Оформление: `primary`, `secondary` и другие. */
|
|
804
|
-
style: string;
|
|
805
|
-
action: {
|
|
806
|
-
type: string;
|
|
807
|
-
[key: string]: unknown;
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
/** Анонс на главной странице платформы. */
|
|
811
|
-
interface Announcement {
|
|
812
|
-
id: string;
|
|
813
|
-
image: {
|
|
814
|
-
url: string;
|
|
815
|
-
width: number;
|
|
816
|
-
height: number;
|
|
817
|
-
};
|
|
818
|
-
title: string;
|
|
819
|
-
description: string;
|
|
820
|
-
/** Дополнительный текст мелким шрифтом. */
|
|
821
|
-
additional_text?: string;
|
|
822
|
-
buttons: AnnouncementButton[];
|
|
823
|
-
}
|
|
824
|
-
/** Баннер текущего события — виджет «портал». */
|
|
825
|
-
interface Portal {
|
|
826
|
-
active: boolean;
|
|
827
|
-
title: string;
|
|
828
|
-
url: string;
|
|
829
|
-
}
|
|
830
|
-
/** Происшествие в истории сервиса. */
|
|
831
|
-
interface StatusIncidentLine {
|
|
832
|
-
/** Вид происшествия. */
|
|
833
|
-
t: IncidentKind;
|
|
834
|
-
/**
|
|
835
|
-
* Готовая строка для показа: `недоступен 6 мин (12:00–12:06)`. Время московское.
|
|
836
|
-
* Длительность и границы интервала отдельными полями не приходят.
|
|
837
|
-
*/
|
|
838
|
-
text: string;
|
|
839
|
-
}
|
|
840
|
-
/** Одни сутки в истории сервиса. */
|
|
841
|
-
interface StatusDay {
|
|
842
|
-
/** Худшее состояние за сутки. */
|
|
843
|
-
type: ServiceState;
|
|
844
|
-
/** Дата суток, `YYYY-MM-DD`. Сутки нарезаны по UTC. */
|
|
845
|
-
date_key: string;
|
|
846
|
-
/** Доступность за сутки в процентах. */
|
|
847
|
-
uptime: number;
|
|
848
|
-
/** Происшествия за сутки. */
|
|
849
|
-
lines: StatusIncidentLine[];
|
|
850
|
-
}
|
|
851
|
-
/** Сервис платформы и его история доступности. */
|
|
852
|
-
interface ServiceStatus {
|
|
853
|
-
/** Идентификатор: `auth`, `main`, `media` и прочие. */
|
|
854
|
-
id: string;
|
|
855
|
-
/** Отображаемое название. */
|
|
856
|
-
name: string;
|
|
857
|
-
current_status: ServiceState;
|
|
858
|
-
/** Пояснение к текущему состоянию, например `No downtime`. */
|
|
859
|
-
current_message: string;
|
|
860
|
-
/** Задержка последней проверки в миллисекундах. */
|
|
861
|
-
latency_ms: number;
|
|
862
|
-
/**
|
|
863
|
-
* Момент последней проверки. Сервер отдаёт `YYYY-MM-DD HH:mm:ss` в UTC, библиотека
|
|
864
|
-
* приводит значение к ISO.
|
|
865
|
-
*/
|
|
866
|
-
last_checked: IsoDate;
|
|
867
|
-
/** Доступность за 90 суток в процентах. */
|
|
868
|
-
uptime_90d: number;
|
|
869
|
-
/**
|
|
870
|
-
* История по суткам. Ключ — сколько суток назад, `'0'` — сегодня.
|
|
871
|
-
*
|
|
872
|
-
* Объект разреженный: сутки без данных сервер пропускает. Ровный массив даёт
|
|
873
|
-
* {@link statusDays}.
|
|
874
|
-
*/
|
|
875
|
-
days: Record<string, StatusDay | undefined>;
|
|
876
|
-
}
|
|
877
|
-
/** Состояние платформы — ответ `itd.platform.status()`. */
|
|
878
|
-
interface PlatformStatus {
|
|
879
|
-
/** Худшее состояние среди сервисов. */
|
|
880
|
-
overall_status: ServiceState;
|
|
881
|
-
/** Когда данные последний раз пересчитаны. */
|
|
882
|
-
updated_at: IsoDate;
|
|
883
|
-
services: ServiceStatus[];
|
|
884
|
-
}
|
|
885
|
-
/** Статус заявки на верификацию. `none` означает, что заявка не подавалась. */
|
|
886
|
-
interface VerificationStatus {
|
|
887
|
-
status: Loose<'none' | 'pending' | 'approved' | 'rejected'>;
|
|
888
|
-
}
|
|
889
|
-
/** Созданная жалоба. */
|
|
890
|
-
interface Report {
|
|
891
|
-
id: string;
|
|
892
|
-
createdAt: IsoDate;
|
|
893
|
-
}
|
|
894
|
-
/** Счётчики поста из `itd.posts.stats()`. */
|
|
895
|
-
interface PostStats {
|
|
896
|
-
id: string;
|
|
897
|
-
likesCount: number;
|
|
898
|
-
commentsCount: number;
|
|
899
|
-
repostsCount: number;
|
|
900
|
-
viewsCount: number;
|
|
901
|
-
/** Преобладающая реакция — эмодзи либо `null`. */
|
|
902
|
-
dominantEmoji: string | null;
|
|
903
|
-
}
|
|
904
|
-
/** Результат реакции на пост. */
|
|
905
|
-
interface LikeResult {
|
|
906
|
-
liked: boolean;
|
|
907
|
-
likesCount: number;
|
|
908
|
-
}
|
|
909
|
-
/** Результат закрепления поста в профиле. */
|
|
910
|
-
interface PinPostResult {
|
|
911
|
-
success: boolean;
|
|
912
|
-
pinnedPostId: string | null;
|
|
913
|
-
}
|
|
914
|
-
/** Закреплённые значки профиля и выбранный из них. */
|
|
915
|
-
interface PinsResult {
|
|
916
|
-
pins: Pin[];
|
|
917
|
-
/** Идентификатор активного значка — строка, а не объект. */
|
|
918
|
-
activePin: string | null;
|
|
919
|
-
}
|
|
920
|
-
/**
|
|
921
|
-
* Разбирает дату API в объект `Date`.
|
|
922
|
-
*
|
|
923
|
-
* @returns `null`, если строки нет или она не разбирается
|
|
924
|
-
*
|
|
925
|
-
* @example
|
|
926
|
-
* ```ts
|
|
927
|
-
* const created = toDate(post.createdAt);
|
|
928
|
-
* ```
|
|
929
|
-
*/
|
|
930
|
-
declare function toDate(value: IsoDate | null | undefined): Date | null;
|
|
931
|
-
/**
|
|
932
|
-
* Разворачивает историю сервиса в массив на 90 суток.
|
|
933
|
-
* Сутки без данных становятся `null`.
|
|
934
|
-
*
|
|
935
|
-
* @returns массив, где индекс — сколько суток назад: `[0]` — сегодня
|
|
936
|
-
*
|
|
937
|
-
* @example
|
|
938
|
-
* ```ts
|
|
939
|
-
* const status = await itd.platform.status();
|
|
940
|
-
* const days = statusDays(status.services[0]);
|
|
941
|
-
*
|
|
942
|
-
* days[0]?.uptime; // доступность за сегодня
|
|
943
|
-
* days.filter((day) => day === null).length; // за сколько суток данных нет
|
|
944
|
-
* ```
|
|
945
|
-
*/
|
|
946
|
-
declare function statusDays(service: ServiceStatus): (StatusDay | null)[];
|
|
947
374
|
//#endregion
|
|
948
375
|
//#region src/core/clock.d.ts
|
|
949
376
|
/**
|
|
@@ -961,6 +388,413 @@ interface ItdClock {
|
|
|
961
388
|
/** Системные часы, используемые клиентом по умолчанию. */
|
|
962
389
|
declare const systemClock: ItdClock;
|
|
963
390
|
//#endregion
|
|
391
|
+
//#region src/core/operations.d.ts
|
|
392
|
+
/** HTTP-метод встроенной операции. */
|
|
393
|
+
type OperationMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
394
|
+
/** Семантическая безопасность автоматического повтора операции. */
|
|
395
|
+
declare const RetrySafety: Readonly<{
|
|
396
|
+
/** Автоматический повтор не создаёт неприемлемого эффекта; обычно это чтение. */
|
|
397
|
+
readonly Safe: "safe";
|
|
398
|
+
/** Повтор операции приводит к тому же состоянию, что и один вызов. */
|
|
399
|
+
readonly Idempotent: "idempotent";
|
|
400
|
+
/** Повтор может создать ещё один побочный эффект. */
|
|
401
|
+
readonly Unsafe: "unsafe";
|
|
402
|
+
}>;
|
|
403
|
+
type RetrySafety = (typeof RetrySafety)[keyof typeof RetrySafety];
|
|
404
|
+
/** Минимальное стабильное описание операции, доступное core и плагинам. */
|
|
405
|
+
interface OperationDefinition {
|
|
406
|
+
readonly method: OperationMethod;
|
|
407
|
+
readonly retrySafety: RetrySafety;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Каталог встроенных операций.
|
|
411
|
+
*
|
|
412
|
+
* ID описывает смысл вызова и не меняется при переносе HTTP-пути. Method и retrySafety
|
|
413
|
+
* хранятся здесь, чтобы resources, retry и плагины не вели независимые таблицы операций.
|
|
414
|
+
*/
|
|
415
|
+
declare const OPERATIONS: Readonly<{
|
|
416
|
+
readonly 'auth.check': Readonly<{
|
|
417
|
+
readonly method: "GET";
|
|
418
|
+
readonly retrySafety: "safe";
|
|
419
|
+
}>;
|
|
420
|
+
readonly 'auth.signUp': Readonly<{
|
|
421
|
+
readonly method: "POST";
|
|
422
|
+
readonly retrySafety: "unsafe";
|
|
423
|
+
}>;
|
|
424
|
+
readonly 'auth.signIn': Readonly<{
|
|
425
|
+
readonly method: "POST";
|
|
426
|
+
readonly retrySafety: "safe";
|
|
427
|
+
}>;
|
|
428
|
+
readonly 'auth.verifyOtp': Readonly<{
|
|
429
|
+
readonly method: "POST";
|
|
430
|
+
readonly retrySafety: "unsafe";
|
|
431
|
+
}>;
|
|
432
|
+
readonly 'auth.resendOtp': Readonly<{
|
|
433
|
+
readonly method: "POST";
|
|
434
|
+
readonly retrySafety: "unsafe";
|
|
435
|
+
}>;
|
|
436
|
+
readonly 'auth.refresh': Readonly<{
|
|
437
|
+
readonly method: "POST";
|
|
438
|
+
readonly retrySafety: "unsafe";
|
|
439
|
+
}>;
|
|
440
|
+
readonly 'auth.logout': Readonly<{
|
|
441
|
+
readonly method: "POST";
|
|
442
|
+
readonly retrySafety: "unsafe";
|
|
443
|
+
}>;
|
|
444
|
+
readonly 'auth.forgotPassword': Readonly<{
|
|
445
|
+
readonly method: "POST";
|
|
446
|
+
readonly retrySafety: "unsafe";
|
|
447
|
+
}>;
|
|
448
|
+
readonly 'auth.resetPassword': Readonly<{
|
|
449
|
+
readonly method: "POST";
|
|
450
|
+
readonly retrySafety: "unsafe";
|
|
451
|
+
}>;
|
|
452
|
+
readonly 'auth.changePassword': Readonly<{
|
|
453
|
+
readonly method: "POST";
|
|
454
|
+
readonly retrySafety: "unsafe";
|
|
455
|
+
}>;
|
|
456
|
+
readonly 'auth.sessions': Readonly<{
|
|
457
|
+
readonly method: "GET";
|
|
458
|
+
readonly retrySafety: "safe";
|
|
459
|
+
}>;
|
|
460
|
+
readonly 'auth.revokeSession': Readonly<{
|
|
461
|
+
readonly method: "DELETE";
|
|
462
|
+
readonly retrySafety: "unsafe";
|
|
463
|
+
}>;
|
|
464
|
+
readonly 'auth.revokeOtherSessions': Readonly<{
|
|
465
|
+
readonly method: "DELETE";
|
|
466
|
+
readonly retrySafety: "unsafe";
|
|
467
|
+
}>;
|
|
468
|
+
readonly 'users.me': Readonly<{
|
|
469
|
+
readonly method: "GET";
|
|
470
|
+
readonly retrySafety: "safe";
|
|
471
|
+
}>;
|
|
472
|
+
readonly 'users.updateMe': Readonly<{
|
|
473
|
+
readonly method: "PUT";
|
|
474
|
+
readonly retrySafety: "idempotent";
|
|
475
|
+
}>;
|
|
476
|
+
readonly 'users.deactivate': Readonly<{
|
|
477
|
+
readonly method: "DELETE";
|
|
478
|
+
readonly retrySafety: "unsafe";
|
|
479
|
+
}>;
|
|
480
|
+
readonly 'users.restore': Readonly<{
|
|
481
|
+
readonly method: "POST";
|
|
482
|
+
readonly retrySafety: "unsafe";
|
|
483
|
+
}>;
|
|
484
|
+
readonly 'users.createProfile': Readonly<{
|
|
485
|
+
readonly method: "POST";
|
|
486
|
+
readonly retrySafety: "unsafe";
|
|
487
|
+
}>;
|
|
488
|
+
readonly 'users.get': Readonly<{
|
|
489
|
+
readonly method: "GET";
|
|
490
|
+
readonly retrySafety: "safe";
|
|
491
|
+
}>;
|
|
492
|
+
readonly 'users.checkUsername': Readonly<{
|
|
493
|
+
readonly method: "GET";
|
|
494
|
+
readonly retrySafety: "safe";
|
|
495
|
+
}>;
|
|
496
|
+
readonly 'users.search': Readonly<{
|
|
497
|
+
readonly method: "GET";
|
|
498
|
+
readonly retrySafety: "safe";
|
|
499
|
+
}>;
|
|
500
|
+
readonly 'users.whoToFollow': Readonly<{
|
|
501
|
+
readonly method: "GET";
|
|
502
|
+
readonly retrySafety: "safe";
|
|
503
|
+
}>;
|
|
504
|
+
readonly 'users.topClans': Readonly<{
|
|
505
|
+
readonly method: "GET";
|
|
506
|
+
readonly retrySafety: "safe";
|
|
507
|
+
}>;
|
|
508
|
+
readonly 'users.follow': Readonly<{
|
|
509
|
+
readonly method: "POST";
|
|
510
|
+
readonly retrySafety: "unsafe";
|
|
511
|
+
}>;
|
|
512
|
+
readonly 'users.unfollow': Readonly<{
|
|
513
|
+
readonly method: "DELETE";
|
|
514
|
+
readonly retrySafety: "unsafe";
|
|
515
|
+
}>;
|
|
516
|
+
readonly 'users.followers': Readonly<{
|
|
517
|
+
readonly method: "GET";
|
|
518
|
+
readonly retrySafety: "safe";
|
|
519
|
+
}>;
|
|
520
|
+
readonly 'users.following': Readonly<{
|
|
521
|
+
readonly method: "GET";
|
|
522
|
+
readonly retrySafety: "safe";
|
|
523
|
+
}>;
|
|
524
|
+
readonly 'users.followStatus': Readonly<{
|
|
525
|
+
readonly method: "POST";
|
|
526
|
+
readonly retrySafety: "safe";
|
|
527
|
+
}>;
|
|
528
|
+
readonly 'users.block': Readonly<{
|
|
529
|
+
readonly method: "POST";
|
|
530
|
+
readonly retrySafety: "unsafe";
|
|
531
|
+
}>;
|
|
532
|
+
readonly 'users.unblock': Readonly<{
|
|
533
|
+
readonly method: "DELETE";
|
|
534
|
+
readonly retrySafety: "unsafe";
|
|
535
|
+
}>;
|
|
536
|
+
readonly 'users.blocked': Readonly<{
|
|
537
|
+
readonly method: "GET";
|
|
538
|
+
readonly retrySafety: "safe";
|
|
539
|
+
}>;
|
|
540
|
+
readonly 'users.getPrivacy': Readonly<{
|
|
541
|
+
readonly method: "GET";
|
|
542
|
+
readonly retrySafety: "safe";
|
|
543
|
+
}>;
|
|
544
|
+
readonly 'users.updatePrivacy': Readonly<{
|
|
545
|
+
readonly method: "PUT";
|
|
546
|
+
readonly retrySafety: "idempotent";
|
|
547
|
+
}>;
|
|
548
|
+
readonly 'users.pins': Readonly<{
|
|
549
|
+
readonly method: "GET";
|
|
550
|
+
readonly retrySafety: "safe";
|
|
551
|
+
}>;
|
|
552
|
+
readonly 'users.setPin': Readonly<{
|
|
553
|
+
readonly method: "PUT";
|
|
554
|
+
readonly retrySafety: "idempotent";
|
|
555
|
+
}>;
|
|
556
|
+
readonly 'users.removePin': Readonly<{
|
|
557
|
+
readonly method: "DELETE";
|
|
558
|
+
readonly retrySafety: "unsafe";
|
|
559
|
+
}>;
|
|
560
|
+
readonly 'posts.list': Readonly<{
|
|
561
|
+
readonly method: "GET";
|
|
562
|
+
readonly retrySafety: "safe";
|
|
563
|
+
}>;
|
|
564
|
+
readonly 'posts.create': Readonly<{
|
|
565
|
+
readonly method: "POST";
|
|
566
|
+
readonly retrySafety: "unsafe";
|
|
567
|
+
}>;
|
|
568
|
+
readonly 'posts.get': Readonly<{
|
|
569
|
+
readonly method: "GET";
|
|
570
|
+
readonly retrySafety: "safe";
|
|
571
|
+
}>;
|
|
572
|
+
readonly 'posts.update': Readonly<{
|
|
573
|
+
readonly method: "PUT";
|
|
574
|
+
readonly retrySafety: "idempotent";
|
|
575
|
+
}>;
|
|
576
|
+
readonly 'posts.remove': Readonly<{
|
|
577
|
+
readonly method: "DELETE";
|
|
578
|
+
readonly retrySafety: "unsafe";
|
|
579
|
+
}>;
|
|
580
|
+
readonly 'posts.restore': Readonly<{
|
|
581
|
+
readonly method: "POST";
|
|
582
|
+
readonly retrySafety: "unsafe";
|
|
583
|
+
}>;
|
|
584
|
+
readonly 'posts.like': Readonly<{
|
|
585
|
+
readonly method: "POST";
|
|
586
|
+
readonly retrySafety: "unsafe";
|
|
587
|
+
}>;
|
|
588
|
+
readonly 'posts.unlike': Readonly<{
|
|
589
|
+
readonly method: "DELETE";
|
|
590
|
+
readonly retrySafety: "unsafe";
|
|
591
|
+
}>;
|
|
592
|
+
readonly 'posts.repost': Readonly<{
|
|
593
|
+
readonly method: "POST";
|
|
594
|
+
readonly retrySafety: "unsafe";
|
|
595
|
+
}>;
|
|
596
|
+
readonly 'posts.unrepost': Readonly<{
|
|
597
|
+
readonly method: "DELETE";
|
|
598
|
+
readonly retrySafety: "unsafe";
|
|
599
|
+
}>;
|
|
600
|
+
readonly 'posts.pin': Readonly<{
|
|
601
|
+
readonly method: "POST";
|
|
602
|
+
readonly retrySafety: "unsafe";
|
|
603
|
+
}>;
|
|
604
|
+
readonly 'posts.unpin': Readonly<{
|
|
605
|
+
readonly method: "DELETE";
|
|
606
|
+
readonly retrySafety: "unsafe";
|
|
607
|
+
}>;
|
|
608
|
+
readonly 'posts.vote': Readonly<{
|
|
609
|
+
readonly method: "POST";
|
|
610
|
+
readonly retrySafety: "unsafe";
|
|
611
|
+
}>;
|
|
612
|
+
readonly 'posts.stats': Readonly<{
|
|
613
|
+
readonly method: "POST";
|
|
614
|
+
readonly retrySafety: "safe";
|
|
615
|
+
}>;
|
|
616
|
+
readonly 'posts.byUser': Readonly<{
|
|
617
|
+
readonly method: "GET";
|
|
618
|
+
readonly retrySafety: "safe";
|
|
619
|
+
}>;
|
|
620
|
+
readonly 'posts.likedByUser': Readonly<{
|
|
621
|
+
readonly method: "GET";
|
|
622
|
+
readonly retrySafety: "safe";
|
|
623
|
+
}>;
|
|
624
|
+
readonly 'posts.comments': Readonly<{
|
|
625
|
+
readonly method: "GET";
|
|
626
|
+
readonly retrySafety: "safe";
|
|
627
|
+
}>;
|
|
628
|
+
readonly 'posts.comment': Readonly<{
|
|
629
|
+
readonly method: "POST";
|
|
630
|
+
readonly retrySafety: "unsafe";
|
|
631
|
+
}>;
|
|
632
|
+
readonly 'comments.replies': Readonly<{
|
|
633
|
+
readonly method: "GET";
|
|
634
|
+
readonly retrySafety: "safe";
|
|
635
|
+
}>;
|
|
636
|
+
readonly 'comments.reply': Readonly<{
|
|
637
|
+
readonly method: "POST";
|
|
638
|
+
readonly retrySafety: "unsafe";
|
|
639
|
+
}>;
|
|
640
|
+
readonly 'comments.update': Readonly<{
|
|
641
|
+
readonly method: "PATCH";
|
|
642
|
+
readonly retrySafety: "idempotent";
|
|
643
|
+
}>;
|
|
644
|
+
readonly 'comments.remove': Readonly<{
|
|
645
|
+
readonly method: "DELETE";
|
|
646
|
+
readonly retrySafety: "unsafe";
|
|
647
|
+
}>;
|
|
648
|
+
readonly 'comments.restore': Readonly<{
|
|
649
|
+
readonly method: "POST";
|
|
650
|
+
readonly retrySafety: "unsafe";
|
|
651
|
+
}>;
|
|
652
|
+
readonly 'comments.like': Readonly<{
|
|
653
|
+
readonly method: "POST";
|
|
654
|
+
readonly retrySafety: "unsafe";
|
|
655
|
+
}>;
|
|
656
|
+
readonly 'comments.unlike': Readonly<{
|
|
657
|
+
readonly method: "DELETE";
|
|
658
|
+
readonly retrySafety: "unsafe";
|
|
659
|
+
}>;
|
|
660
|
+
readonly 'files.upload': Readonly<{
|
|
661
|
+
readonly method: "POST";
|
|
662
|
+
readonly retrySafety: "unsafe";
|
|
663
|
+
}>;
|
|
664
|
+
readonly 'files.get': Readonly<{
|
|
665
|
+
readonly method: "GET";
|
|
666
|
+
readonly retrySafety: "safe";
|
|
667
|
+
}>;
|
|
668
|
+
readonly 'files.remove': Readonly<{
|
|
669
|
+
readonly method: "DELETE";
|
|
670
|
+
readonly retrySafety: "unsafe";
|
|
671
|
+
}>;
|
|
672
|
+
readonly 'notifications.list': Readonly<{
|
|
673
|
+
readonly method: "GET";
|
|
674
|
+
readonly retrySafety: "safe";
|
|
675
|
+
}>;
|
|
676
|
+
readonly 'notifications.count': Readonly<{
|
|
677
|
+
readonly method: "GET";
|
|
678
|
+
readonly retrySafety: "safe";
|
|
679
|
+
}>;
|
|
680
|
+
readonly 'notifications.markRead': Readonly<{
|
|
681
|
+
readonly method: "POST";
|
|
682
|
+
readonly retrySafety: "idempotent";
|
|
683
|
+
}>;
|
|
684
|
+
readonly 'notifications.markReadBatch': Readonly<{
|
|
685
|
+
readonly method: "POST";
|
|
686
|
+
readonly retrySafety: "idempotent";
|
|
687
|
+
}>;
|
|
688
|
+
readonly 'notifications.markAllRead': Readonly<{
|
|
689
|
+
readonly method: "POST";
|
|
690
|
+
readonly retrySafety: "idempotent";
|
|
691
|
+
}>;
|
|
692
|
+
readonly 'notifications.getSettings': Readonly<{
|
|
693
|
+
readonly method: "GET";
|
|
694
|
+
readonly retrySafety: "safe";
|
|
695
|
+
}>;
|
|
696
|
+
readonly 'notifications.updateSettings': Readonly<{
|
|
697
|
+
readonly method: "PUT";
|
|
698
|
+
readonly retrySafety: "idempotent";
|
|
699
|
+
}>;
|
|
700
|
+
readonly 'hashtags.search': Readonly<{
|
|
701
|
+
readonly method: "GET";
|
|
702
|
+
readonly retrySafety: "safe";
|
|
703
|
+
}>;
|
|
704
|
+
readonly 'hashtags.trending': Readonly<{
|
|
705
|
+
readonly method: "GET";
|
|
706
|
+
readonly retrySafety: "safe";
|
|
707
|
+
}>;
|
|
708
|
+
readonly 'hashtags.posts': Readonly<{
|
|
709
|
+
readonly method: "GET";
|
|
710
|
+
readonly retrySafety: "safe";
|
|
711
|
+
}>;
|
|
712
|
+
readonly 'search.all': Readonly<{
|
|
713
|
+
readonly method: "GET";
|
|
714
|
+
readonly retrySafety: "safe";
|
|
715
|
+
}>;
|
|
716
|
+
readonly 'reports.create': Readonly<{
|
|
717
|
+
readonly method: "POST";
|
|
718
|
+
readonly retrySafety: "unsafe";
|
|
719
|
+
}>;
|
|
720
|
+
readonly 'subscription.status': Readonly<{
|
|
721
|
+
readonly method: "GET";
|
|
722
|
+
readonly retrySafety: "safe";
|
|
723
|
+
}>;
|
|
724
|
+
readonly 'subscription.pay': Readonly<{
|
|
725
|
+
readonly method: "POST";
|
|
726
|
+
readonly retrySafety: "unsafe";
|
|
727
|
+
}>;
|
|
728
|
+
readonly 'subscription.setAutoRenewal': Readonly<{
|
|
729
|
+
readonly method: "POST";
|
|
730
|
+
readonly retrySafety: "idempotent";
|
|
731
|
+
}>;
|
|
732
|
+
readonly 'subscription.bindCard': Readonly<{
|
|
733
|
+
readonly method: "POST";
|
|
734
|
+
readonly retrySafety: "unsafe";
|
|
735
|
+
}>;
|
|
736
|
+
readonly 'subscription.methods': Readonly<{
|
|
737
|
+
readonly method: "GET";
|
|
738
|
+
readonly retrySafety: "safe";
|
|
739
|
+
}>;
|
|
740
|
+
readonly 'subscription.setDefaultMethod': Readonly<{
|
|
741
|
+
readonly method: "POST";
|
|
742
|
+
readonly retrySafety: "idempotent";
|
|
743
|
+
}>;
|
|
744
|
+
readonly 'subscription.removeMethod': Readonly<{
|
|
745
|
+
readonly method: "DELETE";
|
|
746
|
+
readonly retrySafety: "unsafe";
|
|
747
|
+
}>;
|
|
748
|
+
readonly 'verification.status': Readonly<{
|
|
749
|
+
readonly method: "GET";
|
|
750
|
+
readonly retrySafety: "safe";
|
|
751
|
+
}>;
|
|
752
|
+
readonly 'verification.submit': Readonly<{
|
|
753
|
+
readonly method: "POST";
|
|
754
|
+
readonly retrySafety: "unsafe";
|
|
755
|
+
}>;
|
|
756
|
+
readonly 'platform.version': Readonly<{
|
|
757
|
+
readonly method: "GET";
|
|
758
|
+
readonly retrySafety: "safe";
|
|
759
|
+
}>;
|
|
760
|
+
readonly 'platform.changelog': Readonly<{
|
|
761
|
+
readonly method: "GET";
|
|
762
|
+
readonly retrySafety: "safe";
|
|
763
|
+
}>;
|
|
764
|
+
readonly 'platform.announcements': Readonly<{
|
|
765
|
+
readonly method: "GET";
|
|
766
|
+
readonly retrySafety: "safe";
|
|
767
|
+
}>;
|
|
768
|
+
readonly 'platform.portal': Readonly<{
|
|
769
|
+
readonly method: "GET";
|
|
770
|
+
readonly retrySafety: "safe";
|
|
771
|
+
}>;
|
|
772
|
+
readonly 'platform.status': Readonly<{
|
|
773
|
+
readonly method: "GET";
|
|
774
|
+
readonly retrySafety: "safe";
|
|
775
|
+
}>;
|
|
776
|
+
readonly 'telemetry.dwell': Readonly<{
|
|
777
|
+
readonly method: "POST";
|
|
778
|
+
readonly retrySafety: "unsafe";
|
|
779
|
+
}>;
|
|
780
|
+
readonly 'telemetry.interaction': Readonly<{
|
|
781
|
+
readonly method: "POST";
|
|
782
|
+
readonly retrySafety: "unsafe";
|
|
783
|
+
}>;
|
|
784
|
+
}>;
|
|
785
|
+
/** Стабильный ID встроенной операции. */
|
|
786
|
+
type BuiltInOperationId = keyof typeof OPERATIONS;
|
|
787
|
+
/** Пользовательская семантическая операция низкоуровневого запроса. */
|
|
788
|
+
type CustomOperationId = `custom:${string}`;
|
|
789
|
+
/** ID любого запроса, видимый transformers и hooks. */
|
|
790
|
+
type OperationId = BuiltInOperationId | CustomOperationId | 'raw';
|
|
791
|
+
/** Проверяет принадлежность ID встроенному каталогу. */
|
|
792
|
+
declare function isBuiltInOperationId(value: string): value is BuiltInOperationId;
|
|
793
|
+
/** HTTP-метод встроенной операции. */
|
|
794
|
+
declare function operationMethod(id: BuiltInOperationId): OperationMethod;
|
|
795
|
+
/** Политика автоматического повтора встроенной операции. */
|
|
796
|
+
declare function operationRetrySafety(id: BuiltInOperationId): RetrySafety;
|
|
797
|
+
//#endregion
|
|
964
798
|
//#region src/core/runtime.d.ts
|
|
965
799
|
/**
|
|
966
800
|
* Как библиотека обращается с cookie.
|
|
@@ -1111,16 +945,16 @@ interface RetryOptions {
|
|
|
1111
945
|
maxDelay?: number | undefined;
|
|
1112
946
|
/** Доля случайного разброса паузы, 0…1. По умолчанию 0.3. */
|
|
1113
947
|
jitter?: number | undefined;
|
|
1114
|
-
/**
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
948
|
+
/** Своя логика: вернуть `true`, чтобы повторить. Заменяет семантическое правило операции. */
|
|
949
|
+
shouldRetry?: ((error: unknown, attempt: number, context: RetryDecisionContext) => boolean) | undefined;
|
|
950
|
+
}
|
|
951
|
+
/** Семантика запроса, доступная пользовательской функции `shouldRetry`. */
|
|
952
|
+
interface RetryDecisionContext {
|
|
953
|
+
operationId: OperationId;
|
|
954
|
+
retrySafety: RetrySafety;
|
|
955
|
+
bodyReplayable: boolean;
|
|
956
|
+
method: string;
|
|
957
|
+
path: string;
|
|
1124
958
|
}
|
|
1125
959
|
/** Настройки ограничения нагрузки на API. */
|
|
1126
960
|
interface RateLimitOptions {
|
|
@@ -1150,6 +984,8 @@ interface RateLimitOptions {
|
|
|
1150
984
|
}
|
|
1151
985
|
/** Данные о запросе, доступные хукам. */
|
|
1152
986
|
interface RequestContext {
|
|
987
|
+
/** Стабильная семантическая операция; `raw` у низкоуровневого вызова без явного ID. */
|
|
988
|
+
operationId: OperationId;
|
|
1153
989
|
method: string;
|
|
1154
990
|
/** Путь без базового URL, например `/api/posts`. */
|
|
1155
991
|
path: string;
|
|
@@ -1164,6 +1000,7 @@ interface ResponseContext extends RequestContext {
|
|
|
1164
1000
|
status: number;
|
|
1165
1001
|
/** Длительность запроса в мс. */
|
|
1166
1002
|
duration: number;
|
|
1003
|
+
/** Отдельная копия ответа: её тело можно прочитать, не мешая разбору внутри SDK. */
|
|
1167
1004
|
response: Response;
|
|
1168
1005
|
}
|
|
1169
1006
|
/** Данные об ошибке запроса. */
|
|
@@ -1211,7 +1048,10 @@ interface ItdClientOptions {
|
|
|
1211
1048
|
* Сервисы платформы на отдельных доменах.
|
|
1212
1049
|
*
|
|
1213
1050
|
* Ключ — имя сервиса, значение — базовый URL или определение целиком. Имя встроенного
|
|
1214
|
-
* сервиса задаёт его
|
|
1051
|
+
* сервиса задаёт его хост; встроен один — `status`.
|
|
1052
|
+
*
|
|
1053
|
+
* `auth` у встроенного сервиса наследуется, у нового выводится по хосту: токен уходит
|
|
1054
|
+
* основному хосту и его поддоменам, остальным — по явному `auth: true`.
|
|
1215
1055
|
*
|
|
1216
1056
|
* @example
|
|
1217
1057
|
* ```ts
|
|
@@ -1276,7 +1116,14 @@ interface ItdClientOptions {
|
|
|
1276
1116
|
/** Как обращаться с cookie. По умолчанию определяется по среде исполнения. */
|
|
1277
1117
|
mode?: RuntimeMode | undefined;
|
|
1278
1118
|
}
|
|
1279
|
-
/**
|
|
1119
|
+
/**
|
|
1120
|
+
* Namespaces расширений отдельной операции.
|
|
1121
|
+
*
|
|
1122
|
+
* Пакеты дополняют интерфейс через declaration merging и владеют только своим полем.
|
|
1123
|
+
* Core передаёт объект operation transformers без знания его содержимого.
|
|
1124
|
+
*/
|
|
1125
|
+
interface RequestExtensions {}
|
|
1126
|
+
/** Опции выполнения отдельного запроса. Передаются последним аргументом методов ресурсов. */
|
|
1280
1127
|
interface RequestOptions {
|
|
1281
1128
|
/** Отмена запроса извне. */
|
|
1282
1129
|
signal?: AbortSignal | undefined;
|
|
@@ -1286,23 +1133,28 @@ interface RequestOptions {
|
|
|
1286
1133
|
headers?: Record<string, string> | undefined;
|
|
1287
1134
|
/** Повторы только для этого запроса. Переопределяют глобальную настройку `retry`. */
|
|
1288
1135
|
retry?: RetryOptions | false | undefined;
|
|
1136
|
+
/**
|
|
1137
|
+
* Явно переопределяет безопасность повтора операции.
|
|
1138
|
+
*
|
|
1139
|
+
* Встроенные resources получают значение из каталога. Опция нужна прежде всего custom/raw
|
|
1140
|
+
* интеграциям и осознанному переопределению серверного контракта.
|
|
1141
|
+
*/
|
|
1142
|
+
retrySafety?: RetrySafety | undefined;
|
|
1143
|
+
/** Настройки подключённых operation extensions, сгруппированные по владельцу. */
|
|
1144
|
+
extensions?: RequestExtensions | undefined;
|
|
1145
|
+
}
|
|
1146
|
+
/** Опции перебора страниц, не являющиеся параметрами endpoint. */
|
|
1147
|
+
interface PaginationOptions extends RequestOptions {
|
|
1148
|
+
/** Максимальное число страниц; без значения перебор продолжается до конца списка. */
|
|
1149
|
+
maxPages?: number | undefined;
|
|
1289
1150
|
}
|
|
1290
|
-
/**
|
|
1291
|
-
* Имена полей {@link RequestOptions} — единственный источник истины.
|
|
1292
|
-
*
|
|
1293
|
-
* Ресурсы переносят в описание запроса только эти поля (плюс заявленные плагинами),
|
|
1294
|
-
* потому что параметры методов подмешивают к ним `limit`, `cursor` и прочее, чему
|
|
1295
|
-
* в транспорте делать нечего. Список стоит рядом с интерфейсом, чтобы новое поле нельзя
|
|
1296
|
-
* было забыть.
|
|
1297
|
-
*
|
|
1298
|
-
* `satisfies` гарантирует, что каждое имя в списке — действительно поле `RequestOptions`.
|
|
1299
|
-
* Обратную полноту (не забыто ли новое поле) проверяет тип {@link RequestOptionKeysComplete}
|
|
1300
|
-
* в тесте: здесь её проверять нельзя — плагины расширяют `RequestOptions` своими опциями
|
|
1301
|
-
* (`encrypt`, `decrypt` и подобными), которых в этом списке быть и не должно.
|
|
1302
|
-
*/
|
|
1303
|
-
declare const REQUEST_OPTION_KEYS: readonly ["signal", "timeout", "headers", "retry"];
|
|
1304
1151
|
/** Полное описание запроса для низкоуровневого `itd.request()`. */
|
|
1305
1152
|
interface RawRequestOptions extends RequestOptions {
|
|
1153
|
+
/**
|
|
1154
|
+
* Семантическое имя низкоуровневого запроса. Встроенные resources выставляют его сами.
|
|
1155
|
+
* Пользовательские значения следует помещать в namespace `custom:`.
|
|
1156
|
+
*/
|
|
1157
|
+
operationId?: OperationId | undefined;
|
|
1306
1158
|
method: string;
|
|
1307
1159
|
/** Путь с ведущим слэшем, например `/api/posts`. Завершающий слэш значим. */
|
|
1308
1160
|
path: string;
|
|
@@ -1333,18 +1185,21 @@ interface RawRequestOptions extends RequestOptions {
|
|
|
1333
1185
|
/**
|
|
1334
1186
|
* Выполнить запрос мимо очереди.
|
|
1335
1187
|
*
|
|
1336
|
-
*
|
|
1337
|
-
*
|
|
1338
|
-
* в очереди и ждёт его результата, — иначе оба ждут друг друга и не завершатся никогда.
|
|
1188
|
+
* Продвинутый escape hatch для служебных интеграций. Встроенные refresh и sign-in проходят
|
|
1189
|
+
* обычную очередь: она охватывает только одну сетевую попытку и не создаёт deadlock.
|
|
1339
1190
|
*/
|
|
1340
1191
|
skipQueue?: boolean | undefined;
|
|
1341
1192
|
/** Вернуть тело ответа без снятия обёртки `{ data: … }`. */
|
|
1342
1193
|
raw?: boolean | undefined;
|
|
1343
1194
|
}
|
|
1195
|
+
/** Запрос внутри pipeline: в отличие от raw input всегда имеет семантический ID. */
|
|
1196
|
+
interface OperationRequestOptions extends RawRequestOptions {
|
|
1197
|
+
operationId: OperationId;
|
|
1198
|
+
}
|
|
1344
1199
|
//#endregion
|
|
1345
1200
|
//#region src/core/version.d.ts
|
|
1346
1201
|
/** Версия библиотеки. Попадает в `User-Agent`. */
|
|
1347
|
-
declare const LIBRARY_VERSION = "0.
|
|
1202
|
+
declare const LIBRARY_VERSION = "0.5.0";
|
|
1348
1203
|
//#endregion
|
|
1349
1204
|
//#region src/core/config.d.ts
|
|
1350
1205
|
/** Базовый URL API итд.com. Домен записан в punycode: `итд.com`. */
|
|
@@ -1367,14 +1222,7 @@ declare const DEFAULT_TIMEOUT = 30000;
|
|
|
1367
1222
|
* В браузере заголовок не выставляется — `User-Agent` там запрещён к изменению, и среда
|
|
1368
1223
|
* молча его игнорирует.
|
|
1369
1224
|
*/
|
|
1370
|
-
declare const DEFAULT_USER_AGENT = "Mozilla/5.0 (compatible; itd-api/0.
|
|
1371
|
-
/** Настройки очереди со всеми значениями по умолчанию. */
|
|
1372
|
-
interface ResolvedRateLimitOptions {
|
|
1373
|
-
concurrency: number;
|
|
1374
|
-
rps: number | undefined;
|
|
1375
|
-
retryDelays: readonly number[];
|
|
1376
|
-
respectHeaders: boolean;
|
|
1377
|
-
}
|
|
1225
|
+
declare const DEFAULT_USER_AGENT = "Mozilla/5.0 (compatible; itd-api/0.5.0; +https://github.com/KiowDev/itd-api)";
|
|
1378
1226
|
/**
|
|
1379
1227
|
* Срез конфигурации, нужный слою авторизации.
|
|
1380
1228
|
*
|
|
@@ -1532,15 +1380,9 @@ type RequestBodyFactory = (context: RequestBodyContext) => PreparedRequestBody |
|
|
|
1532
1380
|
* важнее. Смешивать их в одном объекте нельзя — тогда слой авторизации перебивал бы
|
|
1533
1381
|
* `Authorization`, заданный вызывающим кодом вручную.
|
|
1534
1382
|
*/
|
|
1535
|
-
interface PipelineRequest extends
|
|
1383
|
+
interface PipelineRequest extends OperationRequestOptions {
|
|
1536
1384
|
/** Повторяемое тело. Используется внутренними ресурсами вместо `body`. @internal */
|
|
1537
1385
|
bodyFactory?: RequestBodyFactory | undefined;
|
|
1538
|
-
/**
|
|
1539
|
-
* Разрешает повтор записи после сетевого сбоя. Тело должно быть повторяемым.
|
|
1540
|
-
*
|
|
1541
|
-
* @internal
|
|
1542
|
-
*/
|
|
1543
|
-
retryNetworkWrite?: boolean | undefined;
|
|
1544
1386
|
/**
|
|
1545
1387
|
* Заголовки, добавленные слоями конвейера.
|
|
1546
1388
|
*
|
|
@@ -1550,12 +1392,16 @@ interface PipelineRequest extends RawRequestOptions {
|
|
|
1550
1392
|
*/
|
|
1551
1393
|
layerHeaders?: Record<string, string> | undefined;
|
|
1552
1394
|
/**
|
|
1553
|
-
* Номер попытки, начиная с 1. Проставляет
|
|
1395
|
+
* Номер фактически начатой транспортной попытки, начиная с 1. Проставляет attempt layer.
|
|
1554
1396
|
*
|
|
1555
1397
|
* @internal
|
|
1556
1398
|
*/
|
|
1557
1399
|
attempt?: number | undefined;
|
|
1558
1400
|
}
|
|
1401
|
+
/** Запрос на внешней границе pipeline. Низкоуровневый вызов без ID считается `raw`. */
|
|
1402
|
+
type PipelineRequestInput = Omit<PipelineRequest, 'operationId'> & {
|
|
1403
|
+
operationId?: OperationId | undefined;
|
|
1404
|
+
};
|
|
1559
1405
|
/** Обработчик запроса. Самый внутренний в цепочке — транспорт. */
|
|
1560
1406
|
type RequestHandler = (request: PipelineRequest) => Promise<unknown>;
|
|
1561
1407
|
//#endregion
|
|
@@ -1633,6 +1479,8 @@ declare class AuthManager {
|
|
|
1633
1479
|
get on(): Emitter<AuthEvents>['on'];
|
|
1634
1480
|
/** Подписка на одно срабатывание. */
|
|
1635
1481
|
get once(): Emitter<AuthEvents>['once'];
|
|
1482
|
+
/** Снимает lifecycle-подписки при терминальном освобождении владельца. @internal */
|
|
1483
|
+
dispose(): void;
|
|
1636
1484
|
/**
|
|
1637
1485
|
* Непрозрачная fallback-область авторизации.
|
|
1638
1486
|
*
|
|
@@ -1657,6 +1505,15 @@ declare class AuthManager {
|
|
|
1657
1505
|
hasRefreshSession(): Promise<boolean>;
|
|
1658
1506
|
/** Заголовки авторизации для очередного запроса. Пустой объект, если токена нет. */
|
|
1659
1507
|
getAuthHeaders(): Promise<Record<string, string>>;
|
|
1508
|
+
/**
|
|
1509
|
+
* Заголовки уже подготовленной авторизации без чтения storage или вызова внешнего источника.
|
|
1510
|
+
*
|
|
1511
|
+
* Используются после ожидания транспортной очереди: к этому моменту `getAccessToken()` уже
|
|
1512
|
+
* был вызван снаружи неё, но token мог успеть смениться из-за refresh или `setSession()`.
|
|
1513
|
+
*
|
|
1514
|
+
* @internal
|
|
1515
|
+
*/
|
|
1516
|
+
getCurrentAuthHeaders(): Record<string, string>;
|
|
1660
1517
|
/**
|
|
1661
1518
|
* Идентификатор устройства для заголовка `X-Device-Id`.
|
|
1662
1519
|
*
|
|
@@ -1708,32 +1565,104 @@ declare class AuthManager {
|
|
|
1708
1565
|
clear(): Promise<void>;
|
|
1709
1566
|
}
|
|
1710
1567
|
//#endregion
|
|
1711
|
-
//#region src/core/plugins.d.ts
|
|
1568
|
+
//#region src/core/plugins/contracts.d.ts
|
|
1712
1569
|
/**
|
|
1713
|
-
* Обёртка
|
|
1570
|
+
* Обёртка одной логической операции.
|
|
1714
1571
|
*
|
|
1715
|
-
*
|
|
1716
|
-
*
|
|
1572
|
+
* Вызывается ровно один раз независимо от retry и auth recovery. Может изменить
|
|
1573
|
+
* семантический запрос, обработать разобранный результат или завершить операцию локально.
|
|
1717
1574
|
*
|
|
1718
|
-
* @param request
|
|
1719
|
-
* @param next
|
|
1720
|
-
* @returns
|
|
1575
|
+
* @param request описание логической операции; не изменяйте сам объект — передайте копию в `next`
|
|
1576
|
+
* @param next следующая обёртка либо выполнение операции
|
|
1577
|
+
* @returns разобранный результат в том виде, в котором его получит вызывающий код
|
|
1721
1578
|
*
|
|
1722
|
-
* @example Дописать заголовок ко всем
|
|
1579
|
+
* @example Дописать заголовок ко всем операциям
|
|
1723
1580
|
* ```ts
|
|
1724
|
-
* const transformer:
|
|
1581
|
+
* const transformer: OperationTransformer = (request, next) =>
|
|
1725
1582
|
* next({ ...request, headers: { ...request.headers, 'X-Trace': trace() } });
|
|
1726
1583
|
* ```
|
|
1727
1584
|
*/
|
|
1728
|
-
type
|
|
1729
|
-
/**
|
|
1585
|
+
type OperationTransformer = (request: OperationRequestOptions, next: (request: OperationRequestOptions) => Promise<unknown>) => Promise<unknown>;
|
|
1586
|
+
/** Финальные данные одной транспортной попытки. */
|
|
1587
|
+
interface AttemptContext {
|
|
1588
|
+
/** Стабильная семантическая операция. */
|
|
1589
|
+
readonly operationId: OperationId;
|
|
1590
|
+
/** Нормализованный HTTP-метод. */
|
|
1591
|
+
readonly method: string;
|
|
1592
|
+
/** Исходный путь операции до разрешения service/base URL. */
|
|
1593
|
+
readonly path: string;
|
|
1594
|
+
/** Полностью разрешённый URL со строкой query. */
|
|
1595
|
+
readonly url: string;
|
|
1596
|
+
/** Итоговые заголовки. Сам объект mutable для подписи и diagnostic headers. */
|
|
1597
|
+
readonly headers: Headers;
|
|
1598
|
+
/** Номер transport attempt, начиная с 1. */
|
|
1599
|
+
readonly attempt: number;
|
|
1600
|
+
/** Тело после сериализации либо подготовки body factory. Поток нельзя читать заранее. */
|
|
1601
|
+
readonly body: BodyInit | undefined;
|
|
1602
|
+
/** Общий сигнал отмены и таймаута этой попытки. */
|
|
1603
|
+
readonly signal: AbortSignal;
|
|
1604
|
+
}
|
|
1605
|
+
/**
|
|
1606
|
+
* Продолжение attempt chain.
|
|
1607
|
+
*
|
|
1608
|
+
* В рамках одного interceptor его можно вызвать только один раз. Возвращает сырой ответ:
|
|
1609
|
+
* transport ещё не проверял status и не читал body.
|
|
1610
|
+
*/
|
|
1611
|
+
type AttemptNext = () => Promise<Response>;
|
|
1612
|
+
/**
|
|
1613
|
+
* Обёртка одной транспортной попытки.
|
|
1614
|
+
*
|
|
1615
|
+
* Получает уже разрешённый URL, итоговые заголовки, подготовленное тело и номер попытки.
|
|
1616
|
+
* Может дописать заголовки, измерить wire latency, обработать сырой `Response` или вернуть
|
|
1617
|
+
* синтетический `Response`. Семантический input здесь намеренно недоступен для изменения.
|
|
1618
|
+
*
|
|
1619
|
+
* Вызывается заново для каждого retry и auth recovery. `next()` разрешено вызвать один раз.
|
|
1620
|
+
* Если interceptor читает тело ответа, читать нужно `response.clone()`: исходный body после
|
|
1621
|
+
* цепочки разбирает transport. Исключение interceptor остаётся пользовательской ошибкой и не
|
|
1622
|
+
* классифицируется как сетевой сбой для автоматического retry.
|
|
1623
|
+
*
|
|
1624
|
+
* @param context окончательные данные текущей транспортной попытки
|
|
1625
|
+
* @param next следующий interceptor либо вызов `fetch`
|
|
1626
|
+
* @returns исходный или синтетический сырой `Response`
|
|
1627
|
+
*/
|
|
1628
|
+
type AttemptInterceptor = (context: AttemptContext, next: AttemptNext) => Promise<Response>;
|
|
1629
|
+
/** Регистрация расширений логической операции. */
|
|
1630
|
+
interface OperationExtensions {
|
|
1631
|
+
/**
|
|
1632
|
+
* Подключает transformer.
|
|
1633
|
+
*
|
|
1634
|
+
* Зарегистрированные раньше оборачивают зарегистрированные позже. Возвращённая функция
|
|
1635
|
+
* идемпотентна и снимает только эту регистрацию.
|
|
1636
|
+
*/
|
|
1637
|
+
use(transformer: OperationTransformer): Unsubscribe;
|
|
1638
|
+
}
|
|
1639
|
+
/** Регистрация расширений транспортной попытки. */
|
|
1640
|
+
interface AttemptExtensions {
|
|
1641
|
+
/**
|
|
1642
|
+
* Подключает interceptor.
|
|
1643
|
+
*
|
|
1644
|
+
* Зарегистрированные раньше оборачивают зарегистрированные позже. Возвращённая функция
|
|
1645
|
+
* идемпотентна и снимает только эту регистрацию.
|
|
1646
|
+
*/
|
|
1647
|
+
use(interceptor: AttemptInterceptor): Unsubscribe;
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1650
|
+
* Освобождение ресурсов, заведённых плагином при установке.
|
|
1651
|
+
*
|
|
1652
|
+
* Вызывается после завершения логических операций, уже вошедших в расширения плагина,
|
|
1653
|
+
* поэтому может безопасно закрывать используемые ими соединения и хранилища.
|
|
1654
|
+
*/
|
|
1730
1655
|
type PluginTeardown = () => void | Promise<void>;
|
|
1731
|
-
/**
|
|
1732
|
-
interface
|
|
1656
|
+
/** API, доступный плагину при подключении. */
|
|
1657
|
+
interface PluginApi {
|
|
1733
1658
|
/** Базовый URL клиента — например чтобы разобрать абсолютные ссылки из ответа. */
|
|
1734
1659
|
baseUrl: string;
|
|
1735
1660
|
/** Отладочный вывод клиента, если он включён. */
|
|
1736
1661
|
logger: Logger | undefined;
|
|
1662
|
+
/** Расширения логической операции: выполняются один раз и могут short-circuit сеть. */
|
|
1663
|
+
operations: OperationExtensions;
|
|
1664
|
+
/** Расширения wire attempt: выполняются заново после каждого retry/auth recovery. */
|
|
1665
|
+
attempts: AttemptExtensions;
|
|
1737
1666
|
/**
|
|
1738
1667
|
* Непрозрачная fallback-область текущей авторизации.
|
|
1739
1668
|
*
|
|
@@ -1748,29 +1677,25 @@ interface PluginContext {
|
|
|
1748
1677
|
* несколькими экземплярами клиента одного аккаунта.
|
|
1749
1678
|
*/
|
|
1750
1679
|
getAuthIdentity?: (() => Promise<AuthIdentity>) | undefined;
|
|
1751
|
-
/** Добавляет обёртку запроса. Подключённые раньше оказываются снаружи. */
|
|
1752
|
-
use(transformer: Transformer): void;
|
|
1753
|
-
/**
|
|
1754
|
-
* Добавляет перехватчики отдельных сетевых попыток.
|
|
1755
|
-
*
|
|
1756
|
-
* В отличие от {@link use}, они видят каждый retry и сырой `Response` до чтения тела.
|
|
1757
|
-
* Несколько наборов хуков одного плагина вызываются в порядке регистрации.
|
|
1758
|
-
*/
|
|
1759
|
-
useHooks(hooks: ClientHooks): void;
|
|
1760
1680
|
}
|
|
1761
1681
|
/**
|
|
1762
1682
|
* Плагин клиента.
|
|
1763
1683
|
*
|
|
1764
|
-
* Подключается через `itd.use(plugin)` и
|
|
1765
|
-
*
|
|
1766
|
-
*
|
|
1684
|
+
* Подключается через `itd.use(plugin)` и регистрирует расширения одного или обоих уровней:
|
|
1685
|
+
* {@link OperationTransformer} для логической операции и {@link AttemptInterceptor} для
|
|
1686
|
+
* отдельной транспортной попытки. Core взаимодействует с плагином только через эти контракты
|
|
1687
|
+
* и его lifecycle, не зная деталей реализации.
|
|
1767
1688
|
*
|
|
1768
|
-
*
|
|
1689
|
+
* Настройки отдельного вызова плагин объявляет своим полем в `RequestExtensions` через
|
|
1690
|
+
* declaration merging. Пользователь передаёт их в `RequestOptions.extensions`, а operation
|
|
1691
|
+
* transformer читает только принадлежащий плагину namespace.
|
|
1692
|
+
*
|
|
1693
|
+
* @example Логирование логических операций
|
|
1769
1694
|
* ```ts
|
|
1770
|
-
* const logging:
|
|
1695
|
+
* const logging: ClientPlugin = {
|
|
1771
1696
|
* name: 'logging',
|
|
1772
|
-
* install({
|
|
1773
|
-
* use(async (request, next) => {
|
|
1697
|
+
* install({ operations, logger }) {
|
|
1698
|
+
* operations.use(async (request, next) => {
|
|
1774
1699
|
* logger?.info(`${request.method} ${request.path}`);
|
|
1775
1700
|
* return next(request);
|
|
1776
1701
|
* });
|
|
@@ -1780,153 +1705,269 @@ interface PluginContext {
|
|
|
1780
1705
|
* itd.use(logging);
|
|
1781
1706
|
* ```
|
|
1782
1707
|
*/
|
|
1783
|
-
interface
|
|
1708
|
+
interface ClientPlugin {
|
|
1784
1709
|
/** Имя плагина. Должно быть уникальным: повторное подключение — ошибка. */
|
|
1785
1710
|
name: string;
|
|
1786
|
-
/**
|
|
1787
|
-
* Имена опций запроса, которые плагин читает у методов ресурсов.
|
|
1788
|
-
*
|
|
1789
|
-
* Библиотека этих опций не понимает и ничего с ними не делает — только доносит
|
|
1790
|
-
* от вызова метода до обёртки нетронутыми. Без такого списка чужие поля отсеиваются,
|
|
1791
|
-
* чтобы случайная опечатка в параметрах не уезжала на сервер.
|
|
1792
|
-
*
|
|
1793
|
-
* Имена полей самого запроса (`path`, `body`, `headers`, `signal` и прочие из
|
|
1794
|
-
* `RawRequestOptions`) заявить нельзя: подключение такого плагина завершится ошибкой.
|
|
1795
|
-
*
|
|
1796
|
-
* Типы для них плагин объявляет сам, дополняя `RequestOptions`:
|
|
1797
|
-
* ```ts
|
|
1798
|
-
* declare module 'itd-api' {
|
|
1799
|
-
* interface RequestOptions { encrypt?: string | undefined }
|
|
1800
|
-
* }
|
|
1801
|
-
* ```
|
|
1802
|
-
*/
|
|
1803
|
-
optionKeys?: readonly string[];
|
|
1804
1711
|
/** Плагины, которые обязаны быть подключены раньше этого. */
|
|
1805
1712
|
requires?: readonly string[];
|
|
1806
1713
|
/** Несовместимые плагины. Достаточно объявить конфликт с одной стороны. */
|
|
1807
1714
|
conflicts?: readonly string[];
|
|
1808
|
-
/** Имена плагинов, снаружи которых
|
|
1715
|
+
/** Имена плагинов, снаружи которых должны стоять оба вида расширений этого плагина. */
|
|
1809
1716
|
before?: readonly string[];
|
|
1810
|
-
/** Имена плагинов, внутри которых
|
|
1717
|
+
/** Имена плагинов, внутри которых должны стоять оба вида расширений этого плагина. */
|
|
1811
1718
|
after?: readonly string[];
|
|
1812
1719
|
/**
|
|
1813
1720
|
* Устанавливает плагин.
|
|
1814
1721
|
*
|
|
1815
1722
|
* Может вернуть функцию освобождения ресурсов. Она вызывается при `unuse()` или
|
|
1816
|
-
* окончательном `dispose()` клиента и может быть асинхронной.
|
|
1723
|
+
* окончательном `dispose()` клиента и может быть асинхронной. Сам `install()` синхронный:
|
|
1724
|
+
* регистрация расширений завершается до того, как `use()` вернёт управление.
|
|
1817
1725
|
*/
|
|
1818
|
-
install(
|
|
1726
|
+
install(api: PluginApi): void | PluginTeardown;
|
|
1727
|
+
}
|
|
1728
|
+
//#endregion
|
|
1729
|
+
//#region src/models/users.d.ts
|
|
1730
|
+
/** Значок-«пин» в профиле — награда или отметка платформы. */
|
|
1731
|
+
interface Pin {
|
|
1732
|
+
/** Постоянный идентификатор, например `epepuy_202605_59`. */
|
|
1733
|
+
slug: string;
|
|
1734
|
+
/** Отображаемое название. */
|
|
1735
|
+
name: string;
|
|
1736
|
+
/** Описание, за что выдан. */
|
|
1737
|
+
description: string;
|
|
1738
|
+
/** Адрес изображения. */
|
|
1739
|
+
url: string;
|
|
1740
|
+
/** Когда выдан. Приходит только в списке своих пинов. */
|
|
1741
|
+
grantedAt?: IsoDate;
|
|
1819
1742
|
}
|
|
1820
1743
|
/**
|
|
1821
|
-
*
|
|
1744
|
+
* Автор поста или комментария.
|
|
1822
1745
|
*
|
|
1823
|
-
*
|
|
1824
|
-
* каждый запрос, если плагины есть.
|
|
1746
|
+
* Встречается внутри `post.author` и `comment.author`.
|
|
1825
1747
|
*/
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
/** Имена опций активных плагинов. */
|
|
1831
|
-
get optionKeys(): ReadonlySet<string>;
|
|
1832
|
-
/** Имена плагинов в фактическом порядке выполнения. */
|
|
1833
|
-
names(): string[];
|
|
1834
|
-
/** Подключён ли плагин с таким именем. */
|
|
1835
|
-
has(name: string): boolean;
|
|
1836
|
-
/** Проверяет добавление без вызова `install()`. @internal */
|
|
1837
|
-
assertCanAdd(plugin: ItdPlugin): void;
|
|
1838
|
-
/** Проверяет удаление без изменения реестра. @internal */
|
|
1839
|
-
assertCanRemove(name: string): void;
|
|
1840
|
-
/**
|
|
1841
|
-
* Подключает плагин.
|
|
1842
|
-
*
|
|
1843
|
-
* @throws {ItdConfigError} если плагин задан неверно, уже подключён, нарушает зависимости
|
|
1844
|
-
* или заявил занятое имя опции
|
|
1845
|
-
*/
|
|
1846
|
-
add(plugin: ItdPlugin, context: Omit<PluginContext, 'use' | 'useHooks'>): void;
|
|
1847
|
-
/**
|
|
1848
|
-
* Отключает плагин и вызывает его функцию очистки.
|
|
1849
|
-
*
|
|
1850
|
-
* Новые запросы перестают видеть плагин сразу. Если его обёртка уже выполняется,
|
|
1851
|
-
* очистка дождётся завершения этого логического запроса.
|
|
1852
|
-
*
|
|
1853
|
-
* @returns `false`, если такого плагина не было
|
|
1854
|
-
*/
|
|
1855
|
-
remove(name: string): Promise<boolean>;
|
|
1856
|
-
/**
|
|
1857
|
-
* Отключает все плагины окончательно.
|
|
1858
|
-
*
|
|
1859
|
-
* Очистка идёт изнутри наружу — в порядке, обратном выполнению обёрток.
|
|
1860
|
-
*/
|
|
1861
|
-
dispose(): Promise<void>;
|
|
1862
|
-
/**
|
|
1863
|
-
* Объединяет конструкторские хуки с хуками подключаемых плагинов.
|
|
1864
|
-
*
|
|
1865
|
-
* Возвращённый объект динамический: подключение и отключение плагина начинает действовать
|
|
1866
|
-
* со следующего логического запроса без пересоздания транспорта.
|
|
1867
|
-
*/
|
|
1868
|
-
hooks(base: ClientHooks): ClientHooks;
|
|
1748
|
+
interface Author {
|
|
1749
|
+
id: UserId;
|
|
1750
|
+
username: string;
|
|
1751
|
+
displayName: string;
|
|
1869
1752
|
/**
|
|
1870
|
-
*
|
|
1871
|
-
*
|
|
1872
|
-
* Снимок цепочки берётся в начале: `unuse()` влияет на новые запросы, но не обрывает
|
|
1873
|
-
* уже выполняющийся посередине.
|
|
1753
|
+
* **Эмодзи, а не картинка.**
|
|
1874
1754
|
*
|
|
1875
|
-
*
|
|
1755
|
+
* На итд.com аватар — это символ клана (`🩵`, `🦎`), а не адрес изображения.
|
|
1756
|
+
* Отрисовывать его нужно как текст.
|
|
1876
1757
|
*/
|
|
1877
|
-
|
|
1758
|
+
avatar: string;
|
|
1759
|
+
/** Пройдена ли верификация. */
|
|
1760
|
+
verified: boolean;
|
|
1761
|
+
/** Активный значок профиля. Может отсутствовать. */
|
|
1762
|
+
pin?: Pin | null;
|
|
1763
|
+
/** Есть ли премиум-подписка (значок NUKSTA). */
|
|
1764
|
+
hasNuksta?: boolean;
|
|
1765
|
+
}
|
|
1766
|
+
/**
|
|
1767
|
+
* Участник события в уведомлении.
|
|
1768
|
+
*
|
|
1769
|
+
* Отличается от {@link Author} набором полей: вместо значков приходит связь с вами.
|
|
1770
|
+
*/
|
|
1771
|
+
interface Actor {
|
|
1772
|
+
id: UserId;
|
|
1773
|
+
username: string;
|
|
1774
|
+
displayName: string;
|
|
1775
|
+
/** Эмодзи-аватар, см. {@link Author.avatar}. */
|
|
1776
|
+
avatar: string;
|
|
1777
|
+
/** Подписаны ли вы на этого пользователя. */
|
|
1778
|
+
isFollowing?: boolean;
|
|
1779
|
+
/** Подписан ли он на вас. */
|
|
1780
|
+
isFollowedBy?: boolean;
|
|
1781
|
+
}
|
|
1782
|
+
/**
|
|
1783
|
+
* Пользователь в списках.
|
|
1784
|
+
*
|
|
1785
|
+
* Набор полей зависит от эндпоинта: подписчики и подписки приносят `isFollowing`,
|
|
1786
|
+
* поиск и рекомендации — `followersCount` и `hasNuksta`. Необязательные поля отражают
|
|
1787
|
+
* это различие.
|
|
1788
|
+
*/
|
|
1789
|
+
interface UserSummary {
|
|
1790
|
+
id: UserId;
|
|
1791
|
+
username: string;
|
|
1792
|
+
displayName: string;
|
|
1793
|
+
/** Эмодзи-аватар, см. {@link Author.avatar}. */
|
|
1794
|
+
avatar: string;
|
|
1795
|
+
verified: boolean;
|
|
1796
|
+
/** Подписаны ли вы. Приходит в списках подписчиков и подписок. */
|
|
1797
|
+
isFollowing?: boolean;
|
|
1798
|
+
/** Есть ли премиум. Приходит в поиске и рекомендациях. */
|
|
1799
|
+
hasNuksta?: boolean;
|
|
1800
|
+
/** Число подписчиков. Приходит в поиске и рекомендациях. */
|
|
1801
|
+
followersCount?: number;
|
|
1802
|
+
}
|
|
1803
|
+
/** Поля профиля, общие для своего и чужого. */
|
|
1804
|
+
interface ProfileBase {
|
|
1805
|
+
id: UserId;
|
|
1806
|
+
username: string;
|
|
1807
|
+
displayName: string;
|
|
1808
|
+
/** Эмодзи-аватар, см. {@link Author.avatar}. */
|
|
1809
|
+
avatar: string;
|
|
1810
|
+
/** URL изображения баннера либо `null`. */
|
|
1811
|
+
banner: string | null;
|
|
1812
|
+
/** Описание профиля. */
|
|
1813
|
+
bio: string;
|
|
1814
|
+
verified: boolean;
|
|
1815
|
+
pin?: Pin | null;
|
|
1816
|
+
/** Кто может писать на стену. */
|
|
1817
|
+
wallAccess: WallAccess;
|
|
1818
|
+
/** Кто видит реакции. */
|
|
1819
|
+
likesVisibility: LikesVisibility;
|
|
1820
|
+
followersCount: number;
|
|
1821
|
+
followingCount: number;
|
|
1822
|
+
postsCount: number;
|
|
1823
|
+
createdAt: IsoDate;
|
|
1824
|
+
}
|
|
1825
|
+
/** Состояние подписки на премиум. */
|
|
1826
|
+
interface SubscriptionState {
|
|
1827
|
+
isActive: boolean;
|
|
1828
|
+
expiresAt: IsoDate | null;
|
|
1829
|
+
autoRenewal: boolean;
|
|
1830
|
+
}
|
|
1831
|
+
/**
|
|
1832
|
+
* Свой профиль — ответ `GET /api/users/me`.
|
|
1833
|
+
*
|
|
1834
|
+
* Отличается от чужого наличием {@link subscription} и {@link isPhoneVerified}
|
|
1835
|
+
* и отсутствием полей связи (`isFollowing`, `online`).
|
|
1836
|
+
*/
|
|
1837
|
+
interface MyProfile extends ProfileBase {
|
|
1838
|
+
/** Закрыт ли профиль. */
|
|
1839
|
+
isPrivate: boolean;
|
|
1840
|
+
/** Подтверждён ли телефон. Без него часть действий недоступна. */
|
|
1841
|
+
isPhoneVerified: boolean;
|
|
1842
|
+
/** Своя премиум-подписка. */
|
|
1843
|
+
subscription: SubscriptionState;
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1846
|
+
* Состояние авторизации — ответ `GET /api/profile`.
|
|
1847
|
+
*
|
|
1848
|
+
* Endpoint доступен без сессии: в этом случае `authenticated` равен `false`,
|
|
1849
|
+
* а `user` — `null`.
|
|
1850
|
+
*/
|
|
1851
|
+
interface AuthState {
|
|
1852
|
+
/** Есть ли действующая сессия. */
|
|
1853
|
+
authenticated: boolean;
|
|
1854
|
+
/** Заблокирован ли текущий аккаунт. */
|
|
1855
|
+
banned: boolean;
|
|
1856
|
+
/** Текущий пользователь либо `null` без действующей сессии. */
|
|
1857
|
+
user: MyProfile | null;
|
|
1858
|
+
}
|
|
1859
|
+
/**
|
|
1860
|
+
* Чужой профиль — ответ `GET /api/users/{id|username}`.
|
|
1861
|
+
*
|
|
1862
|
+
* Вместо своей подписки содержит связь с вами и присутствие.
|
|
1863
|
+
*/
|
|
1864
|
+
interface PublicProfile extends ProfileBase {
|
|
1865
|
+
hasNuksta?: boolean;
|
|
1866
|
+
/** Закреплённый пост, если он есть. */
|
|
1867
|
+
pinnedPostId: string | null;
|
|
1868
|
+
/** Подписаны ли вы на него. */
|
|
1869
|
+
isFollowing: boolean;
|
|
1870
|
+
/** Подписан ли он на вас. */
|
|
1871
|
+
isFollowedBy: boolean;
|
|
1872
|
+
/** Сейчас ли пользователь в сети. */
|
|
1873
|
+
online: boolean;
|
|
1874
|
+
/** Когда был в сети. `null`, если скрыто настройками приватности. */
|
|
1875
|
+
lastSeen: IsoDate | null;
|
|
1876
|
+
}
|
|
1877
|
+
/** Профиль: свой либо чужой. Различаются функцией `isMyProfile()`. */
|
|
1878
|
+
type Profile = MyProfile | PublicProfile;
|
|
1879
|
+
/** Настройки приватности профиля. */
|
|
1880
|
+
interface PrivacySettings {
|
|
1881
|
+
/** Закрыт ли профиль: подписка требует одобрения. */
|
|
1882
|
+
isPrivate: boolean;
|
|
1883
|
+
wallAccess: WallAccess;
|
|
1884
|
+
likesVisibility: LikesVisibility;
|
|
1885
|
+
/** Показывать ли время последнего посещения. */
|
|
1886
|
+
showLastSeen: boolean;
|
|
1887
|
+
}
|
|
1888
|
+
/**
|
|
1889
|
+
* Результат подписки на пользователя.
|
|
1890
|
+
*
|
|
1891
|
+
* @example
|
|
1892
|
+
* ```ts
|
|
1893
|
+
* const result = await itd.users.follow('nowkie');
|
|
1894
|
+
* // { following: true, followersCount: 11 }
|
|
1895
|
+
* ```
|
|
1896
|
+
*/
|
|
1897
|
+
interface FollowResult {
|
|
1898
|
+
/** Подписка оформлена. У закрытого профиля отправляется заявка, и здесь будет `false`. */
|
|
1899
|
+
following: boolean;
|
|
1900
|
+
/** Сколько подписчиков стало у пользователя после действия. */
|
|
1901
|
+
followersCount?: number;
|
|
1902
|
+
/** Статус заявки, если профиль закрыт. */
|
|
1903
|
+
status?: Loose<'following' | 'requested'>;
|
|
1904
|
+
}
|
|
1905
|
+
/** Закреплённые значки профиля и выбранный из них. */
|
|
1906
|
+
interface PinsResult {
|
|
1907
|
+
pins: Pin[];
|
|
1908
|
+
/** Идентификатор активного значка — строка, а не объект. */
|
|
1909
|
+
activePin: string | null;
|
|
1878
1910
|
}
|
|
1879
1911
|
//#endregion
|
|
1880
|
-
//#region src/
|
|
1912
|
+
//#region src/models/notifications.d.ts
|
|
1881
1913
|
/**
|
|
1882
|
-
*
|
|
1883
|
-
*
|
|
1884
|
-
* Нужна прежде всего ботам: без неё цикл по сотне постов уходит в API одним залпом
|
|
1885
|
-
* и упирается в `RATE_LIMIT_EXCEEDED`.
|
|
1914
|
+
* Уведомление в единой форме.
|
|
1886
1915
|
*
|
|
1887
|
-
*
|
|
1888
|
-
*
|
|
1916
|
+
* REST-список и SSE-поток отдают уведомления по-разному — разные имена типов, разные имена
|
|
1917
|
+
* полей, один участник против массива. Библиотека приводит оба вида к этой структуре,
|
|
1918
|
+
* поэтому объекты из `itd.notifications.list()` и из потока можно складывать в один список.
|
|
1889
1919
|
*
|
|
1890
|
-
* @
|
|
1920
|
+
* Исходные данные не теряются: серверное имя типа остаётся в {@link rawType},
|
|
1921
|
+
* а весь необработанный объект — в {@link raw}.
|
|
1891
1922
|
*/
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
/**
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1923
|
+
interface Notification {
|
|
1924
|
+
id: string;
|
|
1925
|
+
/** Канонический тип. Старые имена (`like`, `comment`) приведены к новым. */
|
|
1926
|
+
type: NotificationType;
|
|
1927
|
+
/** Имя типа в том виде, в каком его прислал сервер. */
|
|
1928
|
+
rawType: string;
|
|
1929
|
+
/** Объект события: пост, комментарий, пользователь. */
|
|
1930
|
+
entityId: string | null;
|
|
1931
|
+
/** Пост, которому принадлежит комментарий, если событие о комментарии. */
|
|
1932
|
+
parentEntityId: string | null;
|
|
1933
|
+
/** Прочитано ли уведомление. */
|
|
1934
|
+
isRead: boolean;
|
|
1935
|
+
/** Кто совершил действие. Для схлопнутых уведомлений — несколько человек. */
|
|
1936
|
+
actors: Actor[];
|
|
1937
|
+
/** Сколько участников схлопнуто в одно уведомление. Минимум 1. */
|
|
1938
|
+
count: number;
|
|
1939
|
+
/** Текст или заголовок объекта события. */
|
|
1940
|
+
preview: string | null;
|
|
1941
|
+
/** Ссылка перехода, предложенная сервером. Обычно точнее её `resolveNotificationUrl()`. */
|
|
1942
|
+
clickUrl?: string;
|
|
1943
|
+
createdAt: IsoDate;
|
|
1944
|
+
/** Когда уведомление изменилось — например было прочитано. */
|
|
1945
|
+
updatedAt: IsoDate;
|
|
1946
|
+
/** Исходный объект как он пришёл от сервера. */
|
|
1947
|
+
raw: unknown;
|
|
1917
1948
|
}
|
|
1918
1949
|
/**
|
|
1919
|
-
*
|
|
1950
|
+
* Настройки уведомлений.
|
|
1920
1951
|
*
|
|
1921
|
-
*
|
|
1952
|
+
* Сервер отдаёт плоский объект, но исторически знает два набора имён для одних и тех же
|
|
1953
|
+
* настроек (`likes` и `reactions`, `comments` и `replies`). При сохранении библиотека
|
|
1954
|
+
* отправляет оба, при чтении принимает любой.
|
|
1922
1955
|
*/
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
/**
|
|
1927
|
-
|
|
1928
|
-
/**
|
|
1929
|
-
|
|
1956
|
+
interface NotificationSettings {
|
|
1957
|
+
/** Общий выключатель доставки. */
|
|
1958
|
+
enabled: boolean;
|
|
1959
|
+
/** Звук уведомления. */
|
|
1960
|
+
sound: boolean;
|
|
1961
|
+
/** Новые подписчики. */
|
|
1962
|
+
follows: boolean;
|
|
1963
|
+
/** Записи на вашей стене. */
|
|
1964
|
+
wallPosts: boolean;
|
|
1965
|
+
/** Реакции на ваши записи. */
|
|
1966
|
+
likes: boolean;
|
|
1967
|
+
/** Комментарии и ответы. */
|
|
1968
|
+
comments: boolean;
|
|
1969
|
+
/** Упоминания. */
|
|
1970
|
+
mentions: boolean;
|
|
1930
1971
|
}
|
|
1931
1972
|
//#endregion
|
|
1932
1973
|
//#region src/notifications/normalize.d.ts
|
|
@@ -1991,6 +2032,8 @@ interface TransportEvent {
|
|
|
1991
2032
|
interface TransportContext {
|
|
1992
2033
|
/** Базовый URL API. */
|
|
1993
2034
|
baseUrl: string;
|
|
2035
|
+
/** Разрешено ли передавать токен этому сервису. */
|
|
2036
|
+
authorize: boolean;
|
|
1994
2037
|
/** Реализация `fetch`. */
|
|
1995
2038
|
fetch: typeof fetch;
|
|
1996
2039
|
/**
|
|
@@ -2009,15 +2052,7 @@ interface TransportContext {
|
|
|
2009
2052
|
/** Вызывается, когда соединение установлено. */
|
|
2010
2053
|
onOpen: () => void;
|
|
2011
2054
|
}
|
|
2012
|
-
/**
|
|
2013
|
-
* Канал получения событий в реальном времени.
|
|
2014
|
-
*
|
|
2015
|
-
* Сейчас у платформы один такой канал — поток `text/event-stream`. Абстракция нужна
|
|
2016
|
-
* на будущее: политика безопасности сайта уже разрешает `wss://*.xn--d1ah4a.com`,
|
|
2017
|
-
* и когда появится WebSocket, достаточно будет добавить ещё одну реализацию этого
|
|
2018
|
-
* интерфейса. Переподключение, обновление токена и разбор уведомлений от транспорта
|
|
2019
|
-
* не зависят.
|
|
2020
|
-
*/
|
|
2055
|
+
/** Канал получения исходных событий в реальном времени. */
|
|
2021
2056
|
interface RealtimeTransport {
|
|
2022
2057
|
/** Понятное имя для логов и диагностики. */
|
|
2023
2058
|
readonly name: string;
|
|
@@ -2079,17 +2114,28 @@ type RealtimeUpdateType = RealtimeUpdate['type'];
|
|
|
2079
2114
|
type RealtimeUpdateOfType<T extends RealtimeUpdateType> = Extract<RealtimeUpdate, {
|
|
2080
2115
|
type: T;
|
|
2081
2116
|
}>;
|
|
2082
|
-
/**
|
|
2083
|
-
|
|
2117
|
+
/**
|
|
2118
|
+
* Общая форма контекста обработки: то, что есть у любого потока независимо от домена.
|
|
2119
|
+
*
|
|
2120
|
+
* Контекст — обычный объектный литерал, а не класс с геттерами и не `Object.freeze`:
|
|
2121
|
+
* плагины-флейворы присваивают в него свои поля (`ctx.session = …`), а `@itd-api/hydrate`
|
|
2122
|
+
* подменяет `update` и `stream` через `Object.defineProperty`.
|
|
2123
|
+
*
|
|
2124
|
+
* @typeParam U нормализованное обновление домена
|
|
2125
|
+
* @typeParam S поток, который его получил
|
|
2126
|
+
*/
|
|
2127
|
+
interface RealtimeContextBase<U = unknown, S = unknown> {
|
|
2084
2128
|
/** Нормализованные данные обновления. */
|
|
2085
2129
|
readonly update: U;
|
|
2086
2130
|
/** Поток, который получил обновление. */
|
|
2087
|
-
readonly stream:
|
|
2131
|
+
readonly stream: S;
|
|
2088
2132
|
/** Исходный кадр транспорта. Для начальной REST-синхронизации равен `undefined`. */
|
|
2089
2133
|
readonly raw: TransportEvent | undefined;
|
|
2090
2134
|
/** Откуда получены данные. */
|
|
2091
2135
|
readonly origin: RealtimeUpdateOrigin;
|
|
2092
2136
|
}
|
|
2137
|
+
/** Контекст обработки одного обновления потока уведомлений. */
|
|
2138
|
+
type RealtimeContext<U extends RealtimeUpdate = RealtimeUpdate> = RealtimeContextBase<U, ItdRealtime>;
|
|
2093
2139
|
/** Контекст уведомления с типом, суженным фильтром. */
|
|
2094
2140
|
type RealtimeNotificationContext<T extends NotificationType = NotificationType> = RealtimeContext<RealtimeNotificationUpdate<T>>;
|
|
2095
2141
|
/** Условия отбора уведомлений. Все указанные поля объединяются через логическое И. */
|
|
@@ -2112,15 +2158,21 @@ type RealtimeNotificationSelector<T extends NotificationType = NotificationType>
|
|
|
2112
2158
|
/** Продолжает цепочку промежуточных обработчиков потока. */
|
|
2113
2159
|
type RealtimeNext = () => Promise<void>;
|
|
2114
2160
|
/** Обрабатывает обновление потока до его передачи подписчикам. */
|
|
2115
|
-
type RealtimeMiddleware<C extends
|
|
2161
|
+
type RealtimeMiddleware<C extends RealtimeContextBase = RealtimeContext> = (context: C, next: RealtimeNext) => void | Promise<void>;
|
|
2162
|
+
/** Объект, предоставляющий снимок промежуточного обработчика потока. */
|
|
2163
|
+
interface RealtimeMiddlewareObj<C extends RealtimeContextBase = RealtimeContext> {
|
|
2164
|
+
middleware(): RealtimeMiddleware<C>;
|
|
2165
|
+
}
|
|
2116
2166
|
/** Асинхронный обработчик нормализованного обновления потока. */
|
|
2117
|
-
type RealtimeHandler<C extends
|
|
2167
|
+
type RealtimeHandler<C extends RealtimeContextBase = RealtimeContext> = (context: C) => unknown | Promise<unknown>;
|
|
2118
2168
|
/** Условие отбора контекста потока. */
|
|
2119
|
-
type RealtimePredicate = (context:
|
|
2169
|
+
type RealtimePredicate<C extends RealtimeContextBase = RealtimeContext> = (context: C) => boolean;
|
|
2120
2170
|
/** Проверка, сужающая тип контекста потока. */
|
|
2121
|
-
type RealtimeTypeGuard<C extends RealtimeContext> = (context:
|
|
2171
|
+
type RealtimeTypeGuard<C extends B, B extends RealtimeContextBase = RealtimeContext> = (context: B) => context is C;
|
|
2122
2172
|
/** Ключи, по которым обновления нельзя обрабатывать одновременно. */
|
|
2123
|
-
type RealtimeSequentializer = (context:
|
|
2173
|
+
type RealtimeSequentializer<C extends RealtimeContextBase = RealtimeContext> = (context: C) => PropertyKey | readonly PropertyKey[] | undefined;
|
|
2174
|
+
/** Выполняет промежуточные обработчики по порядку и запрещает повторный вызов `next()`. */
|
|
2175
|
+
declare function runRealtimeMiddleware<C extends RealtimeContextBase>(middleware: readonly RealtimeMiddleware<C>[], context: C, terminal: RealtimeNext): Promise<void>;
|
|
2124
2176
|
//#endregion
|
|
2125
2177
|
//#region src/realtime/reconnect.d.ts
|
|
2126
2178
|
/**
|
|
@@ -2148,27 +2200,14 @@ interface ReconnectOptions {
|
|
|
2148
2200
|
maxAttempts?: number;
|
|
2149
2201
|
}
|
|
2150
2202
|
//#endregion
|
|
2151
|
-
//#region src/realtime/
|
|
2152
|
-
/**
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
* Приходит первым кадром сразу после установки соединения.
|
|
2160
|
-
*/
|
|
2161
|
-
ready: {
|
|
2162
|
-
userId: string | undefined;
|
|
2163
|
-
};
|
|
2164
|
-
/**
|
|
2165
|
-
* Получено актуальное число непрочитанных.
|
|
2166
|
-
*
|
|
2167
|
-
* При подключении клиент может запросить начальное значение через REST. Затем событие
|
|
2168
|
-
* возникает, только если счётчик пришёл в потоке. В остальных случаях обновляйте его
|
|
2169
|
-
* в приложении либо запрашивайте `itd.notifications.count()`.
|
|
2170
|
-
*/
|
|
2171
|
-
unreadCount: number;
|
|
2203
|
+
//#region src/realtime/engine.d.ts
|
|
2204
|
+
/**
|
|
2205
|
+
* События, которые движок рассылает сам.
|
|
2206
|
+
*
|
|
2207
|
+
* Ни одно из них не зависит от домена, поэтому они одинаковы у любого потока.
|
|
2208
|
+
* Домен расширяет эту карту своими событиями.
|
|
2209
|
+
*/
|
|
2210
|
+
interface RealtimeEngineEvents<C extends RealtimeContextBase = RealtimeContextBase> {
|
|
2172
2211
|
/** Изменилось состояние соединения. */
|
|
2173
2212
|
status: RealtimeStatus;
|
|
2174
2213
|
/** Соединение оборвалось; будет предпринята попытка переподключения. */
|
|
@@ -2188,18 +2227,46 @@ interface RealtimeEvents {
|
|
|
2188
2227
|
};
|
|
2189
2228
|
/** Попытки исчерпаны — соединение восстановится только ручным `connect()`. */
|
|
2190
2229
|
giveup: undefined;
|
|
2191
|
-
/** Любой исходный кадр транспорта. Отправляется до нормализации и
|
|
2230
|
+
/** Любой исходный кадр транспорта. Отправляется до нормализации и обработчиков. */
|
|
2192
2231
|
message: TransportEvent;
|
|
2193
2232
|
/** Промежуточный обработчик потока завершился исключением. */
|
|
2194
2233
|
middlewareError: {
|
|
2195
2234
|
error: unknown;
|
|
2196
|
-
context:
|
|
2235
|
+
context: C;
|
|
2197
2236
|
};
|
|
2198
|
-
/** Обработчик
|
|
2237
|
+
/** Обработчик обновления завершился исключением. */
|
|
2199
2238
|
handlerError: {
|
|
2200
2239
|
error: unknown;
|
|
2201
|
-
context:
|
|
2240
|
+
context: C;
|
|
2241
|
+
};
|
|
2242
|
+
}
|
|
2243
|
+
//#endregion
|
|
2244
|
+
//#region src/realtime/stream.d.ts
|
|
2245
|
+
/**
|
|
2246
|
+
* События потока уведомлений.
|
|
2247
|
+
*
|
|
2248
|
+
* Общая часть — {@link RealtimeEngineEvents}: статусы, ошибки и переподключение одинаковы
|
|
2249
|
+
* у любого потока. Ниже — то, что есть только у уведомлений.
|
|
2250
|
+
*/
|
|
2251
|
+
interface RealtimeEvents<C extends RealtimeContext = RealtimeContext> extends RealtimeEngineEvents<C> {
|
|
2252
|
+
/** Пришло новое уведомление. */
|
|
2253
|
+
notification: NotificationEvent;
|
|
2254
|
+
/**
|
|
2255
|
+
* Сервер подтвердил подключение и назвал получателя событий.
|
|
2256
|
+
*
|
|
2257
|
+
* Приходит первым кадром сразу после установки соединения.
|
|
2258
|
+
*/
|
|
2259
|
+
ready: {
|
|
2260
|
+
userId: string | undefined;
|
|
2202
2261
|
};
|
|
2262
|
+
/**
|
|
2263
|
+
* Получено актуальное число непрочитанных.
|
|
2264
|
+
*
|
|
2265
|
+
* При подключении клиент может запросить начальное значение через REST. Затем событие
|
|
2266
|
+
* возникает, только если счётчик пришёл в потоке. В остальных случаях обновляйте его
|
|
2267
|
+
* в приложении либо запрашивайте `itd.notifications.count()`.
|
|
2268
|
+
*/
|
|
2269
|
+
unreadCount: number;
|
|
2203
2270
|
}
|
|
2204
2271
|
/** Способ получения событий. */
|
|
2205
2272
|
declare const RealtimeTransportKind: Readonly<{
|
|
@@ -2212,7 +2279,7 @@ declare const RealtimeTransportKind: Readonly<{
|
|
|
2212
2279
|
}>;
|
|
2213
2280
|
type RealtimeTransportKind = (typeof RealtimeTransportKind)[keyof typeof RealtimeTransportKind];
|
|
2214
2281
|
/** Настройки потока уведомлений. */
|
|
2215
|
-
interface RealtimeOptions extends ReconnectOptions {
|
|
2282
|
+
interface RealtimeOptions<C extends RealtimeContext = RealtimeContext> extends ReconnectOptions {
|
|
2216
2283
|
/**
|
|
2217
2284
|
* Транспорт. По умолчанию `auto`: поток событий, если среда умеет читать тело ответа
|
|
2218
2285
|
* по частям, иначе опрос.
|
|
@@ -2255,11 +2322,13 @@ interface RealtimeOptions extends ReconnectOptions {
|
|
|
2255
2322
|
/** Максимальное число одновременно обрабатываемых обновлений. По умолчанию 1. */
|
|
2256
2323
|
concurrency?: number;
|
|
2257
2324
|
/** Возвращает ключи обновлений, которые нельзя обрабатывать одновременно. */
|
|
2258
|
-
sequentialize?: RealtimeSequentializer
|
|
2325
|
+
sequentialize?: RealtimeSequentializer<C>;
|
|
2259
2326
|
}
|
|
2260
2327
|
/** Что поток получает от клиента. */
|
|
2261
2328
|
interface RealtimeDeps {
|
|
2262
2329
|
baseUrl: string;
|
|
2330
|
+
/** Разрешено ли транспорту передавать токен этому сервису. */
|
|
2331
|
+
authorize?: boolean | undefined;
|
|
2263
2332
|
fetch: typeof fetch;
|
|
2264
2333
|
clock?: ItdClock;
|
|
2265
2334
|
/** Общие заголовки клиента для адреса — см. {@link TransportContext.baseHeaders}. */
|
|
@@ -2285,6 +2354,9 @@ interface RealtimeDeps {
|
|
|
2285
2354
|
* Получается вызовом `itd.realtime()`. Соединение поднимается методом {@link connect}
|
|
2286
2355
|
* и держится само: обрывы, обновление токена и повторные попытки библиотека берёт на себя.
|
|
2287
2356
|
*
|
|
2357
|
+
* Параметр типа задаёт форму контекста: плагин может расширить её своими полями
|
|
2358
|
+
* (`ItdRealtime<RealtimeContext & SessionFlavor<S>>`) и типизировать обработчики.
|
|
2359
|
+
*
|
|
2288
2360
|
* @example
|
|
2289
2361
|
* ```ts
|
|
2290
2362
|
* import { NotificationType } from 'itd-api';
|
|
@@ -2302,12 +2374,12 @@ interface RealtimeDeps {
|
|
|
2302
2374
|
* await stream.drain();
|
|
2303
2375
|
* ```
|
|
2304
2376
|
*/
|
|
2305
|
-
declare class ItdRealtime {
|
|
2377
|
+
declare class ItdRealtime<C extends RealtimeContext = RealtimeContext> {
|
|
2306
2378
|
#private;
|
|
2307
|
-
constructor(deps: RealtimeDeps, options?: RealtimeOptions);
|
|
2379
|
+
constructor(deps: RealtimeDeps, options?: RealtimeOptions<C>);
|
|
2308
2380
|
/** Текущее состояние соединения. */
|
|
2309
2381
|
get status(): RealtimeStatus;
|
|
2310
|
-
/**
|
|
2382
|
+
/** Имя используемого транспорта. */
|
|
2311
2383
|
get transport(): string;
|
|
2312
2384
|
/** Базовый URL клиента, создавшего поток. @internal */
|
|
2313
2385
|
get baseUrl(): string;
|
|
@@ -2316,32 +2388,32 @@ declare class ItdRealtime {
|
|
|
2316
2388
|
/** Непрозрачная область авторизации создавшего поток клиента. @internal */
|
|
2317
2389
|
getAuthScope(): string | undefined;
|
|
2318
2390
|
/** Подписывается на событие потока. @returns функция отписки */
|
|
2319
|
-
on<K extends keyof RealtimeEvents
|
|
2391
|
+
on<K extends keyof RealtimeEvents<C>>(event: K, listener: Listener<RealtimeEvents<C>[K]>): Unsubscribe;
|
|
2320
2392
|
/** Подписывается на одно срабатывание. */
|
|
2321
|
-
once<K extends keyof RealtimeEvents
|
|
2393
|
+
once<K extends keyof RealtimeEvents<C>>(event: K, listener: Listener<RealtimeEvents<C>[K]>): Unsubscribe;
|
|
2322
2394
|
/**
|
|
2323
|
-
* Добавляет промежуточный обработчик
|
|
2395
|
+
* Добавляет промежуточный обработчик или объект, предоставляющий его через `middleware()`.
|
|
2324
2396
|
*
|
|
2325
2397
|
* Обработчики выполняются в порядке регистрации. Если `next()` не вызван, обновление не
|
|
2326
2398
|
* передаётся дальше по цепочке, асинхронным обработчикам и слушателям событий.
|
|
2327
2399
|
*
|
|
2328
2400
|
* @returns функция удаления обработчика
|
|
2329
2401
|
*/
|
|
2330
|
-
use(middleware: RealtimeMiddleware): Unsubscribe;
|
|
2402
|
+
use(middleware: RealtimeMiddleware<C> | RealtimeMiddlewareObj<C>): Unsubscribe;
|
|
2331
2403
|
/** Подписывает асинхронный обработчик на все нормализованные обновления. */
|
|
2332
|
-
onUpdate(handler: RealtimeHandler): Unsubscribe;
|
|
2404
|
+
onUpdate(handler: RealtimeHandler<C>): Unsubscribe;
|
|
2333
2405
|
/** Подписывает асинхронный обработчик на обновление указанного типа. */
|
|
2334
|
-
onUpdate<T extends RealtimeUpdateType>(type: T, handler: RealtimeHandler<RealtimeContext<RealtimeUpdateOfType<T>>>): Unsubscribe;
|
|
2406
|
+
onUpdate<T extends RealtimeUpdateType>(type: T, handler: RealtimeHandler<C & RealtimeContext<RealtimeUpdateOfType<T>>>): Unsubscribe;
|
|
2335
2407
|
/** Подписывает асинхронный обработчик по функции сужения типа. */
|
|
2336
|
-
onUpdate<
|
|
2408
|
+
onUpdate<N extends C>(guard: RealtimeTypeGuard<N, C>, handler: RealtimeHandler<N>): Unsubscribe;
|
|
2337
2409
|
/** Подписывает асинхронный обработчик по пользовательскому условию. */
|
|
2338
|
-
onUpdate(predicate: RealtimePredicate
|
|
2410
|
+
onUpdate(predicate: RealtimePredicate<C>, handler: RealtimeHandler<C>): Unsubscribe;
|
|
2339
2411
|
/** Подписывает асинхронный обработчик на уведомления, подходящие под фильтр. */
|
|
2340
|
-
onNotification<T extends NotificationType>(selector: RealtimeNotificationSelector<T>, handler: RealtimeHandler<RealtimeNotificationContext<T>>): Unsubscribe;
|
|
2412
|
+
onNotification<T extends NotificationType>(selector: RealtimeNotificationSelector<T>, handler: RealtimeHandler<C & RealtimeNotificationContext<T>>): Unsubscribe;
|
|
2341
2413
|
/** Подписывает асинхронный обработчик по функции сужения типа уведомления. */
|
|
2342
|
-
onNotification<
|
|
2414
|
+
onNotification<N extends C & RealtimeNotificationContext>(guard: (context: C & RealtimeNotificationContext) => context is N, handler: RealtimeHandler<N>): Unsubscribe;
|
|
2343
2415
|
/** Подписывает асинхронный обработчик по пользовательскому условию. */
|
|
2344
|
-
onNotification(predicate: (context: RealtimeNotificationContext) => boolean, handler: RealtimeHandler<RealtimeNotificationContext>): Unsubscribe;
|
|
2416
|
+
onNotification(predicate: (context: C & RealtimeNotificationContext) => boolean, handler: RealtimeHandler<C & RealtimeNotificationContext>): Unsubscribe;
|
|
2345
2417
|
/**
|
|
2346
2418
|
* Поднимает соединение.
|
|
2347
2419
|
*
|
|
@@ -2349,6 +2421,8 @@ declare class ItdRealtime {
|
|
|
2349
2421
|
* подключения при перерисовке интерфейса.
|
|
2350
2422
|
*
|
|
2351
2423
|
* Возвращает управление сразу после запуска: соединение живёт в фоне.
|
|
2424
|
+
*
|
|
2425
|
+
* @throws если создавший поток клиент уже освобождён
|
|
2352
2426
|
*/
|
|
2353
2427
|
connect(): Promise<void>;
|
|
2354
2428
|
/** Закрывает соединение и отменяет запланированные попытки. */
|
|
@@ -2364,15 +2438,13 @@ declare class ItdRealtime {
|
|
|
2364
2438
|
interface HttpClientDeps {
|
|
2365
2439
|
/** Готовый обработчик — вся цепочка слоёв поверх транспорта. */
|
|
2366
2440
|
handler: RequestHandler;
|
|
2367
|
-
/** Реестр плагинов: у него ресурсы спрашивают имена заявленных опций. */
|
|
2368
|
-
plugins: PluginRegistry;
|
|
2369
2441
|
baseUrl: string;
|
|
2370
2442
|
}
|
|
2371
2443
|
/**
|
|
2372
2444
|
* Точка входа ресурсов в конвейер запросов.
|
|
2373
2445
|
*
|
|
2374
2446
|
* Принимает готовый обработчик — цепочку слоёв поверх транспорта, собранную
|
|
2375
|
-
*
|
|
2447
|
+
* во внутреннем runtime клиента, — и отдаёт ресурсам методы `request`/`operation`.
|
|
2376
2448
|
* О слоях и их порядке ресурсы не знают.
|
|
2377
2449
|
*/
|
|
2378
2450
|
declare class HttpClient {
|
|
@@ -2380,13 +2452,6 @@ declare class HttpClient {
|
|
|
2380
2452
|
constructor(deps: HttpClientDeps);
|
|
2381
2453
|
/** Базовый URL, к которому обращается клиент. */
|
|
2382
2454
|
get baseUrl(): string;
|
|
2383
|
-
/**
|
|
2384
|
-
* Имена опций запроса, заявленные плагинами.
|
|
2385
|
-
*
|
|
2386
|
-
* Читается ресурсами: они переносят в транспорт только известные поля, а чужие,
|
|
2387
|
-
* если их никто не заявил, отсеивают.
|
|
2388
|
-
*/
|
|
2389
|
-
get pluginOptionKeys(): ReadonlySet<string>;
|
|
2390
2455
|
/**
|
|
2391
2456
|
* Выполняет запрос к API через собранный конвейер.
|
|
2392
2457
|
*
|
|
@@ -2396,7 +2461,53 @@ declare class HttpClient {
|
|
|
2396
2461
|
* @throws {ItdAbortError} если запрос отменён через `signal`
|
|
2397
2462
|
* @throws {ItdNetworkError} если запрос не дошёл до сервера
|
|
2398
2463
|
*/
|
|
2399
|
-
request<T = unknown>(options:
|
|
2464
|
+
request<T = unknown>(options: PipelineRequestInput): Promise<T>;
|
|
2465
|
+
/** Выполняет встроенную семантическую операцию, подставляя её HTTP-метод из каталога. */
|
|
2466
|
+
operation<T = unknown>(operationId: BuiltInOperationId, options: Omit<PipelineRequest, 'operationId' | 'method'>): Promise<T>;
|
|
2467
|
+
/** Выполняет внутреннюю операцию финализации после начала `ItdClient.dispose()`. @internal */
|
|
2468
|
+
cleanupOperation<T = unknown>(operationId: BuiltInOperationId, options: Omit<PipelineRequest, 'operationId' | 'method'>): Promise<T>;
|
|
2469
|
+
}
|
|
2470
|
+
//#endregion
|
|
2471
|
+
//#region src/models/account.d.ts
|
|
2472
|
+
/** Активная сессия входа. */
|
|
2473
|
+
interface Session {
|
|
2474
|
+
id: string;
|
|
2475
|
+
/** Та ли это сессия, из которой выполнен запрос. */
|
|
2476
|
+
isCurrent: boolean;
|
|
2477
|
+
createdAt: IsoDate;
|
|
2478
|
+
lastUsedAt: IsoDate;
|
|
2479
|
+
expiresAt: IsoDate;
|
|
2480
|
+
ipAddress: string;
|
|
2481
|
+
/** Код страны по IP, например `RU`. */
|
|
2482
|
+
ipCountry: string | null;
|
|
2483
|
+
ipCity: string | null;
|
|
2484
|
+
deviceType: Loose<'desktop' | 'mobile'>;
|
|
2485
|
+
osName: string | null;
|
|
2486
|
+
osVersion: string | null;
|
|
2487
|
+
/** Название браузера или приложения. */
|
|
2488
|
+
clientName: string | null;
|
|
2489
|
+
clientVersion: string | null;
|
|
2490
|
+
deviceModel: string | null;
|
|
2491
|
+
}
|
|
2492
|
+
/** Состояние платной подписки и её цена. */
|
|
2493
|
+
interface Subscription {
|
|
2494
|
+
/** Активна ли подписка сейчас. */
|
|
2495
|
+
active: boolean;
|
|
2496
|
+
/** Включено ли автопродление. */
|
|
2497
|
+
recurringEnabled: boolean;
|
|
2498
|
+
/** Цена в рублях. */
|
|
2499
|
+
price: number;
|
|
2500
|
+
}
|
|
2501
|
+
/** Сохранённый способ оплаты. */
|
|
2502
|
+
interface PaymentMethod {
|
|
2503
|
+
id: string;
|
|
2504
|
+
/** Последние четыре цифры карты. */
|
|
2505
|
+
last4?: string;
|
|
2506
|
+
/** Платёжная система: `visa`, `mastercard`, `mir`. */
|
|
2507
|
+
brand?: string;
|
|
2508
|
+
/** Основной ли это способ оплаты. */
|
|
2509
|
+
isDefault?: boolean;
|
|
2510
|
+
expiresAt?: IsoDate | null;
|
|
2400
2511
|
}
|
|
2401
2512
|
//#endregion
|
|
2402
2513
|
//#region src/core/pagination.d.ts
|
|
@@ -2525,11 +2636,6 @@ declare class Paginator<T> implements AsyncIterable<T> {
|
|
|
2525
2636
|
}
|
|
2526
2637
|
//#endregion
|
|
2527
2638
|
//#region src/resources/base.d.ts
|
|
2528
|
-
/** Параметры перебираемого списка: опции запроса плюс предел числа страниц. */
|
|
2529
|
-
interface ListParams extends RequestOptions {
|
|
2530
|
-
/** Ограничение числа страниц при переборе. */
|
|
2531
|
-
maxPages?: number | undefined;
|
|
2532
|
-
}
|
|
2533
2639
|
/**
|
|
2534
2640
|
* Описание перебираемого эндпоинта.
|
|
2535
2641
|
*
|
|
@@ -2539,7 +2645,9 @@ interface ListParams extends RequestOptions {
|
|
|
2539
2645
|
* @typeParam T тип элемента списка
|
|
2540
2646
|
* @typeParam P тип параметров метода
|
|
2541
2647
|
*/
|
|
2542
|
-
interface ListingSpec<T, P extends
|
|
2648
|
+
interface ListingSpec<T, P extends object> {
|
|
2649
|
+
/** Стабильная семантическая операция списка. */
|
|
2650
|
+
operationId: BuiltInOperationId | ((params: P) => BuiltInOperationId);
|
|
2543
2651
|
/** Путь эндпоинта. */
|
|
2544
2652
|
path: (params: P) => string;
|
|
2545
2653
|
/** Параметры запроса без полей пагинации — их добавит перебор. */
|
|
@@ -2552,35 +2660,25 @@ interface ListingSpec<T, P extends ListParams> {
|
|
|
2552
2660
|
start: (params: P) => PageState;
|
|
2553
2661
|
}
|
|
2554
2662
|
/** Пара методов, собранная из {@link ListingSpec}: разовая загрузка и перебор. */
|
|
2555
|
-
interface Listing<T, P extends
|
|
2663
|
+
interface Listing<T, P extends object> {
|
|
2556
2664
|
/** Загружает одну страницу с позиции, заданной параметрами. */
|
|
2557
|
-
list(params: P): Promise<Page<T>>;
|
|
2665
|
+
list(params: P, options?: RequestOptions): Promise<Page<T>>;
|
|
2558
2666
|
/** Перебирает страницы, сама подставляя позиции. */
|
|
2559
|
-
iterate(params: P): Paginator<T>;
|
|
2667
|
+
iterate(params: P, options?: PaginationOptions): Paginator<T>;
|
|
2560
2668
|
}
|
|
2561
2669
|
/** Общая основа всех групп методов клиента. */
|
|
2562
2670
|
declare class BaseResource {
|
|
2563
2671
|
/** @internal */
|
|
2564
2672
|
protected readonly http: HttpClient;
|
|
2565
2673
|
constructor(http: HttpClient);
|
|
2566
|
-
/**
|
|
2567
|
-
* Переносит опции запроса в описание транспорта.
|
|
2568
|
-
*
|
|
2569
|
-
* Копируются только поля {@link REQUEST_OPTION_KEYS} и опции, заявленные плагинами:
|
|
2570
|
-
* параметры методов наследуют {@link RequestOptions} и приносят с собой `limit`, `cursor`
|
|
2571
|
-
* и прочее, чему в описании запроса делать нечего. Чужие опции плагинов библиотека
|
|
2572
|
-
* не понимает, но обязана донести до обёрток нетронутыми.
|
|
2573
|
-
*/
|
|
2574
|
-
protected requestOptions(options: RequestOptions | undefined): Partial<RequestOptions>;
|
|
2575
2674
|
/**
|
|
2576
2675
|
* Собирает перебор страниц.
|
|
2577
2676
|
*
|
|
2578
2677
|
* @param mode схема пагинации эндпоинта
|
|
2579
2678
|
* @param load загружает одну страницу для указанной позиции
|
|
2580
|
-
* @param options
|
|
2679
|
+
* @param options только управление самим перебором: предел, отмена и начальная позиция
|
|
2581
2680
|
*/
|
|
2582
|
-
protected paginate<T>(mode: PaginationMode, load: (state: PageState) => Promise<Page<T>>, options?:
|
|
2583
|
-
maxPages?: number;
|
|
2681
|
+
protected paginate<T>(mode: PaginationMode, load: (state: PageState) => Promise<Page<T>>, options?: PaginationOptions & {
|
|
2584
2682
|
start?: PageState;
|
|
2585
2683
|
}): Paginator<T>;
|
|
2586
2684
|
/**
|
|
@@ -2592,6 +2690,7 @@ declare class BaseResource {
|
|
|
2592
2690
|
* @example
|
|
2593
2691
|
* ```ts
|
|
2594
2692
|
* #feed = this.paginated<Post, FeedParams>({
|
|
2693
|
+
* operationId: 'posts.list',
|
|
2595
2694
|
* path: () => '/api/posts',
|
|
2596
2695
|
* query: (p) => ({ tab: p.tab, limit: p.limit }),
|
|
2597
2696
|
* start: (p) => (p.cursor ? { cursor: p.cursor } : {}),
|
|
@@ -2600,7 +2699,7 @@ declare class BaseResource {
|
|
|
2600
2699
|
* });
|
|
2601
2700
|
* ```
|
|
2602
2701
|
*/
|
|
2603
|
-
protected paginated<T, P extends
|
|
2702
|
+
protected paginated<T, P extends object>(spec: ListingSpec<T, P>): Listing<T, P>;
|
|
2604
2703
|
}
|
|
2605
2704
|
//#endregion
|
|
2606
2705
|
//#region src/resources/auth.d.ts
|
|
@@ -2811,95 +2910,9 @@ declare class AuthResource extends BaseResource {
|
|
|
2811
2910
|
sessions(options?: RequestOptions): Promise<Session[]>;
|
|
2812
2911
|
/** Завершает указанную сессию. */
|
|
2813
2912
|
revokeSession(sessionId: string, options?: RequestOptions): Promise<void>;
|
|
2814
|
-
/** Завершает все сессии, кроме текущей. */
|
|
2815
|
-
revokeOtherSessions(options?: RequestOptions): Promise<void>;
|
|
2816
|
-
}
|
|
2817
|
-
//#endregion
|
|
2818
|
-
//#region src/builders/base.d.ts
|
|
2819
|
-
/** Метка билдера. Через `Symbol.for` — чтобы распознавание переживало смешивание ESM и CJS. */
|
|
2820
|
-
declare const BUILDER: unique symbol;
|
|
2821
|
-
/**
|
|
2822
|
-
* Билдер входных данных.
|
|
2823
|
-
*
|
|
2824
|
-
* Билдеры необязательны: любой метод, принимающий билдер, принимает и обычный объект.
|
|
2825
|
-
* Проверки одинаковы в обоих случаях.
|
|
2826
|
-
*/
|
|
2827
|
-
interface ItdBuilder<T> {
|
|
2828
|
-
/** @internal */
|
|
2829
|
-
readonly [BUILDER]: true;
|
|
2830
|
-
/**
|
|
2831
|
-
* Собирает и проверяет результат.
|
|
2832
|
-
*
|
|
2833
|
-
* @throws {ItdConfigError} если нарушены требования к данным
|
|
2834
|
-
*/
|
|
2835
|
-
build(): T;
|
|
2836
|
-
/** Чтобы билдер корректно вёл себя внутри `JSON.stringify`. */
|
|
2837
|
-
toJSON(): T;
|
|
2838
|
-
}
|
|
2839
|
-
/**
|
|
2840
|
-
* Три равноправные формы входа: обычный объект, готовый билдер или функция-настройщик.
|
|
2841
|
-
*
|
|
2842
|
-
* @example
|
|
2843
|
-
* ```ts
|
|
2844
|
-
* itd.posts.create({ content: 'привет' }); // объект
|
|
2845
|
-
* itd.posts.create(post().content('привет')); // билдер
|
|
2846
|
-
* itd.posts.create((p) => p.content('привет')); // функция
|
|
2847
|
-
* ```
|
|
2848
|
-
*/
|
|
2849
|
-
type BuilderInput<T, B extends ItdBuilder<T>> = T | B | ((builder: B) => B | T);
|
|
2850
|
-
/** Является ли значение билдером. */
|
|
2851
|
-
declare function isBuilder<T>(value: unknown): value is ItdBuilder<T>;
|
|
2852
|
-
//#endregion
|
|
2853
|
-
//#region src/builders/poll.d.ts
|
|
2854
|
-
/**
|
|
2855
|
-
* Билдер опроса.
|
|
2856
|
-
*
|
|
2857
|
-
* Неизменяемый: каждый вызов возвращает новый экземпляр, поэтому заготовку можно
|
|
2858
|
-
* переиспользовать, не боясь её испортить. Создаётся функцией {@link poll}.
|
|
2859
|
-
*/
|
|
2860
|
-
declare class PollBuilder implements ItdBuilder<CreatePollInput> {
|
|
2861
|
-
#private;
|
|
2862
|
-
/** @internal */
|
|
2863
|
-
readonly [BUILDER]: true;
|
|
2864
|
-
/** @internal Создавайте билдер функцией {@link poll}. */
|
|
2865
|
-
constructor(state: CreatePollInput);
|
|
2866
|
-
/** Задаёт вопрос. */
|
|
2867
|
-
question(text: string): PollBuilder;
|
|
2868
|
-
/** Добавляет один вариант ответа. */
|
|
2869
|
-
option(text: string): PollBuilder;
|
|
2870
|
-
/**
|
|
2871
|
-
* Добавляет несколько вариантов сразу.
|
|
2872
|
-
*
|
|
2873
|
-
* @example
|
|
2874
|
-
* ```ts
|
|
2875
|
-
* poll('ну как?').options('да', 'нет', 'не знаю');
|
|
2876
|
-
* ```
|
|
2877
|
-
*/
|
|
2878
|
-
options(...texts: string[]): PollBuilder;
|
|
2879
|
-
/** Разрешает выбор нескольких вариантов. */
|
|
2880
|
-
multipleChoice(enabled?: boolean): PollBuilder;
|
|
2881
|
-
build(): CreatePollInput;
|
|
2882
|
-
toJSON(): CreatePollInput;
|
|
2883
|
-
}
|
|
2884
|
-
/**
|
|
2885
|
-
* Начинает сборку опроса.
|
|
2886
|
-
*
|
|
2887
|
-
* @param question вопрос; можно задать позже методом {@link PollBuilder.question}
|
|
2888
|
-
*
|
|
2889
|
-
* @example
|
|
2890
|
-
* ```ts
|
|
2891
|
-
* import { poll } from 'itd-api';
|
|
2892
|
-
*
|
|
2893
|
-
* const q = poll('Какой язык лучше?')
|
|
2894
|
-
* .options('TypeScript', 'JavaScript')
|
|
2895
|
-
* .multipleChoice();
|
|
2896
|
-
*
|
|
2897
|
-
* await itd.posts.create({ content: 'голосуем', poll: q });
|
|
2898
|
-
* ```
|
|
2899
|
-
*/
|
|
2900
|
-
declare function poll(question?: string): PollBuilder;
|
|
2901
|
-
/** Что принимает параметр опроса: объект, билдер или функция-настройщик. */
|
|
2902
|
-
type PollInput = BuilderInput<CreatePollInput, PollBuilder>;
|
|
2913
|
+
/** Завершает все сессии, кроме текущей. */
|
|
2914
|
+
revokeOtherSessions(options?: RequestOptions): Promise<void>;
|
|
2915
|
+
}
|
|
2903
2916
|
//#endregion
|
|
2904
2917
|
//#region src/types/params.d.ts
|
|
2905
2918
|
/** Данные для создания опроса. */
|
|
@@ -2913,8 +2926,13 @@ interface CreatePollInput {
|
|
|
2913
2926
|
/** Разрешить выбор нескольких вариантов. По умолчанию `false`. */
|
|
2914
2927
|
multipleChoice?: boolean;
|
|
2915
2928
|
}
|
|
2916
|
-
/**
|
|
2917
|
-
|
|
2929
|
+
/**
|
|
2930
|
+
* Нормализованные данные для создания поста.
|
|
2931
|
+
*
|
|
2932
|
+
* Это форма, которую возвращают `PostBuilder.build()` и `resolvePost()` после
|
|
2933
|
+
* преобразования вложенных builders. Для входа `itd.posts.create()` см. {@link CreatePostInput}.
|
|
2934
|
+
*/
|
|
2935
|
+
interface CreatePostData {
|
|
2918
2936
|
/** Текст поста. */
|
|
2919
2937
|
content?: string;
|
|
2920
2938
|
/**
|
|
@@ -2933,8 +2951,8 @@ interface CreatePostInput {
|
|
|
2933
2951
|
attachmentIds?: string[];
|
|
2934
2952
|
/** Файлы, которые нужно загрузить перед публикацией. Порядок сохраняется. */
|
|
2935
2953
|
files?: FileInput[];
|
|
2936
|
-
/**
|
|
2937
|
-
poll?:
|
|
2954
|
+
/** Готовые данные опроса. */
|
|
2955
|
+
poll?: CreatePollInput;
|
|
2938
2956
|
}
|
|
2939
2957
|
/** Поля поста, которые принимает `itd.posts.update()`. */
|
|
2940
2958
|
interface UpdatePostInput {
|
|
@@ -2970,6 +2988,41 @@ interface CreateReportInput {
|
|
|
2970
2988
|
description?: string;
|
|
2971
2989
|
}
|
|
2972
2990
|
//#endregion
|
|
2991
|
+
//#region src/builders/base.d.ts
|
|
2992
|
+
/** Метка билдера. Через `Symbol.for` — чтобы распознавание переживало смешивание ESM и CJS. */
|
|
2993
|
+
declare const BUILDER: unique symbol;
|
|
2994
|
+
/**
|
|
2995
|
+
* Билдер входных данных.
|
|
2996
|
+
*
|
|
2997
|
+
* Билдеры необязательны: любой метод, принимающий билдер, принимает и обычный объект.
|
|
2998
|
+
* Проверки одинаковы в обоих случаях.
|
|
2999
|
+
*/
|
|
3000
|
+
interface ItdBuilder<T> {
|
|
3001
|
+
/** @internal */
|
|
3002
|
+
readonly [BUILDER]: true;
|
|
3003
|
+
/**
|
|
3004
|
+
* Собирает и проверяет результат.
|
|
3005
|
+
*
|
|
3006
|
+
* @throws {ItdConfigError} если нарушены требования к данным
|
|
3007
|
+
*/
|
|
3008
|
+
build(): T;
|
|
3009
|
+
/** Чтобы билдер корректно вёл себя внутри `JSON.stringify`. */
|
|
3010
|
+
toJSON(): T;
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
3013
|
+
* Три равноправные формы входа: обычный объект, готовый билдер или функция-настройщик.
|
|
3014
|
+
*
|
|
3015
|
+
* @example
|
|
3016
|
+
* ```ts
|
|
3017
|
+
* itd.posts.create({ content: 'привет' }); // объект
|
|
3018
|
+
* itd.posts.create(post().content('привет')); // билдер
|
|
3019
|
+
* itd.posts.create((p) => p.content('привет')); // функция
|
|
3020
|
+
* ```
|
|
3021
|
+
*/
|
|
3022
|
+
type BuilderInput<T, B extends ItdBuilder<T>> = T | B | ((builder: B) => B | T);
|
|
3023
|
+
/** Является ли значение билдером. */
|
|
3024
|
+
declare function isBuilder<T>(value: unknown): value is ItdBuilder<T>;
|
|
3025
|
+
//#endregion
|
|
2973
3026
|
//#region src/builders/comment.d.ts
|
|
2974
3027
|
/** Внутреннее состояние {@link CommentBuilder}. */
|
|
2975
3028
|
interface CommentState extends CreateCommentInput {
|
|
@@ -3036,12 +3089,162 @@ declare function comment(content?: string): CommentBuilder;
|
|
|
3036
3089
|
/** Что принимает параметр комментария: объект, билдер или функция-настройщик. */
|
|
3037
3090
|
type CommentInput = BuilderInput<CreateCommentInput, CommentBuilder>;
|
|
3038
3091
|
//#endregion
|
|
3092
|
+
//#region src/models/content.d.ts
|
|
3093
|
+
/** Вложение поста или комментария. */
|
|
3094
|
+
interface Attachment {
|
|
3095
|
+
id: string;
|
|
3096
|
+
type: AttachmentType;
|
|
3097
|
+
/** Адрес файла на CDN. */
|
|
3098
|
+
url: string;
|
|
3099
|
+
/** Ширина изображения или видео в пикселях. */
|
|
3100
|
+
width?: number;
|
|
3101
|
+
/** Высота изображения или видео в пикселях. */
|
|
3102
|
+
height?: number;
|
|
3103
|
+
mimeType: string;
|
|
3104
|
+
/** Исходное имя файла. Приходит не всегда. */
|
|
3105
|
+
filename?: string;
|
|
3106
|
+
/** Размер в байтах. Приходит не всегда. */
|
|
3107
|
+
size?: number;
|
|
3108
|
+
/** Длительность аудио или видео в секундах. */
|
|
3109
|
+
duration?: number | null;
|
|
3110
|
+
/** Порядковый номер во вложениях поста. */
|
|
3111
|
+
order?: number;
|
|
3112
|
+
}
|
|
3113
|
+
/** Вариант ответа в опросе. */
|
|
3114
|
+
interface PollOption {
|
|
3115
|
+
id: string;
|
|
3116
|
+
text: string;
|
|
3117
|
+
/** Сколько голосов отдано за этот вариант. */
|
|
3118
|
+
votesCount: number;
|
|
3119
|
+
/** Порядковый номер варианта, начиная с нуля. */
|
|
3120
|
+
position: number;
|
|
3121
|
+
}
|
|
3122
|
+
/** Опрос внутри поста. */
|
|
3123
|
+
interface Poll {
|
|
3124
|
+
id: string;
|
|
3125
|
+
/** Пост, которому принадлежит опрос. */
|
|
3126
|
+
postId: string;
|
|
3127
|
+
question: string;
|
|
3128
|
+
/** Можно ли выбрать несколько вариантов. */
|
|
3129
|
+
multipleChoice: boolean;
|
|
3130
|
+
options: PollOption[];
|
|
3131
|
+
totalVotes: number;
|
|
3132
|
+
/** Голосовали ли вы. */
|
|
3133
|
+
hasVoted: boolean;
|
|
3134
|
+
/** За что проголосовали вы. Пустой массив, если голоса не было. */
|
|
3135
|
+
votedOptionIds: string[];
|
|
3136
|
+
createdAt: IsoDate;
|
|
3137
|
+
}
|
|
3138
|
+
/** Пост ленты, стены или профиля. */
|
|
3139
|
+
interface Post {
|
|
3140
|
+
id: string;
|
|
3141
|
+
content: string;
|
|
3142
|
+
/** Разметка текста. Передаётся без изменений, см. {@link Span}. */
|
|
3143
|
+
spans: Span[];
|
|
3144
|
+
author: Author;
|
|
3145
|
+
attachments: Attachment[];
|
|
3146
|
+
likesCount: number;
|
|
3147
|
+
commentsCount: number;
|
|
3148
|
+
repostsCount: number;
|
|
3149
|
+
viewsCount: number;
|
|
3150
|
+
/** Чья это стена, если пост опубликован не у себя. */
|
|
3151
|
+
wallRecipientId: UserId | null;
|
|
3152
|
+
/** Владелец стены. Приходит не во всех ответах. */
|
|
3153
|
+
wallRecipient?: Author | null;
|
|
3154
|
+
/** Поставили ли вы реакцию. */
|
|
3155
|
+
isLiked: boolean;
|
|
3156
|
+
/** Делали ли вы репост. */
|
|
3157
|
+
isReposted: boolean;
|
|
3158
|
+
/** Засчитан ли просмотр. */
|
|
3159
|
+
isViewed: boolean;
|
|
3160
|
+
/** Ваш ли это пост. */
|
|
3161
|
+
isOwner: boolean;
|
|
3162
|
+
/** Исходный пост, если это репост. */
|
|
3163
|
+
originalPost?: Post | null;
|
|
3164
|
+
poll?: Poll | null;
|
|
3165
|
+
/** Преобладающая реакция — эмодзи либо `null`. */
|
|
3166
|
+
dominantEmoji?: string | null;
|
|
3167
|
+
/** Когда пост отредактировали. `null`, если не редактировали. */
|
|
3168
|
+
editedAt: IsoDate | null;
|
|
3169
|
+
createdAt: IsoDate;
|
|
3170
|
+
/**
|
|
3171
|
+
* Служебная метка показа для телеметрии.
|
|
3172
|
+
*
|
|
3173
|
+
* Нужна только эндпоинтам `itd.telemetry.*`. В остальных случаях игнорируйте.
|
|
3174
|
+
*/
|
|
3175
|
+
vs?: string;
|
|
3176
|
+
/**
|
|
3177
|
+
* Топовые комментарии. Приходят только в ответе `GET /api/posts/{id}`.
|
|
3178
|
+
*
|
|
3179
|
+
* В списках постов поле отсутствует.
|
|
3180
|
+
*/
|
|
3181
|
+
comments?: Comment[];
|
|
3182
|
+
}
|
|
3183
|
+
/** На чей комментарий дан ответ. */
|
|
3184
|
+
interface CommentReplyTo {
|
|
3185
|
+
id: string;
|
|
3186
|
+
username: string;
|
|
3187
|
+
displayName: string;
|
|
3188
|
+
}
|
|
3189
|
+
/** Комментарий к посту или ответ на комментарий. */
|
|
3190
|
+
interface Comment {
|
|
3191
|
+
id: string;
|
|
3192
|
+
/** Текст. У голосового комментария пустой. */
|
|
3193
|
+
content: string;
|
|
3194
|
+
/**
|
|
3195
|
+
* Разметка текста, включая автоматически найденные сервером хэштеги и упоминания.
|
|
3196
|
+
*
|
|
3197
|
+
* Методы создания и редактирования комментария принимают только `content`, поэтому
|
|
3198
|
+
* библиотека не отправляет ручные spans в этих операциях.
|
|
3199
|
+
* Поле необязательно: отдельные ответы сервера могут его не содержать.
|
|
3200
|
+
*/
|
|
3201
|
+
spans?: Span[];
|
|
3202
|
+
author: Author;
|
|
3203
|
+
likesCount: number;
|
|
3204
|
+
repliesCount: number;
|
|
3205
|
+
isLiked: boolean;
|
|
3206
|
+
createdAt: IsoDate;
|
|
3207
|
+
/** Вложения. У голосового — одно аудио с `mimeType: 'audio/ogg'`. */
|
|
3208
|
+
attachments?: Attachment[];
|
|
3209
|
+
/** Вложенные ответы. В списках приходит превью, полный список — через `itd.comments.replies()`. */
|
|
3210
|
+
replies?: Comment[];
|
|
3211
|
+
/** Заполнено только у ответов. */
|
|
3212
|
+
replyTo?: CommentReplyTo;
|
|
3213
|
+
}
|
|
3214
|
+
/** Хэштег. */
|
|
3215
|
+
interface Hashtag {
|
|
3216
|
+
id: string;
|
|
3217
|
+
/** Название без решётки. */
|
|
3218
|
+
name: string;
|
|
3219
|
+
/** Сколько постов с этим хэштегом. */
|
|
3220
|
+
postsCount: number;
|
|
3221
|
+
}
|
|
3222
|
+
/** Счётчики поста из `itd.posts.stats()`. */
|
|
3223
|
+
interface PostStats {
|
|
3224
|
+
id: string;
|
|
3225
|
+
likesCount: number;
|
|
3226
|
+
commentsCount: number;
|
|
3227
|
+
repostsCount: number;
|
|
3228
|
+
viewsCount: number;
|
|
3229
|
+
/** Преобладающая реакция — эмодзи либо `null`. */
|
|
3230
|
+
dominantEmoji: string | null;
|
|
3231
|
+
}
|
|
3232
|
+
/** Результат реакции на пост. */
|
|
3233
|
+
interface LikeResult {
|
|
3234
|
+
liked: boolean;
|
|
3235
|
+
likesCount: number;
|
|
3236
|
+
}
|
|
3237
|
+
/** Результат закрепления поста в профиле. */
|
|
3238
|
+
interface PinPostResult {
|
|
3239
|
+
success: boolean;
|
|
3240
|
+
pinnedPostId: string | null;
|
|
3241
|
+
}
|
|
3242
|
+
//#endregion
|
|
3039
3243
|
//#region src/resources/comments.d.ts
|
|
3040
3244
|
/** Параметры запроса ответов на комментарий. */
|
|
3041
|
-
interface RepliesParams
|
|
3245
|
+
interface RepliesParams {
|
|
3042
3246
|
limit?: number;
|
|
3043
3247
|
page?: number;
|
|
3044
|
-
maxPages?: number;
|
|
3045
3248
|
}
|
|
3046
3249
|
/**
|
|
3047
3250
|
* Комментарии и ответы на них.
|
|
@@ -3059,9 +3262,9 @@ declare class CommentsResource extends BaseResource {
|
|
|
3059
3262
|
*
|
|
3060
3263
|
* Здесь пагинация **постраничная**, в отличие от комментариев к посту, где курсорная.
|
|
3061
3264
|
*/
|
|
3062
|
-
replies(commentId: string, params?: RepliesParams): Promise<Page<Comment>>;
|
|
3265
|
+
replies(commentId: string, params?: RepliesParams, options?: RequestOptions): Promise<Page<Comment>>;
|
|
3063
3266
|
/** Перебирает ответы на комментарий. */
|
|
3064
|
-
iterateReplies(commentId: string, params?: RepliesParams): Paginator<Comment>;
|
|
3267
|
+
iterateReplies(commentId: string, params?: RepliesParams, options?: PaginationOptions): Paginator<Comment>;
|
|
3065
3268
|
/**
|
|
3066
3269
|
* Отвечает на комментарий.
|
|
3067
3270
|
*
|
|
@@ -3093,7 +3296,7 @@ interface UploadedFile {
|
|
|
3093
3296
|
url: string;
|
|
3094
3297
|
}
|
|
3095
3298
|
/** Настройки загрузки. */
|
|
3096
|
-
interface UploadOptions
|
|
3299
|
+
interface UploadOptions {
|
|
3097
3300
|
/** Имя файла. Используется для определения MIME, если тип не задан. */
|
|
3098
3301
|
filename?: string;
|
|
3099
3302
|
/** MIME-тип. По умолчанию определяется по имени или `Blob`. */
|
|
@@ -3119,9 +3322,9 @@ declare class FilesResource extends BaseResource {
|
|
|
3119
3322
|
* Потоковый источник открывается заново при каждой повторной попытке. Буферный источник
|
|
3120
3323
|
* после успешного чтения переиспользуется.
|
|
3121
3324
|
*/
|
|
3122
|
-
upload(input: FileInput,
|
|
3325
|
+
upload(input: FileInput, uploadOptions?: UploadOptions, requestOptions?: RequestOptions): Promise<UploadedFile>;
|
|
3123
3326
|
/** Загружает несколько файлов последовательно, сохраняя порядок. */
|
|
3124
|
-
uploadMany(files: FileInput[],
|
|
3327
|
+
uploadMany(files: FileInput[], uploadOptions?: UploadOptions, requestOptions?: RequestOptions): Promise<string[]>;
|
|
3125
3328
|
/**
|
|
3126
3329
|
* Загружает сведения о файле.
|
|
3127
3330
|
*
|
|
@@ -3134,10 +3337,9 @@ declare class FilesResource extends BaseResource {
|
|
|
3134
3337
|
//#endregion
|
|
3135
3338
|
//#region src/resources/hashtags.d.ts
|
|
3136
3339
|
/** Параметры запроса постов по хэштегу. */
|
|
3137
|
-
interface HashtagPostsParams
|
|
3340
|
+
interface HashtagPostsParams {
|
|
3138
3341
|
limit?: number;
|
|
3139
3342
|
cursor?: string;
|
|
3140
|
-
maxPages?: number;
|
|
3141
3343
|
}
|
|
3142
3344
|
/**
|
|
3143
3345
|
* Хэштеги.
|
|
@@ -3153,29 +3355,28 @@ declare class HashtagsResource extends BaseResource {
|
|
|
3153
3355
|
*/
|
|
3154
3356
|
search(query?: string, params?: {
|
|
3155
3357
|
limit?: number;
|
|
3156
|
-
}
|
|
3358
|
+
}, options?: RequestOptions): Promise<Hashtag[]>;
|
|
3157
3359
|
/** Загружает трендовые хэштеги. */
|
|
3158
3360
|
trending(params?: {
|
|
3159
3361
|
limit?: number;
|
|
3160
|
-
}
|
|
3362
|
+
}, options?: RequestOptions): Promise<Hashtag[]>;
|
|
3161
3363
|
/**
|
|
3162
3364
|
* Загружает страницу постов по хэштегу.
|
|
3163
3365
|
*
|
|
3164
3366
|
* @param tag название без решётки; кодируется автоматически, поэтому кириллица
|
|
3165
3367
|
* и пробелы допустимы
|
|
3166
3368
|
*/
|
|
3167
|
-
posts(tag: string, params?: HashtagPostsParams): Promise<Page<Post>>;
|
|
3369
|
+
posts(tag: string, params?: HashtagPostsParams, options?: RequestOptions): Promise<Page<Post>>;
|
|
3168
3370
|
/** Перебирает посты по хэштегу. */
|
|
3169
|
-
iteratePosts(tag: string, params?: HashtagPostsParams): Paginator<Post>;
|
|
3371
|
+
iteratePosts(tag: string, params?: HashtagPostsParams, options?: PaginationOptions): Paginator<Post>;
|
|
3170
3372
|
}
|
|
3171
3373
|
//#endregion
|
|
3172
3374
|
//#region src/resources/notifications.d.ts
|
|
3173
3375
|
/** Параметры запроса списка уведомлений. */
|
|
3174
|
-
interface NotificationListParams
|
|
3376
|
+
interface NotificationListParams {
|
|
3175
3377
|
limit?: number;
|
|
3176
3378
|
/** Смещение от начала списка. */
|
|
3177
3379
|
offset?: number;
|
|
3178
|
-
maxPages?: number;
|
|
3179
3380
|
}
|
|
3180
3381
|
/** Изменяемые настройки уведомлений. */
|
|
3181
3382
|
type UpdateNotificationSettingsInput = Partial<NotificationSettings>;
|
|
@@ -3198,7 +3399,7 @@ declare class NotificationsResource extends BaseResource {
|
|
|
3198
3399
|
* const next = await itd.notifications.list({ limit: 20, offset: page.nextOffset });
|
|
3199
3400
|
* ```
|
|
3200
3401
|
*/
|
|
3201
|
-
list(params?: NotificationListParams): Promise<Page<Notification>>;
|
|
3402
|
+
list(params?: NotificationListParams, options?: RequestOptions): Promise<Page<Notification>>;
|
|
3202
3403
|
/**
|
|
3203
3404
|
* Перебирает уведомления.
|
|
3204
3405
|
*
|
|
@@ -3209,35 +3410,145 @@ declare class NotificationsResource extends BaseResource {
|
|
|
3209
3410
|
* }
|
|
3210
3411
|
* ```
|
|
3211
3412
|
*/
|
|
3212
|
-
iterate(params?: NotificationListParams): Paginator<Notification>;
|
|
3413
|
+
iterate(params?: NotificationListParams, options?: PaginationOptions): Paginator<Notification>;
|
|
3213
3414
|
/** Загружает число непрочитанных уведомлений. */
|
|
3214
3415
|
count(options?: RequestOptions): Promise<number>;
|
|
3215
3416
|
/**
|
|
3216
|
-
* Отмечает уведомление прочитанным.
|
|
3217
|
-
*
|
|
3218
|
-
* @returns сколько записей отметил сервер
|
|
3417
|
+
* Отмечает уведомление прочитанным.
|
|
3418
|
+
*
|
|
3419
|
+
* @returns сколько записей отметил сервер
|
|
3420
|
+
*/
|
|
3421
|
+
markRead(notificationId: string, options?: RequestOptions): Promise<number>;
|
|
3422
|
+
/**
|
|
3423
|
+
* Отмечает прочитанными сразу несколько уведомлений.
|
|
3424
|
+
*
|
|
3425
|
+
* Список автоматически режется на части по 20 идентификаторов — столько же отправляет
|
|
3426
|
+
* сайт итд.com, поэтому на сервере вероятен предел. Части уходят последовательно,
|
|
3427
|
+
* результат суммируется.
|
|
3428
|
+
*
|
|
3429
|
+
* @returns сколько записей отметил сервер суммарно
|
|
3430
|
+
*/
|
|
3431
|
+
markReadBatch(ids: string[], options?: RequestOptions): Promise<number>;
|
|
3432
|
+
/** Отмечает прочитанными все уведомления. */
|
|
3433
|
+
markAllRead(options?: RequestOptions): Promise<number>;
|
|
3434
|
+
/** Загружает настройки уведомлений. */
|
|
3435
|
+
getSettings(options?: RequestOptions): Promise<NotificationSettings>;
|
|
3436
|
+
/**
|
|
3437
|
+
* Обновляет настройки уведомлений.
|
|
3438
|
+
*
|
|
3439
|
+
* Отправляются только изменяемые поля, в том же виде, в каком сервер их возвращает.
|
|
3440
|
+
*/
|
|
3441
|
+
updateSettings(input: UpdateNotificationSettingsInput, options?: RequestOptions): Promise<NotificationSettings>;
|
|
3442
|
+
}
|
|
3443
|
+
//#endregion
|
|
3444
|
+
//#region src/models/platform.d.ts
|
|
3445
|
+
/** Клан в рейтинге. */
|
|
3446
|
+
interface Clan {
|
|
3447
|
+
/** Эмодзи клана — оно же аватар его участников. */
|
|
3448
|
+
avatar: string;
|
|
3449
|
+
memberCount: number;
|
|
3450
|
+
}
|
|
3451
|
+
/** Запись журнала изменений платформы. */
|
|
3452
|
+
interface ChangelogEntry {
|
|
3453
|
+
version: string;
|
|
3454
|
+
date: string;
|
|
3455
|
+
changes: string[];
|
|
3456
|
+
}
|
|
3457
|
+
/** Кнопка в анонсе платформы. */
|
|
3458
|
+
interface AnnouncementButton {
|
|
3459
|
+
title: string;
|
|
3460
|
+
/** Оформление: `primary`, `secondary` и другие. */
|
|
3461
|
+
style: string;
|
|
3462
|
+
action: {
|
|
3463
|
+
type: string;
|
|
3464
|
+
[key: string]: unknown;
|
|
3465
|
+
};
|
|
3466
|
+
}
|
|
3467
|
+
/** Анонс на главной странице платформы. */
|
|
3468
|
+
interface Announcement {
|
|
3469
|
+
id: string;
|
|
3470
|
+
image: {
|
|
3471
|
+
url: string;
|
|
3472
|
+
width: number;
|
|
3473
|
+
height: number;
|
|
3474
|
+
};
|
|
3475
|
+
title: string;
|
|
3476
|
+
description: string;
|
|
3477
|
+
/** Дополнительный текст мелким шрифтом. */
|
|
3478
|
+
additional_text?: string;
|
|
3479
|
+
buttons: AnnouncementButton[];
|
|
3480
|
+
}
|
|
3481
|
+
/** Баннер текущего события — виджет «портал». */
|
|
3482
|
+
interface Portal {
|
|
3483
|
+
active: boolean;
|
|
3484
|
+
title: string;
|
|
3485
|
+
url: string;
|
|
3486
|
+
}
|
|
3487
|
+
/** Статус заявки на верификацию. `none` означает, что заявка не подавалась. */
|
|
3488
|
+
interface VerificationStatus {
|
|
3489
|
+
status: Loose<'none' | 'pending' | 'approved' | 'rejected'>;
|
|
3490
|
+
}
|
|
3491
|
+
/** Созданная жалоба. */
|
|
3492
|
+
interface Report {
|
|
3493
|
+
id: string;
|
|
3494
|
+
createdAt: IsoDate;
|
|
3495
|
+
}
|
|
3496
|
+
//#endregion
|
|
3497
|
+
//#region src/models/status.d.ts
|
|
3498
|
+
/** Происшествие в истории сервиса. */
|
|
3499
|
+
interface StatusIncidentLine {
|
|
3500
|
+
/** Вид происшествия. */
|
|
3501
|
+
t: IncidentKind;
|
|
3502
|
+
/**
|
|
3503
|
+
* Готовая строка для показа: `недоступен 6 мин (12:00–12:06)`. Время московское.
|
|
3504
|
+
* Длительность и границы интервала отдельными полями не приходят.
|
|
3219
3505
|
*/
|
|
3220
|
-
|
|
3506
|
+
text: string;
|
|
3507
|
+
}
|
|
3508
|
+
/** Одни сутки в истории сервиса. */
|
|
3509
|
+
interface StatusDay {
|
|
3510
|
+
/** Худшее состояние за сутки. */
|
|
3511
|
+
type: ServiceState;
|
|
3512
|
+
/** Дата суток, `YYYY-MM-DD`. Сутки нарезаны по UTC. */
|
|
3513
|
+
date_key: string;
|
|
3514
|
+
/** Доступность за сутки в процентах. */
|
|
3515
|
+
uptime: number;
|
|
3516
|
+
/** Происшествия за сутки. */
|
|
3517
|
+
lines: StatusIncidentLine[];
|
|
3518
|
+
}
|
|
3519
|
+
/** Сервис платформы и его история доступности. */
|
|
3520
|
+
interface ServiceStatus {
|
|
3521
|
+
/** Идентификатор: `auth`, `main`, `media` и прочие. */
|
|
3522
|
+
id: string;
|
|
3523
|
+
/** Отображаемое название. */
|
|
3524
|
+
name: string;
|
|
3525
|
+
current_status: ServiceState;
|
|
3526
|
+
/** Пояснение к текущему состоянию, например `No downtime`. */
|
|
3527
|
+
current_message: string;
|
|
3528
|
+
/** Задержка последней проверки в миллисекундах. */
|
|
3529
|
+
latency_ms: number;
|
|
3221
3530
|
/**
|
|
3222
|
-
*
|
|
3223
|
-
*
|
|
3224
|
-
* Список автоматически режется на части по 20 идентификаторов — столько же отправляет
|
|
3225
|
-
* сайт итд.com, поэтому на сервере вероятен предел. Части уходят последовательно,
|
|
3226
|
-
* результат суммируется.
|
|
3227
|
-
*
|
|
3228
|
-
* @returns сколько записей отметил сервер суммарно
|
|
3531
|
+
* Момент последней проверки. Сервер отдаёт `YYYY-MM-DD HH:mm:ss` в UTC, библиотека
|
|
3532
|
+
* приводит значение к ISO.
|
|
3229
3533
|
*/
|
|
3230
|
-
|
|
3231
|
-
/**
|
|
3232
|
-
|
|
3233
|
-
/** Загружает настройки уведомлений. */
|
|
3234
|
-
getSettings(options?: RequestOptions): Promise<NotificationSettings>;
|
|
3534
|
+
last_checked: IsoDate;
|
|
3535
|
+
/** Доступность за 90 суток в процентах. */
|
|
3536
|
+
uptime_90d: number;
|
|
3235
3537
|
/**
|
|
3236
|
-
*
|
|
3538
|
+
* История по суткам. Ключ — сколько суток назад, `'0'` — сегодня.
|
|
3237
3539
|
*
|
|
3238
|
-
*
|
|
3540
|
+
* Объект разреженный: сутки без данных сервер пропускает. Ровный массив даёт
|
|
3541
|
+
* `statusDays()`.
|
|
3239
3542
|
*/
|
|
3240
|
-
|
|
3543
|
+
days: Record<string, StatusDay | undefined>;
|
|
3544
|
+
}
|
|
3545
|
+
/** Состояние платформы — ответ `itd.platform.status()`. */
|
|
3546
|
+
interface PlatformStatus {
|
|
3547
|
+
/** Худшее состояние среди сервисов. */
|
|
3548
|
+
overall_status: ServiceState;
|
|
3549
|
+
/** Когда данные последний раз пересчитаны. */
|
|
3550
|
+
updated_at: IsoDate;
|
|
3551
|
+
services: ServiceStatus[];
|
|
3241
3552
|
}
|
|
3242
3553
|
//#endregion
|
|
3243
3554
|
//#region src/resources/platform.d.ts
|
|
@@ -3415,8 +3726,64 @@ declare function parseMarkdown(source: string, options?: ParseMarkupOptions): Te
|
|
|
3415
3726
|
*/
|
|
3416
3727
|
declare function parseHtml(source: string, options?: ParseMarkupOptions): TextMarkup;
|
|
3417
3728
|
//#endregion
|
|
3729
|
+
//#region src/builders/poll.d.ts
|
|
3730
|
+
/**
|
|
3731
|
+
* Билдер опроса.
|
|
3732
|
+
*
|
|
3733
|
+
* Неизменяемый: каждый вызов возвращает новый экземпляр, поэтому заготовку можно
|
|
3734
|
+
* переиспользовать, не боясь её испортить. Создаётся функцией {@link poll}.
|
|
3735
|
+
*/
|
|
3736
|
+
declare class PollBuilder implements ItdBuilder<CreatePollInput> {
|
|
3737
|
+
#private;
|
|
3738
|
+
/** @internal */
|
|
3739
|
+
readonly [BUILDER]: true;
|
|
3740
|
+
/** @internal Создавайте билдер функцией {@link poll}. */
|
|
3741
|
+
constructor(state: CreatePollInput);
|
|
3742
|
+
/** Задаёт вопрос. */
|
|
3743
|
+
question(text: string): PollBuilder;
|
|
3744
|
+
/** Добавляет один вариант ответа. */
|
|
3745
|
+
option(text: string): PollBuilder;
|
|
3746
|
+
/**
|
|
3747
|
+
* Добавляет несколько вариантов сразу.
|
|
3748
|
+
*
|
|
3749
|
+
* @example
|
|
3750
|
+
* ```ts
|
|
3751
|
+
* poll('ну как?').options('да', 'нет', 'не знаю');
|
|
3752
|
+
* ```
|
|
3753
|
+
*/
|
|
3754
|
+
options(...texts: string[]): PollBuilder;
|
|
3755
|
+
/** Разрешает выбор нескольких вариантов. */
|
|
3756
|
+
multipleChoice(enabled?: boolean): PollBuilder;
|
|
3757
|
+
build(): CreatePollInput;
|
|
3758
|
+
toJSON(): CreatePollInput;
|
|
3759
|
+
}
|
|
3760
|
+
/**
|
|
3761
|
+
* Начинает сборку опроса.
|
|
3762
|
+
*
|
|
3763
|
+
* @param question вопрос; можно задать позже методом {@link PollBuilder.question}
|
|
3764
|
+
*
|
|
3765
|
+
* @example
|
|
3766
|
+
* ```ts
|
|
3767
|
+
* import { poll } from 'itd-api';
|
|
3768
|
+
*
|
|
3769
|
+
* const q = poll('Какой язык лучше?')
|
|
3770
|
+
* .options('TypeScript', 'JavaScript')
|
|
3771
|
+
* .multipleChoice();
|
|
3772
|
+
*
|
|
3773
|
+
* await itd.posts.create({ content: 'голосуем', poll: q });
|
|
3774
|
+
* ```
|
|
3775
|
+
*/
|
|
3776
|
+
declare function poll(question?: string): PollBuilder;
|
|
3777
|
+
/** Что принимает параметр опроса: объект, билдер или функция-настройщик. */
|
|
3778
|
+
type PollInput = BuilderInput<CreatePollInput, PollBuilder>;
|
|
3779
|
+
//#endregion
|
|
3418
3780
|
//#region src/builders/post.d.ts
|
|
3419
3781
|
declare const BUILD_UPDATE: unique symbol;
|
|
3782
|
+
/** Данные для создания поста, включая поддерживаемые builder-формы вложенного опроса. */
|
|
3783
|
+
interface CreatePostInput extends Omit<CreatePostData, 'poll'> {
|
|
3784
|
+
/** Опрос: обычный объект, {@link PollBuilder} или функция-настройщик. */
|
|
3785
|
+
poll?: PollInput;
|
|
3786
|
+
}
|
|
3420
3787
|
/** Внутреннее состояние {@link PostBuilder}. */
|
|
3421
3788
|
interface PostState extends CreatePostInput {
|
|
3422
3789
|
content: string;
|
|
@@ -3438,7 +3805,7 @@ interface PostState extends CreatePostInput {
|
|
|
3438
3805
|
* await itd.posts.create(onWall.content('второй')); // заготовка не испорчена
|
|
3439
3806
|
* ```
|
|
3440
3807
|
*/
|
|
3441
|
-
declare class PostBuilder implements ItdBuilder<
|
|
3808
|
+
declare class PostBuilder implements ItdBuilder<CreatePostData> {
|
|
3442
3809
|
#private;
|
|
3443
3810
|
/** @internal */
|
|
3444
3811
|
readonly [BUILDER]: true;
|
|
@@ -3504,10 +3871,10 @@ declare class PostBuilder implements ItdBuilder<CreatePostInput> {
|
|
|
3504
3871
|
* ```
|
|
3505
3872
|
*/
|
|
3506
3873
|
poll(input: PollInput): PostBuilder;
|
|
3507
|
-
build():
|
|
3874
|
+
build(): CreatePostData;
|
|
3508
3875
|
/** @internal Собирает данные по правилам `posts.update`, не применяя правила создания. */
|
|
3509
3876
|
[BUILD_UPDATE](): UpdatePostInput;
|
|
3510
|
-
toJSON():
|
|
3877
|
+
toJSON(): CreatePostData;
|
|
3511
3878
|
}
|
|
3512
3879
|
/**
|
|
3513
3880
|
* Начинает сборку поста.
|
|
@@ -3533,7 +3900,7 @@ type PostUpdateInput = UpdatePostInput | PostBuilder | ((builder: PostBuilder) =
|
|
|
3533
3900
|
//#endregion
|
|
3534
3901
|
//#region src/resources/posts.d.ts
|
|
3535
3902
|
/** Параметры запроса ленты. */
|
|
3536
|
-
interface FeedParams
|
|
3903
|
+
interface FeedParams {
|
|
3537
3904
|
/** Вкладка ленты. По умолчанию сервер отдаёт популярное. */
|
|
3538
3905
|
tab?: FeedTab;
|
|
3539
3906
|
/** Сколько постов на страницу. */
|
|
@@ -3544,21 +3911,18 @@ interface FeedParams extends RequestOptions {
|
|
|
3544
3911
|
* Передавайте значение как есть: его формат зависит от вкладки и может измениться.
|
|
3545
3912
|
*/
|
|
3546
3913
|
cursor?: string;
|
|
3547
|
-
/** Ограничение числа страниц при переборе. */
|
|
3548
|
-
maxPages?: number;
|
|
3549
3914
|
}
|
|
3550
3915
|
/** Параметры запроса постов пользователя. */
|
|
3551
|
-
interface UserPostsParams
|
|
3916
|
+
interface UserPostsParams {
|
|
3552
3917
|
limit?: number;
|
|
3553
3918
|
cursor?: string;
|
|
3554
3919
|
/** Порядок сортировки. */
|
|
3555
3920
|
sort?: string;
|
|
3556
3921
|
/** Закреплённый пост, чтобы сервер поднял его наверх. */
|
|
3557
3922
|
pinnedPostId?: string;
|
|
3558
|
-
maxPages?: number;
|
|
3559
3923
|
}
|
|
3560
3924
|
/** Параметры запроса комментариев к посту. */
|
|
3561
|
-
interface CommentsParams
|
|
3925
|
+
interface CommentsParams {
|
|
3562
3926
|
limit?: number;
|
|
3563
3927
|
/**
|
|
3564
3928
|
* Курсор следующей страницы: идентификатор последнего полученного комментария.
|
|
@@ -3567,7 +3931,6 @@ interface CommentsParams extends RequestOptions {
|
|
|
3567
3931
|
*/
|
|
3568
3932
|
cursor?: string;
|
|
3569
3933
|
sort?: CommentSort;
|
|
3570
|
-
maxPages?: number;
|
|
3571
3934
|
}
|
|
3572
3935
|
/**
|
|
3573
3936
|
* Посты: лента, публикация, реакции, репосты, комментарии.
|
|
@@ -3588,7 +3951,7 @@ declare class PostsResource extends BaseResource {
|
|
|
3588
3951
|
* const next = await itd.posts.list({ tab: FeedTab.Following, cursor: page.nextCursor ?? undefined });
|
|
3589
3952
|
* ```
|
|
3590
3953
|
*/
|
|
3591
|
-
list(params?: FeedParams): Promise<Page<Post>>;
|
|
3954
|
+
list(params?: FeedParams, options?: RequestOptions): Promise<Page<Post>>;
|
|
3592
3955
|
/**
|
|
3593
3956
|
* Перебирает ленту, сама подставляя курсоры.
|
|
3594
3957
|
*
|
|
@@ -3599,7 +3962,7 @@ declare class PostsResource extends BaseResource {
|
|
|
3599
3962
|
* }
|
|
3600
3963
|
* ```
|
|
3601
3964
|
*/
|
|
3602
|
-
iterate(params?: FeedParams): Paginator<Post>;
|
|
3965
|
+
iterate(params?: FeedParams, options?: PaginationOptions): Paginator<Post>;
|
|
3603
3966
|
/**
|
|
3604
3967
|
* Публикует пост.
|
|
3605
3968
|
*
|
|
@@ -3666,22 +4029,22 @@ declare class PostsResource extends BaseResource {
|
|
|
3666
4029
|
*
|
|
3667
4030
|
* Принимает и UUID, и имя пользователя.
|
|
3668
4031
|
*/
|
|
3669
|
-
byUser(user: UserRef, params?: UserPostsParams): Promise<Page<Post>>;
|
|
4032
|
+
byUser(user: UserRef, params?: UserPostsParams, options?: RequestOptions): Promise<Page<Post>>;
|
|
3670
4033
|
/** Перебирает стену пользователя. Что именно в неё входит — см. {@link byUser}. */
|
|
3671
|
-
iterateByUser(user: UserRef, params?: UserPostsParams): Paginator<Post>;
|
|
4034
|
+
iterateByUser(user: UserRef, params?: UserPostsParams, options?: PaginationOptions): Paginator<Post>;
|
|
3672
4035
|
/** Загружает страницу постов, которые пользователь отметил реакцией. */
|
|
3673
|
-
likedByUser(user: UserRef, params?: UserPostsParams): Promise<Page<Post>>;
|
|
4036
|
+
likedByUser(user: UserRef, params?: UserPostsParams, options?: RequestOptions): Promise<Page<Post>>;
|
|
3674
4037
|
/** Перебирает посты, которые пользователь отметил реакцией. */
|
|
3675
|
-
iterateLikedByUser(user: UserRef, params?: UserPostsParams): Paginator<Post>;
|
|
4038
|
+
iterateLikedByUser(user: UserRef, params?: UserPostsParams, options?: PaginationOptions): Paginator<Post>;
|
|
3676
4039
|
/**
|
|
3677
4040
|
* Загружает страницу комментариев к посту.
|
|
3678
4041
|
*
|
|
3679
4042
|
* У этого эндпоинта курсор и признак продолжения лежат рядом со списком, а не внутри
|
|
3680
4043
|
* объекта `pagination`, как у остальных, — разница скрыта внутри.
|
|
3681
4044
|
*/
|
|
3682
|
-
comments(postId: string, params?: CommentsParams): Promise<Page<Comment>>;
|
|
4045
|
+
comments(postId: string, params?: CommentsParams, options?: RequestOptions): Promise<Page<Comment>>;
|
|
3683
4046
|
/** Перебирает комментарии к посту. */
|
|
3684
|
-
iterateComments(postId: string, params?: CommentsParams): Paginator<Comment>;
|
|
4047
|
+
iterateComments(postId: string, params?: CommentsParams, options?: PaginationOptions): Paginator<Comment>;
|
|
3685
4048
|
/**
|
|
3686
4049
|
* Комментирует пост.
|
|
3687
4050
|
*
|
|
@@ -3826,8 +4189,8 @@ declare class SubscriptionResource extends BaseResource {
|
|
|
3826
4189
|
}
|
|
3827
4190
|
//#endregion
|
|
3828
4191
|
//#region src/resources/telemetry.d.ts
|
|
3829
|
-
/**
|
|
3830
|
-
interface TelemetryOptions
|
|
4192
|
+
/** Параметры событий телеметрии. */
|
|
4193
|
+
interface TelemetryOptions {
|
|
3831
4194
|
/** Переопределяет идентификатор сессии телеметрии (`sid`) для этого запроса. */
|
|
3832
4195
|
sid?: string;
|
|
3833
4196
|
}
|
|
@@ -3959,7 +4322,7 @@ interface TelemetryBatch {
|
|
|
3959
4322
|
*
|
|
3960
4323
|
* Опции позволяют заменить, например, отменённый `signal` при повторной попытке.
|
|
3961
4324
|
*/
|
|
3962
|
-
flush(options?:
|
|
4325
|
+
flush(options?: RequestOptions): Promise<void>;
|
|
3963
4326
|
/** Отправляет накопленные события и закрывает накопитель. */
|
|
3964
4327
|
close(): Promise<void>;
|
|
3965
4328
|
}
|
|
@@ -3971,24 +4334,25 @@ interface TelemetryBatch {
|
|
|
3971
4334
|
*/
|
|
3972
4335
|
declare class TelemetryResource extends BaseResource {
|
|
3973
4336
|
#private;
|
|
4337
|
+
constructor(http: HttpClient);
|
|
3974
4338
|
/** Идентификатор сессии телеметрии, общий для всех событий этого ресурса. */
|
|
3975
4339
|
get sessionId(): string;
|
|
3976
4340
|
/** Отправляет события просмотра постов (`POST /api/v1/i`). */
|
|
3977
|
-
dwell(entries: readonly DwellEntry[],
|
|
4341
|
+
dwell(entries: readonly DwellEntry[], telemetryOptions?: TelemetryOptions, requestOptions?: RequestOptions): Promise<unknown>;
|
|
3978
4342
|
/** Отправляет события взаимодействия с контентом (`POST /api/v1/x`). */
|
|
3979
|
-
interaction(entries: readonly InteractionEntry[],
|
|
4343
|
+
interaction(entries: readonly InteractionEntry[], telemetryOptions?: TelemetryOptions, requestOptions?: RequestOptions): Promise<unknown>;
|
|
3980
4344
|
/** Начинает измерять время просмотра и отправляет результат после `finish()`. */
|
|
3981
|
-
startView(input: ViewTrackerInput, options?: ViewTrackerOptions): ViewTracker;
|
|
4345
|
+
startView(input: ViewTrackerInput, options?: ViewTrackerOptions, requestOptions?: RequestOptions): ViewTracker;
|
|
3982
4346
|
/** Отправляет событие открытия фотографии. */
|
|
3983
|
-
photoOpen(input: PhotoOpenInput,
|
|
4347
|
+
photoOpen(input: PhotoOpenInput, telemetryOptions?: TelemetryOptions, requestOptions?: RequestOptions): Promise<unknown>;
|
|
3984
4348
|
/** Отправляет событие прогресса просмотра видео. */
|
|
3985
|
-
videoProgress(input: VideoProgressInput,
|
|
4349
|
+
videoProgress(input: VideoProgressInput, telemetryOptions?: TelemetryOptions, requestOptions?: RequestOptions): Promise<unknown>;
|
|
3986
4350
|
/**
|
|
3987
4351
|
* Создаёт накопитель с явными `flush()` и `close()`.
|
|
3988
4352
|
*
|
|
3989
4353
|
* Создание и добавление записей не выполняют сетевых запросов.
|
|
3990
4354
|
*/
|
|
3991
|
-
batch(options?: TelemetryBatchOptions): TelemetryBatch;
|
|
4355
|
+
batch(options?: TelemetryBatchOptions, requestOptions?: RequestOptions): TelemetryBatch;
|
|
3992
4356
|
/** Закрывает все созданные накопители, отправляя оставшиеся записи. */
|
|
3993
4357
|
close(): Promise<void>;
|
|
3994
4358
|
}
|
|
@@ -4000,12 +4364,11 @@ declare class TelemetryResource extends BaseResource {
|
|
|
4000
4364
|
* ⚠️ Списки подписчиков, подписок и заблокированных на сервере **не листаются**:
|
|
4001
4365
|
* `page` он игнорирует, а `limit` зажимает на 20. Подробности — в {@link UsersResource.followers}.
|
|
4002
4366
|
*/
|
|
4003
|
-
interface UserListParams
|
|
4367
|
+
interface UserListParams {
|
|
4004
4368
|
/** Сколько записей вернуть. Значения больше 20 сервер молча уменьшает до 20. */
|
|
4005
4369
|
limit?: number;
|
|
4006
4370
|
/** Номер страницы. Сервер его игнорирует — оставлен на случай, если пагинацию починят. */
|
|
4007
4371
|
page?: number;
|
|
4008
|
-
maxPages?: number;
|
|
4009
4372
|
}
|
|
4010
4373
|
/** Изменяемые поля своего профиля. */
|
|
4011
4374
|
interface UpdateProfileInput {
|
|
@@ -4027,7 +4390,7 @@ type UpdatePrivacyInput = Partial<PrivacySettings>;
|
|
|
4027
4390
|
declare class UsersResource extends BaseResource {
|
|
4028
4391
|
#private;
|
|
4029
4392
|
constructor(http: HttpClient, deps: {
|
|
4030
|
-
uploadFile: (file: FileInput,
|
|
4393
|
+
uploadFile: (file: FileInput, uploadOptions?: UploadOptions, requestOptions?: RequestOptions) => Promise<UploadedFile>;
|
|
4031
4394
|
});
|
|
4032
4395
|
/** Загружает свой профиль — с подпиской и признаком подтверждённого телефона. */
|
|
4033
4396
|
me(options?: RequestOptions): Promise<MyProfile>;
|
|
@@ -4044,7 +4407,7 @@ declare class UsersResource extends BaseResource {
|
|
|
4044
4407
|
* await itd.users.setBanner(file, { filename: 'banner.webp' });
|
|
4045
4408
|
* ```
|
|
4046
4409
|
*/
|
|
4047
|
-
setBanner(file: FileInput,
|
|
4410
|
+
setBanner(file: FileInput, uploadOptions?: UploadOptions, requestOptions?: RequestOptions): Promise<MyProfile>;
|
|
4048
4411
|
/** Удаляет баннер профиля, устанавливая `bannerId` в `null`. */
|
|
4049
4412
|
removeBanner(options?: RequestOptions): Promise<MyProfile>;
|
|
4050
4413
|
/** Деактивирует аккаунт. Вернуть его можно через {@link restore}. */
|
|
@@ -4074,7 +4437,7 @@ declare class UsersResource extends BaseResource {
|
|
|
4074
4437
|
/** Ищет пользователей по строке запроса. */
|
|
4075
4438
|
search(query: string, params?: {
|
|
4076
4439
|
limit?: number;
|
|
4077
|
-
}
|
|
4440
|
+
}, options?: RequestOptions): Promise<UserSummary[]>;
|
|
4078
4441
|
/** Загружает рекомендации, на кого подписаться. */
|
|
4079
4442
|
whoToFollow(options?: RequestOptions): Promise<UserSummary[]>;
|
|
4080
4443
|
/** Загружает рейтинг кланов. */
|
|
@@ -4098,18 +4461,18 @@ declare class UsersResource extends BaseResource {
|
|
|
4098
4461
|
* Числу `total` доверять тоже не стоит: оно расходится с `followersCount` из профиля —
|
|
4099
4462
|
* на проверенных аккаунтах занижено примерно на 1–4%.
|
|
4100
4463
|
*/
|
|
4101
|
-
followers(user: UserRef, params?: UserListParams): Promise<Page<UserSummary>>;
|
|
4464
|
+
followers(user: UserRef, params?: UserListParams, options?: RequestOptions): Promise<Page<UserSummary>>;
|
|
4102
4465
|
/**
|
|
4103
4466
|
* Перебирает подписчиков.
|
|
4104
4467
|
*
|
|
4105
4468
|
* ⚠️ Перебор закончится после первых 20 записей: сервер список не листает —
|
|
4106
4469
|
* см. {@link followers}. Метод оставлен на случай, если пагинацию починят.
|
|
4107
4470
|
*/
|
|
4108
|
-
iterateFollowers(user: UserRef, params?: UserListParams): Paginator<UserSummary>;
|
|
4471
|
+
iterateFollowers(user: UserRef, params?: UserListParams, options?: PaginationOptions): Paginator<UserSummary>;
|
|
4109
4472
|
/** Загружает подписки пользователя. Ограничения те же, что у {@link followers}. */
|
|
4110
|
-
following(user: UserRef, params?: UserListParams): Promise<Page<UserSummary>>;
|
|
4473
|
+
following(user: UserRef, params?: UserListParams, options?: RequestOptions): Promise<Page<UserSummary>>;
|
|
4111
4474
|
/** Перебирает подписки. Закончится после первых 20 записей — см. {@link followers}. */
|
|
4112
|
-
iterateFollowing(user: UserRef, params?: UserListParams): Paginator<UserSummary>;
|
|
4475
|
+
iterateFollowing(user: UserRef, params?: UserListParams, options?: PaginationOptions): Paginator<UserSummary>;
|
|
4113
4476
|
/**
|
|
4114
4477
|
* Проверяет, подписаны ли вы, сразу для нескольких пользователей.
|
|
4115
4478
|
*
|
|
@@ -4127,9 +4490,9 @@ declare class UsersResource extends BaseResource {
|
|
|
4127
4490
|
/** Снимает блокировку. */
|
|
4128
4491
|
unblock(user: UserRef, options?: RequestOptions): Promise<void>;
|
|
4129
4492
|
/** Загружает заблокированных пользователей. Ограничения те же, что у {@link followers}. */
|
|
4130
|
-
blocked(params?: UserListParams): Promise<Page<UserSummary>>;
|
|
4493
|
+
blocked(params?: UserListParams, options?: RequestOptions): Promise<Page<UserSummary>>;
|
|
4131
4494
|
/** Перебирает заблокированных. Закончится после первых 20 записей — см. {@link followers}. */
|
|
4132
|
-
iterateBlocked(params?: UserListParams): Paginator<UserSummary>;
|
|
4495
|
+
iterateBlocked(params?: UserListParams, options?: PaginationOptions): Paginator<UserSummary>;
|
|
4133
4496
|
/** Загружает настройки приватности. */
|
|
4134
4497
|
getPrivacy(options?: RequestOptions): Promise<PrivacySettings>;
|
|
4135
4498
|
/** Обновляет настройки приватности. Передавайте только изменяемые поля. */
|
|
@@ -4165,19 +4528,6 @@ declare global {
|
|
|
4165
4528
|
readonly asyncDispose: unique symbol;
|
|
4166
4529
|
}
|
|
4167
4530
|
}
|
|
4168
|
-
/**
|
|
4169
|
-
* Скрытые параметры конструктора — не часть публичного API.
|
|
4170
|
-
*
|
|
4171
|
-
* @internal
|
|
4172
|
-
*/
|
|
4173
|
-
interface ItdClientInternals {
|
|
4174
|
-
/**
|
|
4175
|
-
* Готовая очередь запросов — так {@link ItdAccounts} с `rateLimitScope: 'shared'` даёт
|
|
4176
|
-
* нескольким клиентам одну на всех. Свою клиент в этом случае не заводит и, что важнее,
|
|
4177
|
-
* не гасит при `close()`: чужие ожидающие запросы это отменило бы.
|
|
4178
|
-
*/
|
|
4179
|
-
queues?: RequestQueuePool | undefined;
|
|
4180
|
-
}
|
|
4181
4531
|
/**
|
|
4182
4532
|
* Клиент API итд.com.
|
|
4183
4533
|
*
|
|
@@ -4212,32 +4562,32 @@ interface ItdClientInternals {
|
|
|
4212
4562
|
declare class ItdClient {
|
|
4213
4563
|
#private;
|
|
4214
4564
|
/** Авторизация, сессии и пароли. */
|
|
4215
|
-
|
|
4565
|
+
get auth(): AuthResource;
|
|
4216
4566
|
/** Профили, подписки, блокировки, приватность. */
|
|
4217
|
-
|
|
4567
|
+
get users(): UsersResource;
|
|
4218
4568
|
/** Лента, публикация, реакции, репосты, комментарии к постам. */
|
|
4219
|
-
|
|
4569
|
+
get posts(): PostsResource;
|
|
4220
4570
|
/** Ответы на комментарии и действия над ними. */
|
|
4221
|
-
|
|
4571
|
+
get comments(): CommentsResource;
|
|
4222
4572
|
/** Загрузка файлов и медиа. */
|
|
4223
|
-
|
|
4573
|
+
get files(): FilesResource;
|
|
4224
4574
|
/** Уведомления: список, счётчик, отметки о прочтении, настройки. */
|
|
4225
|
-
|
|
4575
|
+
get notifications(): NotificationsResource;
|
|
4226
4576
|
/** Хэштеги и посты по ним. */
|
|
4227
|
-
|
|
4577
|
+
get hashtags(): HashtagsResource;
|
|
4228
4578
|
/** Глобальный поиск по пользователям и хэштегам. */
|
|
4229
|
-
|
|
4579
|
+
get search(): SearchResource;
|
|
4230
4580
|
/** Жалобы на контент и пользователей. */
|
|
4231
|
-
|
|
4581
|
+
get reports(): ReportsResource;
|
|
4232
4582
|
/** Верификация профиля. */
|
|
4233
|
-
|
|
4583
|
+
get verification(): VerificationResource;
|
|
4234
4584
|
/** Подписка и способы оплаты. */
|
|
4235
|
-
|
|
4585
|
+
get subscription(): SubscriptionResource;
|
|
4236
4586
|
/** Сведения о платформе: версии приложений, изменения, анонсы, баннер события. */
|
|
4237
|
-
|
|
4587
|
+
get platform(): PlatformResource;
|
|
4238
4588
|
/** Телеметрия просмотров. */
|
|
4239
|
-
|
|
4240
|
-
constructor(options?: ItdClientOptions
|
|
4589
|
+
get telemetry(): TelemetryResource;
|
|
4590
|
+
constructor(options?: ItdClientOptions);
|
|
4241
4591
|
/** Базовый URL, к которому обращается клиент. */
|
|
4242
4592
|
get baseUrl(): string;
|
|
4243
4593
|
/**
|
|
@@ -4250,26 +4600,33 @@ declare class ItdClient {
|
|
|
4250
4600
|
* ```ts
|
|
4251
4601
|
* const raw = await itd.request({ method: 'GET', path: '/api/posts', raw: true });
|
|
4252
4602
|
* ```
|
|
4603
|
+
*
|
|
4604
|
+
* @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
|
|
4253
4605
|
*/
|
|
4254
4606
|
request<T = unknown>(options: RawRequestOptions): Promise<T>;
|
|
4255
4607
|
/**
|
|
4256
4608
|
* Подключает плагин.
|
|
4257
4609
|
*
|
|
4258
|
-
* Плагин
|
|
4259
|
-
*
|
|
4260
|
-
* момент, но обычно это делают сразу после создания клиента.
|
|
4610
|
+
* Плагин может независимо регистрировать transformer логической операции и interceptor
|
|
4611
|
+
* транспортной попытки. Оба контракта охватывают все методы клиента. Подключать плагин
|
|
4612
|
+
* можно в любой момент, но обычно это делают сразу после создания клиента.
|
|
4261
4613
|
*
|
|
4262
4614
|
* @throws {ItdConfigError} если плагин задан неверно или уже подключён
|
|
4615
|
+
* @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
|
|
4263
4616
|
*
|
|
4264
4617
|
* @example
|
|
4265
4618
|
* ```ts
|
|
4266
4619
|
* import { crypt } from '@itd-api/crypto';
|
|
4267
4620
|
*
|
|
4268
4621
|
* itd.use(crypt());
|
|
4269
|
-
* await itd.posts.create({
|
|
4622
|
+
* await itd.posts.create({
|
|
4623
|
+
* content: 'секрет',
|
|
4624
|
+
* }, {
|
|
4625
|
+
* extensions: { crypto: { encrypt: 'invisible' } },
|
|
4626
|
+
* });
|
|
4270
4627
|
* ```
|
|
4271
4628
|
*/
|
|
4272
|
-
use(plugin:
|
|
4629
|
+
use(plugin: ClientPlugin): this;
|
|
4273
4630
|
/** Имена подключённых плагинов в фактическом порядке выполнения обёрток. */
|
|
4274
4631
|
pluginNames(): string[];
|
|
4275
4632
|
/** Подключён ли плагин с таким именем. */
|
|
@@ -4295,6 +4652,7 @@ declare class ItdClient {
|
|
|
4295
4652
|
* поддоменам. Стороннему хосту токен нужно разрешить явно: `auth: true`.
|
|
4296
4653
|
*
|
|
4297
4654
|
* @throws {ItdConfigError} если определение неверно или имя уже занято
|
|
4655
|
+
* @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
|
|
4298
4656
|
*
|
|
4299
4657
|
* @example Сервис платформы на поддомене — токен уходит сам
|
|
4300
4658
|
* ```ts
|
|
@@ -4349,6 +4707,8 @@ declare class ItdClient {
|
|
|
4349
4707
|
*
|
|
4350
4708
|
* await stream.connect();
|
|
4351
4709
|
* ```
|
|
4710
|
+
*
|
|
4711
|
+
* @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
|
|
4352
4712
|
*/
|
|
4353
4713
|
realtime(options?: RealtimeOptions): ItdRealtime;
|
|
4354
4714
|
/**
|
|
@@ -4361,6 +4721,17 @@ declare class ItdClient {
|
|
|
4361
4721
|
* Общая очередь, полученная от {@link ItdAccounts}, не останавливается: её гасит сам
|
|
4362
4722
|
* контейнер, когда закрывает все аккаунты разом.
|
|
4363
4723
|
*
|
|
4724
|
+
* Терминальное освобождение — это {@link dispose}.
|
|
4725
|
+
*/
|
|
4726
|
+
close(): Promise<void>;
|
|
4727
|
+
/**
|
|
4728
|
+
* Окончательно освобождает клиент: выполняет {@link close} и отключает все плагины.
|
|
4729
|
+
*
|
|
4730
|
+
* Терминальное состояние устанавливается сразу при первом вызове. После этого новые
|
|
4731
|
+
* запросы, подключение плагинов, регистрация сервисов и создание или повторный запуск
|
|
4732
|
+
* realtime-потоков завершаются с {@link ItdStateError}. Повторные вызовы возвращают
|
|
4733
|
+
* тот же результат очистки.
|
|
4734
|
+
*
|
|
4364
4735
|
* @example
|
|
4365
4736
|
* ```ts
|
|
4366
4737
|
* await using itd = new ItdClient({ auth: token });
|
|
@@ -4368,14 +4739,6 @@ declare class ItdClient {
|
|
|
4368
4739
|
* // dispose() вызовется сам на выходе из блока
|
|
4369
4740
|
* ```
|
|
4370
4741
|
*/
|
|
4371
|
-
close(): Promise<void>;
|
|
4372
|
-
/**
|
|
4373
|
-
* Окончательно освобождает клиент: выполняет {@link close} и отключает все плагины.
|
|
4374
|
-
*
|
|
4375
|
-
* В отличие от `close()`, после `dispose()` плагины не восстанавливаются автоматически.
|
|
4376
|
-
* Сам клиент остаётся пригоден для обычных запросов; при необходимости плагины можно
|
|
4377
|
-
* подключить заново через {@link use}.
|
|
4378
|
-
*/
|
|
4379
4742
|
dispose(): Promise<void>;
|
|
4380
4743
|
/** Позволяет использовать клиент с `await using`. */
|
|
4381
4744
|
[Symbol.asyncDispose](): Promise<void>;
|
|
@@ -4400,7 +4763,11 @@ declare class ItdClient {
|
|
|
4400
4763
|
* ```
|
|
4401
4764
|
*/
|
|
4402
4765
|
getUserId(): Promise<UserId | undefined>;
|
|
4403
|
-
/**
|
|
4766
|
+
/**
|
|
4767
|
+
* Восстанавливает сохранённую сессию, включая cookie.
|
|
4768
|
+
*
|
|
4769
|
+
* @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
|
|
4770
|
+
*/
|
|
4404
4771
|
setSession(session: ItdSession): Promise<void>;
|
|
4405
4772
|
}
|
|
4406
4773
|
/**
|
|
@@ -4432,7 +4799,7 @@ interface ItdAccountsOptions extends Omit<ItdClientOptions, 'auth' | 'storage' |
|
|
|
4432
4799
|
/** Общее хранилище сессий всех аккаунтов. По умолчанию {@link MemoryMultiTokenStorage}. */
|
|
4433
4800
|
storage?: MultiTokenStorage | undefined;
|
|
4434
4801
|
/** Плагины, подключаемые каждому аккаунту, в том числе добавленному позже. */
|
|
4435
|
-
plugins?: readonly
|
|
4802
|
+
plugins?: readonly ClientPlugin[] | undefined;
|
|
4436
4803
|
/**
|
|
4437
4804
|
* Как делить очередь запросов. По умолчанию `'account'` — своя у каждого.
|
|
4438
4805
|
*
|
|
@@ -4598,7 +4965,7 @@ declare class ItdAccounts {
|
|
|
4598
4965
|
* accounts.use(crypt());
|
|
4599
4966
|
* ```
|
|
4600
4967
|
*/
|
|
4601
|
-
use(plugin:
|
|
4968
|
+
use(plugin: ClientPlugin): this;
|
|
4602
4969
|
/** Имена общих плагинов в фактическом порядке выполнения обёрток. */
|
|
4603
4970
|
pluginNames(): string[];
|
|
4604
4971
|
/** Подключён ли общий плагин с таким именем. */
|
|
@@ -4651,7 +5018,9 @@ declare class ItdAccounts {
|
|
|
4651
5018
|
* Окончательно освобождает контейнер и отключает общие плагины у всех аккаунтов.
|
|
4652
5019
|
*
|
|
4653
5020
|
* Для временной остановки потоков и очереди без отключения плагинов используйте
|
|
4654
|
-
* {@link close}.
|
|
5021
|
+
* {@link close}. Терминальное состояние устанавливается сразу: контейнер отзывает
|
|
5022
|
+
* storage-срезы и подписки, а новые аккаунты, запросы его клиентов и плагины после
|
|
5023
|
+
* первого `dispose()` больше не допускаются.
|
|
4655
5024
|
*/
|
|
4656
5025
|
dispose(): Promise<void>;
|
|
4657
5026
|
/** Позволяет использовать контейнер с `await using`. */
|
|
@@ -4664,6 +5033,22 @@ declare class ItdAccounts {
|
|
|
4664
5033
|
*/
|
|
4665
5034
|
declare function createAccounts(options?: ItdAccountsOptions): ItdAccounts;
|
|
4666
5035
|
//#endregion
|
|
5036
|
+
//#region src/core/attachments/factories.d.ts
|
|
5037
|
+
/** Создаёт URL-источник в выбранном режиме. */
|
|
5038
|
+
declare function fromUrl(url: string, options: UrlFileOptions & {
|
|
5039
|
+
mode: typeof FileTransferMode.Stream;
|
|
5040
|
+
}): StreamFile;
|
|
5041
|
+
declare function fromUrl(url: string, options?: UrlFileOptions & {
|
|
5042
|
+
mode?: typeof FileTransferMode.Buffer;
|
|
5043
|
+
}): LazyFile;
|
|
5044
|
+
declare function fromUrl(url: string, options: UrlFileOptions): LazyFile | StreamFile;
|
|
5045
|
+
/**
|
|
5046
|
+
* Создаёт повторяемый пользовательский поток.
|
|
5047
|
+
*
|
|
5048
|
+
* Фабрика вызывается заново для каждой попытки; возвращать один и тот же поток нельзя.
|
|
5049
|
+
*/
|
|
5050
|
+
declare function fromStream(factory: (context: FileContext) => ReadableStream<Uint8Array> | FileStreamContent | Promise<ReadableStream<Uint8Array> | FileStreamContent>, options?: FromStreamOptions): StreamFile;
|
|
5051
|
+
//#endregion
|
|
4667
5052
|
//#region src/core/errors.d.ts
|
|
4668
5053
|
/** Бренд, по которому ошибки библиотеки распознаются надёжнее, чем через `instanceof`. */
|
|
4669
5054
|
declare const ITD_ERROR: unique symbol;
|
|
@@ -4681,6 +5066,8 @@ declare const ItdErrorKind: Readonly<{
|
|
|
4681
5066
|
readonly Timeout: "timeout";
|
|
4682
5067
|
/** Запрос отменён через `AbortSignal`. */
|
|
4683
5068
|
readonly Abort: "abort";
|
|
5069
|
+
/** Операция невозможна в текущем состоянии объекта. */
|
|
5070
|
+
readonly State: "state";
|
|
4684
5071
|
/** Не удалось получить или подготовить содержимое вложения. */
|
|
4685
5072
|
readonly File: "file";
|
|
4686
5073
|
/** Некорректная конфигурация или аргументы — обнаружено до обращения к сети. */
|
|
@@ -4950,6 +5337,17 @@ declare class ItdAbortError extends ItdError {
|
|
|
4950
5337
|
cause?: unknown;
|
|
4951
5338
|
});
|
|
4952
5339
|
}
|
|
5340
|
+
/**
|
|
5341
|
+
* Операция невозможна в текущем состоянии объекта.
|
|
5342
|
+
*
|
|
5343
|
+
* Например, клиент уже окончательно освобождён через `dispose()` и не может выполнять
|
|
5344
|
+
* новые запросы или создавать realtime-потоки.
|
|
5345
|
+
*/
|
|
5346
|
+
declare class ItdStateError extends ItdError {
|
|
5347
|
+
constructor(message: string, options?: {
|
|
5348
|
+
cause?: unknown;
|
|
5349
|
+
});
|
|
5350
|
+
}
|
|
4953
5351
|
/**
|
|
4954
5352
|
* Некорректная конфигурация или аргументы — обнаружено до обращения к сети.
|
|
4955
5353
|
*
|
|
@@ -4957,7 +5355,9 @@ declare class ItdAbortError extends ItdError {
|
|
|
4957
5355
|
* с одним вариантом ответа.
|
|
4958
5356
|
*/
|
|
4959
5357
|
declare class ItdConfigError extends ItdError {
|
|
4960
|
-
constructor(message: string
|
|
5358
|
+
constructor(message: string, options?: {
|
|
5359
|
+
cause?: unknown;
|
|
5360
|
+
});
|
|
4961
5361
|
}
|
|
4962
5362
|
/** Любая ошибка, порождённая этой библиотекой. */
|
|
4963
5363
|
declare function isItdError(value: unknown): value is ItdError;
|
|
@@ -4965,6 +5365,8 @@ declare function isItdError(value: unknown): value is ItdError;
|
|
|
4965
5365
|
declare function isItdApiError(value: unknown): value is ItdApiError;
|
|
4966
5366
|
/** Ошибка получения или чтения вложения. */
|
|
4967
5367
|
declare function isItdFileError(value: unknown): value is ItdFileError;
|
|
5368
|
+
/** Операция невозможна в текущем состоянии объекта. */
|
|
5369
|
+
declare function isItdStateError(value: unknown): value is ItdStateError;
|
|
4968
5370
|
/** Ошибка валидации: `VALIDATION_ERROR` либо статус `400`/`422`. */
|
|
4969
5371
|
declare function isItdValidationError(value: unknown): value is ItdValidationError;
|
|
4970
5372
|
/** Ошибка авторизации: истёкший или отозванный токен. */
|
|
@@ -5009,6 +5411,46 @@ type AllowedMimeType = (typeof ALLOWED_MIME_TYPES)[number];
|
|
|
5009
5411
|
* ```
|
|
5010
5412
|
*/
|
|
5011
5413
|
declare function utcStampToIso(value: string): string;
|
|
5414
|
+
/**
|
|
5415
|
+
* Разбирает дату API в объект `Date`.
|
|
5416
|
+
*
|
|
5417
|
+
* @returns `null`, если строки нет или она не разбирается
|
|
5418
|
+
*
|
|
5419
|
+
* @example
|
|
5420
|
+
* ```ts
|
|
5421
|
+
* const created = toDate(post.createdAt);
|
|
5422
|
+
* ```
|
|
5423
|
+
*/
|
|
5424
|
+
declare function toDate(value: IsoDate | null | undefined): Date | null;
|
|
5425
|
+
//#endregion
|
|
5426
|
+
//#region src/models/guards.d.ts
|
|
5427
|
+
/**
|
|
5428
|
+
* Свой ли это профиль.
|
|
5429
|
+
*
|
|
5430
|
+
* @example
|
|
5431
|
+
* ```ts
|
|
5432
|
+
* if (isMyProfile(profile)) console.log(profile.subscription.isActive);
|
|
5433
|
+
* ```
|
|
5434
|
+
*/
|
|
5435
|
+
declare function isMyProfile(profile: Profile): profile is MyProfile;
|
|
5436
|
+
//#endregion
|
|
5437
|
+
//#region src/models/status-helpers.d.ts
|
|
5438
|
+
/**
|
|
5439
|
+
* Разворачивает историю сервиса в массив на 90 суток.
|
|
5440
|
+
* Сутки без данных становятся `null`.
|
|
5441
|
+
*
|
|
5442
|
+
* @returns массив, где индекс — сколько суток назад: `[0]` — сегодня
|
|
5443
|
+
*
|
|
5444
|
+
* @example
|
|
5445
|
+
* ```ts
|
|
5446
|
+
* const status = await itd.platform.status();
|
|
5447
|
+
* const days = statusDays(status.services[0]);
|
|
5448
|
+
*
|
|
5449
|
+
* days[0]?.uptime; // доступность за сегодня
|
|
5450
|
+
* days.filter((day) => day === null).length; // за сколько суток данных нет
|
|
5451
|
+
* ```
|
|
5452
|
+
*/
|
|
5453
|
+
declare function statusDays(service: ServiceStatus): (StatusDay | null)[];
|
|
5012
5454
|
//#endregion
|
|
5013
5455
|
//#region src/notifications/text.d.ts
|
|
5014
5456
|
/**
|
|
@@ -5074,20 +5516,9 @@ declare function isKnownNotificationType(type: string): boolean;
|
|
|
5074
5516
|
*/
|
|
5075
5517
|
declare function resolveNotificationUrl(notification: Notification): string;
|
|
5076
5518
|
//#endregion
|
|
5077
|
-
//#region src/realtime/poll.d.ts
|
|
5078
|
-
/** Настройки опроса. */
|
|
5079
|
-
interface PollTransportOptions {
|
|
5080
|
-
/** Часы опроса. Обычно подменяются только в тестах. */
|
|
5081
|
-
clock?: ItdClock;
|
|
5082
|
-
/** Как часто опрашивать сервер, мс. По умолчанию 15 000. */
|
|
5083
|
-
interval?: number;
|
|
5084
|
-
/** Сколько уведомлений запрашивать за раз. По умолчанию 20. */
|
|
5085
|
-
limit?: number;
|
|
5086
|
-
}
|
|
5087
|
-
//#endregion
|
|
5088
5519
|
//#region src/realtime/router.d.ts
|
|
5089
5520
|
/** Выбирает маршрут обновления. `undefined` и `null` означают отсутствие маршрута. */
|
|
5090
|
-
type RealtimeRouteSelector<K extends PropertyKey> = (context:
|
|
5521
|
+
type RealtimeRouteSelector<K extends PropertyKey, C extends RealtimeContextBase = RealtimeContext> = (context: C) => K | null | undefined | Promise<K | null | undefined>;
|
|
5091
5522
|
/**
|
|
5092
5523
|
* Направляет обновления потока в именованные цепочки промежуточных обработчиков.
|
|
5093
5524
|
*
|
|
@@ -5102,18 +5533,91 @@ type RealtimeRouteSelector<K extends PropertyKey> = (context: RealtimeContext) =
|
|
|
5102
5533
|
* }
|
|
5103
5534
|
* await next();
|
|
5104
5535
|
* });
|
|
5105
|
-
* stream.use(router
|
|
5536
|
+
* stream.use(router);
|
|
5106
5537
|
* ```
|
|
5107
5538
|
*/
|
|
5108
|
-
declare class RealtimeRouter<K extends PropertyKey = PropertyKey> {
|
|
5539
|
+
declare class RealtimeRouter<K extends PropertyKey = PropertyKey, C extends RealtimeContextBase = RealtimeContext> implements RealtimeMiddlewareObj<C> {
|
|
5109
5540
|
#private;
|
|
5110
|
-
constructor(selector: RealtimeRouteSelector<K>);
|
|
5541
|
+
constructor(selector: RealtimeRouteSelector<K, C>);
|
|
5111
5542
|
/** Добавляет промежуточные обработчики к маршруту и возвращает функцию их удаления. */
|
|
5112
|
-
route(key: K, ...middleware: readonly RealtimeMiddleware[]): Unsubscribe;
|
|
5543
|
+
route(key: K, ...middleware: readonly RealtimeMiddleware<C>[]): Unsubscribe;
|
|
5113
5544
|
/** Добавляет промежуточные обработчики для обновлений без зарегистрированного маршрута. */
|
|
5114
|
-
otherwise(...middleware: readonly RealtimeMiddleware[]): Unsubscribe;
|
|
5115
|
-
/** Возвращает
|
|
5116
|
-
middleware(): RealtimeMiddleware
|
|
5545
|
+
otherwise(...middleware: readonly RealtimeMiddleware<C>[]): Unsubscribe;
|
|
5546
|
+
/** Возвращает снимок маршрутов для `stream.use(router)` или ручной композиции. */
|
|
5547
|
+
middleware(): RealtimeMiddleware<C>;
|
|
5548
|
+
}
|
|
5549
|
+
//#endregion
|
|
5550
|
+
//#region src/realtime/composer.d.ts
|
|
5551
|
+
/** Функция или объектный middleware, который можно добавить в {@link RealtimeComposer}. */
|
|
5552
|
+
type RealtimeMiddlewareLike<C extends RealtimeContextBase = RealtimeContext> = RealtimeMiddleware<C> | RealtimeMiddlewareObj<C>;
|
|
5553
|
+
/** Один middleware или последовательность middleware для ветки composer. */
|
|
5554
|
+
type RealtimeMiddlewareGroup<C extends RealtimeContextBase = RealtimeContext> = RealtimeMiddlewareLike<C> | readonly RealtimeMiddlewareLike<C>[];
|
|
5555
|
+
/** Синхронное или асинхронное условие ветвления composer. */
|
|
5556
|
+
type RealtimeFilter<C extends RealtimeContextBase = RealtimeContext> = (context: C) => boolean | Promise<boolean>;
|
|
5557
|
+
/** Ошибка локальной realtime-ветки вместе с контекстом обрабатываемого обновления. */
|
|
5558
|
+
interface RealtimeErrorContext<C extends RealtimeContextBase = RealtimeContext> {
|
|
5559
|
+
/** Исходное исключение middleware. */
|
|
5560
|
+
readonly error: unknown;
|
|
5561
|
+
/** Контекст обновления, на котором завершилась ветка. */
|
|
5562
|
+
readonly context: C;
|
|
5563
|
+
}
|
|
5564
|
+
/** Обработчик локальной границы ошибок composer. */
|
|
5565
|
+
type RealtimeErrorBoundary<C extends RealtimeContextBase = RealtimeContext> = (failure: RealtimeErrorContext<C>, next: RealtimeNext) => unknown | Promise<unknown>;
|
|
5566
|
+
/** Именованные ветки для {@link RealtimeComposer.route}. */
|
|
5567
|
+
type RealtimeRouteTable<K extends string | symbol, C extends RealtimeContextBase = RealtimeContext> = Partial<Record<K, RealtimeMiddlewareGroup<C>>>;
|
|
5568
|
+
/**
|
|
5569
|
+
* Собирает переиспользуемый feature-модуль из realtime middleware.
|
|
5570
|
+
*
|
|
5571
|
+
* Composer не открывает соединение и не планирует конкурентность: готовый объект подключается
|
|
5572
|
+
* через `stream.use(composer)`, а выполнение остаётся обязанностью существующего dispatcher.
|
|
5573
|
+
* Для каждого принятого update используется снимок всей вложенной структуры composer.
|
|
5574
|
+
*
|
|
5575
|
+
* @example
|
|
5576
|
+
* ```ts
|
|
5577
|
+
* const feature = new RealtimeComposer<AppRealtimeContext>();
|
|
5578
|
+
* const safe = feature.errorBoundary(reportFeatureError);
|
|
5579
|
+
* safe.filter(isPostUpdate).use(handlePost);
|
|
5580
|
+
* stream.use(feature);
|
|
5581
|
+
* ```
|
|
5582
|
+
*/
|
|
5583
|
+
declare class RealtimeComposer<C extends RealtimeContextBase = RealtimeContext> implements RealtimeMiddlewareObj<C> {
|
|
5584
|
+
#private;
|
|
5585
|
+
constructor(...middleware: readonly RealtimeMiddlewareLike<C>[]);
|
|
5586
|
+
/** Добавляет middleware в конец текущей onion-цепочки. */
|
|
5587
|
+
use(...middleware: readonly RealtimeMiddlewareLike<C>[]): this;
|
|
5588
|
+
/** Создаёт дочернюю ветку, выполняемую только когда type guard принимает контекст. */
|
|
5589
|
+
filter<N extends C>(predicate: RealtimeTypeGuard<N, C>, ...middleware: readonly RealtimeMiddlewareLike<N>[]): RealtimeComposer<N>;
|
|
5590
|
+
/** Создаёт дочернюю ветку по синхронному или асинхронному условию. */
|
|
5591
|
+
filter(predicate: RealtimeFilter<C>, ...middleware: readonly RealtimeMiddlewareLike<C>[]): RealtimeComposer<C>;
|
|
5592
|
+
/**
|
|
5593
|
+
* Направляет контекст в одну именованную ветку.
|
|
5594
|
+
*
|
|
5595
|
+
* Неизвестный ключ без fallback пропускает update следующему внешнему middleware. Для
|
|
5596
|
+
* динамической регистрации и числовых ключей используйте {@link RealtimeRouter} напрямую.
|
|
5597
|
+
*/
|
|
5598
|
+
route<K extends string | symbol>(selector: RealtimeRouteSelector<K, C>, routes: RealtimeRouteTable<K, C>, fallback?: RealtimeMiddlewareGroup<C>): this;
|
|
5599
|
+
/**
|
|
5600
|
+
* Создаёт дочернюю ветку с локальной границей ошибок.
|
|
5601
|
+
*
|
|
5602
|
+
* Граница защищает только переданные и затем добавленные в возвращённый composer middleware.
|
|
5603
|
+
* Ошибки внешней цепочки намеренно не перехватываются. Обработчик может вызвать `next()`,
|
|
5604
|
+
* чтобы после ошибки продолжить внешнюю цепочку, либо повторно выбросить исключение. Внешняя
|
|
5605
|
+
* цепочка начинается после полного завершения защищённой ветки, а не входит в её onion-вызов.
|
|
5606
|
+
*/
|
|
5607
|
+
errorBoundary(handler: RealtimeErrorBoundary<C>, ...middleware: readonly RealtimeMiddlewareLike<C>[]): RealtimeComposer<C>;
|
|
5608
|
+
/** Возвращает snapshot-aware middleware для `stream.use()` или вложенного composer. */
|
|
5609
|
+
middleware(): RealtimeMiddleware<C>;
|
|
5610
|
+
}
|
|
5611
|
+
//#endregion
|
|
5612
|
+
//#region src/realtime/poll.d.ts
|
|
5613
|
+
/** Настройки опроса. */
|
|
5614
|
+
interface PollTransportOptions {
|
|
5615
|
+
/** Часы опроса. Обычно подменяются только в тестах. */
|
|
5616
|
+
clock?: ItdClock;
|
|
5617
|
+
/** Как часто опрашивать сервер, мс. По умолчанию 15 000. */
|
|
5618
|
+
interval?: number;
|
|
5619
|
+
/** Сколько уведомлений запрашивать за раз. По умолчанию 20. */
|
|
5620
|
+
limit?: number;
|
|
5117
5621
|
}
|
|
5118
5622
|
//#endregion
|
|
5119
5623
|
//#region src/realtime/sse.d.ts
|
|
@@ -5141,6 +5645,50 @@ interface SseTransportOptions {
|
|
|
5141
5645
|
handshakeTimeout?: number;
|
|
5142
5646
|
}
|
|
5143
5647
|
//#endregion
|
|
5648
|
+
//#region src/realtime/websocket.d.ts
|
|
5649
|
+
/** Стандартный путь WebSocket-подключения. */
|
|
5650
|
+
declare const WEBSOCKET_PATH = "/api/ws";
|
|
5651
|
+
/** Дополнительные параметры конструктора, поддерживаемые Node-реализациями вроде `ws`. */
|
|
5652
|
+
interface WebSocketImplementationOptions {
|
|
5653
|
+
headers?: Record<string, string> | undefined;
|
|
5654
|
+
handshakeTimeout?: number | undefined;
|
|
5655
|
+
}
|
|
5656
|
+
/** Конструктор WebSocket, который можно передать вместо глобальной реализации. */
|
|
5657
|
+
interface WebSocketLike {
|
|
5658
|
+
new (url: string | URL, protocols?: string | string[], options?: WebSocketImplementationOptions): unknown;
|
|
5659
|
+
}
|
|
5660
|
+
/** Определяет, был ли отказ до открытия сокета вызван недействительным токеном. */
|
|
5661
|
+
type WebSocketOpenFailureClassifier = (error: unknown, signal: AbortSignal) => boolean | Promise<boolean>;
|
|
5662
|
+
/** Настройки WebSocket-транспорта. */
|
|
5663
|
+
interface WebSocketTransportOptions {
|
|
5664
|
+
/** Путь апгрейда. По умолчанию `/api/ws`. */
|
|
5665
|
+
path?: string | undefined;
|
|
5666
|
+
/** Реализация WebSocket для сред без глобальной либо для передачи заголовков апгрейда. */
|
|
5667
|
+
webSocketImpl?: WebSocketLike | undefined;
|
|
5668
|
+
/** Способ передачи токена. `auto` выбирает заголовок при инъекции и query иначе. */
|
|
5669
|
+
auth?: 'query' | 'header' | 'auto' | undefined;
|
|
5670
|
+
/** Молчание открытого соединения до переподключения, мс. По умолчанию 90 000. */
|
|
5671
|
+
idleTimeout?: number | undefined;
|
|
5672
|
+
/** Период текстового `ping`, мс. По умолчанию 30 000. */
|
|
5673
|
+
keepAlive?: number | undefined;
|
|
5674
|
+
/** Максимальное время установки соединения, мс. По умолчанию 20 000. */
|
|
5675
|
+
handshakeTimeout?: number | undefined;
|
|
5676
|
+
/**
|
|
5677
|
+
* Проверяет отказ до `open`, когда среда скрыла HTTP-статус WebSocket-upgrade.
|
|
5678
|
+
* `true` преобразует отказ в {@link UnauthorizedStreamError}.
|
|
5679
|
+
*/
|
|
5680
|
+
classifyOpenFailure?: WebSocketOpenFailureClassifier | undefined;
|
|
5681
|
+
/** Часы транспорта. Обычно подменяются только в тестах. */
|
|
5682
|
+
clock?: ItdClock | undefined;
|
|
5683
|
+
}
|
|
5684
|
+
/** Транспорт исходных realtime-событий поверх стандартного WebSocket. */
|
|
5685
|
+
declare class WebSocketTransport implements RealtimeTransport {
|
|
5686
|
+
#private;
|
|
5687
|
+
readonly name = "ws";
|
|
5688
|
+
constructor(options?: WebSocketTransportOptions);
|
|
5689
|
+
connect(context: TransportContext): Promise<void>;
|
|
5690
|
+
}
|
|
5691
|
+
//#endregion
|
|
5144
5692
|
//#region src/spans/render.d.ts
|
|
5145
5693
|
/** Формат результата {@link renderSpans}. */
|
|
5146
5694
|
declare const SpanRenderFormat: Readonly<{
|
|
@@ -5172,5 +5720,5 @@ interface RenderSpansOptions {
|
|
|
5172
5720
|
*/
|
|
5173
5721
|
declare function renderSpans(content: string, spans?: readonly Span[] | null | undefined, options?: RenderSpansOptions): string;
|
|
5174
5722
|
//#endregion
|
|
5175
|
-
export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AUTH_FLAG_COOKIE, AUTH_PATHS, AccessType, type AccountEvents, type Actor, type AddAccountOptions, type AllowedMimeType, type Announcement, type AnnouncementButton, type Attachment, AttachmentType, type AudioMimeType, type AuthEvents, type AuthIdentity, type AuthInput, type AuthResource, type AuthState, type Author, type AutoSpansOptions, BUILT_IN_SERVICES, type BuilderInput, type CaptchaCredentials, type ChangelogEntry, type Clan, type ClientHooks, type Comment, type CommentBuilder, type CommentInput, type CommentReplyTo, CommentSort, type CommentsParams, type CommentsResource, type CreateCommentInput, type CreatePollInput, type CreatePostInput, type CreateReportInput, type Credentials, type CredentialsAuth, DEFAULT_BASE_URL, DEFAULT_FILE_STREAM_BUFFER_BYTES, DEFAULT_STATUS_BASE_URL, DEFAULT_TIMEOUT, DEFAULT_UPLOAD_TIMEOUT, DEFAULT_URL_FILE_MAX_BYTES, DEFAULT_USER_AGENT, DEVICE_ID_HEADER, DetectedRuntime, type DwellEntry, type ErrorContextHook, type FeedParams, FeedTab, type FileContent, type FileContext, type FileInput, type FileStreamContent, type FileStreamOptions, FileTransferMode, type FilesResource, type FollowResult, type ForgotPasswordInput, type FromStreamOptions, type Hashtag, type HashtagPostsParams, type HashtagsResource, IMAGE_MIME_TYPES, type ImageMimeType, IncidentKind, type InteractionEntry, InteractionType, type IsoDate, ItdAbortError, ItdAccounts, type ItdAccountsOptions, ItdApiError, type ItdApiErrorInit, ItdApiErrorKind, ItdAuthError, type ItdBuilder, ItdClient, type ItdClientOptions, type ItdClock, ItdConfigError, ItdConflictError, ItdError, ItdErrorCode, ItdErrorKind, type ItdFieldErrors, ItdFileError, ItdFileErrorReason, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdPhoneVerificationError,
|
|
5723
|
+
export { ALLOWED_MIME_TYPES, AUDIO_MIME_TYPES, AUTH_FLAG_COOKIE, AUTH_PATHS, AccessType, type AccountEvents, type Actor, type AddAccountOptions, type AllowedMimeType, type Announcement, type AnnouncementButton, type Attachment, AttachmentType, type AttemptContext, type AttemptExtensions, type AttemptInterceptor, type AttemptNext, type AudioMimeType, type AuthEvents, type AuthIdentity, type AuthInput, type AuthResource, type AuthState, type Author, type AutoSpansOptions, BUILT_IN_SERVICES, type BuilderInput, type BuiltInOperationId, type CaptchaCredentials, type ChangelogEntry, type Clan, type ClientHooks, type ClientPlugin, type Comment, type CommentBuilder, type CommentInput, type CommentReplyTo, CommentSort, type CommentsParams, type CommentsResource, type CreateCommentInput, type CreatePollInput, type CreatePostData, type CreatePostInput, type CreateReportInput, type Credentials, type CredentialsAuth, type CustomOperationId, DEFAULT_BASE_URL, DEFAULT_FILE_STREAM_BUFFER_BYTES, DEFAULT_STATUS_BASE_URL, DEFAULT_TIMEOUT, DEFAULT_UPLOAD_TIMEOUT, DEFAULT_URL_FILE_MAX_BYTES, DEFAULT_USER_AGENT, DEVICE_ID_HEADER, DetectedRuntime, type DwellEntry, type EnumerableKeyValueStore, type ErrorContextHook, type FeedParams, FeedTab, type FileContent, type FileContext, type FileInput, type FileStreamContent, type FileStreamOptions, FileTransferMode, type FilesResource, type FollowResult, type ForgotPasswordInput, type FromStreamOptions, type Hashtag, type HashtagPostsParams, type HashtagsResource, IMAGE_MIME_TYPES, type ImageMimeType, IncidentKind, type InteractionEntry, InteractionType, type IsoDate, ItdAbortError, ItdAccounts, type ItdAccountsOptions, ItdApiError, type ItdApiErrorInit, ItdApiErrorKind, ItdAuthError, type ItdBuilder, ItdClient, type ItdClientOptions, type ItdClock, ItdConfigError, ItdConflictError, ItdError, ItdErrorCode, ItdErrorKind, type ItdFieldErrors, ItdFileError, ItdFileErrorReason, ItdForbiddenError, ItdNetworkError, ItdNotFoundError, ItdPhoneVerificationError, ItdRateLimitError, ItdRealtime, ItdServerError, type ItdSession, ItdStateError, ItdTimeoutError, ItdValidationError, type KeyValueCodec, type KeyValueStore, type KeyValueStoreKeys, type KeyValueStoreResult, LIBRARY_VERSION, type LazyFile, type LikeResult, LikesVisibility, type Listener, type Logger, type Loose, MAX_RECONNECT_ATTEMPTS, type MarkupBuilder, type MarkupContent, type MarkupInput, type MarkupSpan, MemoryKeyValueStore, MemoryMultiTokenStorage, MemoryTokenStorage, type MultiTokenStorage, type MultiTokenStorageAdapterOptions, type MyProfile, NOTIFICATION_TYPE_ALIASES, type Notification, type NotificationEvent, type NotificationEventOfType, type NotificationListParams, type NotificationOfType, type NotificationSettings, NotificationType, type NotificationsResource, OPERATIONS, type OperationDefinition, type OperationExtensions, type OperationId, type OperationMethod, type OperationRequestOptions, type OperationTransformer, type Page, type PageState, PaginationMode, type PaginationOptions, Paginator, type PaginatorOptions, type ParseMarkupOptions, type PaymentMethod, type PhotoOpenInput, type Pin, type PinPostResult, type PinsResult, type PlatformClientVersion, type PlatformResource, type PlatformStatus, type PlatformVersions, type PluginApi, type PluginTeardown, type Poll, type PollBuilder, type PollInput, type PollOption, type PollTransportOptions, type Portal, type Post, type PostBuilder, type PostInput, type PostStats, type PostUpdateInput, type PostsResource, type PrivacySettings, type Profile, type PublicProfile, type QueryParams, type QueryValue, RECONNECT_BACKOFF, RECONNECT_JITTER, REFRESH_COOKIE, REFRESH_COOKIE_PATH, type RateLimitOptions, type RateLimitScope, type RawRequestOptions, RealtimeComposer, type RealtimeContext, type RealtimeContextBase, type RealtimeDeps, type RealtimeEngineEvents, type RealtimeErrorBoundary, type RealtimeErrorContext, type RealtimeEvents, type RealtimeFilter, type RealtimeHandler, type RealtimeMiddleware, type RealtimeMiddlewareGroup, type RealtimeMiddlewareLike, type RealtimeMiddlewareObj, type RealtimeNext, type RealtimeNotificationContext, type RealtimeNotificationFilter, type RealtimeNotificationSelector, type RealtimeNotificationUpdate, type RealtimeOptions, type RealtimePredicate, type RealtimeRouteSelector, type RealtimeRouteTable, RealtimeRouter, type RealtimeSequentializer, RealtimeStatus, type RealtimeTransport, RealtimeTransportKind, type RealtimeTypeGuard, type RealtimeUnknownUpdate, type RealtimeUnreadCountUpdate, type RealtimeUpdate, type RealtimeUpdateOfType, RealtimeUpdateOrigin, RealtimeUpdateType, type ReconnectOptions, type RecordKeyValueStoreSource, type RemoveAccountOptions, type RenderSpansOptions, type RepliesParams, type Report, type ReportBuilder, type ReportInput, ReportReason, ReportTargetType, type ReportsResource, type RequestContext, type RequestExtensions, type RequestOptions, type ResetPasswordInput, type ResponseContext, type RetryContext, type RetryDecisionContext, type RetryOptions, RetrySafety, RuntimeMode, STATUS_SERVICE, STREAM_PATH, type SearchResource, type SearchResult, type ServiceDefinition, ServiceRegistry, ServiceState, type ServiceStatus, type Session, type SignInResult, SignInStatus, type Span, SpanRenderFormat, SpanType, type SseTransportOptions, type StatusDay, type StatusIncidentLine, type StreamFile, type Subscription, type SubscriptionResource, type SubscriptionState, TURNSTILE_SITE_KEY, type TelemetryBatch, type TelemetryBatchOptions, type TelemetryClock, type TelemetryOptions, type TelemetryResource, type TextMarkup, type TokenStorage, type TokenStorageAdapterOptions, type TransportContext, type TransportEvent, UnauthorizedStreamError, type Unsubscribe, type UpdateNotificationSettingsInput, type UpdatePostInput, type UpdatePrivacyInput, type UpdateProfileInput, type UploadOptions, type UploadedFile, type UrlFile, type UrlFileOptions, type UserId, type UserListParams, type UserPostsParams, type UserRef, type UserSummary, type UsersResource, VIDEO_MIME_TYPES, type VerificationResource, type VerificationStatus, type VideoMimeType, type VideoProgressInput, ViewReason, ViewSource, type ViewTracker, type ViewTrackerInput, type ViewTrackerOptions, WEBSOCKET_PATH, WallAccess, type WebSocketImplementationOptions, type WebSocketLike, type WebSocketOpenFailureClassifier, WebSocketTransport, type WebSocketTransportOptions, autoSpans, canonicalNotificationType, comment, createAccounts, createClient, createKeyValueStore, createMultiTokenStorage, createRecordKeyValueStore, createTokenStorage, formatNotificationText, fromStream, fromUrl, isBuilder, isBuiltInOperationId, isEnumerableKeyValueStore, isItdApiError, isItdAuthError, isItdConflictError, isItdError, isItdFileError, isItdForbiddenError, isItdNotFoundError, isItdPhoneVerificationError, isItdRateLimitError, isItdServerError, isItdStateError, isItdValidationError, isKnownNotificationType, isMyProfile, mapPage, markup, normalizeNotification, operationMethod, operationRetrySafety, parseHtml, parseMarkdown, poll, post, readNotificationEvent, readUnreadCountEvent, renderSpans, report, resolveNotificationUrl, runRealtimeMiddleware, scopedTokenStorage, statusDays, systemClock, toDate, utcStampToIso, withCodec, withNamespace };
|
|
5176
5724
|
//# sourceMappingURL=index.d.ts.map
|