@sevn/reqcache 1.1.0 → 1.3.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 +115 -1
- package/dist/index.d.ts +77 -7
- package/dist/index.esm.js +215 -11
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +215 -11
- package/dist/index.js.map +1 -1
- package/dist/request-cache.d.ts +76 -6
- package/package.json +1 -1
package/dist/request-cache.d.ts
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* 1. Primeira chamada -> faz o fetch e grava a entrada da rota no array.
|
|
14
14
|
* 2. Durante o TTL -> devolve os dados do cache, sem tocar na rede.
|
|
15
15
|
* 3. Após expirar -> SÓ revalida quando o client chamar de novo (lazy).
|
|
16
|
-
* Se houver `monotonicKey`, só aceita o novo dado quando
|
|
17
|
-
*
|
|
16
|
+
* Se houver `monotonicKey`, só aceita o novo dado quando TODAS as chaves
|
|
17
|
+
* tiverem AVANÇADO; senão mantém o antigo.
|
|
18
18
|
*
|
|
19
19
|
* Proteção de espaço (limite de ~5 MB do localStorage):
|
|
20
20
|
* - `maxEntries`: ao gravar, se passar do limite, remove a rota menos
|
|
@@ -31,13 +31,48 @@ export interface StorageLike {
|
|
|
31
31
|
setItem(key: string, value: string): void;
|
|
32
32
|
removeItem(key: string): void;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Como comparar o valor de uma chave monotônica:
|
|
36
|
+
* - `"number"` — numérica. Aceita `number` e string numérica ("2232575810").
|
|
37
|
+
* - `"date"` — por timestamp. Aceita o que o `Date.parse` resolver
|
|
38
|
+
* ("2026-10-04T18:23:00Z") e também epoch em ms.
|
|
39
|
+
* - `"string"` — lexicográfica.
|
|
40
|
+
*/
|
|
41
|
+
export type MonotonicType = "number" | "date" | "string";
|
|
42
|
+
/**
|
|
43
|
+
* Chave(s) monotônica(s). Três formas:
|
|
44
|
+
* - `"summary.ballots_counted"` — uma chave, tipo detectado pelo valor.
|
|
45
|
+
* - `["idg", "summary.last_updated"]` — várias, tipo detectado pelo valor.
|
|
46
|
+
* - `{ idg: "number", "summary.last_updated": "date" }` — várias, com o tipo
|
|
47
|
+
* declarado por nome de chave (recomendado: não depende de adivinhação).
|
|
48
|
+
*/
|
|
49
|
+
export type MonotonicKey = string | string[] | Record<string, MonotonicType>;
|
|
34
50
|
export interface GetFetchOptions {
|
|
35
51
|
/**
|
|
36
|
-
* Caminho da chave
|
|
37
|
-
*
|
|
38
|
-
*
|
|
52
|
+
* Caminho(s) da chave monotônica. Suporta aninhamento com ponto.
|
|
53
|
+
*
|
|
54
|
+
* monotonicKey: "resultado.votosApurados"
|
|
55
|
+
* monotonicKey: ["idg", "summary.last_updated"]
|
|
56
|
+
* monotonicKey: { idg: "number", "summary.last_updated": "date" }
|
|
57
|
+
*
|
|
58
|
+
* Com mais de uma chave, TODAS são comparadas e o dado novo só é aceito
|
|
59
|
+
* quando todas concordam que ele é mais recente — se qualquer uma vier
|
|
60
|
+
* igual ou menor, a resposta é descartada e o dado em cache é mantido.
|
|
61
|
+
* A comparação é sempre estrita: o valor novo precisa ser MAIOR que o
|
|
62
|
+
* guardado, nunca igual.
|
|
63
|
+
*
|
|
64
|
+
* O tipo de cada chave é resolvido nesta ordem:
|
|
65
|
+
* 1. declarado na forma de mapa;
|
|
66
|
+
* 2. conhecido pelo NOME da chave (`idg` é número, `last_updated` é data —
|
|
67
|
+
* veja `TIPOS_POR_NOME`, extensível via `monotonicTypes` na config);
|
|
68
|
+
* 3. detectado pelo valor: número, string que converte para número finito,
|
|
69
|
+
* string que o `Date.parse` resolve e, por fim, lexicográfica.
|
|
70
|
+
*
|
|
71
|
+
* TODAS as chaves precisam ter crescido. Uma chave incomparável (ausente de
|
|
72
|
+
* um dos lados, ilegível ou fora do tipo esperado) conta como "não cresceu"
|
|
73
|
+
* e derruba a resposta nova junto com as demais.
|
|
39
74
|
*/
|
|
40
|
-
monotonicKey?:
|
|
75
|
+
monotonicKey?: MonotonicKey;
|
|
41
76
|
/** Opções nativas repassadas ao fetch (headers, method, body, signal...). */
|
|
42
77
|
fetchOptions?: RequestInit;
|
|
43
78
|
/**
|
|
@@ -67,6 +102,10 @@ export interface CacheEntry<T = unknown> {
|
|
|
67
102
|
expiresAt: number;
|
|
68
103
|
lastAccess: number;
|
|
69
104
|
}
|
|
105
|
+
/** Uma linha de log do modo debug. */
|
|
106
|
+
export interface DebugLogFn {
|
|
107
|
+
(message: string, details?: Record<string, unknown>): void;
|
|
108
|
+
}
|
|
70
109
|
export interface RequestCacheConfig {
|
|
71
110
|
/** Storage a usar. Padrão: localStorage (se disponível). */
|
|
72
111
|
storage?: StorageLike;
|
|
@@ -74,6 +113,30 @@ export interface RequestCacheConfig {
|
|
|
74
113
|
storageKey?: string;
|
|
75
114
|
/** Máximo de rotas em cache. Excedeu -> remove a menos usada (LRU). Padrão 100. */
|
|
76
115
|
maxEntries?: number;
|
|
116
|
+
/**
|
|
117
|
+
* Se true, imprime logs detalhados de cada operação (fetch de rede,
|
|
118
|
+
* cache hit, deduplicação, fallback, LRU, etc.). Padrão false.
|
|
119
|
+
* Útil para identificar se estão sendo feitas mais chamadas de rede
|
|
120
|
+
* do que o necessário. Pode ser ligado/desligado em runtime com
|
|
121
|
+
* `setDebug()`.
|
|
122
|
+
*/
|
|
123
|
+
debug?: boolean;
|
|
124
|
+
/** Logger customizado usado quando `debug` está ligado. Padrão: `console.debug`. */
|
|
125
|
+
logger?: DebugLogFn;
|
|
126
|
+
/**
|
|
127
|
+
* Tipos monotônicos adicionais, por nome de chave. Somado (e com prioridade
|
|
128
|
+
* sobre) a tabela embutida `TIPOS_POR_NOME`, para que o chamador possa
|
|
129
|
+
* continuar passando `monotonicKey` como lista de caminhos e ainda assim ter
|
|
130
|
+
* a comparação certa:
|
|
131
|
+
*
|
|
132
|
+
* new RequestCache({ monotonicTypes: { data_apuracao: "date" } })
|
|
133
|
+
* ...
|
|
134
|
+
* getFetch(url, 10_000, { monotonicKey: ["idg", "data_apuracao"] })
|
|
135
|
+
*
|
|
136
|
+
* Aceita o caminho completo ("summary.last_updated") ou só o último trecho
|
|
137
|
+
* ("last_updated").
|
|
138
|
+
*/
|
|
139
|
+
monotonicTypes?: Record<string, MonotonicType>;
|
|
77
140
|
}
|
|
78
141
|
export declare class RequestCache {
|
|
79
142
|
private storage;
|
|
@@ -82,7 +145,12 @@ export declare class RequestCache {
|
|
|
82
145
|
private inflight;
|
|
83
146
|
/** Relógio de acesso monotônico: sempre cresce, mesmo com acessos no mesmo ms. */
|
|
84
147
|
private tick;
|
|
148
|
+
private debug;
|
|
149
|
+
private logger;
|
|
150
|
+
private monotonicTypes;
|
|
85
151
|
constructor(config?: RequestCacheConfig);
|
|
152
|
+
/** Liga/desliga o modo debug em runtime, sem precisar recriar a instância. */
|
|
153
|
+
setDebug(enabled: boolean): void;
|
|
86
154
|
/**
|
|
87
155
|
* Busca uma URL usando cache.
|
|
88
156
|
* @param url Rota da requisição (também é a chave do cache).
|
|
@@ -102,6 +170,8 @@ export declare class RequestCache {
|
|
|
102
170
|
clear(): void;
|
|
103
171
|
/** Retorna um número de acesso estritamente crescente (para o LRU). */
|
|
104
172
|
private nextAccess;
|
|
173
|
+
/** Emite uma linha de log, só quando o modo debug está ligado. */
|
|
174
|
+
private log;
|
|
105
175
|
/**
|
|
106
176
|
* Tenta cada URL da lista em ordem (primário, depois os `fallbackUrls`).
|
|
107
177
|
* Devolve o JSON da primeira que responder OK; se todas falharem, lança o
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sevn/reqcache",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Cache de requisicoes HTTP em localStorage, com regra monotonica, deduplicacao e limite LRU. Pensado para cenarios de alto volume (ex.: apuracao de eleicoes).",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|