@itd-api/cache 0.0.2 → 0.2.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 CHANGED
@@ -3,12 +3,18 @@
3
3
  TTL/LRU-кэш и дедупликация одновременных запросов для
4
4
  [`itd-api`](https://github.com/KiowDev/itd-api).
5
5
 
6
+ [Руководство](https://kiowdev.github.io/itd-api/packages/cache) ·
7
+ [API из TSDoc](https://kiowdev.github.io/itd-api/api/generated/cache/)
8
+
6
9
  ## Установка
7
10
 
8
11
  ```bash
9
12
  npm install itd-api @itd-api/cache
10
13
  ```
11
14
 
15
+ Поддерживается `itd-api >=0.8.0 <1.0.0`: пакет использует отдельное поле
16
+ `RequestOptions.extensions` и стабильный `operationId` запроса.
17
+
12
18
  ## Быстрый старт
13
19
 
14
20
  ```ts
@@ -18,7 +24,7 @@ import { ItdClient } from 'itd-api';
18
24
  const itd = new ItdClient({ auth: process.env.ITD_TOKEN });
19
25
  const cached = cache({
20
26
  ttl: 60_000,
21
- routes: ['users.get', 'posts.get', 'posts.list'],
27
+ operations: ['users.get', 'posts.get', 'posts.list'],
22
28
  });
23
29
 
24
30
  itd.use(cached);
@@ -27,16 +33,24 @@ const first = await itd.posts.get(postId); // запрос к API
27
33
  const second = await itd.posts.get(postId); // ответ из кэша
28
34
  ```
29
35
 
30
- Кэшируются только перечисленные маршруты. Query, path и body входят в ключ, поэтому
36
+ Операции подключаемых модулей тоже можно кэшировать. Например, модуль Pixel Battle задаёт
37
+ `CachePolicyKind.Query` в `annotations.cache`, а пользователь добавляет полный `operationId`
38
+ в `operations`.
39
+
40
+ Кэшируются только перечисленные операции. Query, path и body входят в ключ, поэтому
31
41
  разные страницы ленты, профили и наборы идентификаторов хранятся отдельно. Одинаковые
32
42
  запросы, запущенные одновременно, выполняют один сетевой вызов.
33
43
 
44
+ Имена в `operations` — постоянные `operationId`, а не HTTP-пути. Изменение маршрута не ломает
45
+ правила кэша. Низкоуровневый `itd.request()` без явного идентификатора операции считается
46
+ операцией `raw`; совпадение URL со встроенным ресурсом не включает кэш автоматически.
47
+
34
48
  ## Настройки
35
49
 
36
50
  ```ts
37
51
  const cached = cache({
38
52
  ttl: 60_000,
39
- routes: ['users.get', 'posts.get'],
53
+ operations: ['users.get', 'posts.get'],
40
54
  maxEntries: 500,
41
55
  deduplicate: true,
42
56
  });
@@ -45,7 +59,7 @@ const cached = cache({
45
59
  | Поле | Значение |
46
60
  |---|---|
47
61
  | `ttl` | срок хранения успешного ответа в миллисекундах |
48
- | `routes` | операции, ответы которых нужно кэшировать |
62
+ | `operations` | операции, ответы которых нужно кэшировать |
49
63
  | `maxEntries` | предел LRU-кэша; по умолчанию `500` |
50
64
  | `deduplicate` | объединение одновременных запросов; по умолчанию `true` |
51
65
 
@@ -55,8 +69,8 @@ const cached = cache({
55
69
  ## Управление отдельным запросом
56
70
 
57
71
  ```ts
58
- await itd.posts.get(postId, { cache: 'reload' });
59
- await itd.posts.get(postId, { cache: 'no-store' });
72
+ await itd.posts.get(postId, { extensions: { cache: 'reload' } });
73
+ await itd.posts.get(postId, { extensions: { cache: 'no-store' } });
60
74
  ```
61
75
 
62
76
  - `reload` пропускает готовый ответ, запрашивает новый и заменяет запись;
@@ -68,9 +82,9 @@ await itd.posts.get(postId, { cache: 'no-store' });
68
82
 
69
83
  ## Инвалидация
70
84
 
71
- После успешной мутации плагин удаляет связанные читающие маршруты. Например, реакция на
85
+ После успешной мутации плагин удаляет связанные читающие операции. Например, реакция на
72
86
  пост сбрасывает кэш постов и статистики, но не затрагивает профили, файлы и настройки
73
- платформы. Маршруты с общими данными инвалидируются во всех аккаунтах экземпляра: изменение
87
+ платформы. Операции с общими данными инвалидируются во всех аккаунтах экземпляра: изменение
74
88
  поста одним аккаунтом должно быть видно остальным. Персональные настройки и уведомления
75
89
  инвалидируются у всех копий клиента с тем же пользователем. Изменение сессий сбрасывает все
76
90
  варианты `auth.sessions` этого аккаунта, включая варианты других сессий.
@@ -86,15 +100,15 @@ cached.invalidate('posts.get', 'posts.list');
86
100
  cached.clear();
87
101
  ```
88
102
 
89
- `invalidate()` удаляет все варианты выбранных маршрутов во всех подключённых клиентах.
103
+ `invalidate()` удаляет все варианты выбранных операций во всех подключённых клиентах.
90
104
  `clear()` очищает всё хранилище. Оба метода защищены от гонки: запрос, начатый до очистки,
91
105
  не запишет устаревший результат после неё.
92
106
 
93
- ## Realtime
107
+ ## События
94
108
 
95
109
  ```ts
96
- const stream = itd.realtime();
97
- const detachCache = cached.attachRealtime(stream);
110
+ const stream = itd.notifications.events;
111
+ const detachCache = cached.attachNotificationEvents(stream);
98
112
 
99
113
  await stream.connect();
100
114
 
@@ -104,12 +118,16 @@ stream.disconnect();
104
118
  ```
105
119
 
106
120
  Привязка сразу очищает `notifications.list` и `notifications.count` аккаунта, который
107
- создал поток. Новое уведомление сбрасывает оба маршрута во всех копиях клиента с тем же
108
- пользователем, событие `unreadCount` — их счётчик. Кэш других аккаунтов и остальные маршруты
121
+ создал поток. Новое уведомление сбрасывает обе операции во всех копиях клиента с тем же
122
+ пользователем, событие `unreadCount` — их счётчик. Кэш других аккаунтов и остальные операции
109
123
  поток не изменяет.
110
124
 
111
- У стороннего realtime-объекта без доступных идентификатора пользователя и базового URL
112
- используется безопасный fallback: маршруты уведомлений инвалидируются во всех аккаунтах.
125
+ Инвалидация подключается как промежуточный обработчик. Вызывайте
126
+ `attachNotificationEvents()` до прикладных обработчиков, которые могут не вызвать `next()`:
127
+ тогда отфильтрованное для интерфейса обновление всё равно не оставит устаревший кэш.
128
+
129
+ У стороннего событийного объекта без доступных идентификатора пользователя и базового URL
130
+ операции уведомлений инвалидируются во всех аккаунтах.
113
131
 
114
132
  ## Несколько клиентов
115
133
 
@@ -141,28 +159,28 @@ clientB.use(shared);
141
159
  копиями не объединяет.
142
160
 
143
161
  `maxEntries` ограничивает весь экземпляр `shared`, а `clear()` и `invalidate()` управляют
144
- всеми его разделами. `attachRealtime()` затрагивает аккаунт создавшего поток клиента.
162
+ всеми его разделами. `attachNotificationEvents()` затрагивает аккаунт создавшего поток клиента.
145
163
  Смена сессии сохраняет общий кэш, смена пользователя автоматически выбирает другой раздел.
146
164
 
147
165
  ## Ключ
148
166
 
149
167
  В ключ входят:
150
168
 
151
- - имя маршрута, HTTP-метод и path;
169
+ - имя операции, HTTP-метод и path;
152
170
  - базовый URL и идентификатор пользователя; для `auth.sessions` также идентификатор сессии;
153
171
  - `service` или разовый `baseUrl`;
154
- - query и JSON-body;
172
+ - параметры строки запроса и JSON-тело;
155
173
  - режим `raw`, `skipAuth` и опции других плагинов, влияющие на ответ.
156
174
 
157
175
  Токен и заголовки в ключ не входят. Также не учитываются `signal`, `timeout` и настройки
158
- повторов. Несериализуемый JSON-body выполняется без кэширования.
176
+ повторов. Запрос с несериализуемым JSON-телом выполняется без кэширования.
159
177
 
160
178
  Ответ хранится как независимая копия: изменение полученного объекта не меняет следующие
161
179
  результаты.
162
180
 
163
- ## Доступные маршруты
181
+ ## Доступные операции
164
182
 
165
- | Раздел | Маршруты |
183
+ | Раздел | Операции |
166
184
  |---|---|
167
185
  | Auth | `auth.sessions` |
168
186
  | Users | `users.me`, `users.get`, `users.checkUsername`, `users.search`, `users.whoToFollow`, `users.topClans`, `users.followers`, `users.following`, `users.blocked`, `users.getPrivacy`, `users.pins`, `users.followStatus` |
@@ -174,16 +192,16 @@ clientB.use(shared);
174
192
  | Files | `files.get` |
175
193
  | Subscription | `subscription.status`, `subscription.methods` |
176
194
  | Verification | `verification.status` |
177
- | Platform | `platform.changelog`, `platform.announcements`, `platform.portal`, `platform.status` |
195
+ | Platform | `platform.changelog`, `platform.announcements`, `platform.portal`, `status.get` |
178
196
 
179
- Страницы, загружаемые итераторами, используют маршрут соответствующего списочного метода:
197
+ Страницы, загружаемые итераторами, используют операцию соответствующего списочного метода:
180
198
  `posts.iterate()` — `posts.list`, `users.iterateFollowers()` — `users.followers` и так
181
199
  далее.
182
200
 
183
201
  Каталог доступен программно:
184
202
 
185
203
  ```ts
186
- import { CACHE_ROUTES } from '@itd-api/cache';
204
+ import { CACHE_OPERATIONS } from '@itd-api/cache';
187
205
 
188
- console.log(CACHE_ROUTES.map(({ id }) => id));
206
+ console.log(CACHE_OPERATIONS.map(({ id }) => id));
189
207
  ```