@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/dist/index.d.ts CHANGED
@@ -1,280 +1,222 @@
1
- import { RawRequestOptions, ItdPlugin, ItdRealtime, Unsubscribe } from 'itd-api';
2
-
3
- /** Ошибка настройки или использования плагина кэша. */
4
- declare class CacheError extends Error {
5
- readonly name = "CacheError";
6
- }
7
-
8
- /** Описание читающего маршрута itd-api. */
9
- interface CacheRoute {
10
- /** Публичное имя для настройки плагина. */
11
- id: string;
12
- /** Раздел клиента. */
13
- category: string;
14
- /** HTTP-метод маршрута. */
15
- method: string;
16
- /** Путь без query и базового URL. */
17
- path: RegExp;
18
- }
19
- /**
20
- * Читающие маршруты, которые можно кэшировать.
21
- *
22
- * Порядок значим: точные служебные пути стоят перед динамическими маршрутами.
23
- */
24
- declare const CACHE_ROUTES: readonly [{
25
- readonly id: "auth.sessions";
26
- readonly category: "auth";
27
- readonly method: "GET";
28
- readonly path: RegExp;
29
- }, {
30
- readonly id: "users.me";
31
- readonly category: "users";
32
- readonly method: "GET";
33
- readonly path: RegExp;
34
- }, {
35
- readonly id: "users.checkUsername";
36
- readonly category: "users";
37
- readonly method: "GET";
38
- readonly path: RegExp;
39
- }, {
40
- readonly id: "users.search";
41
- readonly category: "users";
42
- readonly method: "GET";
43
- readonly path: RegExp;
44
- }, {
45
- readonly id: "users.whoToFollow";
46
- readonly category: "users";
47
- readonly method: "GET";
48
- readonly path: RegExp;
49
- }, {
50
- readonly id: "users.topClans";
51
- readonly category: "users";
52
- readonly method: "GET";
53
- readonly path: RegExp;
54
- }, {
55
- readonly id: "users.followers";
56
- readonly category: "users";
57
- readonly method: "GET";
58
- readonly path: RegExp;
59
- }, {
60
- readonly id: "users.following";
61
- readonly category: "users";
62
- readonly method: "GET";
63
- readonly path: RegExp;
64
- }, {
65
- readonly id: "users.blocked";
66
- readonly category: "users";
67
- readonly method: "GET";
68
- readonly path: RegExp;
69
- }, {
70
- readonly id: "users.getPrivacy";
71
- readonly category: "users";
72
- readonly method: "GET";
73
- readonly path: RegExp;
74
- }, {
75
- readonly id: "users.pins";
76
- readonly category: "users";
77
- readonly method: "GET";
78
- readonly path: RegExp;
79
- }, {
80
- readonly id: "users.followStatus";
81
- readonly category: "users";
82
- readonly method: "POST";
83
- readonly path: RegExp;
84
- }, {
85
- readonly id: "users.get";
86
- readonly category: "users";
87
- readonly method: "GET";
88
- readonly path: RegExp;
89
- }, {
90
- readonly id: "posts.list";
91
- readonly category: "posts";
92
- readonly method: "GET";
93
- readonly path: RegExp;
94
- }, {
95
- readonly id: "posts.likedByUser";
96
- readonly category: "posts";
97
- readonly method: "GET";
98
- readonly path: RegExp;
99
- }, {
100
- readonly id: "posts.byUser";
101
- readonly category: "posts";
102
- readonly method: "GET";
103
- readonly path: RegExp;
104
- }, {
105
- readonly id: "posts.comments";
106
- readonly category: "posts";
107
- readonly method: "GET";
108
- readonly path: RegExp;
109
- }, {
110
- readonly id: "posts.stats";
111
- readonly category: "posts";
112
- readonly method: "POST";
113
- readonly path: RegExp;
114
- }, {
115
- readonly id: "posts.get";
116
- readonly category: "posts";
117
- readonly method: "GET";
118
- readonly path: RegExp;
119
- }, {
120
- readonly id: "comments.replies";
121
- readonly category: "comments";
122
- readonly method: "GET";
123
- readonly path: RegExp;
124
- }, {
125
- readonly id: "notifications.list";
126
- readonly category: "notifications";
127
- readonly method: "GET";
128
- readonly path: RegExp;
129
- }, {
130
- readonly id: "notifications.count";
131
- readonly category: "notifications";
132
- readonly method: "GET";
133
- readonly path: RegExp;
134
- }, {
135
- readonly id: "notifications.getSettings";
136
- readonly category: "notifications";
137
- readonly method: "GET";
138
- readonly path: RegExp;
139
- }, {
140
- readonly id: "hashtags.search";
141
- readonly category: "hashtags";
142
- readonly method: "GET";
143
- readonly path: RegExp;
144
- }, {
145
- readonly id: "hashtags.trending";
146
- readonly category: "hashtags";
147
- readonly method: "GET";
148
- readonly path: RegExp;
149
- }, {
150
- readonly id: "hashtags.posts";
151
- readonly category: "hashtags";
152
- readonly method: "GET";
153
- readonly path: RegExp;
154
- }, {
155
- readonly id: "search.all";
156
- readonly category: "search";
157
- readonly method: "GET";
158
- readonly path: RegExp;
159
- }, {
160
- readonly id: "files.get";
161
- readonly category: "files";
162
- readonly method: "GET";
163
- readonly path: RegExp;
164
- }, {
165
- readonly id: "subscription.status";
166
- readonly category: "subscription";
167
- readonly method: "GET";
168
- readonly path: RegExp;
169
- }, {
170
- readonly id: "subscription.methods";
171
- readonly category: "subscription";
172
- readonly method: "GET";
173
- readonly path: RegExp;
174
- }, {
175
- readonly id: "verification.status";
176
- readonly category: "verification";
177
- readonly method: "GET";
178
- readonly path: RegExp;
179
- }, {
180
- readonly id: "platform.changelog";
181
- readonly category: "platform";
182
- readonly method: "GET";
183
- readonly path: RegExp;
184
- }, {
185
- readonly id: "platform.announcements";
186
- readonly category: "platform";
187
- readonly method: "GET";
188
- readonly path: RegExp;
189
- }, {
190
- readonly id: "platform.portal";
191
- readonly category: "platform";
192
- readonly method: "GET";
193
- readonly path: RegExp;
194
- }, {
195
- readonly id: "platform.status";
196
- readonly category: "platform";
197
- readonly method: "GET";
198
- readonly path: RegExp;
199
- }];
200
- /** Имя маршрута, доступное в `cache({ routes: … })`. */
201
- type CacheRouteId = (typeof CACHE_ROUTES)[number]['id'];
202
- /** Раздел маршрута. */
203
- type CacheRouteCategory = (typeof CACHE_ROUTES)[number]['category'];
204
- /** Проверяет публичное имя маршрута. */
205
- declare function isCacheRouteId(value: string): value is CacheRouteId;
206
- /** Находит читающий маршрут по HTTP-методу и пути. */
207
- declare function cacheRoute(method: string, path: string): (typeof CACHE_ROUTES)[number] | undefined;
208
-
209
- /**
210
- * Собирает ключ из значений, влияющих на адрес, тело или разобранный ответ.
211
- *
212
- * Заголовки и транспортные опции намеренно не входят. Если тело либо опция другого
213
- * плагина не сериализуются как JSON, запрос выполняется без кэша.
214
- */
215
- declare function buildCacheKey(route: CacheRouteId, request: RawRequestOptions): string | undefined;
216
-
1
+ import { ClientPlugin, NotificationEventContext, NotificationEvents, OperationId, OperationRequestOptions, Unsubscribe } from "itd-api";
2
+ //#region src/plugin.d.ts
217
3
  /** Режимы кэширования отдельного запроса. */
218
4
  declare const CacheModes: Readonly<{
219
- /** Отдать свежий кэш, иначе выполнить запрос и сохранить ответ. */
220
- readonly Default: "default";
221
- /** Пропустить сохранённое значение, выполнить запрос и перезаписать кэш. */
222
- readonly Reload: "reload";
223
- /** Не читать и не писать кэш для этого запроса. */
224
- readonly NoStore: "no-store";
5
+ /** Отдать свежий кэш, иначе выполнить запрос и сохранить ответ. */
6
+ readonly Default: "default";
7
+ /** Пропустить сохранённое значение, выполнить запрос и перезаписать кэш. */
8
+ readonly Reload: "reload";
9
+ /** Не читать и не писать кэш для этого запроса. */
10
+ readonly NoStore: "no-store";
225
11
  }>;
226
12
  /** Поведение кэша для отдельного запроса. */
227
13
  type CacheMode = (typeof CacheModes)[keyof typeof CacheModes];
228
14
  /** Настройки плагина. */
229
15
  interface CacheOptions {
230
- /** Сколько миллисекунд хранить успешный ответ. */
231
- ttl: number;
232
- /** Какие операции itd-api кэшировать. */
233
- routes: readonly CacheRouteId[];
234
- /** Максимальное количество ответов. По умолчанию 500. */
235
- maxEntries?: number | undefined;
236
- /** Объединять ли одновременные одинаковые запросы. По умолчанию `true`. */
237
- deduplicate?: boolean | undefined;
16
+ /** Сколько миллисекунд хранить успешный ответ. */
17
+ ttl: number;
18
+ /** Какие операции itd-api кэшировать. */
19
+ operations: readonly OperationId[];
20
+ /** Максимальное количество ответов. По умолчанию 500. */
21
+ maxEntries?: number | undefined;
22
+ /** Объединять ли одновременные одинаковые запросы. По умолчанию `true`. */
23
+ deduplicate?: boolean | undefined;
238
24
  }
239
25
  /** Плагин и управление созданным им хранилищем. */
240
- interface CachePlugin extends ItdPlugin {
241
- /** Количество готовых ответов во всех разделах кэша. */
242
- readonly size: number;
243
- /** Удаляет все ответы и не даёт выполняющимся запросам вернуть устаревший результат. */
244
- clear(): void;
245
- /** Удаляет все варианты названных маршрутов во всех подключённых клиентах. */
246
- invalidate(...routes: CacheRouteId[]): void;
247
- /**
248
- * Очищает список и счётчик уведомлений по событиям realtime.
249
- *
250
- * Сразу удаляет прежние значения и возвращает функцию отписки.
251
- */
252
- attachRealtime(stream: ItdRealtime): Unsubscribe;
26
+ interface CachePlugin extends ClientPlugin {
27
+ /** Количество готовых ответов во всех разделах кэша. */
28
+ readonly size: number;
29
+ /** Удаляет все ответы и не даёт выполняющимся запросам вернуть устаревший результат. */
30
+ clear(): void;
31
+ /** Удаляет все варианты названных операций во всех подключённых клиентах. */
32
+ invalidate(...operations: OperationId[]): void;
33
+ /**
34
+ * Подключает инвалидацию к нормализованным событиям уведомлений.
35
+ *
36
+ * Удаляет сохранённые список и счётчик, затем отслеживает обновления через промежуточный
37
+ * обработчик. Подключайте его до обработчиков, способных остановить цепочку.
38
+ */
39
+ attachNotificationEvents<C extends NotificationEventContext>(stream: NotificationEvents<C>): Unsubscribe;
253
40
  }
254
- /** Создаёт TTL/LRU-кэш разобранных ответов itd-api. */
41
+ /** Создаёт TTL/LRU-кэш нормализованных результатов itd-api. */
255
42
  declare function cache(options: CacheOptions): CachePlugin;
256
-
43
+ //#endregion
44
+ //#region src/policy.d.ts
45
+ /** Виды политики кэша, объявляемой в метаданных операции. */
46
+ declare const CachePolicyKind: Readonly<{
47
+ readonly Query: "query";
48
+ readonly Mutation: "mutation";
49
+ }>;
50
+ type CachePolicyKind = (typeof CachePolicyKind)[keyof typeof CachePolicyKind];
51
+ /** Области изоляции данных кэша. */
52
+ declare const CachePolicyScope: Readonly<{
53
+ readonly Account: "account";
54
+ readonly Session: "session";
55
+ }>;
56
+ type CachePolicyScope = (typeof CachePolicyScope)[keyof typeof CachePolicyScope];
57
+ /** Способы инвалидации кэша после мутации. */
58
+ declare const CacheInvalidation: Readonly<{
59
+ readonly All: "all";
60
+ }>;
61
+ type CacheInvalidation = (typeof CacheInvalidation)[keyof typeof CacheInvalidation];
62
+ //#endregion
63
+ //#region src/errors.d.ts
64
+ /** Ошибка настройки или использования плагина кэша. */
65
+ declare class CacheError extends Error {
66
+ readonly name = "CacheError";
67
+ }
68
+ //#endregion
69
+ //#region src/key.d.ts
257
70
  /**
258
- * `@itd-api/cache` TTL/LRU-кэш и дедупликация запросов для itd-api.
259
- *
260
- * @example
261
- * ```ts
262
- * import { cache } from '@itd-api/cache';
263
- *
264
- * itd.use(cache({
265
- * ttl: 60_000,
266
- * routes: ['users.get', 'posts.get', 'posts.list'],
267
- * }));
268
- * ```
71
+ * Собирает ключ из значений, влияющих на адрес, тело или разобранный ответ.
269
72
  *
270
- * @packageDocumentation
73
+ * Заголовки и транспортные опции намеренно не входят. Если тело либо опция другого
74
+ * плагина не сериализуются как JSON, запрос выполняется без кэша.
271
75
  */
272
-
76
+ declare function buildCacheKey(operation: OperationId, request: OperationRequestOptions): string | undefined;
77
+ //#endregion
78
+ //#region src/operations.d.ts
79
+ /** Описание читающей операции itd-api. */
80
+ interface CacheOperation {
81
+ /** Стабильный ID операции и публичное имя для настройки плагина. */
82
+ id: OperationId;
83
+ /** Раздел клиента. */
84
+ category: string;
85
+ }
86
+ /** Читающие операции, которые можно кэшировать. */
87
+ declare const CACHE_OPERATIONS: readonly [Readonly<{
88
+ readonly id: "auth.sessions";
89
+ readonly category: "auth";
90
+ }>, Readonly<{
91
+ readonly id: "users.me";
92
+ readonly category: "users";
93
+ }>, Readonly<{
94
+ readonly id: "users.checkUsername";
95
+ readonly category: "users";
96
+ }>, Readonly<{
97
+ readonly id: "users.search";
98
+ readonly category: "users";
99
+ }>, Readonly<{
100
+ readonly id: "users.whoToFollow";
101
+ readonly category: "users";
102
+ }>, Readonly<{
103
+ readonly id: "users.topClans";
104
+ readonly category: "users";
105
+ }>, Readonly<{
106
+ readonly id: "users.followers";
107
+ readonly category: "users";
108
+ }>, Readonly<{
109
+ readonly id: "users.following";
110
+ readonly category: "users";
111
+ }>, Readonly<{
112
+ readonly id: "users.blocked";
113
+ readonly category: "users";
114
+ }>, Readonly<{
115
+ readonly id: "users.getPrivacy";
116
+ readonly category: "users";
117
+ }>, Readonly<{
118
+ readonly id: "users.pins";
119
+ readonly category: "users";
120
+ }>, Readonly<{
121
+ readonly id: "users.followStatus";
122
+ readonly category: "users";
123
+ }>, Readonly<{
124
+ readonly id: "users.get";
125
+ readonly category: "users";
126
+ }>, Readonly<{
127
+ readonly id: "posts.list";
128
+ readonly category: "posts";
129
+ }>, Readonly<{
130
+ readonly id: "posts.likedByUser";
131
+ readonly category: "posts";
132
+ }>, Readonly<{
133
+ readonly id: "posts.byUser";
134
+ readonly category: "posts";
135
+ }>, Readonly<{
136
+ readonly id: "posts.comments";
137
+ readonly category: "posts";
138
+ }>, Readonly<{
139
+ readonly id: "posts.stats";
140
+ readonly category: "posts";
141
+ }>, Readonly<{
142
+ readonly id: "posts.get";
143
+ readonly category: "posts";
144
+ }>, Readonly<{
145
+ readonly id: "comments.replies";
146
+ readonly category: "comments";
147
+ }>, Readonly<{
148
+ readonly id: "notifications.list";
149
+ readonly category: "notifications";
150
+ }>, Readonly<{
151
+ readonly id: "notifications.count";
152
+ readonly category: "notifications";
153
+ }>, Readonly<{
154
+ readonly id: "notifications.getSettings";
155
+ readonly category: "notifications";
156
+ }>, Readonly<{
157
+ readonly id: "hashtags.search";
158
+ readonly category: "hashtags";
159
+ }>, Readonly<{
160
+ readonly id: "hashtags.trending";
161
+ readonly category: "hashtags";
162
+ }>, Readonly<{
163
+ readonly id: "hashtags.posts";
164
+ readonly category: "hashtags";
165
+ }>, Readonly<{
166
+ readonly id: "search.all";
167
+ readonly category: "search";
168
+ }>, Readonly<{
169
+ readonly id: "files.get";
170
+ readonly category: "files";
171
+ }>, Readonly<{
172
+ readonly id: "subscription.status";
173
+ readonly category: "subscription";
174
+ }>, Readonly<{
175
+ readonly id: "subscription.methods";
176
+ readonly category: "subscription";
177
+ }>, Readonly<{
178
+ readonly id: "verification.status";
179
+ readonly category: "verification";
180
+ }>, Readonly<{
181
+ readonly id: "platform.changelog";
182
+ readonly category: "platform";
183
+ }>, Readonly<{
184
+ readonly id: "platform.announcements";
185
+ readonly category: "platform";
186
+ }>, Readonly<{
187
+ readonly id: "platform.portal";
188
+ readonly category: "platform";
189
+ }>, Readonly<{
190
+ readonly id: "status.get";
191
+ readonly category: "platform";
192
+ }>];
193
+ /** Имя операции, доступное в `cache({ operations: … })`. */
194
+ type CacheOperationId = (typeof CACHE_OPERATIONS)[number]['id'];
195
+ /** Раздел операции. */
196
+ type CacheOperationCategory = (typeof CACHE_OPERATIONS)[number]['category'];
197
+ /** Проверяет публичное имя кэшируемой операции. */
198
+ declare function isCacheOperationId(value: string): value is CacheOperationId;
199
+ /** Находит читающую операцию по стабильному семантическому ID. */
200
+ declare function cacheOperation(operationId: OperationId): (typeof CACHE_OPERATIONS)[number] | undefined;
201
+ //#endregion
202
+ //#region src/index.d.ts
273
203
  declare module 'itd-api' {
274
- interface RequestOptions {
275
- /** Управление кэшем подключённого `@itd-api/cache`. */
276
- cache?: CacheMode | undefined;
277
- }
204
+ interface OperationAnnotations {
205
+ /** Правило кэширования операции подключаемого модуля. */
206
+ readonly cache?: {
207
+ readonly kind: typeof CachePolicyKind.Query;
208
+ readonly scope?: CachePolicyScope | undefined;
209
+ } | {
210
+ readonly kind: typeof CachePolicyKind.Mutation;
211
+ readonly invalidates: readonly OperationId[] | CacheInvalidation;
212
+ readonly scope?: typeof CachePolicyScope.Account | undefined;
213
+ } | undefined;
214
+ }
215
+ interface RequestExtensions {
216
+ /** Управление кэшем подключённого `@itd-api/cache`. */
217
+ cache?: CacheMode | undefined;
218
+ }
278
219
  }
279
-
280
- export { CACHE_ROUTES, CacheError, type CacheMode, CacheModes, type CacheOptions, type CachePlugin, type CacheRoute, type CacheRouteCategory, type CacheRouteId, buildCacheKey, cache, cacheRoute, isCacheRouteId };
220
+ //#endregion
221
+ export { CACHE_OPERATIONS, CacheError, CacheInvalidation, type CacheMode, CacheModes, type CacheOperation, type CacheOperationCategory, type CacheOperationId, type CacheOptions, type CachePlugin, CachePolicyKind, CachePolicyScope, buildCacheKey, cache, cacheOperation, isCacheOperationId };
222
+ //# sourceMappingURL=index.d.ts.map