rust-node-cache 0.1.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/binding.js ADDED
@@ -0,0 +1,315 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /* prettier-ignore */
4
+
5
+ /* auto-generated by NAPI-RS */
6
+
7
+ const { existsSync, readFileSync } = require('fs')
8
+ const { join } = require('path')
9
+
10
+ const { platform, arch } = process
11
+
12
+ let nativeBinding = null
13
+ let localFileExisted = false
14
+ let loadError = null
15
+
16
+ function isMusl() {
17
+ // For Node 10
18
+ if (!process.report || typeof process.report.getReport !== 'function') {
19
+ try {
20
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
+ return readFileSync(lddPath, 'utf8').includes('musl')
22
+ } catch (e) {
23
+ return true
24
+ }
25
+ } else {
26
+ const { glibcVersionRuntime } = process.report.getReport().header
27
+ return !glibcVersionRuntime
28
+ }
29
+ }
30
+
31
+ switch (platform) {
32
+ case 'android':
33
+ switch (arch) {
34
+ case 'arm64':
35
+ localFileExisted = existsSync(join(__dirname, 'rust-node-cache.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./rust-node-cache.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('rust-node-cache-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'rust-node-cache.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./rust-node-cache.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('rust-node-cache-android-arm-eabi')
53
+ }
54
+ } catch (e) {
55
+ loadError = e
56
+ }
57
+ break
58
+ default:
59
+ throw new Error(`Unsupported architecture on Android ${arch}`)
60
+ }
61
+ break
62
+ case 'win32':
63
+ switch (arch) {
64
+ case 'x64':
65
+ localFileExisted = existsSync(
66
+ join(__dirname, 'rust-node-cache.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./rust-node-cache.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('rust-node-cache-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'rust-node-cache.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./rust-node-cache.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('rust-node-cache-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'rust-node-cache.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./rust-node-cache.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('rust-node-cache-win32-arm64-msvc')
101
+ }
102
+ } catch (e) {
103
+ loadError = e
104
+ }
105
+ break
106
+ default:
107
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
+ }
109
+ break
110
+ case 'darwin':
111
+ localFileExisted = existsSync(join(__dirname, 'rust-node-cache.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./rust-node-cache.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('rust-node-cache-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'rust-node-cache.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./rust-node-cache.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('rust-node-cache-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'rust-node-cache.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./rust-node-cache.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('rust-node-cache-darwin-arm64')
142
+ }
143
+ } catch (e) {
144
+ loadError = e
145
+ }
146
+ break
147
+ default:
148
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
+ }
150
+ break
151
+ case 'freebsd':
152
+ if (arch !== 'x64') {
153
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
+ }
155
+ localFileExisted = existsSync(join(__dirname, 'rust-node-cache.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./rust-node-cache.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('rust-node-cache-freebsd-x64')
161
+ }
162
+ } catch (e) {
163
+ loadError = e
164
+ }
165
+ break
166
+ case 'linux':
167
+ switch (arch) {
168
+ case 'x64':
169
+ if (isMusl()) {
170
+ localFileExisted = existsSync(
171
+ join(__dirname, 'rust-node-cache.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./rust-node-cache.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('rust-node-cache-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'rust-node-cache.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./rust-node-cache.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('rust-node-cache-linux-x64-gnu')
191
+ }
192
+ } catch (e) {
193
+ loadError = e
194
+ }
195
+ }
196
+ break
197
+ case 'arm64':
198
+ if (isMusl()) {
199
+ localFileExisted = existsSync(
200
+ join(__dirname, 'rust-node-cache.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./rust-node-cache.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('rust-node-cache-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'rust-node-cache.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./rust-node-cache.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('rust-node-cache-linux-arm64-gnu')
220
+ }
221
+ } catch (e) {
222
+ loadError = e
223
+ }
224
+ }
225
+ break
226
+ case 'arm':
227
+ if (isMusl()) {
228
+ localFileExisted = existsSync(
229
+ join(__dirname, 'rust-node-cache.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./rust-node-cache.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('rust-node-cache-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'rust-node-cache.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./rust-node-cache.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('rust-node-cache-linux-arm-gnueabihf')
249
+ }
250
+ } catch (e) {
251
+ loadError = e
252
+ }
253
+ }
254
+ break
255
+ case 'riscv64':
256
+ if (isMusl()) {
257
+ localFileExisted = existsSync(
258
+ join(__dirname, 'rust-node-cache.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./rust-node-cache.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('rust-node-cache-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'rust-node-cache.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./rust-node-cache.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('rust-node-cache-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'rust-node-cache.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./rust-node-cache.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('rust-node-cache-linux-s390x-gnu')
293
+ }
294
+ } catch (e) {
295
+ loadError = e
296
+ }
297
+ break
298
+ default:
299
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
300
+ }
301
+ break
302
+ default:
303
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
304
+ }
305
+
306
+ if (!nativeBinding) {
307
+ if (loadError) {
308
+ throw loadError
309
+ }
310
+ throw new Error(`Failed to load native binding`)
311
+ }
312
+
313
+ const { Cache } = nativeBinding
314
+
315
+ module.exports.Cache = Cache
@@ -0,0 +1,34 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { Cache } from './index.mjs';
3
+
4
+ /**
5
+ * Integração com Express: cache de respostas JSON.
6
+ *
7
+ * Uso:
8
+ * import { Cache } from "rust-node-cache";
9
+ * import { cacheMiddleware } from "rust-node-cache/express";
10
+ *
11
+ * const cache = new Cache();
12
+ * app.get("/users/:id", cacheMiddleware({ cache, ttlSeconds: 60 }), handler);
13
+ *
14
+ * O middleware intercepta `res.json`: num HIT responde direto do cache; num
15
+ * MISS deixa o handler rodar e guarda o corpo da resposta (apenas em 2xx).
16
+ */
17
+
18
+ interface CacheMiddlewareOptions {
19
+ /** Instância de cache a usar. */
20
+ cache: Cache;
21
+ /** TTL aplicado às respostas guardadas (em segundos). */
22
+ ttlSeconds?: number;
23
+ /** Métodos HTTP elegíveis para cache. Padrão: `["GET"]`. */
24
+ methods?: string[];
25
+ /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */
26
+ keyGenerator?: (req: Request) => string;
27
+ }
28
+ /**
29
+ * Cria um middleware Express que cacheia respostas JSON. Adiciona o cabeçalho
30
+ * `X-Cache: HIT|MISS` para facilitar a observabilidade.
31
+ */
32
+ declare function cacheMiddleware(options: CacheMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
33
+
34
+ export { type CacheMiddlewareOptions, cacheMiddleware };
@@ -0,0 +1,34 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import { Cache } from './index.js';
3
+
4
+ /**
5
+ * Integração com Express: cache de respostas JSON.
6
+ *
7
+ * Uso:
8
+ * import { Cache } from "rust-node-cache";
9
+ * import { cacheMiddleware } from "rust-node-cache/express";
10
+ *
11
+ * const cache = new Cache();
12
+ * app.get("/users/:id", cacheMiddleware({ cache, ttlSeconds: 60 }), handler);
13
+ *
14
+ * O middleware intercepta `res.json`: num HIT responde direto do cache; num
15
+ * MISS deixa o handler rodar e guarda o corpo da resposta (apenas em 2xx).
16
+ */
17
+
18
+ interface CacheMiddlewareOptions {
19
+ /** Instância de cache a usar. */
20
+ cache: Cache;
21
+ /** TTL aplicado às respostas guardadas (em segundos). */
22
+ ttlSeconds?: number;
23
+ /** Métodos HTTP elegíveis para cache. Padrão: `["GET"]`. */
24
+ methods?: string[];
25
+ /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */
26
+ keyGenerator?: (req: Request) => string;
27
+ }
28
+ /**
29
+ * Cria um middleware Express que cacheia respostas JSON. Adiciona o cabeçalho
30
+ * `X-Cache: HIT|MISS` para facilitar a observabilidade.
31
+ */
32
+ declare function cacheMiddleware(options: CacheMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
33
+
34
+ export { type CacheMiddlewareOptions, cacheMiddleware };
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // js/express.ts
21
+ var express_exports = {};
22
+ __export(express_exports, {
23
+ cacheMiddleware: () => cacheMiddleware
24
+ });
25
+ module.exports = __toCommonJS(express_exports);
26
+ function cacheMiddleware(options) {
27
+ const { cache } = options;
28
+ const ttlSeconds = options.ttlSeconds;
29
+ const methods = options.methods ?? ["GET"];
30
+ const keyGenerator = options.keyGenerator ?? ((req) => `${req.method}:${req.originalUrl}`);
31
+ return function rustNodeCache(req, res, next) {
32
+ if (!methods.includes(req.method)) {
33
+ next();
34
+ return;
35
+ }
36
+ const key = keyGenerator(req);
37
+ const cached = cache.get(key);
38
+ if (cached !== null) {
39
+ res.setHeader("X-Cache", "HIT");
40
+ res.json(cached);
41
+ return;
42
+ }
43
+ res.setHeader("X-Cache", "MISS");
44
+ const originalJson = res.json.bind(res);
45
+ res.json = (body) => {
46
+ if (res.statusCode >= 200 && res.statusCode < 300) {
47
+ cache.set(key, body, ttlSeconds ? { ttlSeconds } : void 0);
48
+ }
49
+ return originalJson(body);
50
+ };
51
+ next();
52
+ };
53
+ }
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ cacheMiddleware
57
+ });
58
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../js/express.ts"],"sourcesContent":["/**\n * Integração com Express: cache de respostas JSON.\n *\n * Uso:\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 * O middleware intercepta `res.json`: num HIT responde direto do cache; num\n * MISS deixa o handler rodar e guarda o corpo da resposta (apenas em 2xx).\n */\n\nimport type { Request, Response, NextFunction } from \"express\";\nimport type { Cache } from \"./index\";\n\nexport interface CacheMiddlewareOptions {\n /** Instância de cache a usar. */\n cache: Cache;\n /** TTL aplicado às respostas guardadas (em segundos). */\n ttlSeconds?: number;\n /** Métodos HTTP elegíveis para cache. Padrão: `[\"GET\"]`. */\n methods?: string[];\n /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */\n keyGenerator?: (req: Request) => string;\n}\n\n/**\n * Cria um middleware Express que cacheia respostas JSON. Adiciona o cabeçalho\n * `X-Cache: HIT|MISS` para facilitar a observabilidade.\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 // Só guardamos respostas bem-sucedidas (2xx).\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":[]}
@@ -0,0 +1,33 @@
1
+ // js/express.ts
2
+ function cacheMiddleware(options) {
3
+ const { cache } = options;
4
+ const ttlSeconds = options.ttlSeconds;
5
+ const methods = options.methods ?? ["GET"];
6
+ const keyGenerator = options.keyGenerator ?? ((req) => `${req.method}:${req.originalUrl}`);
7
+ return function rustNodeCache(req, res, next) {
8
+ if (!methods.includes(req.method)) {
9
+ next();
10
+ return;
11
+ }
12
+ const key = keyGenerator(req);
13
+ const cached = cache.get(key);
14
+ if (cached !== null) {
15
+ res.setHeader("X-Cache", "HIT");
16
+ res.json(cached);
17
+ return;
18
+ }
19
+ res.setHeader("X-Cache", "MISS");
20
+ const originalJson = res.json.bind(res);
21
+ res.json = (body) => {
22
+ if (res.statusCode >= 200 && res.statusCode < 300) {
23
+ cache.set(key, body, ttlSeconds ? { ttlSeconds } : void 0);
24
+ }
25
+ return originalJson(body);
26
+ };
27
+ next();
28
+ };
29
+ }
30
+ export {
31
+ cacheMiddleware
32
+ };
33
+ //# sourceMappingURL=express.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../js/express.ts"],"sourcesContent":["/**\n * Integração com Express: cache de respostas JSON.\n *\n * Uso:\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 * O middleware intercepta `res.json`: num HIT responde direto do cache; num\n * MISS deixa o handler rodar e guarda o corpo da resposta (apenas em 2xx).\n */\n\nimport type { Request, Response, NextFunction } from \"express\";\nimport type { Cache } from \"./index\";\n\nexport interface CacheMiddlewareOptions {\n /** Instância de cache a usar. */\n cache: Cache;\n /** TTL aplicado às respostas guardadas (em segundos). */\n ttlSeconds?: number;\n /** Métodos HTTP elegíveis para cache. Padrão: `[\"GET\"]`. */\n methods?: string[];\n /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */\n keyGenerator?: (req: Request) => string;\n}\n\n/**\n * Cria um middleware Express que cacheia respostas JSON. Adiciona o cabeçalho\n * `X-Cache: HIT|MISS` para facilitar a observabilidade.\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 // Só guardamos respostas bem-sucedidas (2xx).\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":[]}
@@ -0,0 +1,33 @@
1
+ import { FastifyRequest, FastifyInstance } from 'fastify';
2
+ import { Cache } from './index.mjs';
3
+
4
+ /**
5
+ * Integração com Fastify: cache de respostas JSON via plugin.
6
+ *
7
+ * Uso:
8
+ * import { Cache } from "rust-node-cache";
9
+ * import { cachePlugin } from "rust-node-cache/fastify";
10
+ *
11
+ * const cache = new Cache();
12
+ * fastify.register(cachePlugin, { cache, ttlSeconds: 60 });
13
+ *
14
+ * Fluxo: o hook `onRequest` checa o cache e, num HIT, responde imediatamente
15
+ * (curto-circuito). Num MISS, o hook `onSend` guarda o payload serializado.
16
+ */
17
+
18
+ interface CachePluginOptions {
19
+ /** Instância de cache a usar. */
20
+ cache: Cache;
21
+ /** TTL aplicado às respostas guardadas (em segundos). */
22
+ ttlSeconds?: number;
23
+ /** Métodos HTTP elegíveis para cache. Padrão: `["GET"]`. */
24
+ methods?: string[];
25
+ /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */
26
+ keyGenerator?: (req: FastifyRequest) => string;
27
+ }
28
+ /**
29
+ * Plugin Fastify que cacheia respostas JSON. Use com `fastify.register`.
30
+ */
31
+ declare function cachePlugin(fastify: FastifyInstance, options: CachePluginOptions): Promise<void>;
32
+
33
+ export { type CachePluginOptions, cachePlugin };
@@ -0,0 +1,33 @@
1
+ import { FastifyRequest, FastifyInstance } from 'fastify';
2
+ import { Cache } from './index.js';
3
+
4
+ /**
5
+ * Integração com Fastify: cache de respostas JSON via plugin.
6
+ *
7
+ * Uso:
8
+ * import { Cache } from "rust-node-cache";
9
+ * import { cachePlugin } from "rust-node-cache/fastify";
10
+ *
11
+ * const cache = new Cache();
12
+ * fastify.register(cachePlugin, { cache, ttlSeconds: 60 });
13
+ *
14
+ * Fluxo: o hook `onRequest` checa o cache e, num HIT, responde imediatamente
15
+ * (curto-circuito). Num MISS, o hook `onSend` guarda o payload serializado.
16
+ */
17
+
18
+ interface CachePluginOptions {
19
+ /** Instância de cache a usar. */
20
+ cache: Cache;
21
+ /** TTL aplicado às respostas guardadas (em segundos). */
22
+ ttlSeconds?: number;
23
+ /** Métodos HTTP elegíveis para cache. Padrão: `["GET"]`. */
24
+ methods?: string[];
25
+ /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */
26
+ keyGenerator?: (req: FastifyRequest) => string;
27
+ }
28
+ /**
29
+ * Plugin Fastify que cacheia respostas JSON. Use com `fastify.register`.
30
+ */
31
+ declare function cachePlugin(fastify: FastifyInstance, options: CachePluginOptions): Promise<void>;
32
+
33
+ export { type CachePluginOptions, cachePlugin };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // js/fastify.ts
21
+ var fastify_exports = {};
22
+ __export(fastify_exports, {
23
+ cachePlugin: () => cachePlugin
24
+ });
25
+ module.exports = __toCommonJS(fastify_exports);
26
+ var CACHE_KEY = /* @__PURE__ */ Symbol("rustNodeCacheKey");
27
+ async function cachePlugin(fastify, options) {
28
+ const { cache } = options;
29
+ const ttlSeconds = options.ttlSeconds;
30
+ const methods = options.methods ?? ["GET"];
31
+ const keyGenerator = options.keyGenerator ?? ((req) => `${req.method}:${req.url}`);
32
+ fastify.addHook(
33
+ "onRequest",
34
+ (request, reply, done) => {
35
+ if (!methods.includes(request.method)) {
36
+ done();
37
+ return;
38
+ }
39
+ const key = keyGenerator(request);
40
+ const cached = cache.get(key);
41
+ if (cached !== null) {
42
+ reply.header("X-Cache", "HIT");
43
+ reply.send(cached);
44
+ return;
45
+ }
46
+ reply.header("X-Cache", "MISS");
47
+ request[CACHE_KEY] = key;
48
+ done();
49
+ }
50
+ );
51
+ fastify.addHook(
52
+ "onSend",
53
+ (request, reply, payload, done) => {
54
+ const key = request[CACHE_KEY];
55
+ if (key && typeof payload === "string" && reply.statusCode >= 200 && reply.statusCode < 300) {
56
+ try {
57
+ cache.set(
58
+ key,
59
+ JSON.parse(payload),
60
+ ttlSeconds ? { ttlSeconds } : void 0
61
+ );
62
+ } catch {
63
+ }
64
+ }
65
+ done(null, payload);
66
+ }
67
+ );
68
+ }
69
+ // Annotate the CommonJS export names for ESM import in node:
70
+ 0 && (module.exports = {
71
+ cachePlugin
72
+ });
73
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../js/fastify.ts"],"sourcesContent":["/**\n * Integração com Fastify: cache de respostas JSON via plugin.\n *\n * Uso:\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 * Fluxo: o hook `onRequest` checa o cache e, num HIT, responde imediatamente\n * (curto-circuito). Num MISS, o hook `onSend` guarda o payload serializado.\n */\n\nimport type {\n FastifyInstance,\n FastifyReply,\n FastifyRequest,\n} from \"fastify\";\nimport type { Cache } from \"./index\";\n\nexport interface CachePluginOptions {\n /** Instância de cache a usar. */\n cache: Cache;\n /** TTL aplicado às respostas guardadas (em segundos). */\n ttlSeconds?: number;\n /** Métodos HTTP elegíveis para cache. Padrão: `[\"GET\"]`. */\n methods?: string[];\n /** Gera a chave de cache a partir da requisição. Padrão: `METHOD:url`. */\n keyGenerator?: (req: FastifyRequest) => string;\n}\n\n// Guardamos a chave calculada na própria request entre os hooks.\nconst CACHE_KEY = Symbol(\"rustNodeCacheKey\");\n\n/**\n * Plugin Fastify que cacheia respostas JSON. Use com `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; // não chama done(): a resposta já foi enviada.\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 // payload não-JSON: simplesmente não cacheia.\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":[]}