rust-node-cache 0.2.0 → 0.2.1
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 +19 -0
- package/binding.d.ts +25 -25
- package/dist/express.d.mts +10 -10
- package/dist/express.d.ts +10 -10
- package/dist/express.js.map +1 -1
- package/dist/express.mjs.map +1 -1
- package/dist/fastify.d.mts +9 -9
- package/dist/fastify.d.ts +9 -9
- package/dist/fastify.js.map +1 -1
- package/dist/fastify.mjs.map +1 -1
- package/dist/index.d.mts +42 -42
- package/dist/index.d.ts +42 -42
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12 -12
- package/dist/index.mjs.map +1 -1
- package/dist/nestjs.d.mts +11 -11
- package/dist/nestjs.d.ts +11 -11
- package/dist/nestjs.js.map +1 -1
- package/dist/nestjs.mjs.map +1 -1
- package/package.json +4 -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-arm64-musl.node +0 -0
- package/rust-node-cache.linux-x64-gnu.node +0 -0
- package/rust-node-cache.linux-x64-musl.node +0 -0
- package/rust-node-cache.win32-x64-msvc.node +0 -0
package/README.md
CHANGED
|
@@ -44,6 +44,25 @@ Works with both **ESM** and **CommonJS**, and requires **Node.js 18+**.
|
|
|
44
44
|
|
|
45
45
|
---
|
|
46
46
|
|
|
47
|
+
## Supported platforms
|
|
48
|
+
|
|
49
|
+
Prebuilt binaries are published for:
|
|
50
|
+
|
|
51
|
+
| OS | Architecture | Triple |
|
|
52
|
+
| ------- | --------------------- | ---------------------------- |
|
|
53
|
+
| macOS | arm64 | `aarch64-apple-darwin` |
|
|
54
|
+
| macOS | x64 | `x86_64-apple-darwin` |
|
|
55
|
+
| Linux | x64 (glibc) | `x86_64-unknown-linux-gnu` |
|
|
56
|
+
| Linux | arm64 (glibc) | `aarch64-unknown-linux-gnu` |
|
|
57
|
+
| Linux | x64 (musl, Alpine) | `x86_64-unknown-linux-musl` |
|
|
58
|
+
| Linux | arm64 (musl, Alpine) | `aarch64-unknown-linux-musl` |
|
|
59
|
+
| Windows | x64 | `x86_64-pc-windows-msvc` |
|
|
60
|
+
|
|
61
|
+
Every release is installed from the packed tarball and exercised on each of these platforms
|
|
62
|
+
in CI before it is published.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
47
66
|
## Quick Start
|
|
48
67
|
|
|
49
68
|
```ts
|
package/binding.d.ts
CHANGED
|
@@ -4,32 +4,32 @@
|
|
|
4
4
|
/* auto-generated by NAPI-RS */
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Constructor options:
|
|
8
8
|
* `new Cache({ maxSize, evictionPolicy, cleanupIntervalSeconds })`.
|
|
9
9
|
*/
|
|
10
10
|
export interface CacheOptions {
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* `evictionPolicy`.
|
|
12
|
+
* Optional limit on the number of keys. What happens when it is reached
|
|
13
|
+
* depends on `evictionPolicy`.
|
|
14
14
|
*/
|
|
15
15
|
maxSize?: number
|
|
16
16
|
/**
|
|
17
|
-
* `"reject"` (
|
|
18
|
-
* `"lru"` —
|
|
17
|
+
* `"reject"` (default) — `set` of a new key returns `false` when full;
|
|
18
|
+
* `"lru"` — removes the least recently used entry and goes on.
|
|
19
19
|
*/
|
|
20
20
|
evictionPolicy?: string
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* When set (> 0), starts a thread that sweeps expired entries every N
|
|
23
|
+
* seconds (background expiration, on top of the lazy one).
|
|
24
24
|
*/
|
|
25
25
|
cleanupIntervalSeconds?: number
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
27
|
+
/** Per-write options: `cache.set(key, value, { ttlSeconds })`. */
|
|
28
28
|
export interface SetOptions {
|
|
29
|
-
/**
|
|
29
|
+
/** Time to live in seconds. Absent => the entry does not expire by time. */
|
|
30
30
|
ttlSeconds?: number
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
32
|
+
/** Object returned by `cache.stats()`. `i64` fields become `number` in JS. */
|
|
33
33
|
export interface CacheStatsObject {
|
|
34
34
|
hits: number
|
|
35
35
|
misses: number
|
|
@@ -40,34 +40,34 @@ export interface CacheStatsObject {
|
|
|
40
40
|
size: number
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* In-memory cache exposed to Node as the `Cache` class.
|
|
44
44
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
45
|
+
* It delegates everything to `RustCache` (which holds the `DashMap` and the
|
|
46
|
+
* atomic counters). Every method takes `&self`: the state is concurrent
|
|
47
|
+
* inside, so it is safe to use from several threads (such as the sweeper).
|
|
48
48
|
*/
|
|
49
49
|
export declare class Cache {
|
|
50
|
-
/** `new Cache()`
|
|
50
|
+
/** `new Cache()` or `new Cache({ maxSize, evictionPolicy, cleanupIntervalSeconds })`. */
|
|
51
51
|
constructor(options?: CacheOptions | undefined | null)
|
|
52
|
-
/**
|
|
52
|
+
/** The active eviction policy: `"reject"` or `"lru"`. */
|
|
53
53
|
get evictionPolicy(): string
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
55
|
+
* Inserts or updates a key. Returns `true` on success, `false` if the cache
|
|
56
|
+
* is full (`maxSize`) and the key is new.
|
|
57
57
|
*/
|
|
58
58
|
set(key: string, value: any, options?: SetOptions | undefined | null): boolean
|
|
59
|
-
/**
|
|
59
|
+
/** Reads a key. Returns the value, or `null` if missing or expired. */
|
|
60
60
|
get(key: string): any | null
|
|
61
|
-
/**
|
|
61
|
+
/** Removes a key. Returns `true` if it existed, `false` otherwise. */
|
|
62
62
|
delete(key: string): boolean
|
|
63
|
-
/**
|
|
63
|
+
/** Whether the key exists and is still valid (not expired). */
|
|
64
64
|
exists(key: string): boolean
|
|
65
|
-
/**
|
|
65
|
+
/** Removes every entry from the cache. */
|
|
66
66
|
clear(): void
|
|
67
|
-
/**
|
|
67
|
+
/** Number of keys currently stored. */
|
|
68
68
|
size(): number
|
|
69
|
-
/**
|
|
69
|
+
/** Sweeps and removes every expired entry. Returns how many it removed. */
|
|
70
70
|
cleanupExpired(): number
|
|
71
|
-
/**
|
|
71
|
+
/** Accumulated statistics + the current size. */
|
|
72
72
|
stats(): CacheStatsObject
|
|
73
73
|
}
|
package/dist/express.d.mts
CHANGED
|
@@ -2,32 +2,32 @@ import { Request, Response, NextFunction } from 'express';
|
|
|
2
2
|
import { Cache } from './index.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Express integration: caching of JSON responses.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Usage:
|
|
8
8
|
* import { Cache } from "rust-node-cache";
|
|
9
9
|
* import { cacheMiddleware } from "rust-node-cache/express";
|
|
10
10
|
*
|
|
11
11
|
* const cache = new Cache();
|
|
12
12
|
* app.get("/users/:id", cacheMiddleware({ cache, ttlSeconds: 60 }), handler);
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* MISS
|
|
14
|
+
* The middleware intercepts `res.json`: on a HIT it responds straight from the
|
|
15
|
+
* cache; on a MISS it lets the handler run and stores the response body (2xx only).
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
interface CacheMiddlewareOptions {
|
|
19
|
-
/**
|
|
19
|
+
/** Cache instance to use. */
|
|
20
20
|
cache: Cache;
|
|
21
|
-
/** TTL
|
|
21
|
+
/** TTL applied to stored responses (in seconds). */
|
|
22
22
|
ttlSeconds?: number;
|
|
23
|
-
/**
|
|
23
|
+
/** HTTP methods eligible for caching. Default: `["GET"]`. */
|
|
24
24
|
methods?: string[];
|
|
25
|
-
/**
|
|
25
|
+
/** Builds the cache key from the request. Default: `METHOD:url`. */
|
|
26
26
|
keyGenerator?: (req: Request) => string;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
* `X-Cache: HIT|MISS`
|
|
29
|
+
* Creates an Express middleware that caches JSON responses. Adds an
|
|
30
|
+
* `X-Cache: HIT|MISS` header for observability.
|
|
31
31
|
*/
|
|
32
32
|
declare function cacheMiddleware(options: CacheMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
33
33
|
|
package/dist/express.d.ts
CHANGED
|
@@ -2,32 +2,32 @@ import { Request, Response, NextFunction } from 'express';
|
|
|
2
2
|
import { Cache } from './index.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Express integration: caching of JSON responses.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Usage:
|
|
8
8
|
* import { Cache } from "rust-node-cache";
|
|
9
9
|
* import { cacheMiddleware } from "rust-node-cache/express";
|
|
10
10
|
*
|
|
11
11
|
* const cache = new Cache();
|
|
12
12
|
* app.get("/users/:id", cacheMiddleware({ cache, ttlSeconds: 60 }), handler);
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* MISS
|
|
14
|
+
* The middleware intercepts `res.json`: on a HIT it responds straight from the
|
|
15
|
+
* cache; on a MISS it lets the handler run and stores the response body (2xx only).
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
interface CacheMiddlewareOptions {
|
|
19
|
-
/**
|
|
19
|
+
/** Cache instance to use. */
|
|
20
20
|
cache: Cache;
|
|
21
|
-
/** TTL
|
|
21
|
+
/** TTL applied to stored responses (in seconds). */
|
|
22
22
|
ttlSeconds?: number;
|
|
23
|
-
/**
|
|
23
|
+
/** HTTP methods eligible for caching. Default: `["GET"]`. */
|
|
24
24
|
methods?: string[];
|
|
25
|
-
/**
|
|
25
|
+
/** Builds the cache key from the request. Default: `METHOD:url`. */
|
|
26
26
|
keyGenerator?: (req: Request) => string;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
* `X-Cache: HIT|MISS`
|
|
29
|
+
* Creates an Express middleware that caches JSON responses. Adds an
|
|
30
|
+
* `X-Cache: HIT|MISS` header for observability.
|
|
31
31
|
*/
|
|
32
32
|
declare function cacheMiddleware(options: CacheMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
33
33
|
|
package/dist/express.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/express.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../js/express.ts"],"sourcesContent":["/**\n * Express integration: caching of JSON responses.\n *\n * Usage:\n * import { Cache } from \"rust-node-cache\";\n * import { cacheMiddleware } from \"rust-node-cache/express\";\n *\n * const cache = new Cache();\n * app.get(\"/users/:id\", cacheMiddleware({ cache, ttlSeconds: 60 }), handler);\n *\n * The middleware intercepts `res.json`: on a HIT it responds straight from the\n * cache; on a MISS it lets the handler run and stores the response body (2xx only).\n */\n\nimport type { Request, Response, NextFunction } from \"express\";\nimport type { Cache } from \"./index\";\n\nexport interface CacheMiddlewareOptions {\n /** Cache instance to use. */\n cache: Cache;\n /** TTL applied to stored responses (in seconds). */\n ttlSeconds?: number;\n /** HTTP methods eligible for caching. Default: `[\"GET\"]`. */\n methods?: string[];\n /** Builds the cache key from the request. Default: `METHOD:url`. */\n keyGenerator?: (req: Request) => string;\n}\n\n/**\n * Creates an Express middleware that caches JSON responses. Adds an\n * `X-Cache: HIT|MISS` header for observability.\n */\nexport function cacheMiddleware(options: CacheMiddlewareOptions) {\n const { cache } = options;\n const ttlSeconds = options.ttlSeconds;\n const methods = options.methods ?? [\"GET\"];\n const keyGenerator =\n options.keyGenerator ?? ((req: Request) => `${req.method}:${req.originalUrl}`);\n\n return function rustNodeCache(\n req: Request,\n res: Response,\n next: NextFunction,\n ): void {\n if (!methods.includes(req.method)) {\n next();\n return;\n }\n\n const key = keyGenerator(req);\n const cached = cache.get(key);\n if (cached !== null) {\n res.setHeader(\"X-Cache\", \"HIT\");\n res.json(cached);\n return;\n }\n\n res.setHeader(\"X-Cache\", \"MISS\");\n const originalJson = res.json.bind(res);\n res.json = (body: unknown): Response => {\n // Only successful responses (2xx) are stored.\n if (res.statusCode >= 200 && res.statusCode < 300) {\n cache.set(key, body, ttlSeconds ? { ttlSeconds } : undefined);\n }\n return originalJson(body);\n };\n\n next();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCO,SAAS,gBAAgB,SAAiC;AAC/D,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,QAAQ,WAAW,CAAC,KAAK;AACzC,QAAM,eACJ,QAAQ,iBAAiB,CAAC,QAAiB,GAAG,IAAI,MAAM,IAAI,IAAI,WAAW;AAE7E,SAAO,SAAS,cACd,KACA,KACA,MACM;AACN,QAAI,CAAC,QAAQ,SAAS,IAAI,MAAM,GAAG;AACjC,WAAK;AACL;AAAA,IACF;AAEA,UAAM,MAAM,aAAa,GAAG;AAC5B,UAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,QAAI,WAAW,MAAM;AACnB,UAAI,UAAU,WAAW,KAAK;AAC9B,UAAI,KAAK,MAAM;AACf;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,MAAM;AAC/B,UAAM,eAAe,IAAI,KAAK,KAAK,GAAG;AACtC,QAAI,OAAO,CAAC,SAA4B;AAEtC,UAAI,IAAI,cAAc,OAAO,IAAI,aAAa,KAAK;AACjD,cAAM,IAAI,KAAK,MAAM,aAAa,EAAE,WAAW,IAAI,MAAS;AAAA,MAC9D;AACA,aAAO,aAAa,IAAI;AAAA,IAC1B;AAEA,SAAK;AAAA,EACP;AACF;","names":[]}
|
package/dist/express.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/express.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../js/express.ts"],"sourcesContent":["/**\n * Express integration: caching of JSON responses.\n *\n * Usage:\n * import { Cache } from \"rust-node-cache\";\n * import { cacheMiddleware } from \"rust-node-cache/express\";\n *\n * const cache = new Cache();\n * app.get(\"/users/:id\", cacheMiddleware({ cache, ttlSeconds: 60 }), handler);\n *\n * The middleware intercepts `res.json`: on a HIT it responds straight from the\n * cache; on a MISS it lets the handler run and stores the response body (2xx only).\n */\n\nimport type { Request, Response, NextFunction } from \"express\";\nimport type { Cache } from \"./index\";\n\nexport interface CacheMiddlewareOptions {\n /** Cache instance to use. */\n cache: Cache;\n /** TTL applied to stored responses (in seconds). */\n ttlSeconds?: number;\n /** HTTP methods eligible for caching. Default: `[\"GET\"]`. */\n methods?: string[];\n /** Builds the cache key from the request. Default: `METHOD:url`. */\n keyGenerator?: (req: Request) => string;\n}\n\n/**\n * Creates an Express middleware that caches JSON responses. Adds an\n * `X-Cache: HIT|MISS` header for observability.\n */\nexport function cacheMiddleware(options: CacheMiddlewareOptions) {\n const { cache } = options;\n const ttlSeconds = options.ttlSeconds;\n const methods = options.methods ?? [\"GET\"];\n const keyGenerator =\n options.keyGenerator ?? ((req: Request) => `${req.method}:${req.originalUrl}`);\n\n return function rustNodeCache(\n req: Request,\n res: Response,\n next: NextFunction,\n ): void {\n if (!methods.includes(req.method)) {\n next();\n return;\n }\n\n const key = keyGenerator(req);\n const cached = cache.get(key);\n if (cached !== null) {\n res.setHeader(\"X-Cache\", \"HIT\");\n res.json(cached);\n return;\n }\n\n res.setHeader(\"X-Cache\", \"MISS\");\n const originalJson = res.json.bind(res);\n res.json = (body: unknown): Response => {\n // Only successful responses (2xx) are stored.\n if (res.statusCode >= 200 && res.statusCode < 300) {\n cache.set(key, body, ttlSeconds ? { ttlSeconds } : undefined);\n }\n return originalJson(body);\n };\n\n next();\n };\n}\n"],"mappings":";AAgCO,SAAS,gBAAgB,SAAiC;AAC/D,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,QAAQ,WAAW,CAAC,KAAK;AACzC,QAAM,eACJ,QAAQ,iBAAiB,CAAC,QAAiB,GAAG,IAAI,MAAM,IAAI,IAAI,WAAW;AAE7E,SAAO,SAAS,cACd,KACA,KACA,MACM;AACN,QAAI,CAAC,QAAQ,SAAS,IAAI,MAAM,GAAG;AACjC,WAAK;AACL;AAAA,IACF;AAEA,UAAM,MAAM,aAAa,GAAG;AAC5B,UAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,QAAI,WAAW,MAAM;AACnB,UAAI,UAAU,WAAW,KAAK;AAC9B,UAAI,KAAK,MAAM;AACf;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,MAAM;AAC/B,UAAM,eAAe,IAAI,KAAK,KAAK,GAAG;AACtC,QAAI,OAAO,CAAC,SAA4B;AAEtC,UAAI,IAAI,cAAc,OAAO,IAAI,aAAa,KAAK;AACjD,cAAM,IAAI,KAAK,MAAM,aAAa,EAAE,WAAW,IAAI,MAAS;AAAA,MAC9D;AACA,aAAO,aAAa,IAAI;AAAA,IAC1B;AAEA,SAAK;AAAA,EACP;AACF;","names":[]}
|
package/dist/fastify.d.mts
CHANGED
|
@@ -2,31 +2,31 @@ import { FastifyRequest, FastifyInstance } from 'fastify';
|
|
|
2
2
|
import { Cache } from './index.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Fastify integration: caching of JSON responses through a plugin.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Usage:
|
|
8
8
|
* import { Cache } from "rust-node-cache";
|
|
9
9
|
* import { cachePlugin } from "rust-node-cache/fastify";
|
|
10
10
|
*
|
|
11
11
|
* const cache = new Cache();
|
|
12
12
|
* fastify.register(cachePlugin, { cache, ttlSeconds: 60 });
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* (
|
|
14
|
+
* Flow: the `onRequest` hook checks the cache and, on a HIT, responds right away
|
|
15
|
+
* (short-circuit). On a MISS, the `onSend` hook stores the serialized payload.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
interface CachePluginOptions {
|
|
19
|
-
/**
|
|
19
|
+
/** Cache instance to use. */
|
|
20
20
|
cache: Cache;
|
|
21
|
-
/** TTL
|
|
21
|
+
/** TTL applied to stored responses (in seconds). */
|
|
22
22
|
ttlSeconds?: number;
|
|
23
|
-
/**
|
|
23
|
+
/** HTTP methods eligible for caching. Default: `["GET"]`. */
|
|
24
24
|
methods?: string[];
|
|
25
|
-
/**
|
|
25
|
+
/** Builds the cache key from the request. Default: `METHOD:url`. */
|
|
26
26
|
keyGenerator?: (req: FastifyRequest) => string;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Fastify plugin that caches JSON responses. Use it with `fastify.register`.
|
|
30
30
|
*/
|
|
31
31
|
declare function cachePlugin(fastify: FastifyInstance, options: CachePluginOptions): Promise<void>;
|
|
32
32
|
|
package/dist/fastify.d.ts
CHANGED
|
@@ -2,31 +2,31 @@ import { FastifyRequest, FastifyInstance } from 'fastify';
|
|
|
2
2
|
import { Cache } from './index.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Fastify integration: caching of JSON responses through a plugin.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Usage:
|
|
8
8
|
* import { Cache } from "rust-node-cache";
|
|
9
9
|
* import { cachePlugin } from "rust-node-cache/fastify";
|
|
10
10
|
*
|
|
11
11
|
* const cache = new Cache();
|
|
12
12
|
* fastify.register(cachePlugin, { cache, ttlSeconds: 60 });
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* (
|
|
14
|
+
* Flow: the `onRequest` hook checks the cache and, on a HIT, responds right away
|
|
15
|
+
* (short-circuit). On a MISS, the `onSend` hook stores the serialized payload.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
interface CachePluginOptions {
|
|
19
|
-
/**
|
|
19
|
+
/** Cache instance to use. */
|
|
20
20
|
cache: Cache;
|
|
21
|
-
/** TTL
|
|
21
|
+
/** TTL applied to stored responses (in seconds). */
|
|
22
22
|
ttlSeconds?: number;
|
|
23
|
-
/**
|
|
23
|
+
/** HTTP methods eligible for caching. Default: `["GET"]`. */
|
|
24
24
|
methods?: string[];
|
|
25
|
-
/**
|
|
25
|
+
/** Builds the cache key from the request. Default: `METHOD:url`. */
|
|
26
26
|
keyGenerator?: (req: FastifyRequest) => string;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Fastify plugin that caches JSON responses. Use it with `fastify.register`.
|
|
30
30
|
*/
|
|
31
31
|
declare function cachePlugin(fastify: FastifyInstance, options: CachePluginOptions): Promise<void>;
|
|
32
32
|
|
package/dist/fastify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/fastify.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../js/fastify.ts"],"sourcesContent":["/**\n * Fastify integration: caching of JSON responses through a plugin.\n *\n * Usage:\n * import { Cache } from \"rust-node-cache\";\n * import { cachePlugin } from \"rust-node-cache/fastify\";\n *\n * const cache = new Cache();\n * fastify.register(cachePlugin, { cache, ttlSeconds: 60 });\n *\n * Flow: the `onRequest` hook checks the cache and, on a HIT, responds right away\n * (short-circuit). On a MISS, the `onSend` hook stores the serialized payload.\n */\n\nimport type {\n FastifyInstance,\n FastifyReply,\n FastifyRequest,\n} from \"fastify\";\nimport type { Cache } from \"./index\";\n\nexport interface CachePluginOptions {\n /** Cache instance to use. */\n cache: Cache;\n /** TTL applied to stored responses (in seconds). */\n ttlSeconds?: number;\n /** HTTP methods eligible for caching. Default: `[\"GET\"]`. */\n methods?: string[];\n /** Builds the cache key from the request. Default: `METHOD:url`. */\n keyGenerator?: (req: FastifyRequest) => string;\n}\n\n// The computed key is kept on the request itself between hooks.\nconst CACHE_KEY = Symbol(\"rustNodeCacheKey\");\n\n/**\n * Fastify plugin that caches JSON responses. Use it with `fastify.register`.\n */\nexport async function cachePlugin(\n fastify: FastifyInstance,\n options: CachePluginOptions,\n): Promise<void> {\n const { cache } = options;\n const ttlSeconds = options.ttlSeconds;\n const methods = options.methods ?? [\"GET\"];\n const keyGenerator =\n options.keyGenerator ?? ((req: FastifyRequest) => `${req.method}:${req.url}`);\n\n fastify.addHook(\n \"onRequest\",\n (request: FastifyRequest, reply: FastifyReply, done: () => void) => {\n if (!methods.includes(request.method)) {\n done();\n return;\n }\n\n const key = keyGenerator(request);\n const cached = cache.get(key);\n if (cached !== null) {\n reply.header(\"X-Cache\", \"HIT\");\n reply.send(cached);\n return; // done() is not called: the response was already sent.\n }\n\n reply.header(\"X-Cache\", \"MISS\");\n (request as unknown as Record<symbol, string>)[CACHE_KEY] = key;\n done();\n },\n );\n\n fastify.addHook(\n \"onSend\",\n (\n request: FastifyRequest,\n reply: FastifyReply,\n payload: unknown,\n done: (err: Error | null, value?: unknown) => void,\n ) => {\n const key = (request as unknown as Record<symbol, string | undefined>)[\n CACHE_KEY\n ];\n if (\n key &&\n typeof payload === \"string\" &&\n reply.statusCode >= 200 &&\n reply.statusCode < 300\n ) {\n try {\n cache.set(\n key,\n JSON.parse(payload),\n ttlSeconds ? { ttlSeconds } : undefined,\n );\n } catch {\n // non-JSON payload: simply not cached.\n }\n }\n done(null, payload);\n },\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCA,IAAM,YAAY,uBAAO,kBAAkB;AAK3C,eAAsB,YACpB,SACA,SACe;AACf,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,QAAQ,WAAW,CAAC,KAAK;AACzC,QAAM,eACJ,QAAQ,iBAAiB,CAAC,QAAwB,GAAG,IAAI,MAAM,IAAI,IAAI,GAAG;AAE5E,UAAQ;AAAA,IACN;AAAA,IACA,CAAC,SAAyB,OAAqB,SAAqB;AAClE,UAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,GAAG;AACrC,aAAK;AACL;AAAA,MACF;AAEA,YAAM,MAAM,aAAa,OAAO;AAChC,YAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,UAAI,WAAW,MAAM;AACnB,cAAM,OAAO,WAAW,KAAK;AAC7B,cAAM,KAAK,MAAM;AACjB;AAAA,MACF;AAEA,YAAM,OAAO,WAAW,MAAM;AAC9B,MAAC,QAA8C,SAAS,IAAI;AAC5D,WAAK;AAAA,IACP;AAAA,EACF;AAEA,UAAQ;AAAA,IACN;AAAA,IACA,CACE,SACA,OACA,SACA,SACG;AACH,YAAM,MAAO,QACX,SACF;AACA,UACE,OACA,OAAO,YAAY,YACnB,MAAM,cAAc,OACpB,MAAM,aAAa,KACnB;AACA,YAAI;AACF,gBAAM;AAAA,YACJ;AAAA,YACA,KAAK,MAAM,OAAO;AAAA,YAClB,aAAa,EAAE,WAAW,IAAI;AAAA,UAChC;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AACA,WAAK,MAAM,OAAO;AAAA,IACpB;AAAA,EACF;AACF;","names":[]}
|
package/dist/fastify.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/fastify.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../js/fastify.ts"],"sourcesContent":["/**\n * Fastify integration: caching of JSON responses through a plugin.\n *\n * Usage:\n * import { Cache } from \"rust-node-cache\";\n * import { cachePlugin } from \"rust-node-cache/fastify\";\n *\n * const cache = new Cache();\n * fastify.register(cachePlugin, { cache, ttlSeconds: 60 });\n *\n * Flow: the `onRequest` hook checks the cache and, on a HIT, responds right away\n * (short-circuit). On a MISS, the `onSend` hook stores the serialized payload.\n */\n\nimport type {\n FastifyInstance,\n FastifyReply,\n FastifyRequest,\n} from \"fastify\";\nimport type { Cache } from \"./index\";\n\nexport interface CachePluginOptions {\n /** Cache instance to use. */\n cache: Cache;\n /** TTL applied to stored responses (in seconds). */\n ttlSeconds?: number;\n /** HTTP methods eligible for caching. Default: `[\"GET\"]`. */\n methods?: string[];\n /** Builds the cache key from the request. Default: `METHOD:url`. */\n keyGenerator?: (req: FastifyRequest) => string;\n}\n\n// The computed key is kept on the request itself between hooks.\nconst CACHE_KEY = Symbol(\"rustNodeCacheKey\");\n\n/**\n * Fastify plugin that caches JSON responses. Use it with `fastify.register`.\n */\nexport async function cachePlugin(\n fastify: FastifyInstance,\n options: CachePluginOptions,\n): Promise<void> {\n const { cache } = options;\n const ttlSeconds = options.ttlSeconds;\n const methods = options.methods ?? [\"GET\"];\n const keyGenerator =\n options.keyGenerator ?? ((req: FastifyRequest) => `${req.method}:${req.url}`);\n\n fastify.addHook(\n \"onRequest\",\n (request: FastifyRequest, reply: FastifyReply, done: () => void) => {\n if (!methods.includes(request.method)) {\n done();\n return;\n }\n\n const key = keyGenerator(request);\n const cached = cache.get(key);\n if (cached !== null) {\n reply.header(\"X-Cache\", \"HIT\");\n reply.send(cached);\n return; // done() is not called: the response was already sent.\n }\n\n reply.header(\"X-Cache\", \"MISS\");\n (request as unknown as Record<symbol, string>)[CACHE_KEY] = key;\n done();\n },\n );\n\n fastify.addHook(\n \"onSend\",\n (\n request: FastifyRequest,\n reply: FastifyReply,\n payload: unknown,\n done: (err: Error | null, value?: unknown) => void,\n ) => {\n const key = (request as unknown as Record<symbol, string | undefined>)[\n CACHE_KEY\n ];\n if (\n key &&\n typeof payload === \"string\" &&\n reply.statusCode >= 200 &&\n reply.statusCode < 300\n ) {\n try {\n cache.set(\n key,\n JSON.parse(payload),\n ttlSeconds ? { ttlSeconds } : undefined,\n );\n } catch {\n // non-JSON payload: simply not cached.\n }\n }\n done(null, payload);\n },\n );\n}\n"],"mappings":";AAiCA,IAAM,YAAY,uBAAO,kBAAkB;AAK3C,eAAsB,YACpB,SACA,SACe;AACf,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,QAAQ,WAAW,CAAC,KAAK;AACzC,QAAM,eACJ,QAAQ,iBAAiB,CAAC,QAAwB,GAAG,IAAI,MAAM,IAAI,IAAI,GAAG;AAE5E,UAAQ;AAAA,IACN;AAAA,IACA,CAAC,SAAyB,OAAqB,SAAqB;AAClE,UAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,GAAG;AACrC,aAAK;AACL;AAAA,MACF;AAEA,YAAM,MAAM,aAAa,OAAO;AAChC,YAAM,SAAS,MAAM,IAAI,GAAG;AAC5B,UAAI,WAAW,MAAM;AACnB,cAAM,OAAO,WAAW,KAAK;AAC7B,cAAM,KAAK,MAAM;AACjB;AAAA,MACF;AAEA,YAAM,OAAO,WAAW,MAAM;AAC9B,MAAC,QAA8C,SAAS,IAAI;AAC5D,WAAK;AAAA,IACP;AAAA,EACF;AAEA,UAAQ;AAAA,IACN;AAAA,IACA,CACE,SACA,OACA,SACA,SACG;AACH,YAAM,MAAO,QACX,SACF;AACA,UACE,OACA,OAAO,YAAY,YACnB,MAAM,cAAc,OACpB,MAAM,aAAa,KACnB;AACA,YAAI;AACF,gBAAM;AAAA,YACJ;AAAA,YACA,KAAK,MAAM,OAAO;AAAA,YAClB,aAAa,EAAE,WAAW,IAAI;AAAA,UAChC;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AACA,WAAK,MAAM,OAAO;AAAA,IACpB;AAAA,EACF;AACF;","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* rust-node-cache — API
|
|
2
|
+
* rust-node-cache — public API (TypeScript).
|
|
3
3
|
*
|
|
4
4
|
* "Ultra-fast in-memory cache powered by Rust."
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
6
|
+
* This layer is a thin, typed wrapper over the native `Cache` class generated
|
|
7
|
+
* by Rust/napi-rs. Why wrap it instead of re-exporting it directly?
|
|
8
|
+
* - it allows ergonomic **generics**: `cache.get<User>("user:1")`;
|
|
9
|
+
* - it normalizes `undefined`/`null` so a miss always returns `null`;
|
|
10
|
+
* - it gives one place for the JSDoc and for evolving the API without breaking the Rust core.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* The cost is one extra function call per operation — negligible next to the
|
|
13
|
+
* real work (serialization + DashMap access) done in Rust.
|
|
14
14
|
*/
|
|
15
|
-
/**
|
|
15
|
+
/** Eviction strategy when `maxSize` is reached. */
|
|
16
16
|
type EvictionPolicy = "reject" | "lru";
|
|
17
|
-
/**
|
|
17
|
+
/** Cache constructor options. */
|
|
18
18
|
interface CacheOptions {
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
* `evictionPolicy`.
|
|
20
|
+
* Maximum number of keys. What happens when it is reached depends on
|
|
21
|
+
* `evictionPolicy`. No value => unlimited cache.
|
|
22
22
|
*/
|
|
23
23
|
maxSize?: number;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* - `"reject"` (
|
|
27
|
-
* - `"lru"`:
|
|
25
|
+
* Policy when `maxSize` is reached on a **new** key:
|
|
26
|
+
* - `"reject"` (default): `set` returns `false` (overwriting still works);
|
|
27
|
+
* - `"lru"`: removes the least recently used entry and goes on.
|
|
28
28
|
*/
|
|
29
29
|
evictionPolicy?: EvictionPolicy;
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* When set (> 0), starts a thread that sweeps expired entries every N
|
|
32
|
+
* seconds (background expiration, on top of the lazy one on access).
|
|
33
33
|
*/
|
|
34
34
|
cleanupIntervalSeconds?: number;
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
36
|
+
/** Per-write options. */
|
|
37
37
|
interface SetOptions {
|
|
38
|
-
/**
|
|
38
|
+
/** Time to live in seconds. Absent => the entry does not expire by time. */
|
|
39
39
|
ttlSeconds?: number;
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
41
|
+
/** Accumulated cache statistics (plus the current size). */
|
|
42
42
|
interface CacheStats {
|
|
43
|
-
/**
|
|
43
|
+
/** Reads that found a valid entry. */
|
|
44
44
|
hits: number;
|
|
45
|
-
/**
|
|
45
|
+
/** Reads without a valid key (missing or expired). */
|
|
46
46
|
misses: number;
|
|
47
|
-
/** Total
|
|
47
|
+
/** Total writes (`set`). */
|
|
48
48
|
sets: number;
|
|
49
|
-
/** Total
|
|
49
|
+
/** Total explicit removals (`delete`). */
|
|
50
50
|
deletes: number;
|
|
51
|
-
/** Total
|
|
51
|
+
/** Total entries removed by expiration. */
|
|
52
52
|
expired: number;
|
|
53
|
-
/** Total
|
|
53
|
+
/** Total entries removed by eviction (LRU policy when `maxSize` is reached). */
|
|
54
54
|
evicted: number;
|
|
55
|
-
/**
|
|
55
|
+
/** Number of keys stored right now. */
|
|
56
56
|
size: number;
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
59
|
+
* In-memory cache with a Rust core (DashMap + atomic counters). Thread-safe,
|
|
60
|
+
* with an optional TTL per entry.
|
|
61
61
|
*
|
|
62
62
|
* @example
|
|
63
63
|
* ```ts
|
|
@@ -69,38 +69,38 @@ interface CacheStats {
|
|
|
69
69
|
* ```
|
|
70
70
|
*/
|
|
71
71
|
declare class Cache {
|
|
72
|
-
/**
|
|
72
|
+
/** Instance of the native (Rust) class. */
|
|
73
73
|
private readonly native;
|
|
74
74
|
constructor(options?: CacheOptions);
|
|
75
|
-
/**
|
|
75
|
+
/** The active eviction policy: `"reject"` or `"lru"`. */
|
|
76
76
|
get evictionPolicy(): EvictionPolicy;
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* Stores (or overwrites) a value. The value is serialized as JSON in the core.
|
|
79
79
|
*
|
|
80
|
-
* @returns `true`
|
|
80
|
+
* @returns `true` on success; `false` if `maxSize` was reached and the key is new.
|
|
81
81
|
*/
|
|
82
82
|
set<T>(key: string, value: T, options?: SetOptions): boolean;
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Reads a value. Applies lazy expiration: expired keys count as a miss.
|
|
85
85
|
*
|
|
86
|
-
* @returns
|
|
86
|
+
* @returns the deserialized value, or `null` if missing or expired.
|
|
87
87
|
*/
|
|
88
88
|
get<T = unknown>(key: string): T | null;
|
|
89
|
-
/**
|
|
89
|
+
/** Removes a key. Returns `true` if it existed. */
|
|
90
90
|
delete(key: string): boolean;
|
|
91
|
-
/**
|
|
91
|
+
/** Whether the key exists and is still valid (not expired). */
|
|
92
92
|
exists(key: string): boolean;
|
|
93
|
-
/**
|
|
93
|
+
/** Empties the cache (does not reset the historical `stats` counters). */
|
|
94
94
|
clear(): void;
|
|
95
|
-
/**
|
|
95
|
+
/** Number of keys currently stored. */
|
|
96
96
|
size(): number;
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* Sweeps and removes every expired entry at once.
|
|
99
99
|
*
|
|
100
|
-
* @returns
|
|
100
|
+
* @returns how many entries were removed.
|
|
101
101
|
*/
|
|
102
102
|
cleanupExpired(): number;
|
|
103
|
-
/**
|
|
103
|
+
/** Returns the accumulated statistics + the current size. */
|
|
104
104
|
stats(): CacheStats;
|
|
105
105
|
}
|
|
106
106
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* rust-node-cache — API
|
|
2
|
+
* rust-node-cache — public API (TypeScript).
|
|
3
3
|
*
|
|
4
4
|
* "Ultra-fast in-memory cache powered by Rust."
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
6
|
+
* This layer is a thin, typed wrapper over the native `Cache` class generated
|
|
7
|
+
* by Rust/napi-rs. Why wrap it instead of re-exporting it directly?
|
|
8
|
+
* - it allows ergonomic **generics**: `cache.get<User>("user:1")`;
|
|
9
|
+
* - it normalizes `undefined`/`null` so a miss always returns `null`;
|
|
10
|
+
* - it gives one place for the JSDoc and for evolving the API without breaking the Rust core.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* The cost is one extra function call per operation — negligible next to the
|
|
13
|
+
* real work (serialization + DashMap access) done in Rust.
|
|
14
14
|
*/
|
|
15
|
-
/**
|
|
15
|
+
/** Eviction strategy when `maxSize` is reached. */
|
|
16
16
|
type EvictionPolicy = "reject" | "lru";
|
|
17
|
-
/**
|
|
17
|
+
/** Cache constructor options. */
|
|
18
18
|
interface CacheOptions {
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
* `evictionPolicy`.
|
|
20
|
+
* Maximum number of keys. What happens when it is reached depends on
|
|
21
|
+
* `evictionPolicy`. No value => unlimited cache.
|
|
22
22
|
*/
|
|
23
23
|
maxSize?: number;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* - `"reject"` (
|
|
27
|
-
* - `"lru"`:
|
|
25
|
+
* Policy when `maxSize` is reached on a **new** key:
|
|
26
|
+
* - `"reject"` (default): `set` returns `false` (overwriting still works);
|
|
27
|
+
* - `"lru"`: removes the least recently used entry and goes on.
|
|
28
28
|
*/
|
|
29
29
|
evictionPolicy?: EvictionPolicy;
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* When set (> 0), starts a thread that sweeps expired entries every N
|
|
32
|
+
* seconds (background expiration, on top of the lazy one on access).
|
|
33
33
|
*/
|
|
34
34
|
cleanupIntervalSeconds?: number;
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
36
|
+
/** Per-write options. */
|
|
37
37
|
interface SetOptions {
|
|
38
|
-
/**
|
|
38
|
+
/** Time to live in seconds. Absent => the entry does not expire by time. */
|
|
39
39
|
ttlSeconds?: number;
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
41
|
+
/** Accumulated cache statistics (plus the current size). */
|
|
42
42
|
interface CacheStats {
|
|
43
|
-
/**
|
|
43
|
+
/** Reads that found a valid entry. */
|
|
44
44
|
hits: number;
|
|
45
|
-
/**
|
|
45
|
+
/** Reads without a valid key (missing or expired). */
|
|
46
46
|
misses: number;
|
|
47
|
-
/** Total
|
|
47
|
+
/** Total writes (`set`). */
|
|
48
48
|
sets: number;
|
|
49
|
-
/** Total
|
|
49
|
+
/** Total explicit removals (`delete`). */
|
|
50
50
|
deletes: number;
|
|
51
|
-
/** Total
|
|
51
|
+
/** Total entries removed by expiration. */
|
|
52
52
|
expired: number;
|
|
53
|
-
/** Total
|
|
53
|
+
/** Total entries removed by eviction (LRU policy when `maxSize` is reached). */
|
|
54
54
|
evicted: number;
|
|
55
|
-
/**
|
|
55
|
+
/** Number of keys stored right now. */
|
|
56
56
|
size: number;
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
59
|
+
* In-memory cache with a Rust core (DashMap + atomic counters). Thread-safe,
|
|
60
|
+
* with an optional TTL per entry.
|
|
61
61
|
*
|
|
62
62
|
* @example
|
|
63
63
|
* ```ts
|
|
@@ -69,38 +69,38 @@ interface CacheStats {
|
|
|
69
69
|
* ```
|
|
70
70
|
*/
|
|
71
71
|
declare class Cache {
|
|
72
|
-
/**
|
|
72
|
+
/** Instance of the native (Rust) class. */
|
|
73
73
|
private readonly native;
|
|
74
74
|
constructor(options?: CacheOptions);
|
|
75
|
-
/**
|
|
75
|
+
/** The active eviction policy: `"reject"` or `"lru"`. */
|
|
76
76
|
get evictionPolicy(): EvictionPolicy;
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* Stores (or overwrites) a value. The value is serialized as JSON in the core.
|
|
79
79
|
*
|
|
80
|
-
* @returns `true`
|
|
80
|
+
* @returns `true` on success; `false` if `maxSize` was reached and the key is new.
|
|
81
81
|
*/
|
|
82
82
|
set<T>(key: string, value: T, options?: SetOptions): boolean;
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Reads a value. Applies lazy expiration: expired keys count as a miss.
|
|
85
85
|
*
|
|
86
|
-
* @returns
|
|
86
|
+
* @returns the deserialized value, or `null` if missing or expired.
|
|
87
87
|
*/
|
|
88
88
|
get<T = unknown>(key: string): T | null;
|
|
89
|
-
/**
|
|
89
|
+
/** Removes a key. Returns `true` if it existed. */
|
|
90
90
|
delete(key: string): boolean;
|
|
91
|
-
/**
|
|
91
|
+
/** Whether the key exists and is still valid (not expired). */
|
|
92
92
|
exists(key: string): boolean;
|
|
93
|
-
/**
|
|
93
|
+
/** Empties the cache (does not reset the historical `stats` counters). */
|
|
94
94
|
clear(): void;
|
|
95
|
-
/**
|
|
95
|
+
/** Number of keys currently stored. */
|
|
96
96
|
size(): number;
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* Sweeps and removes every expired entry at once.
|
|
99
99
|
*
|
|
100
|
-
* @returns
|
|
100
|
+
* @returns how many entries were removed.
|
|
101
101
|
*/
|
|
102
102
|
cleanupExpired(): number;
|
|
103
|
-
/**
|
|
103
|
+
/** Returns the accumulated statistics + the current size. */
|
|
104
104
|
stats(): CacheStats;
|
|
105
105
|
}
|
|
106
106
|
|
package/dist/index.js
CHANGED
|
@@ -43,52 +43,52 @@ var Cache2 = class {
|
|
|
43
43
|
cleanupIntervalSeconds: options.cleanupIntervalSeconds
|
|
44
44
|
}) : new native.Cache();
|
|
45
45
|
}
|
|
46
|
-
/**
|
|
46
|
+
/** The active eviction policy: `"reject"` or `"lru"`. */
|
|
47
47
|
get evictionPolicy() {
|
|
48
48
|
return this.native.evictionPolicy;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* Stores (or overwrites) a value. The value is serialized as JSON in the core.
|
|
52
52
|
*
|
|
53
|
-
* @returns `true`
|
|
53
|
+
* @returns `true` on success; `false` if `maxSize` was reached and the key is new.
|
|
54
54
|
*/
|
|
55
55
|
set(key, value, options) {
|
|
56
56
|
return this.native.set(key, value, options);
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
59
|
+
* Reads a value. Applies lazy expiration: expired keys count as a miss.
|
|
60
60
|
*
|
|
61
|
-
* @returns
|
|
61
|
+
* @returns the deserialized value, or `null` if missing or expired.
|
|
62
62
|
*/
|
|
63
63
|
get(key) {
|
|
64
64
|
const value = this.native.get(key);
|
|
65
65
|
return value === null || value === void 0 ? null : value;
|
|
66
66
|
}
|
|
67
|
-
/**
|
|
67
|
+
/** Removes a key. Returns `true` if it existed. */
|
|
68
68
|
delete(key) {
|
|
69
69
|
return this.native.delete(key);
|
|
70
70
|
}
|
|
71
|
-
/**
|
|
71
|
+
/** Whether the key exists and is still valid (not expired). */
|
|
72
72
|
exists(key) {
|
|
73
73
|
return this.native.exists(key);
|
|
74
74
|
}
|
|
75
|
-
/**
|
|
75
|
+
/** Empties the cache (does not reset the historical `stats` counters). */
|
|
76
76
|
clear() {
|
|
77
77
|
this.native.clear();
|
|
78
78
|
}
|
|
79
|
-
/**
|
|
79
|
+
/** Number of keys currently stored. */
|
|
80
80
|
size() {
|
|
81
81
|
return this.native.size();
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Sweeps and removes every expired entry at once.
|
|
85
85
|
*
|
|
86
|
-
* @returns
|
|
86
|
+
* @returns how many entries were removed.
|
|
87
87
|
*/
|
|
88
88
|
cleanupExpired() {
|
|
89
89
|
return this.native.cleanupExpired();
|
|
90
90
|
}
|
|
91
|
-
/**
|
|
91
|
+
/** Returns the accumulated statistics + the current size. */
|
|
92
92
|
stats() {
|
|
93
93
|
return this.native.stats();
|
|
94
94
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — API
|
|
1
|
+
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — public API (TypeScript).\n *\n * \"Ultra-fast in-memory cache powered by Rust.\"\n *\n * This layer is a thin, typed wrapper over the native `Cache` class generated\n * by Rust/napi-rs. Why wrap it instead of re-exporting it directly?\n * - it allows ergonomic **generics**: `cache.get<User>(\"user:1\")`;\n * - it normalizes `undefined`/`null` so a miss always returns `null`;\n * - it gives one place for the JSDoc and for evolving the API without breaking the Rust core.\n *\n * The cost is one extra function call per operation — negligible next to the\n * real work (serialization + DashMap access) done in Rust.\n */\n\n// Namespace import: works the same in CommonJS and ESM when consuming the native\n// addon (a CJS module generated by napi-rs).\nimport * as native from \"../binding.js\";\n\n/** Eviction strategy when `maxSize` is reached. */\nexport type EvictionPolicy = \"reject\" | \"lru\";\n\n/** Cache constructor options. */\nexport interface CacheOptions {\n /**\n * Maximum number of keys. What happens when it is reached depends on\n * `evictionPolicy`. No value => unlimited cache.\n */\n maxSize?: number;\n /**\n * Policy when `maxSize` is reached on a **new** key:\n * - `\"reject\"` (default): `set` returns `false` (overwriting still works);\n * - `\"lru\"`: removes the least recently used entry and goes on.\n */\n evictionPolicy?: EvictionPolicy;\n /**\n * When set (> 0), starts a thread that sweeps expired entries every N\n * seconds (background expiration, on top of the lazy one on access).\n */\n cleanupIntervalSeconds?: number;\n}\n\n/** Per-write options. */\nexport interface SetOptions {\n /** Time to live in seconds. Absent => the entry does not expire by time. */\n ttlSeconds?: number;\n}\n\n/** Accumulated cache statistics (plus the current size). */\nexport interface CacheStats {\n /** Reads that found a valid entry. */\n hits: number;\n /** Reads without a valid key (missing or expired). */\n misses: number;\n /** Total writes (`set`). */\n sets: number;\n /** Total explicit removals (`delete`). */\n deletes: number;\n /** Total entries removed by expiration. */\n expired: number;\n /** Total entries removed by eviction (LRU policy when `maxSize` is reached). */\n evicted: number;\n /** Number of keys stored right now. */\n size: number;\n}\n\n/**\n * In-memory cache with a Rust core (DashMap + atomic counters). Thread-safe,\n * with an optional TTL per entry.\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 /** Instance of the native (Rust) class. */\n private readonly native: native.Cache;\n\n constructor(options: CacheOptions = {}) {\n // An options object is passed to Rust only when it carries something.\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 /** The active eviction policy: `\"reject\"` or `\"lru\"`. */\n get evictionPolicy(): EvictionPolicy {\n return this.native.evictionPolicy as EvictionPolicy;\n }\n\n /**\n * Stores (or overwrites) a value. The value is serialized as JSON in the core.\n *\n * @returns `true` on success; `false` if `maxSize` was reached and the key is new.\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 * Reads a value. Applies lazy expiration: expired keys count as a miss.\n *\n * @returns the deserialized value, or `null` if missing or expired.\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 /** Removes a key. Returns `true` if it existed. */\n delete(key: string): boolean {\n return this.native.delete(key);\n }\n\n /** Whether the key exists and is still valid (not expired). */\n exists(key: string): boolean {\n return this.native.exists(key);\n }\n\n /** Empties the cache (does not reset the historical `stats` counters). */\n clear(): void {\n this.native.clear();\n }\n\n /** Number of keys currently stored. */\n size(): number {\n return this.native.size();\n }\n\n /**\n * Sweeps and removes every expired entry at once.\n *\n * @returns how many entries were removed.\n */\n cleanupExpired(): number {\n return this.native.cleanupExpired();\n }\n\n /** Returns the accumulated statistics + the current size. */\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
|
@@ -9,52 +9,52 @@ var Cache2 = class {
|
|
|
9
9
|
cleanupIntervalSeconds: options.cleanupIntervalSeconds
|
|
10
10
|
}) : new native.Cache();
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
12
|
+
/** The active eviction policy: `"reject"` or `"lru"`. */
|
|
13
13
|
get evictionPolicy() {
|
|
14
14
|
return this.native.evictionPolicy;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Stores (or overwrites) a value. The value is serialized as JSON in the core.
|
|
18
18
|
*
|
|
19
|
-
* @returns `true`
|
|
19
|
+
* @returns `true` on success; `false` if `maxSize` was reached and the key is new.
|
|
20
20
|
*/
|
|
21
21
|
set(key, value, options) {
|
|
22
22
|
return this.native.set(key, value, options);
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Reads a value. Applies lazy expiration: expired keys count as a miss.
|
|
26
26
|
*
|
|
27
|
-
* @returns
|
|
27
|
+
* @returns the deserialized value, or `null` if missing or expired.
|
|
28
28
|
*/
|
|
29
29
|
get(key) {
|
|
30
30
|
const value = this.native.get(key);
|
|
31
31
|
return value === null || value === void 0 ? null : value;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
33
|
+
/** Removes a key. Returns `true` if it existed. */
|
|
34
34
|
delete(key) {
|
|
35
35
|
return this.native.delete(key);
|
|
36
36
|
}
|
|
37
|
-
/**
|
|
37
|
+
/** Whether the key exists and is still valid (not expired). */
|
|
38
38
|
exists(key) {
|
|
39
39
|
return this.native.exists(key);
|
|
40
40
|
}
|
|
41
|
-
/**
|
|
41
|
+
/** Empties the cache (does not reset the historical `stats` counters). */
|
|
42
42
|
clear() {
|
|
43
43
|
this.native.clear();
|
|
44
44
|
}
|
|
45
|
-
/**
|
|
45
|
+
/** Number of keys currently stored. */
|
|
46
46
|
size() {
|
|
47
47
|
return this.native.size();
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
50
|
+
* Sweeps and removes every expired entry at once.
|
|
51
51
|
*
|
|
52
|
-
* @returns
|
|
52
|
+
* @returns how many entries were removed.
|
|
53
53
|
*/
|
|
54
54
|
cleanupExpired() {
|
|
55
55
|
return this.native.cleanupExpired();
|
|
56
56
|
}
|
|
57
|
-
/**
|
|
57
|
+
/** Returns the accumulated statistics + the current size. */
|
|
58
58
|
stats() {
|
|
59
59
|
return this.native.stats();
|
|
60
60
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — API
|
|
1
|
+
{"version":3,"sources":["../js/index.ts"],"sourcesContent":["/**\n * rust-node-cache — public API (TypeScript).\n *\n * \"Ultra-fast in-memory cache powered by Rust.\"\n *\n * This layer is a thin, typed wrapper over the native `Cache` class generated\n * by Rust/napi-rs. Why wrap it instead of re-exporting it directly?\n * - it allows ergonomic **generics**: `cache.get<User>(\"user:1\")`;\n * - it normalizes `undefined`/`null` so a miss always returns `null`;\n * - it gives one place for the JSDoc and for evolving the API without breaking the Rust core.\n *\n * The cost is one extra function call per operation — negligible next to the\n * real work (serialization + DashMap access) done in Rust.\n */\n\n// Namespace import: works the same in CommonJS and ESM when consuming the native\n// addon (a CJS module generated by napi-rs).\nimport * as native from \"../binding.js\";\n\n/** Eviction strategy when `maxSize` is reached. */\nexport type EvictionPolicy = \"reject\" | \"lru\";\n\n/** Cache constructor options. */\nexport interface CacheOptions {\n /**\n * Maximum number of keys. What happens when it is reached depends on\n * `evictionPolicy`. No value => unlimited cache.\n */\n maxSize?: number;\n /**\n * Policy when `maxSize` is reached on a **new** key:\n * - `\"reject\"` (default): `set` returns `false` (overwriting still works);\n * - `\"lru\"`: removes the least recently used entry and goes on.\n */\n evictionPolicy?: EvictionPolicy;\n /**\n * When set (> 0), starts a thread that sweeps expired entries every N\n * seconds (background expiration, on top of the lazy one on access).\n */\n cleanupIntervalSeconds?: number;\n}\n\n/** Per-write options. */\nexport interface SetOptions {\n /** Time to live in seconds. Absent => the entry does not expire by time. */\n ttlSeconds?: number;\n}\n\n/** Accumulated cache statistics (plus the current size). */\nexport interface CacheStats {\n /** Reads that found a valid entry. */\n hits: number;\n /** Reads without a valid key (missing or expired). */\n misses: number;\n /** Total writes (`set`). */\n sets: number;\n /** Total explicit removals (`delete`). */\n deletes: number;\n /** Total entries removed by expiration. */\n expired: number;\n /** Total entries removed by eviction (LRU policy when `maxSize` is reached). */\n evicted: number;\n /** Number of keys stored right now. */\n size: number;\n}\n\n/**\n * In-memory cache with a Rust core (DashMap + atomic counters). Thread-safe,\n * with an optional TTL per entry.\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 /** Instance of the native (Rust) class. */\n private readonly native: native.Cache;\n\n constructor(options: CacheOptions = {}) {\n // An options object is passed to Rust only when it carries something.\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 /** The active eviction policy: `\"reject\"` or `\"lru\"`. */\n get evictionPolicy(): EvictionPolicy {\n return this.native.evictionPolicy as EvictionPolicy;\n }\n\n /**\n * Stores (or overwrites) a value. The value is serialized as JSON in the core.\n *\n * @returns `true` on success; `false` if `maxSize` was reached and the key is new.\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 * Reads a value. Applies lazy expiration: expired keys count as a miss.\n *\n * @returns the deserialized value, or `null` if missing or expired.\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 /** Removes a key. Returns `true` if it existed. */\n delete(key: string): boolean {\n return this.native.delete(key);\n }\n\n /** Whether the key exists and is still valid (not expired). */\n exists(key: string): boolean {\n return this.native.exists(key);\n }\n\n /** Empties the cache (does not reset the historical `stats` counters). */\n clear(): void {\n this.native.clear();\n }\n\n /** Number of keys currently stored. */\n size(): number {\n return this.native.size();\n }\n\n /**\n * Sweeps and removes every expired entry at once.\n *\n * @returns how many entries were removed.\n */\n cleanupExpired(): number {\n return this.native.cleanupExpired();\n }\n\n /** Returns the accumulated statistics + the current size. */\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/dist/nestjs.d.mts
CHANGED
|
@@ -3,36 +3,36 @@ import { Observable } from 'rxjs';
|
|
|
3
3
|
import { Cache } from './index.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* NestJS integration: a response caching interceptor.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Usage:
|
|
9
9
|
* import { Cache } from "rust-node-cache";
|
|
10
10
|
* import { CacheInterceptor } from "rust-node-cache/nestjs";
|
|
11
11
|
*
|
|
12
12
|
* const cache = new Cache();
|
|
13
13
|
* app.useGlobalInterceptors(new CacheInterceptor({ cache, ttlSeconds: 60 }));
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* `@nestjs/common` is imported with `import type`, so there is NO runtime import
|
|
16
|
+
* of Nest here — the package does not force Nest as a dependency. The only runtime
|
|
17
|
+
* dependencies are RxJS's `of`/`tap` operators (present in any Nest app).
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
interface CacheInterceptorOptions {
|
|
21
|
-
/**
|
|
21
|
+
/** Cache instance to use. */
|
|
22
22
|
cache: Cache;
|
|
23
|
-
/** TTL
|
|
23
|
+
/** TTL applied to stored responses (in seconds). */
|
|
24
24
|
ttlSeconds?: number;
|
|
25
|
-
/**
|
|
25
|
+
/** HTTP methods eligible for caching. Default: `["GET"]`. */
|
|
26
26
|
methods?: string[];
|
|
27
|
-
/**
|
|
27
|
+
/** Builds the cache key from the request. Default: `METHOD:url`. */
|
|
28
28
|
keyGenerator?: (req: {
|
|
29
29
|
method: string;
|
|
30
30
|
url: string;
|
|
31
31
|
}) => string;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* NestJS interceptor that caches the value returned by handlers. On a HIT, it
|
|
35
|
+
* returns the cached value without running the handler.
|
|
36
36
|
*/
|
|
37
37
|
declare class CacheInterceptor implements NestInterceptor {
|
|
38
38
|
private readonly cache;
|
package/dist/nestjs.d.ts
CHANGED
|
@@ -3,36 +3,36 @@ import { Observable } from 'rxjs';
|
|
|
3
3
|
import { Cache } from './index.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* NestJS integration: a response caching interceptor.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Usage:
|
|
9
9
|
* import { Cache } from "rust-node-cache";
|
|
10
10
|
* import { CacheInterceptor } from "rust-node-cache/nestjs";
|
|
11
11
|
*
|
|
12
12
|
* const cache = new Cache();
|
|
13
13
|
* app.useGlobalInterceptors(new CacheInterceptor({ cache, ttlSeconds: 60 }));
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* `@nestjs/common` is imported with `import type`, so there is NO runtime import
|
|
16
|
+
* of Nest here — the package does not force Nest as a dependency. The only runtime
|
|
17
|
+
* dependencies are RxJS's `of`/`tap` operators (present in any Nest app).
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
interface CacheInterceptorOptions {
|
|
21
|
-
/**
|
|
21
|
+
/** Cache instance to use. */
|
|
22
22
|
cache: Cache;
|
|
23
|
-
/** TTL
|
|
23
|
+
/** TTL applied to stored responses (in seconds). */
|
|
24
24
|
ttlSeconds?: number;
|
|
25
|
-
/**
|
|
25
|
+
/** HTTP methods eligible for caching. Default: `["GET"]`. */
|
|
26
26
|
methods?: string[];
|
|
27
|
-
/**
|
|
27
|
+
/** Builds the cache key from the request. Default: `METHOD:url`. */
|
|
28
28
|
keyGenerator?: (req: {
|
|
29
29
|
method: string;
|
|
30
30
|
url: string;
|
|
31
31
|
}) => string;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* NestJS interceptor that caches the value returned by handlers. On a HIT, it
|
|
35
|
+
* returns the cached value without running the handler.
|
|
36
36
|
*/
|
|
37
37
|
declare class CacheInterceptor implements NestInterceptor {
|
|
38
38
|
private readonly cache;
|
package/dist/nestjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/nestjs.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../js/nestjs.ts"],"sourcesContent":["/**\n * NestJS integration: a response caching interceptor.\n *\n * Usage:\n * import { Cache } from \"rust-node-cache\";\n * import { CacheInterceptor } from \"rust-node-cache/nestjs\";\n *\n * const cache = new Cache();\n * app.useGlobalInterceptors(new CacheInterceptor({ cache, ttlSeconds: 60 }));\n *\n * `@nestjs/common` is imported with `import type`, so there is NO runtime import\n * of Nest here — the package does not force Nest as a dependency. The only runtime\n * dependencies are RxJS's `of`/`tap` operators (present in any Nest app).\n */\n\nimport type {\n CallHandler,\n ExecutionContext,\n NestInterceptor,\n} from \"@nestjs/common\";\nimport type { Observable } from \"rxjs\";\nimport { of, tap } from \"rxjs\";\nimport type { Cache } from \"./index\";\n\nexport interface CacheInterceptorOptions {\n /** Cache instance to use. */\n cache: Cache;\n /** TTL applied to stored responses (in seconds). */\n ttlSeconds?: number;\n /** HTTP methods eligible for caching. Default: `[\"GET\"]`. */\n methods?: string[];\n /** Builds the cache key from the request. Default: `METHOD:url`. */\n keyGenerator?: (req: { method: string; url: string }) => string;\n}\n\n/**\n * NestJS interceptor that caches the value returned by handlers. On a HIT, it\n * returns the cached value without running the handler.\n */\nexport class CacheInterceptor implements NestInterceptor {\n private readonly cache: Cache;\n private readonly ttlSeconds?: number;\n private readonly methods: string[];\n private readonly keyGenerator: (req: {\n method: string;\n url: string;\n }) => string;\n\n constructor(options: CacheInterceptorOptions) {\n this.cache = options.cache;\n this.ttlSeconds = options.ttlSeconds;\n this.methods = options.methods ?? [\"GET\"];\n this.keyGenerator =\n options.keyGenerator ?? ((req) => `${req.method}:${req.url}`);\n }\n\n intercept(\n context: ExecutionContext,\n next: CallHandler,\n ): Observable<unknown> {\n const req = context.switchToHttp().getRequest<{\n method: string;\n url: string;\n }>();\n\n if (!this.methods.includes(req.method)) {\n return next.handle();\n }\n\n const key = this.keyGenerator(req);\n const cached = this.cache.get(key);\n if (cached !== null) {\n return of(cached);\n }\n\n return next.handle().pipe(\n tap((body) => {\n if (body !== undefined && body !== null) {\n this.cache.set(\n key,\n body,\n this.ttlSeconds ? { ttlSeconds: this.ttlSeconds } : undefined,\n );\n }\n }),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,kBAAwB;AAkBjB,IAAM,mBAAN,MAAkD;AAAA,EASvD,YAAY,SAAkC;AAC5C,SAAK,QAAQ,QAAQ;AACrB,SAAK,aAAa,QAAQ;AAC1B,SAAK,UAAU,QAAQ,WAAW,CAAC,KAAK;AACxC,SAAK,eACH,QAAQ,iBAAiB,CAAC,QAAQ,GAAG,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EAC9D;AAAA,EAEA,UACE,SACA,MACqB;AACrB,UAAM,MAAM,QAAQ,aAAa,EAAE,WAGhC;AAEH,QAAI,CAAC,KAAK,QAAQ,SAAS,IAAI,MAAM,GAAG;AACtC,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,UAAM,MAAM,KAAK,aAAa,GAAG;AACjC,UAAM,SAAS,KAAK,MAAM,IAAI,GAAG;AACjC,QAAI,WAAW,MAAM;AACnB,iBAAO,gBAAG,MAAM;AAAA,IAClB;AAEA,WAAO,KAAK,OAAO,EAAE;AAAA,UACnB,iBAAI,CAAC,SAAS;AACZ,YAAI,SAAS,UAAa,SAAS,MAAM;AACvC,eAAK,MAAM;AAAA,YACT;AAAA,YACA;AAAA,YACA,KAAK,aAAa,EAAE,YAAY,KAAK,WAAW,IAAI;AAAA,UACtD;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
|
package/dist/nestjs.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../js/nestjs.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../js/nestjs.ts"],"sourcesContent":["/**\n * NestJS integration: a response caching interceptor.\n *\n * Usage:\n * import { Cache } from \"rust-node-cache\";\n * import { CacheInterceptor } from \"rust-node-cache/nestjs\";\n *\n * const cache = new Cache();\n * app.useGlobalInterceptors(new CacheInterceptor({ cache, ttlSeconds: 60 }));\n *\n * `@nestjs/common` is imported with `import type`, so there is NO runtime import\n * of Nest here — the package does not force Nest as a dependency. The only runtime\n * dependencies are RxJS's `of`/`tap` operators (present in any Nest app).\n */\n\nimport type {\n CallHandler,\n ExecutionContext,\n NestInterceptor,\n} from \"@nestjs/common\";\nimport type { Observable } from \"rxjs\";\nimport { of, tap } from \"rxjs\";\nimport type { Cache } from \"./index\";\n\nexport interface CacheInterceptorOptions {\n /** Cache instance to use. */\n cache: Cache;\n /** TTL applied to stored responses (in seconds). */\n ttlSeconds?: number;\n /** HTTP methods eligible for caching. Default: `[\"GET\"]`. */\n methods?: string[];\n /** Builds the cache key from the request. Default: `METHOD:url`. */\n keyGenerator?: (req: { method: string; url: string }) => string;\n}\n\n/**\n * NestJS interceptor that caches the value returned by handlers. On a HIT, it\n * returns the cached value without running the handler.\n */\nexport class CacheInterceptor implements NestInterceptor {\n private readonly cache: Cache;\n private readonly ttlSeconds?: number;\n private readonly methods: string[];\n private readonly keyGenerator: (req: {\n method: string;\n url: string;\n }) => string;\n\n constructor(options: CacheInterceptorOptions) {\n this.cache = options.cache;\n this.ttlSeconds = options.ttlSeconds;\n this.methods = options.methods ?? [\"GET\"];\n this.keyGenerator =\n options.keyGenerator ?? ((req) => `${req.method}:${req.url}`);\n }\n\n intercept(\n context: ExecutionContext,\n next: CallHandler,\n ): Observable<unknown> {\n const req = context.switchToHttp().getRequest<{\n method: string;\n url: string;\n }>();\n\n if (!this.methods.includes(req.method)) {\n return next.handle();\n }\n\n const key = this.keyGenerator(req);\n const cached = this.cache.get(key);\n if (cached !== null) {\n return of(cached);\n }\n\n return next.handle().pipe(\n tap((body) => {\n if (body !== undefined && body !== null) {\n this.cache.set(\n key,\n body,\n this.ttlSeconds ? { ttlSeconds: this.ttlSeconds } : undefined,\n );\n }\n }),\n );\n }\n}\n"],"mappings":";AAqBA,SAAS,IAAI,WAAW;AAkBjB,IAAM,mBAAN,MAAkD;AAAA,EASvD,YAAY,SAAkC;AAC5C,SAAK,QAAQ,QAAQ;AACrB,SAAK,aAAa,QAAQ;AAC1B,SAAK,UAAU,QAAQ,WAAW,CAAC,KAAK;AACxC,SAAK,eACH,QAAQ,iBAAiB,CAAC,QAAQ,GAAG,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EAC9D;AAAA,EAEA,UACE,SACA,MACqB;AACrB,UAAM,MAAM,QAAQ,aAAa,EAAE,WAGhC;AAEH,QAAI,CAAC,KAAK,QAAQ,SAAS,IAAI,MAAM,GAAG;AACtC,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,UAAM,MAAM,KAAK,aAAa,GAAG;AACjC,UAAM,SAAS,KAAK,MAAM,IAAI,GAAG;AACjC,QAAI,WAAW,MAAM;AACnB,aAAO,GAAG,MAAM;AAAA,IAClB;AAEA,WAAO,KAAK,OAAO,EAAE;AAAA,MACnB,IAAI,CAAC,SAAS;AACZ,YAAI,SAAS,UAAa,SAAS,MAAM;AACvC,eAAK,MAAM;AAAA,YACT;AAAA,YACA;AAAA,YACA,KAAK,aAAa,EAAE,YAAY,KAAK,WAAW,IAAI;AAAA,UACtD;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rust-node-cache",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Ultra-fast in-memory cache for Node.js powered by Rust.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cache",
|
|
@@ -66,7 +66,9 @@
|
|
|
66
66
|
"aarch64-apple-darwin",
|
|
67
67
|
"aarch64-unknown-linux-gnu",
|
|
68
68
|
"x86_64-unknown-linux-gnu",
|
|
69
|
-
"x86_64-pc-windows-msvc"
|
|
69
|
+
"x86_64-pc-windows-msvc",
|
|
70
|
+
"x86_64-unknown-linux-musl",
|
|
71
|
+
"aarch64-unknown-linux-musl"
|
|
70
72
|
]
|
|
71
73
|
}
|
|
72
74
|
},
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|