itd-api 0.0.11 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +8 -4
  2. package/dist/{chunk-TB7HW3VX.js → chunk-6FB4HTKH.js} +660 -174
  3. package/dist/chunk-6FB4HTKH.js.map +1 -0
  4. package/dist/{chunk-QD4UHJFF.cjs → chunk-73CISRBG.cjs} +660 -174
  5. package/dist/chunk-73CISRBG.cjs.map +1 -0
  6. package/dist/{index-CrlTO7sR.d.cts → index-BZF4K90s.d.cts} +125 -22
  7. package/dist/{index-CrlTO7sR.d.ts → index-BZF4K90s.d.ts} +125 -22
  8. package/dist/index.cjs +109 -109
  9. package/dist/index.d.cts +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/node.cjs +112 -112
  13. package/dist/node.d.cts +2 -2
  14. package/dist/node.d.ts +2 -2
  15. package/dist/node.js +2 -2
  16. package/guides/README.md +2 -0
  17. package/guides/multi-accounts/README.md +2 -1
  18. package/guides/plugins/README.md +93 -2
  19. package/guides/reference/README.md +67 -0
  20. package/guides/reference/accounts.md +101 -0
  21. package/guides/reference/auth.md +141 -0
  22. package/guides/reference/builders.md +135 -0
  23. package/guides/reference/client.md +184 -0
  24. package/guides/reference/comments.md +58 -0
  25. package/guides/reference/discovery.md +81 -0
  26. package/guides/reference/enums.md +103 -0
  27. package/guides/reference/errors.md +107 -0
  28. package/guides/reference/files.md +73 -0
  29. package/guides/reference/models.md +448 -0
  30. package/guides/reference/notifications.md +77 -0
  31. package/guides/reference/pagination.md +82 -0
  32. package/guides/reference/platform.md +47 -0
  33. package/guides/reference/posts.md +157 -0
  34. package/guides/reference/realtime.md +78 -0
  35. package/guides/reference/reports.md +28 -0
  36. package/guides/reference/subscription.md +41 -0
  37. package/guides/reference/users.md +146 -0
  38. package/guides/reference/verification.md +24 -0
  39. package/package.json +1 -1
  40. package/dist/chunk-QD4UHJFF.cjs.map +0 -1
  41. package/dist/chunk-TB7HW3VX.js.map +0 -1
@@ -0,0 +1,184 @@
1
+ # Клиент — `ItdClient`
2
+
3
+ Точка входа. Группирует ресурсы (`itd.posts`, `itd.users`, …) и берёт на себя авторизацию,
4
+ обновление токена, повторы и очередь запросов. Достаточно **одного экземпляра на приложение**.
5
+
6
+ ```ts
7
+ new ItdClient(options?: ItdClientOptions)
8
+ createClient(options?: ItdClientOptions): ItdClient // то же самое, фабрика
9
+ ```
10
+
11
+ Точка входа `itd-api/node` дополнительно даёт загрузку файлов по пути и файловые хранилища
12
+ (`FileTokenStorage`, `FileMultiTokenStorage`).
13
+
14
+ ## Ресурсы
15
+
16
+ | Свойство | Ресурс |
17
+ |---|---|
18
+ | `itd.auth` | [Авторизация](./auth.md) |
19
+ | `itd.users` | [Пользователи](./users.md) |
20
+ | `itd.posts` | [Посты](./posts.md) |
21
+ | `itd.comments` | [Комментарии](./comments.md) |
22
+ | `itd.files` | [Файлы](./files.md) |
23
+ | `itd.notifications` | [Уведомления](./notifications.md) |
24
+ | `itd.hashtags`, `itd.search` | [Поиск и обнаружение](./discovery.md) |
25
+ | `itd.reports` | [Жалобы](./reports.md) |
26
+ | `itd.verification` | [Верификация](./verification.md) |
27
+ | `itd.subscription` | [Подписка](./subscription.md) |
28
+ | `itd.platform` | [Платформа](./platform.md) |
29
+ | `itd.telemetry` | телеметрия просмотров |
30
+
31
+ ## Методы
32
+
33
+ ```ts
34
+ get baseUrl: string
35
+ ```
36
+ Базовый URL, к которому обращается клиент.
37
+
38
+ ```ts
39
+ request<T = unknown>(options: RawRequestOptions): Promise<T>
40
+ ```
41
+ Произвольный запрос к API — запасной путь, когда нужного метода нет. Проходит через ту же
42
+ авторизацию, очередь и обработку ошибок. С `raw: true` возвращает тело без снятия обёртки
43
+ `{ data: … }`.
44
+
45
+ ```ts
46
+ use(plugin: ItdPlugin): this
47
+ pluginNames(): string[]
48
+ hasPlugin(name: string): boolean
49
+ unuse(name: string): Promise<boolean>
50
+ ```
51
+ Подключает плагин — обёртку вокруг запроса и разобранного ответа сразу для всех ресурсов.
52
+ Официальные плагины: [`@itd-api/cache`](../plugins/README.md),
53
+ [`@itd-api/crypto`](../plugins/README.md). Остальные методы показывают фактический порядок
54
+ плагинов, проверяют наличие и отключают плагин с вызовом его teardown.
55
+
56
+ ```ts
57
+ defineService(definition: ServiceDefinition): this
58
+ serviceBaseUrl(name: string): string
59
+ ```
60
+ Регистрирует / читает домен платформы, отличный от основного (запросы с `{ service: 'имя' }`).
61
+ Bearer-токен по умолчанию уходит только на основной хост и его поддомены.
62
+
63
+ ```ts
64
+ realtime(options?: RealtimeOptions): ItdRealtime
65
+ ```
66
+ Создаёт поток уведомлений. Каждый вызов — новый независимый поток. См. [Realtime](./realtime.md).
67
+
68
+ ```ts
69
+ on<K>(event: K, listener): Unsubscribe
70
+ ```
71
+ Подписывается на [события авторизации](#события). Возвращает функцию отписки.
72
+
73
+ ```ts
74
+ close(): Promise<void>
75
+ dispose(): Promise<void>
76
+ ```
77
+ `close()` временно останавливает очередь и закрывает потоки уведомлений; после него клиентом
78
+ можно пользоваться снова. `dispose()` дополнительно отключает плагины и освобождает их
79
+ ресурсы. `await using` вызывает `dispose()`.
80
+
81
+ ```ts
82
+ getSession(): Promise<ItdSession | null>
83
+ setSession(session: ItdSession): Promise<void>
84
+ getUserId(): Promise<UserId | undefined>
85
+ ```
86
+ Читает / восстанавливает текущую сессию целиком и идентификатор аккаунта из токена (без запроса).
87
+
88
+ ## События
89
+
90
+ Метод `itd.on(event, listener)` — ключи `AuthEvents`:
91
+
92
+ | Событие | Данные | Когда |
93
+ |---|---|---|
94
+ | `tokens` | `{ accessToken }` | токен получен или обновлён |
95
+ | `signIn` | `{ accessToken }` | выполнен вход |
96
+ | `signOut` | — | сессия очищена |
97
+ | `authError` | `{ error }` | обновить сессию не удалось; запросы будут падать с 401 |
98
+
99
+ ## Опции конструктора
100
+
101
+ ```ts
102
+ interface ItdClientOptions {
103
+ baseUrl?: string; // по умолчанию https://xn--d1ah4a.com
104
+ services?: Record<string, string | Omit<ServiceDefinition, 'name'>>;
105
+ auth?: AuthInput; // см. ниже
106
+ storage?: TokenStorage; // по умолчанию MemoryTokenStorage
107
+ autoRefresh?: boolean; // обновлять токен при 401; по умолчанию true
108
+ reloginOnRefreshFailure?: boolean; // войти заново при неудаче refresh (нужны email+пароль)
109
+ fetch?: typeof fetch; // своя реализация: Deno, RN, тесты, прокси
110
+ timeout?: number; // по умолчанию 30000; 0 — без ограничения
111
+ retry?: RetryOptions | false;
112
+ rateLimit?: RateLimitOptions | false;
113
+ hooks?: ClientHooks;
114
+ logger?: Logger | boolean; // true — писать в console (токены маскируются)
115
+ headers?: Record<string, string>;
116
+ deviceId?: string; // X-Device-Id; стабильный; иначе заведётся сам
117
+ userAgent?: string | false; // false — не слать; в браузере не действует
118
+ mode?: RuntimeMode; // как обращаться с cookie
119
+ }
120
+ ```
121
+
122
+ ### Авторизация (`AuthInput`)
123
+
124
+ ```ts
125
+ type AuthInput =
126
+ | string // готовый accessToken
127
+ | { accessToken: string; refreshToken?: string } // восстановить сессию
128
+ | { email: string; password: string; // залогиниться самому
129
+ turnstileToken?: string;
130
+ getTurnstileToken?: () => string | Promise<string> }
131
+ | { getToken: () => string | null | Promise<string | null> }; // токен извне
132
+ ```
133
+
134
+ ### Повторы (`RetryOptions`)
135
+
136
+ ```ts
137
+ interface RetryOptions {
138
+ attempts?: number; // всего попыток, включая первую; по умолчанию 3
139
+ baseDelay?: number; // базовая пауза, удваивается; по умолчанию 500
140
+ maxDelay?: number; // верхняя граница; по умолчанию 30000
141
+ jitter?: number; // разброс 0…1; по умолчанию 0.3
142
+ retryWrites?: boolean; // повторять запись при сбоях; по умолчанию false
143
+ shouldRetry?: (error: unknown, attempt: number) => boolean;
144
+ }
145
+ ```
146
+
147
+ ### Очередь и лимиты (`RateLimitOptions`)
148
+
149
+ ```ts
150
+ interface RateLimitOptions {
151
+ concurrency?: number; // одновременных запросов; по умолчанию 6
152
+ rps?: number; // верхняя граница запросов в секунду
153
+ retryDelays?: readonly number[]; // паузы при 429; [1000, 5000, 30000, 60000, 90000]
154
+ respectHeaders?: boolean; // тормозить по x-ratelimit-*; по умолчанию true
155
+ }
156
+ ```
157
+
158
+ ### Хуки (`ClientHooks`)
159
+
160
+ ```ts
161
+ interface ClientHooks {
162
+ onRequest?(ctx: RequestContext): void | Promise<void>; // до отправки, headers изменяемы
163
+ onResponse?(ctx: ResponseContext): void | Promise<void>; // после успеха, до разбора тела
164
+ onError?(ctx: ErrorContextHook): void | Promise<void>; // при любой ошибке запроса
165
+ onRetry?(ctx: RetryContext): void | Promise<void>; // перед паузой между попытками
166
+ }
167
+ ```
168
+
169
+ ### Произвольный запрос (`RawRequestOptions`)
170
+
171
+ ```ts
172
+ interface RawRequestOptions extends RequestOptions {
173
+ method: string;
174
+ path: string; // с ведущим слэшем; завершающий слэш значим
175
+ service?: string; // хост зарегистрированного сервиса
176
+ baseUrl?: string; // хост этого запроса; важнее service
177
+ query?: QueryParams;
178
+ body?: unknown; // JSON; для файлов — FormData
179
+ skipAuth?: boolean; // не подставлять токен; false — разрешить внешнему хосту
180
+ skipAuthRefresh?: boolean; // не обновлять токен при 401
181
+ skipQueue?: boolean; // мимо очереди
182
+ raw?: boolean; // вернуть тело без снятия обёртки { data }
183
+ }
184
+ ```
@@ -0,0 +1,58 @@
1
+ # Комментарии — `itd.comments`
2
+
3
+ Ответы на комментарии и действия над ними. Комментарии **к посту** живут в
4
+ [`itd.posts`](./posts.md#комментарии-к-посту): `itd.posts.comments()` и `itd.posts.comment()`.
5
+
6
+ ## Ответы
7
+
8
+ ```ts
9
+ replies(commentId: string, params?: RepliesParams): Promise<Page<Comment>>
10
+ iterateReplies(commentId: string, params?: RepliesParams): Paginator<Comment>
11
+ ```
12
+ Ответы на комментарий. Здесь пагинация **постраничная** (у комментариев к посту — курсорная).
13
+ См. [`Comment`](./models.md#comment).
14
+
15
+ ```ts
16
+ reply(commentId: string, input: CommentInput | string): Promise<Comment>
17
+ ```
18
+ Отвечает на комментарий. Поддерживает `replyTo(userId)` в билдере — адресат ответа.
19
+
20
+ ## Действия
21
+
22
+ ```ts
23
+ update(commentId: string, content: string): Promise<Comment>
24
+ ```
25
+ Редактирует текст комментария.
26
+
27
+ ```ts
28
+ remove(commentId: string): Promise<void>
29
+ restore(commentId: string): Promise<Comment>
30
+ ```
31
+ Удаляет / восстанавливает комментарий.
32
+
33
+ ```ts
34
+ like(commentId: string): Promise<LikeResult>
35
+ unlike(commentId: string): Promise<LikeResult>
36
+ ```
37
+ Ставит / убирает реакцию. См. [`LikeResult`](./models.md#likeresult).
38
+
39
+ ## Типы
40
+
41
+ ```ts
42
+ type CommentInput = CreateCommentInput | CommentBuilder | ((b: CommentBuilder) => CommentBuilder | CreateCommentInput);
43
+
44
+ interface CreateCommentInput {
45
+ content?: string; // у голосового пустой
46
+ attachmentIds?: string[];
47
+ files?: FileInput[];
48
+ replyToUserId?: UserId; // только в reply(), не в комментарии к посту
49
+ }
50
+
51
+ interface RepliesParams extends RequestOptions {
52
+ limit?: number;
53
+ page?: number;
54
+ maxPages?: number;
55
+ }
56
+ ```
57
+
58
+ См. также [Билдеры](./builders.md) (`comment()`).
@@ -0,0 +1,81 @@
1
+ # Поиск и обнаружение — `itd.search`, `itd.hashtags`
2
+
3
+ Глобальный поиск, хэштеги и тренды, а также рекомендации, кланы и баннер события. Часть
4
+ методов физически принадлежит другим ресурсам (`itd.users`, `itd.platform`) — здесь они
5
+ собраны по смыслу.
6
+
7
+ ## Глобальный поиск — `itd.search`
8
+
9
+ ```ts
10
+ all(query: string): Promise<SearchResult>
11
+ ```
12
+ Ищет пользователей и хэштеги одним запросом.
13
+
14
+ ```ts
15
+ interface SearchResult {
16
+ users: UserSummary[]; // см. models.md#usersummary
17
+ hashtags: Hashtag[]; // см. models.md#hashtag
18
+ }
19
+ ```
20
+
21
+ ## Хэштеги — `itd.hashtags`
22
+
23
+ ```ts
24
+ search(query?: string, params?: { limit?: number }): Promise<Hashtag[]>
25
+ ```
26
+ Ищет хэштеги. Без строки запроса возвращает общий список.
27
+
28
+ ```ts
29
+ trending(params?: { limit?: number }): Promise<Hashtag[]>
30
+ ```
31
+ Трендовые хэштеги.
32
+
33
+ ```ts
34
+ posts(tag: string, params?: HashtagPostsParams): Promise<Page<Post>>
35
+ iteratePosts(tag: string, params?: HashtagPostsParams): Paginator<Post>
36
+ ```
37
+ Посты по хэштегу. Курсорная пагинация. `tag` — без решётки; кодируется автоматически,
38
+ кириллица и пробелы допустимы. См. [`Post`](./models.md#post).
39
+
40
+ ```ts
41
+ interface HashtagPostsParams extends RequestOptions {
42
+ limit?: number;
43
+ cursor?: string;
44
+ maxPages?: number;
45
+ }
46
+ ```
47
+
48
+ ## Пользователи — `itd.users`
49
+
50
+ Полное описание — в [Пользователи](./users.md#поиск-и-рекомендации).
51
+
52
+ ```ts
53
+ itd.users.search(query: string, params?: { limit?: number }): Promise<UserSummary[]>
54
+ ```
55
+ Поиск пользователей по строке.
56
+
57
+ ```ts
58
+ itd.users.whoToFollow(): Promise<UserSummary[]>
59
+ ```
60
+ Рекомендации, на кого подписаться.
61
+
62
+ ```ts
63
+ itd.users.topClans(): Promise<Clan[]>
64
+ ```
65
+ Рейтинг кланов. См. [`Clan`](./models.md#clan).
66
+
67
+ ## Портал — `itd.platform`
68
+
69
+ ```ts
70
+ itd.platform.portal(): Promise<Portal>
71
+ ```
72
+ Баннер текущего события — виджет «портал». См. [`Portal`](./models.md#portal) и
73
+ [Платформа](./platform.md).
74
+
75
+ ```ts
76
+ interface Portal {
77
+ active: boolean;
78
+ title: string;
79
+ url: string;
80
+ }
81
+ ```
@@ -0,0 +1,103 @@
1
+ # Перечисления
2
+
3
+ Перечисления заданы парой «замороженный объект + одноимённый тип»: `FeedTab.Popular` работает
4
+ как константа, `FeedTab` — как тип. Обычные строки тоже принимаются
5
+ (`itd.posts.list({ tab: 'popular' })`).
6
+
7
+ **Открытые** множества (помечены `Loose`) не ломаются, если сервер пришлёт значение вне перечня;
8
+ **закрытые** — сервер отвергнет неизвестное. Перебрать значения в рантайме: `Object.values(FeedTab)`.
9
+
10
+ ## FeedTab
11
+
12
+ Вкладка ленты. Закрытое.
13
+
14
+ | Значение | Курсор | Описание |
15
+ |---|---|---|
16
+ | `Popular` = `'popular'` | номер страницы (`"2"`) | популярное |
17
+ | `Following` = `'following'` | отметка времени | записи тех, на кого вы подписаны |
18
+ | `Clan` = `'clan'` | отметка времени | лента клана |
19
+
20
+ ## CommentSort
21
+
22
+ Порядок комментариев к посту.
23
+
24
+ `Newest` `'newest'` · `Oldest` `'oldest'` · `Popular` `'popular'`.
25
+
26
+ ## AttachmentType
27
+
28
+ Тип вложения.
29
+
30
+ `Image` `'image'` · `Video` `'video'` · `Audio` `'audio'` (голосовые: `audio/ogg`, с `duration`).
31
+
32
+ ## SpanType
33
+
34
+ Тип фрагмента разметки. Открытое.
35
+
36
+ `Hashtag` (имя в `tag`) · `Mention` (имя в `tag`/`username`) · `Link` (адрес в `url`) ·
37
+ `Bold` · `Italic` · `Underline` · `Strike` · `Spoiler` · `Monospace` · `Quote`.
38
+
39
+ ## ReportTargetType
40
+
41
+ На что подаётся жалоба. `Post` `'post'` · `Comment` `'comment'` · `User` `'user'`.
42
+
43
+ ## ReportReason
44
+
45
+ Причина жалобы. Закрытое.
46
+
47
+ `Spam` · `Violence` · `Hate` · `Adult` · `Fraud` · `Other`.
48
+
49
+ ## NotificationType
50
+
51
+ Канонический тип уведомления. Открытое. REST отдаёт старые имена, поток — новые; библиотека
52
+ приводит их к этому набору, сохраняя исходное в `rawType`.
53
+
54
+ | Значение | Старое имя | Событие |
55
+ |---|---|---|
56
+ | `PostReaction` `'post_reaction'` | `like` | реакция на пост |
57
+ | `PostComment` `'post_comment'` | `comment` | комментарий к посту |
58
+ | `CommentReply` `'comment_reply'` | `reply` | ответ на комментарий |
59
+ | `PostRepost` `'post_repost'` | `repost` | репост |
60
+ | `PostMention` `'post_mention'` | `mention` | упоминание в посте |
61
+ | `CommentReaction` `'comment_reaction'` | — | реакция на комментарий |
62
+ | `CommentMention` `'comment_mention'` | — | упоминание в комментарии |
63
+ | `WallPost` `'wall_post'` | — | запись на вашей стене |
64
+ | `Follow` `'follow'` | — | на вас подписались |
65
+ | `FollowRequest` `'follow_request'` | — | заявка на подписку |
66
+ | `FollowAccepted` `'follow_accepted'` | — | заявка принята |
67
+ | `VerificationApproved` / `VerificationRejected` | — | верификация (только REST) |
68
+
69
+ ## AccessType, WallAccess, LikesVisibility
70
+
71
+ Уровень доступа к разделу профиля. Открытое. `WallAccess` и `LikesVisibility` — псевдонимы
72
+ `AccessType`.
73
+
74
+ `Nobody` `'nobody'` · `Mutual` `'mutual'` (взаимные) · `Followers` `'followers'` · `Everyone` `'everyone'`.
75
+
76
+ ## RealtimeStatus
77
+
78
+ Состояние realtime-соединения.
79
+
80
+ `Connecting` · `Connected` · `Error` · `Disconnected`.
81
+
82
+ ## ServiceState
83
+
84
+ Состояние сервиса платформы. Открытое.
85
+
86
+ `Operational` `'operational'` · `Degraded` `'degraded'` · `Downtime` `'downtime'`.
87
+
88
+ ## IncidentKind
89
+
90
+ Вид происшествия в истории сервиса. Открытое. `Down` `'down'` · `Degraded` `'deg'`.
91
+
92
+ ## OAuthProvider
93
+
94
+ Провайдер внешнего входа. `Yandex` `'yandex'` · `Google` `'google'`.
95
+
96
+ ## SignInStatus
97
+
98
+ Чем закончился вход. `Authenticated` `'authenticated'` · `OtpRequired` `'otp_required'`.
99
+
100
+ ## Телеметрия (экспериментально)
101
+
102
+ `InteractionType`, `ViewSource`, `ViewReason` — числовые коды для недокументированных
103
+ эндпоинтов `itd.telemetry.*`. Библиотека сама их не отправляет.
@@ -0,0 +1,107 @@
1
+ # Ошибки
2
+
3
+ Все ошибки библиотеки — подклассы `ItdError`. Ошибки сервера (HTTP ≥ 400) сведены к одной
4
+ иерархии `ItdApiError` независимо от формы ответа.
5
+
6
+ ```ts
7
+ try {
8
+ await itd.users.updateMe({ username: 'занятое_имя' });
9
+ } catch (error) {
10
+ if (error instanceof ItdValidationError) error.fieldErrors.username; // ['Имя уже занято']
11
+ else if (error instanceof ItdRateLimitError) error.rateLimitRemaining;
12
+ else if (isItdApiError(error)) console.log(error.status, error.code);
13
+ else throw error;
14
+ }
15
+ ```
16
+
17
+ ## Иерархия
18
+
19
+ ```
20
+ ItdError
21
+ ├─ ItdApiError сервер ответил статусом ≥ 400
22
+ │ ├─ ItdValidationError 400 / 422 — данные не прошли валидацию
23
+ │ ├─ ItdAuthError 401 — токен отсутствует, истёк или отозван
24
+ │ ├─ ItdForbiddenError 403 — доступ запрещён или ограничен приватностью
25
+ │ ├─ ItdNotFoundError 404 — сущность не найдена
26
+ │ ├─ ItdConflictError 409 — сущность уже существует
27
+ │ ├─ ItdRateLimitError 429 — превышен лимит запросов
28
+ │ ├─ ItdPhoneVerificationError PHONE_VERIFICATION_REQUIRED
29
+ │ └─ ItdServerError 5xx — ошибка на стороне сервера
30
+ ├─ ItdNetworkError запрос не дошёл до сервера
31
+ ├─ ItdTimeoutError истёк таймаут
32
+ ├─ ItdAbortError отменён через AbortSignal
33
+ └─ ItdConfigError неверная конфигурация или аргументы (до обращения к сети; бросают билдеры)
34
+ ```
35
+
36
+ Категория ошибки — в поле `kind` (`ItdErrorKind`): `'api'` | `'network'` | `'timeout'` |
37
+ `'abort'` | `'config'`.
38
+
39
+ ## `ItdApiError`
40
+
41
+ ```ts
42
+ class ItdApiError extends ItdError {
43
+ status: number; // HTTP-статус
44
+ code: ItdErrorCode; // строковый код, например 'VALIDATION_ERROR'
45
+ detail: string | undefined;
46
+ title: string | undefined;
47
+ fieldErrors: ItdFieldErrors; // { поле: ['ошибка'] }; {} если нет
48
+ requestId: string | undefined;
49
+ method: string;
50
+ path: string;
51
+ raw: unknown; // тело ответа как пришло
52
+ response: Response | undefined;
53
+ retryAfter: number | undefined; // мс; итд.com его не присылает
54
+ rateLimit: number | undefined; // x-ratelimit-limit
55
+ rateLimitRemaining: number | undefined;// x-ratelimit-remaining
56
+ apiKind: ItdApiErrorKind; // разновидность для сравнения
57
+
58
+ hasCode(...codes: ItdErrorCode[]): boolean; // проверить код
59
+ get isRetryable: boolean; // 429 или ≥ 500
60
+ }
61
+ ```
62
+
63
+ `ItdPhoneVerificationError` дополнительно даёт `verificationUrl` — ссылку на Telegram-бота
64
+ подтверждения.
65
+
66
+ `ItdNetworkError` / `ItdTimeoutError` содержат `method` и `path`; `ItdTimeoutError` — ещё
67
+ и `timeout`.
68
+
69
+ ## Функции-предикаты
70
+
71
+ Определяют ошибку **по данным**, а не через `instanceof` (надёжнее при двух копиях пакета
72
+ или смешении ESM/CJS):
73
+
74
+ ```ts
75
+ isItdError(v) // любая ошибка библиотеки
76
+ isItdApiError(v) // ответ сервера ≥ 400
77
+ isItdValidationError(v)
78
+ isItdAuthError(v)
79
+ isItdForbiddenError(v)
80
+ isItdNotFoundError(v)
81
+ isItdConflictError(v)
82
+ isItdRateLimitError(v)
83
+ isItdPhoneVerificationError(v)
84
+ isItdServerError(v)
85
+ ```
86
+
87
+ ## Коды ошибок — `ItdErrorCode`
88
+
89
+ Строковые коды из поля `code`. Список открыт. Ключи повторяют написание сервера — код из
90
+ ответа можно найти поиском один в один. Проверять удобно через `error.hasCode(…)`.
91
+
92
+ Основные группы:
93
+
94
+ - **Общие:** `BAD_REQUEST`, `UNAUTHORIZED`, `ACCESS_DENIED`, `ENTITY_NOT_FOUND`, `NOT_FOUND`,
95
+ `ENTITY_ALREADY_EXISTS`, `VALIDATION_ERROR`, `BUSINESS_RULE_VIOLATION`, `RATE_LIMIT_EXCEEDED`,
96
+ `UNKNOWN_ERROR`.
97
+ - **Капча/OTP:** `TURNSTILE_VERIFICATION_FAILED`, `CAPTCHA_FAILED`, `OTP_INVALID`,
98
+ `INVALID_FLOW_TOKEN`, `MISSING_FLOW_TOKEN`.
99
+ - **Аккаунт:** `ACCOUNT_DEACTIVATED`, `ACCOUNT_INVALID_CREDENTIALS`, `ACCOUNT_TEMPORARILY_LOCKED`,
100
+ `ACCOUNT_CURRENT_PASSWORD_INCORRECT`, `ACCOUNT_EMAIL_DOMAIN_NOT_ALLOWED`.
101
+ - **Сессия:** `SESSION_EXPIRED`, `SESSION_REVOKED`, `SESSION_INVALID_REFRESH_TOKEN`,
102
+ `SESSION_NOT_FOUND`, `REFRESH_TOKEN_MISSING`.
103
+ - **Профиль/контент:** `PROFILE_USERNAME_TAKEN`, `PROFILE_RESTRICTION_ACTIVE`,
104
+ `PROFILE_MODIFICATION_RESTRICTED`, `CONTENT_MODERATION_FAILED`, `WRITE_ACCESS_RESTRICTED`.
105
+ - **Файлы:** `FILE_TOO_LARGE`, `UNSUPPORTED_FILE_TYPE`, `UPLOAD_FAILED`,
106
+ `VIDEO_REQUIRES_VERIFICATION`.
107
+ - **Телефон:** `PHONE_VERIFICATION_REQUIRED`.
@@ -0,0 +1,73 @@
1
+ # Файлы — `itd.files`
2
+
3
+ Загрузка и удаление медиа. Обычно вызывать напрямую не нужно: [`itd.posts.create()`](./posts.md)
4
+ и `itd.posts.comment()` загружают файлы сами через поле `files`.
5
+
6
+ Загрузка файла **по пути** (строка) работает только в Node, Bun и Deno — подключите точку
7
+ входа `itd-api/node`. В браузере и React Native передавайте `File` или `Blob`.
8
+
9
+ ## Методы
10
+
11
+ ```ts
12
+ upload(input: FileInput, options?: UploadOptions): Promise<UploadedFile>
13
+ ```
14
+ Загружает файл и возвращает его идентификатор и CDN-адрес. Таймаут по умолчанию —
15
+ `DEFAULT_UPLOAD_TIMEOUT` (300 000 мс): видео не укладывается в обычные 30 секунд.
16
+
17
+ ```ts
18
+ uploadMany(files: FileInput[], options?: UploadOptions): Promise<string[]>
19
+ ```
20
+ Загружает несколько файлов **последовательно**, сохраняя порядок. Возвращает идентификаторы
21
+ вложений в порядке входных файлов.
22
+
23
+ ```ts
24
+ remove(fileId: string): Promise<void>
25
+ ```
26
+ Удаляет загруженный файл.
27
+
28
+ ```ts
29
+ get(fileId: string): Promise<unknown>
30
+ ```
31
+ Сведения о файле. На практике сервер отвечает `404` даже на только что загруженный,
32
+ ещё не прикреплённый файл, — метод оставлен для полноты.
33
+
34
+ ## Типы
35
+
36
+ ```ts
37
+ type FileInput =
38
+ | Blob
39
+ | ArrayBuffer
40
+ | Uint8Array
41
+ | string // путь на диске (только Node/Bun/Deno)
42
+ | { data: Blob | ArrayBuffer | Uint8Array; filename?: string; contentType?: string };
43
+
44
+ interface UploadedFile {
45
+ id: string; // передаётся в attachmentIds
46
+ url: string; // адрес на CDN
47
+ }
48
+
49
+ interface UploadOptions extends RequestOptions {
50
+ filename?: string; // по нему определяется тип, если не задан
51
+ contentType?: string; // MIME; иначе по имени файла или самому Blob
52
+ validateMime?: boolean; // проверять тип до отправки; по умолчанию true
53
+ }
54
+
55
+ const DEFAULT_UPLOAD_TIMEOUT = 300_000;
56
+ ```
57
+
58
+ ## Допустимые типы
59
+
60
+ Наборы MIME экспортируются из корня пакета — по ним библиотека проверяет вложения до отправки
61
+ (`validateMime`):
62
+
63
+ ```ts
64
+ ALLOWED_MIME_TYPES // весь список
65
+ IMAGE_MIME_TYPES // изображения
66
+ VIDEO_MIME_TYPES // видео
67
+ AUDIO_MIME_TYPES // аудио (голосовые: audio/ogg)
68
+ ```
69
+
70
+ Кроме типа сервер проверяет и само изображение: слишком маленькие картинки он отклоняет
71
+ («Не удалось проверить изображение»); 64×64 проходит. Загрузка видео может требовать
72
+ верификации (`VIDEO_REQUIRES_VERIFICATION`), лимит частоты у `/api/files/upload` — 15 запросов
73
+ в окне.