rust-node-cache 0.1.0 → 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 +48 -11
- package/binding.d.ts +22 -3
- package/dist/index.d.mts +20 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/rust-node-cache.darwin-arm64.node +0 -0
- package/rust-node-cache.darwin-x64.node +0 -0
- package/rust-node-cache.linux-arm64-gnu.node +0 -0
- package/rust-node-cache.linux-x64-gnu.node +0 -0
- package/rust-node-cache.win32-x64-msvc.node +0 -0
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ is **no compiler required at install time** on supported platforms.
|
|
|
15
15
|

|
|
16
16
|

|
|
17
17
|
|
|
18
|
+
🌐 **Website:** [rust-node-cache.vercel.app](https://rust-node-cache.vercel.app/)
|
|
19
|
+
|
|
18
20
|
---
|
|
19
21
|
|
|
20
22
|
## Features
|
|
@@ -22,8 +24,10 @@ is **no compiler required at install time** on supported platforms.
|
|
|
22
24
|
- 🦀 **Rust-powered** core for predictable, low-overhead performance
|
|
23
25
|
- 🔒 **Thread-safe** via `DashMap` (lock-sharded concurrent map)
|
|
24
26
|
- ⏱️ **TTL support** per entry (lazy expiration + active cleanup)
|
|
27
|
+
- 🧹 **Background expiration** — optional sweeper thread (`cleanupIntervalSeconds`)
|
|
28
|
+
- 🧠 **LRU eviction** — bound the cache by `maxSize` with `evictionPolicy: "lru"`
|
|
25
29
|
- ⚡ **Fast reads** and **fast writes**
|
|
26
|
-
- 📊 Built-in **statistics** (hits, misses, sets, deletes, expired, size)
|
|
30
|
+
- 📊 Built-in **statistics** (hits, misses, sets, deletes, expired, evicted, size)
|
|
27
31
|
- 🧩 **TypeScript** support with generics out of the box
|
|
28
32
|
- 🌐 **Framework agnostic** — works with Express, Fastify, NestJS, Hono,
|
|
29
33
|
Next.js, or plain Node.js
|
|
@@ -140,6 +144,35 @@ an active sweep:
|
|
|
140
144
|
const removed = cache.cleanupExpired(); // number of entries removed
|
|
141
145
|
```
|
|
142
146
|
|
|
147
|
+
Or let the cache sweep for you in the background — set `cleanupIntervalSeconds`
|
|
148
|
+
and a thread reclaims expired entries on its own (no manual `cleanupExpired()`):
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const cache = new Cache({ cleanupIntervalSeconds: 30 });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The thread is tied to the cache's lifetime: it stops automatically when the cache
|
|
155
|
+
is garbage-collected.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Eviction (maxSize)
|
|
160
|
+
|
|
161
|
+
Cap the number of keys with `maxSize`. When the cache is full and a **new** key
|
|
162
|
+
is written, `evictionPolicy` decides what happens:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// Default: reject the write (set returns false), keep existing entries.
|
|
166
|
+
const a = new Cache({ maxSize: 1000 }); // evictionPolicy: "reject"
|
|
167
|
+
|
|
168
|
+
// LRU: evict the least-recently-used entry to make room, then insert.
|
|
169
|
+
const b = new Cache({ maxSize: 1000, evictionPolicy: "lru" });
|
|
170
|
+
b.evictionPolicy; // "lru"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
LRU recency is tracked per entry (updated on every `get` hit) and the evicted
|
|
174
|
+
count is surfaced in `stats().evicted`. Overwriting an existing key never evicts.
|
|
175
|
+
|
|
143
176
|
---
|
|
144
177
|
|
|
145
178
|
## Statistics
|
|
@@ -157,6 +190,7 @@ Returns:
|
|
|
157
190
|
sets: 800,
|
|
158
191
|
deletes: 20,
|
|
159
192
|
expired: 15,
|
|
193
|
+
evicted: 40,
|
|
160
194
|
size: 780
|
|
161
195
|
}
|
|
162
196
|
```
|
|
@@ -206,8 +240,9 @@ Bincode) later without touching the cache logic.
|
|
|
206
240
|
|
|
207
241
|
| Method | Returns | Description |
|
|
208
242
|
| ------------------------------ | -------------- | ----------------------------------------------------------------- |
|
|
209
|
-
| `new Cache(options?)` | `Cache` | Create a cache
|
|
243
|
+
| `new Cache(options?)` | `Cache` | Create a cache (`maxSize`, `evictionPolicy`, `cleanupIntervalSeconds`). |
|
|
210
244
|
| `set(key, value, options?)` | `boolean` | Store/overwrite a value. `options.ttlSeconds` sets expiration. |
|
|
245
|
+
| `evictionPolicy` (getter) | `string` | The active policy: `"reject"` or `"lru"`. |
|
|
211
246
|
| `get<T>(key)` | `T \| null` | Read a value (lazy-expires stale entries). |
|
|
212
247
|
| `delete(key)` | `boolean` | Remove a key. `true` if it existed. |
|
|
213
248
|
| `exists(key)` | `boolean` | Whether the key exists and is valid. |
|
|
@@ -221,6 +256,8 @@ Bincode) later without touching the cache logic.
|
|
|
221
256
|
```ts
|
|
222
257
|
interface CacheOptions {
|
|
223
258
|
maxSize?: number;
|
|
259
|
+
evictionPolicy?: "reject" | "lru"; // default "reject"
|
|
260
|
+
cleanupIntervalSeconds?: number; // enables the background sweeper
|
|
224
261
|
}
|
|
225
262
|
|
|
226
263
|
interface SetOptions {
|
|
@@ -233,6 +270,7 @@ interface CacheStats {
|
|
|
233
270
|
sets: number;
|
|
234
271
|
deletes: number;
|
|
235
272
|
expired: number;
|
|
273
|
+
evicted: number;
|
|
236
274
|
size: number;
|
|
237
275
|
}
|
|
238
276
|
```
|
|
@@ -321,15 +359,14 @@ Coming soon.
|
|
|
321
359
|
|
|
322
360
|
## Roadmap
|
|
323
361
|
|
|
324
|
-
| Version | Feature |
|
|
325
|
-
| ------- | ------------------------ |
|
|
326
|
-
| v0.1 | Basic cache |
|
|
327
|
-
| v0.2 | TTL cleanup thread
|
|
328
|
-
| v0.3 |
|
|
329
|
-
| v0.4 |
|
|
330
|
-
| v0.5 |
|
|
331
|
-
| v0.6 |
|
|
332
|
-
| v0.7 | ImmutableLog integration |
|
|
362
|
+
| Version | Feature | Status |
|
|
363
|
+
| ------- | ------------------------ | ------ |
|
|
364
|
+
| v0.1 | Basic cache | ✅ |
|
|
365
|
+
| v0.2 | TTL cleanup thread + LRU eviction | ✅ |
|
|
366
|
+
| v0.3 | LFU cache | 🔜 |
|
|
367
|
+
| v0.4 | Redis synchronization | 🔜 |
|
|
368
|
+
| v0.5 | Prometheus metrics | 🔜 |
|
|
369
|
+
| v0.6 | ImmutableLog integration | 🔜 |
|
|
333
370
|
|
|
334
371
|
### Future: ImmutableLog Integration
|
|
335
372
|
|
package/binding.d.ts
CHANGED
|
@@ -3,10 +3,26 @@
|
|
|
3
3
|
|
|
4
4
|
/* auto-generated by NAPI-RS */
|
|
5
5
|
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Opções do construtor:
|
|
8
|
+
* `new Cache({ maxSize, evictionPolicy, cleanupIntervalSeconds })`.
|
|
9
|
+
*/
|
|
7
10
|
export interface CacheOptions {
|
|
8
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Limite opcional de chaves. Comportamento ao atingir depende de
|
|
13
|
+
* `evictionPolicy`.
|
|
14
|
+
*/
|
|
9
15
|
maxSize?: number
|
|
16
|
+
/**
|
|
17
|
+
* `"reject"` (padrão) — `set` de chave nova retorna `false` quando cheio;
|
|
18
|
+
* `"lru"` — remove a entrada menos recentemente usada e prossegue.
|
|
19
|
+
*/
|
|
20
|
+
evictionPolicy?: string
|
|
21
|
+
/**
|
|
22
|
+
* Se definido (> 0), liga uma thread que varre entradas expiradas a cada
|
|
23
|
+
* N segundos (expiração em background, além da lazy).
|
|
24
|
+
*/
|
|
25
|
+
cleanupIntervalSeconds?: number
|
|
10
26
|
}
|
|
11
27
|
/** Opções por escrita: `cache.set(key, value, { ttlSeconds })`. */
|
|
12
28
|
export interface SetOptions {
|
|
@@ -20,6 +36,7 @@ export interface CacheStatsObject {
|
|
|
20
36
|
sets: number
|
|
21
37
|
deletes: number
|
|
22
38
|
expired: number
|
|
39
|
+
evicted: number
|
|
23
40
|
size: number
|
|
24
41
|
}
|
|
25
42
|
/**
|
|
@@ -30,8 +47,10 @@ export interface CacheStatsObject {
|
|
|
30
47
|
* concorrente por dentro, várias chamadas podem rodar em paralelo.
|
|
31
48
|
*/
|
|
32
49
|
export declare class Cache {
|
|
33
|
-
/** `new Cache()` ou `new Cache({ maxSize })`. */
|
|
50
|
+
/** `new Cache()` ou `new Cache({ maxSize, evictionPolicy, cleanupIntervalSeconds })`. */
|
|
34
51
|
constructor(options?: CacheOptions | undefined | null)
|
|
52
|
+
/** A política de evicção ativa: `"reject"` ou `"lru"`. */
|
|
53
|
+
get evictionPolicy(): string
|
|
35
54
|
/**
|
|
36
55
|
* Insere/atualiza uma chave. Retorna `true` em sucesso, `false` se o cache
|
|
37
56
|
* estiver cheio (`maxSize`) e a chave for nova.
|
package/dist/index.d.mts
CHANGED
|
@@ -12,14 +12,26 @@
|
|
|
12
12
|
* O custo é uma chamada de função extra por operação — desprezível frente ao
|
|
13
13
|
* trabalho real (serialização + acesso ao DashMap) que acontece no Rust.
|
|
14
14
|
*/
|
|
15
|
+
/** Estratégia de evicção quando `maxSize` é atingido. */
|
|
16
|
+
type EvictionPolicy = "reject" | "lru";
|
|
15
17
|
/** Opções do construtor do cache. */
|
|
16
18
|
interface CacheOptions {
|
|
17
19
|
/**
|
|
18
|
-
* Limite máximo de chaves.
|
|
19
|
-
*
|
|
20
|
-
* Sem valor => cache ilimitado.
|
|
20
|
+
* Limite máximo de chaves. O que acontece ao atingir depende de
|
|
21
|
+
* `evictionPolicy`. Sem valor => cache ilimitado.
|
|
21
22
|
*/
|
|
22
23
|
maxSize?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Política ao atingir `maxSize` numa chave **nova**:
|
|
26
|
+
* - `"reject"` (padrão): `set` retorna `false` (sobrescrever continua ok);
|
|
27
|
+
* - `"lru"`: remove a entrada menos recentemente usada e prossegue.
|
|
28
|
+
*/
|
|
29
|
+
evictionPolicy?: EvictionPolicy;
|
|
30
|
+
/**
|
|
31
|
+
* Se definido (> 0), liga uma thread que varre entradas expiradas a cada
|
|
32
|
+
* N segundos (expiração em background, além da preguiçosa por acesso).
|
|
33
|
+
*/
|
|
34
|
+
cleanupIntervalSeconds?: number;
|
|
23
35
|
}
|
|
24
36
|
/** Opções por operação de escrita. */
|
|
25
37
|
interface SetOptions {
|
|
@@ -38,6 +50,8 @@ interface CacheStats {
|
|
|
38
50
|
deletes: number;
|
|
39
51
|
/** Total de entradas removidas por expiração. */
|
|
40
52
|
expired: number;
|
|
53
|
+
/** Total de entradas removidas por evicção (política LRU ao atingir `maxSize`). */
|
|
54
|
+
evicted: number;
|
|
41
55
|
/** Número de chaves armazenadas agora. */
|
|
42
56
|
size: number;
|
|
43
57
|
}
|
|
@@ -58,6 +72,8 @@ declare class Cache {
|
|
|
58
72
|
/** Instância da classe nativa (Rust). */
|
|
59
73
|
private readonly native;
|
|
60
74
|
constructor(options?: CacheOptions);
|
|
75
|
+
/** A política de evicção ativa: `"reject"` ou `"lru"`. */
|
|
76
|
+
get evictionPolicy(): EvictionPolicy;
|
|
61
77
|
/**
|
|
62
78
|
* Armazena (ou sobrescreve) um valor. O valor é serializado como JSON no core.
|
|
63
79
|
*
|
|
@@ -88,4 +104,4 @@ declare class Cache {
|
|
|
88
104
|
stats(): CacheStats;
|
|
89
105
|
}
|
|
90
106
|
|
|
91
|
-
export { Cache, type CacheOptions, type CacheStats, type SetOptions };
|
|
107
|
+
export { Cache, type CacheOptions, type CacheStats, type EvictionPolicy, type SetOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,14 +12,26 @@
|
|
|
12
12
|
* O custo é uma chamada de função extra por operação — desprezível frente ao
|
|
13
13
|
* trabalho real (serialização + acesso ao DashMap) que acontece no Rust.
|
|
14
14
|
*/
|
|
15
|
+
/** Estratégia de evicção quando `maxSize` é atingido. */
|
|
16
|
+
type EvictionPolicy = "reject" | "lru";
|
|
15
17
|
/** Opções do construtor do cache. */
|
|
16
18
|
interface CacheOptions {
|
|
17
19
|
/**
|
|
18
|
-
* Limite máximo de chaves.
|
|
19
|
-
*
|
|
20
|
-
* Sem valor => cache ilimitado.
|
|
20
|
+
* Limite máximo de chaves. O que acontece ao atingir depende de
|
|
21
|
+
* `evictionPolicy`. Sem valor => cache ilimitado.
|
|
21
22
|
*/
|
|
22
23
|
maxSize?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Política ao atingir `maxSize` numa chave **nova**:
|
|
26
|
+
* - `"reject"` (padrão): `set` retorna `false` (sobrescrever continua ok);
|
|
27
|
+
* - `"lru"`: remove a entrada menos recentemente usada e prossegue.
|
|
28
|
+
*/
|
|
29
|
+
evictionPolicy?: EvictionPolicy;
|
|
30
|
+
/**
|
|
31
|
+
* Se definido (> 0), liga uma thread que varre entradas expiradas a cada
|
|
32
|
+
* N segundos (expiração em background, além da preguiçosa por acesso).
|
|
33
|
+
*/
|
|
34
|
+
cleanupIntervalSeconds?: number;
|
|
23
35
|
}
|
|
24
36
|
/** Opções por operação de escrita. */
|
|
25
37
|
interface SetOptions {
|
|
@@ -38,6 +50,8 @@ interface CacheStats {
|
|
|
38
50
|
deletes: number;
|
|
39
51
|
/** Total de entradas removidas por expiração. */
|
|
40
52
|
expired: number;
|
|
53
|
+
/** Total de entradas removidas por evicção (política LRU ao atingir `maxSize`). */
|
|
54
|
+
evicted: number;
|
|
41
55
|
/** Número de chaves armazenadas agora. */
|
|
42
56
|
size: number;
|
|
43
57
|
}
|
|
@@ -58,6 +72,8 @@ declare class Cache {
|
|
|
58
72
|
/** Instância da classe nativa (Rust). */
|
|
59
73
|
private readonly native;
|
|
60
74
|
constructor(options?: CacheOptions);
|
|
75
|
+
/** A política de evicção ativa: `"reject"` ou `"lru"`. */
|
|
76
|
+
get evictionPolicy(): EvictionPolicy;
|
|
61
77
|
/**
|
|
62
78
|
* Armazena (ou sobrescreve) um valor. O valor é serializado como JSON no core.
|
|
63
79
|
*
|
|
@@ -88,4 +104,4 @@ declare class Cache {
|
|
|
88
104
|
stats(): CacheStats;
|
|
89
105
|
}
|
|
90
106
|
|
|
91
|
-
export { Cache, type CacheOptions, type CacheStats, type SetOptions };
|
|
107
|
+
export { Cache, type CacheOptions, type CacheStats, type EvictionPolicy, type SetOptions };
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,16 @@ module.exports = __toCommonJS(index_exports);
|
|
|
36
36
|
var native = __toESM(require("../binding.js"));
|
|
37
37
|
var Cache2 = class {
|
|
38
38
|
constructor(options = {}) {
|
|
39
|
-
|
|
39
|
+
const hasOptions = options.maxSize !== void 0 || options.evictionPolicy !== void 0 || options.cleanupIntervalSeconds !== void 0;
|
|
40
|
+
this.native = hasOptions ? new native.Cache({
|
|
41
|
+
maxSize: options.maxSize,
|
|
42
|
+
evictionPolicy: options.evictionPolicy,
|
|
43
|
+
cleanupIntervalSeconds: options.cleanupIntervalSeconds
|
|
44
|
+
}) : new native.Cache();
|
|
45
|
+
}
|
|
46
|
+
/** A política de evicção ativa: `"reject"` ou `"lru"`. */
|
|
47
|
+
get evictionPolicy() {
|
|
48
|
+
return this.native.evictionPolicy;
|
|
40
49
|
}
|
|
41
50
|
/**
|
|
42
51
|
* Armazena (ou sobrescreve) um valor. O valor é serializado como JSON no core.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — API pública (TypeScript).\n *\n * \"Ultra-fast in-memory cache powered by Rust.\"\n *\n * Esta camada é um wrapper fino e tipado sobre a classe `Cache` nativa gerada\n * pelo Rust/napi-rs. Por que envolver em vez de re-exportar direto?\n * - permite **genéricos** ergonômicos: `cache.get<User>(\"user:1\")`;\n * - normaliza `undefined`/`null` para sempre devolver `null` num miss;\n * - dá um único lugar para JSDoc e para evoluir a API sem quebrar o core Rust.\n *\n * O custo é uma chamada de função extra por operação — desprezível frente ao\n * trabalho real (serialização + acesso ao DashMap) que acontece no Rust.\n */\n\n// Namespace import: funciona igual em CommonJS e ESM ao consumir o addon nativo\n// (que é um módulo CJS gerado pelo napi-rs).\nimport * as native from \"../binding.js\";\n\n/** Opções do construtor do cache. */\nexport interface CacheOptions {\n /**\n * Limite máximo de chaves.
|
|
1
|
+
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — API pública (TypeScript).\n *\n * \"Ultra-fast in-memory cache powered by Rust.\"\n *\n * Esta camada é um wrapper fino e tipado sobre a classe `Cache` nativa gerada\n * pelo Rust/napi-rs. Por que envolver em vez de re-exportar direto?\n * - permite **genéricos** ergonômicos: `cache.get<User>(\"user:1\")`;\n * - normaliza `undefined`/`null` para sempre devolver `null` num miss;\n * - dá um único lugar para JSDoc e para evoluir a API sem quebrar o core Rust.\n *\n * O custo é uma chamada de função extra por operação — desprezível frente ao\n * trabalho real (serialização + acesso ao DashMap) que acontece no Rust.\n */\n\n// Namespace import: funciona igual em CommonJS e ESM ao consumir o addon nativo\n// (que é um módulo CJS gerado pelo napi-rs).\nimport * as native from \"../binding.js\";\n\n/** Estratégia de evicção quando `maxSize` é atingido. */\nexport type EvictionPolicy = \"reject\" | \"lru\";\n\n/** Opções do construtor do cache. */\nexport interface CacheOptions {\n /**\n * Limite máximo de chaves. O que acontece ao atingir depende de\n * `evictionPolicy`. Sem valor => cache ilimitado.\n */\n maxSize?: number;\n /**\n * Política ao atingir `maxSize` numa chave **nova**:\n * - `\"reject\"` (padrão): `set` retorna `false` (sobrescrever continua ok);\n * - `\"lru\"`: remove a entrada menos recentemente usada e prossegue.\n */\n evictionPolicy?: EvictionPolicy;\n /**\n * Se definido (> 0), liga uma thread que varre entradas expiradas a cada\n * N segundos (expiração em background, além da preguiçosa por acesso).\n */\n cleanupIntervalSeconds?: number;\n}\n\n/** Opções por operação de escrita. */\nexport interface SetOptions {\n /** Tempo de vida em segundos. Ausente => a entrada não expira por tempo. */\n ttlSeconds?: number;\n}\n\n/** Estatísticas acumuladas do cache (mais o tamanho atual). */\nexport interface CacheStats {\n /** Leituras que encontraram uma entrada válida. */\n hits: number;\n /** Leituras sem chave válida (ausente ou expirada). */\n misses: number;\n /** Total de escritas (`set`). */\n sets: number;\n /** Total de remoções explícitas (`delete`). */\n deletes: number;\n /** Total de entradas removidas por expiração. */\n expired: number;\n /** Total de entradas removidas por evicção (política LRU ao atingir `maxSize`). */\n evicted: number;\n /** Número de chaves armazenadas agora. */\n size: number;\n}\n\n/**\n * Cache em memória ultrarrápido com núcleo em Rust (DashMap + contadores\n * atômicos). Thread-safe e com suporte a TTL por entrada.\n *\n * @example\n * ```ts\n * import { Cache } from \"rust-node-cache\";\n *\n * const cache = new Cache();\n * cache.set(\"user:1\", { id: 1, name: \"Roberto\" });\n * cache.get<{ id: number; name: string }>(\"user:1\"); // { id: 1, name: \"Roberto\" }\n * ```\n */\nexport class Cache {\n /** Instância da classe nativa (Rust). */\n private readonly native: native.Cache;\n\n constructor(options: CacheOptions = {}) {\n // Só repassamos um objeto de opções ao Rust quando há algo relevante.\n const hasOptions =\n options.maxSize !== undefined ||\n options.evictionPolicy !== undefined ||\n options.cleanupIntervalSeconds !== undefined;\n this.native = hasOptions\n ? new native.Cache({\n maxSize: options.maxSize,\n evictionPolicy: options.evictionPolicy,\n cleanupIntervalSeconds: options.cleanupIntervalSeconds,\n })\n : new native.Cache();\n }\n\n /** A política de evicção ativa: `\"reject\"` ou `\"lru\"`. */\n get evictionPolicy(): EvictionPolicy {\n return this.native.evictionPolicy as EvictionPolicy;\n }\n\n /**\n * Armazena (ou sobrescreve) um valor. O valor é serializado como JSON no core.\n *\n * @returns `true` em sucesso; `false` se `maxSize` foi atingido e a chave é nova.\n */\n set<T>(key: string, value: T, options?: SetOptions): boolean {\n return this.native.set(key, value as unknown as object, options);\n }\n\n /**\n * Lê um valor. Aplica expiração preguiçosa: chaves vencidas contam como miss.\n *\n * @returns o valor desserializado, ou `null` se ausente/expirado.\n */\n get<T = unknown>(key: string): T | null {\n const value = this.native.get(key);\n return value === null || value === undefined ? null : (value as T);\n }\n\n /** Remove uma chave. Retorna `true` se ela existia. */\n delete(key: string): boolean {\n return this.native.delete(key);\n }\n\n /** Indica se a chave existe e está válida (não expirada). */\n exists(key: string): boolean {\n return this.native.exists(key);\n }\n\n /** Esvazia o cache (não zera os contadores históricos de `stats`). */\n clear(): void {\n this.native.clear();\n }\n\n /** Número de chaves armazenadas no momento. */\n size(): number {\n return this.native.size();\n }\n\n /**\n * Varre e remove todas as entradas expiradas de uma só vez.\n *\n * @returns quantas entradas foram removidas.\n */\n cleanupExpired(): number {\n return this.native.cleanupExpired();\n }\n\n /** Retorna as estatísticas acumuladas + o tamanho atual. */\n stats(): CacheStats {\n return this.native.stats();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,eAAAA;AAAA;AAAA;AAiBA,aAAwB;AA8DjB,IAAMA,SAAN,MAAY;AAAA,EAIjB,YAAY,UAAwB,CAAC,GAAG;AAEtC,UAAM,aACJ,QAAQ,YAAY,UACpB,QAAQ,mBAAmB,UAC3B,QAAQ,2BAA2B;AACrC,SAAK,SAAS,aACV,IAAW,aAAM;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,gBAAgB,QAAQ;AAAA,MACxB,wBAAwB,QAAQ;AAAA,IAClC,CAAC,IACD,IAAW,aAAM;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,iBAAiC;AACnC,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,KAAa,OAAU,SAA+B;AAC3D,WAAO,KAAK,OAAO,IAAI,KAAK,OAA4B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAiB,KAAuB;AACtC,UAAM,QAAQ,KAAK,OAAO,IAAI,GAAG;AACjC,WAAO,UAAU,QAAQ,UAAU,SAAY,OAAQ;AAAA,EACzD;AAAA;AAAA,EAGA,OAAO,KAAsB;AAC3B,WAAO,KAAK,OAAO,OAAO,GAAG;AAAA,EAC/B;AAAA;AAAA,EAGA,OAAO,KAAsB;AAC3B,WAAO,KAAK,OAAO,OAAO,GAAG;AAAA,EAC/B;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA;AAAA,EAGA,OAAe;AACb,WAAO,KAAK,OAAO,KAAK;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAyB;AACvB,WAAO,KAAK,OAAO,eAAe;AAAA,EACpC;AAAA;AAAA,EAGA,QAAoB;AAClB,WAAO,KAAK,OAAO,MAAM;AAAA,EAC3B;AACF;","names":["Cache"]}
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
import * as native from "../binding.js";
|
|
3
3
|
var Cache2 = class {
|
|
4
4
|
constructor(options = {}) {
|
|
5
|
-
|
|
5
|
+
const hasOptions = options.maxSize !== void 0 || options.evictionPolicy !== void 0 || options.cleanupIntervalSeconds !== void 0;
|
|
6
|
+
this.native = hasOptions ? new native.Cache({
|
|
7
|
+
maxSize: options.maxSize,
|
|
8
|
+
evictionPolicy: options.evictionPolicy,
|
|
9
|
+
cleanupIntervalSeconds: options.cleanupIntervalSeconds
|
|
10
|
+
}) : new native.Cache();
|
|
11
|
+
}
|
|
12
|
+
/** A política de evicção ativa: `"reject"` ou `"lru"`. */
|
|
13
|
+
get evictionPolicy() {
|
|
14
|
+
return this.native.evictionPolicy;
|
|
6
15
|
}
|
|
7
16
|
/**
|
|
8
17
|
* Armazena (ou sobrescreve) um valor. O valor é serializado como JSON no core.
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — API pública (TypeScript).\n *\n * \"Ultra-fast in-memory cache powered by Rust.\"\n *\n * Esta camada é um wrapper fino e tipado sobre a classe `Cache` nativa gerada\n * pelo Rust/napi-rs. Por que envolver em vez de re-exportar direto?\n * - permite **genéricos** ergonômicos: `cache.get<User>(\"user:1\")`;\n * - normaliza `undefined`/`null` para sempre devolver `null` num miss;\n * - dá um único lugar para JSDoc e para evoluir a API sem quebrar o core Rust.\n *\n * O custo é uma chamada de função extra por operação — desprezível frente ao\n * trabalho real (serialização + acesso ao DashMap) que acontece no Rust.\n */\n\n// Namespace import: funciona igual em CommonJS e ESM ao consumir o addon nativo\n// (que é um módulo CJS gerado pelo napi-rs).\nimport * as native from \"../binding.js\";\n\n/** Opções do construtor do cache. */\nexport interface CacheOptions {\n /**\n * Limite máximo de chaves.
|
|
1
|
+
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — API pública (TypeScript).\n *\n * \"Ultra-fast in-memory cache powered by Rust.\"\n *\n * Esta camada é um wrapper fino e tipado sobre a classe `Cache` nativa gerada\n * pelo Rust/napi-rs. Por que envolver em vez de re-exportar direto?\n * - permite **genéricos** ergonômicos: `cache.get<User>(\"user:1\")`;\n * - normaliza `undefined`/`null` para sempre devolver `null` num miss;\n * - dá um único lugar para JSDoc e para evoluir a API sem quebrar o core Rust.\n *\n * O custo é uma chamada de função extra por operação — desprezível frente ao\n * trabalho real (serialização + acesso ao DashMap) que acontece no Rust.\n */\n\n// Namespace import: funciona igual em CommonJS e ESM ao consumir o addon nativo\n// (que é um módulo CJS gerado pelo napi-rs).\nimport * as native from \"../binding.js\";\n\n/** Estratégia de evicção quando `maxSize` é atingido. */\nexport type EvictionPolicy = \"reject\" | \"lru\";\n\n/** Opções do construtor do cache. */\nexport interface CacheOptions {\n /**\n * Limite máximo de chaves. O que acontece ao atingir depende de\n * `evictionPolicy`. Sem valor => cache ilimitado.\n */\n maxSize?: number;\n /**\n * Política ao atingir `maxSize` numa chave **nova**:\n * - `\"reject\"` (padrão): `set` retorna `false` (sobrescrever continua ok);\n * - `\"lru\"`: remove a entrada menos recentemente usada e prossegue.\n */\n evictionPolicy?: EvictionPolicy;\n /**\n * Se definido (> 0), liga uma thread que varre entradas expiradas a cada\n * N segundos (expiração em background, além da preguiçosa por acesso).\n */\n cleanupIntervalSeconds?: number;\n}\n\n/** Opções por operação de escrita. */\nexport interface SetOptions {\n /** Tempo de vida em segundos. Ausente => a entrada não expira por tempo. */\n ttlSeconds?: number;\n}\n\n/** Estatísticas acumuladas do cache (mais o tamanho atual). */\nexport interface CacheStats {\n /** Leituras que encontraram uma entrada válida. */\n hits: number;\n /** Leituras sem chave válida (ausente ou expirada). */\n misses: number;\n /** Total de escritas (`set`). */\n sets: number;\n /** Total de remoções explícitas (`delete`). */\n deletes: number;\n /** Total de entradas removidas por expiração. */\n expired: number;\n /** Total de entradas removidas por evicção (política LRU ao atingir `maxSize`). */\n evicted: number;\n /** Número de chaves armazenadas agora. */\n size: number;\n}\n\n/**\n * Cache em memória ultrarrápido com núcleo em Rust (DashMap + contadores\n * atômicos). Thread-safe e com suporte a TTL por entrada.\n *\n * @example\n * ```ts\n * import { Cache } from \"rust-node-cache\";\n *\n * const cache = new Cache();\n * cache.set(\"user:1\", { id: 1, name: \"Roberto\" });\n * cache.get<{ id: number; name: string }>(\"user:1\"); // { id: 1, name: \"Roberto\" }\n * ```\n */\nexport class Cache {\n /** Instância da classe nativa (Rust). */\n private readonly native: native.Cache;\n\n constructor(options: CacheOptions = {}) {\n // Só repassamos um objeto de opções ao Rust quando há algo relevante.\n const hasOptions =\n options.maxSize !== undefined ||\n options.evictionPolicy !== undefined ||\n options.cleanupIntervalSeconds !== undefined;\n this.native = hasOptions\n ? new native.Cache({\n maxSize: options.maxSize,\n evictionPolicy: options.evictionPolicy,\n cleanupIntervalSeconds: options.cleanupIntervalSeconds,\n })\n : new native.Cache();\n }\n\n /** A política de evicção ativa: `\"reject\"` ou `\"lru\"`. */\n get evictionPolicy(): EvictionPolicy {\n return this.native.evictionPolicy as EvictionPolicy;\n }\n\n /**\n * Armazena (ou sobrescreve) um valor. O valor é serializado como JSON no core.\n *\n * @returns `true` em sucesso; `false` se `maxSize` foi atingido e a chave é nova.\n */\n set<T>(key: string, value: T, options?: SetOptions): boolean {\n return this.native.set(key, value as unknown as object, options);\n }\n\n /**\n * Lê um valor. Aplica expiração preguiçosa: chaves vencidas contam como miss.\n *\n * @returns o valor desserializado, ou `null` se ausente/expirado.\n */\n get<T = unknown>(key: string): T | null {\n const value = this.native.get(key);\n return value === null || value === undefined ? null : (value as T);\n }\n\n /** Remove uma chave. Retorna `true` se ela existia. */\n delete(key: string): boolean {\n return this.native.delete(key);\n }\n\n /** Indica se a chave existe e está válida (não expirada). */\n exists(key: string): boolean {\n return this.native.exists(key);\n }\n\n /** Esvazia o cache (não zera os contadores históricos de `stats`). */\n clear(): void {\n this.native.clear();\n }\n\n /** Número de chaves armazenadas no momento. */\n size(): number {\n return this.native.size();\n }\n\n /**\n * Varre e remove todas as entradas expiradas de uma só vez.\n *\n * @returns quantas entradas foram removidas.\n */\n cleanupExpired(): number {\n return this.native.cleanupExpired();\n }\n\n /** Retorna as estatísticas acumuladas + o tamanho atual. */\n stats(): CacheStats {\n return this.native.stats();\n }\n}\n"],"mappings":";AAiBA,YAAY,YAAY;AA8DjB,IAAMA,SAAN,MAAY;AAAA,EAIjB,YAAY,UAAwB,CAAC,GAAG;AAEtC,UAAM,aACJ,QAAQ,YAAY,UACpB,QAAQ,mBAAmB,UAC3B,QAAQ,2BAA2B;AACrC,SAAK,SAAS,aACV,IAAW,aAAM;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,gBAAgB,QAAQ;AAAA,MACxB,wBAAwB,QAAQ;AAAA,IAClC,CAAC,IACD,IAAW,aAAM;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,iBAAiC;AACnC,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,KAAa,OAAU,SAA+B;AAC3D,WAAO,KAAK,OAAO,IAAI,KAAK,OAA4B,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAiB,KAAuB;AACtC,UAAM,QAAQ,KAAK,OAAO,IAAI,GAAG;AACjC,WAAO,UAAU,QAAQ,UAAU,SAAY,OAAQ;AAAA,EACzD;AAAA;AAAA,EAGA,OAAO,KAAsB;AAC3B,WAAO,KAAK,OAAO,OAAO,GAAG;AAAA,EAC/B;AAAA;AAAA,EAGA,OAAO,KAAsB;AAC3B,WAAO,KAAK,OAAO,OAAO,GAAG;AAAA,EAC/B;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA;AAAA,EAGA,OAAe;AACb,WAAO,KAAK,OAAO,KAAK;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAyB;AACvB,WAAO,KAAK,OAAO,eAAe;AAAA,EACpC;AAAA;AAAA,EAGA,QAAoB;AAClB,WAAO,KAAK,OAAO,MAAM;AAAA,EAC3B;AACF;","names":["Cache"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rust-node-cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Ultra-fast in-memory cache for Node.js powered by Rust.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cache",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"type": "git",
|
|
24
24
|
"url": "https://github.com/robertolima-dev/rust-node-cache.git"
|
|
25
25
|
},
|
|
26
|
-
"homepage": "https://
|
|
26
|
+
"homepage": "https://rust-node-cache.vercel.app",
|
|
27
27
|
"main": "dist/index.js",
|
|
28
28
|
"module": "dist/index.mjs",
|
|
29
29
|
"types": "dist/index.d.ts",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|