@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.
@@ -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 o valor numérico
17
- * dessa chave for MAIOR que o guardado; senão mantém o antigo.
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 numérica monotônica. Suporta aninhamento com ponto.
37
- * Ex.: "total", "resultado.votosApurados", "data.candidato.votos".
38
- * Se o valor novo NÃO for maior que o antigo, mantém o dado em cache.
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?: string;
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.1.0",
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",