layercache 1.3.0 → 1.3.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 +2 -13
- package/dist/cli.cjs +23 -1
- package/dist/cli.js +23 -1
- package/dist/{edge-BXWTKlI1.d.cts → edge-CUHTP9Bc.d.cts} +2 -0
- package/dist/{edge-BXWTKlI1.d.ts → edge-CUHTP9Bc.d.ts} +2 -0
- package/dist/edge.d.cts +1 -1
- package/dist/edge.d.ts +1 -1
- package/dist/index.cjs +267 -31
- package/dist/index.d.cts +48 -3
- package/dist/index.d.ts +48 -3
- package/dist/index.js +265 -29
- package/package.json +1 -1
- package/packages/nestjs/dist/index.cjs +57 -11
- package/packages/nestjs/dist/index.d.cts +2 -0
- package/packages/nestjs/dist/index.d.ts +2 -0
- package/packages/nestjs/dist/index.js +57 -11
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache_2.0-green" alt="license"></a>
|
|
16
16
|
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-first-3178C6?logo=typescript&logoColor=white" alt="TypeScript"></a>
|
|
17
17
|
<img src="https://img.shields.io/badge/Node.js-%E2%89%A5_20-339933?logo=nodedotjs&logoColor=white" alt="Node.js >= 20">
|
|
18
|
-
<img src="https://img.shields.io/badge/tests-
|
|
18
|
+
<img src="https://img.shields.io/badge/tests-467_passing-brightgreen" alt="tests">
|
|
19
19
|
<a href="https://coveralls.io/github/flyingsquirrel0419/layercache?branch=main"><img src="https://coveralls.io/repos/github/flyingsquirrel0419/layercache/badge.svg?branch=main&t=20260410" alt="Coveralls"></a>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
@@ -326,18 +326,7 @@ const cache = new CacheStack(
|
|
|
326
326
|
└─────────────────────┴────────┘
|
|
327
327
|
```
|
|
328
328
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
```bash
|
|
332
|
-
npm run bench:direct
|
|
333
|
-
npm run bench:edge
|
|
334
|
-
npm run bench:slow-redis
|
|
335
|
-
npm run bench:queue-amplification
|
|
336
|
-
npm run bench:http
|
|
337
|
-
npm run bench:multi-process-fanout
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
The benchmark harness defaults to `/root/cache-test/data/users.json` so the in-repo scripts stay aligned with the external reproduction workspace. Set `LAYERCACHE_BENCH_FIXTURE_PATH` if you want to point at a different workload fixture.
|
|
329
|
+
Benchmark commands, fixtures, and scenario notes live in [docs/benchmarking.md](./docs/benchmarking.md).
|
|
341
330
|
|
|
342
331
|
---
|
|
343
332
|
|
package/dist/cli.cjs
CHANGED
|
@@ -365,6 +365,18 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
365
365
|
process.exitCode = 1;
|
|
366
366
|
return;
|
|
367
367
|
}
|
|
368
|
+
if (isPlaintextRedisUrl(redisUrl)) {
|
|
369
|
+
if (args.requireTls) {
|
|
370
|
+
process.stderr.write(
|
|
371
|
+
"Error: --require-tls is set but the URL uses redis:// (plaintext). Use rediss:// for TLS-encrypted connections.\n"
|
|
372
|
+
);
|
|
373
|
+
process.exitCode = 1;
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
process.stderr.write(
|
|
377
|
+
"Warning: connecting to Redis without TLS (redis://). All data including cached values and credentials will be transmitted in plaintext. Use rediss:// in production environments, or set --require-tls.\n"
|
|
378
|
+
);
|
|
379
|
+
}
|
|
368
380
|
const redis = new import_ioredis.default(redisUrl, {
|
|
369
381
|
connectTimeout: CONNECT_TIMEOUT_MS,
|
|
370
382
|
lazyConnect: true,
|
|
@@ -484,6 +496,8 @@ function parseArgs(argv) {
|
|
|
484
496
|
} else if (token === "--tag-index-prefix") {
|
|
485
497
|
parsed.tagIndexPrefix = value;
|
|
486
498
|
index += 1;
|
|
499
|
+
} else if (token === "--require-tls") {
|
|
500
|
+
parsed.requireTls = true;
|
|
487
501
|
}
|
|
488
502
|
}
|
|
489
503
|
return parsed;
|
|
@@ -515,7 +529,7 @@ async function scanKeys(redis, pattern) {
|
|
|
515
529
|
}
|
|
516
530
|
function printUsage() {
|
|
517
531
|
process.stdout.write(
|
|
518
|
-
"Usage:\n layercache stats --redis <url> [--pattern <glob>]\n layercache keys --redis <url> [--pattern <glob>]\n layercache inspect --redis <url> --key <key>\n layercache invalidate --redis <url> [--pattern <glob> | --tag <tag>] [--tag-index-prefix <prefix>]\n\nOptions:\n --redis <url> Redis connection URL (e.g. redis://localhost:6379)\n --pattern <glob> Glob pattern to filter keys (default: *)\n --key <key> Exact cache key to inspect\n --tag <tag> Invalidate by tag name\n --tag-index-prefix <prefix> Redis key prefix for tag index (default: layercache:tag-index)\n"
|
|
532
|
+
"Usage:\n layercache stats --redis <url> [--pattern <glob>]\n layercache keys --redis <url> [--pattern <glob>]\n layercache inspect --redis <url> --key <key>\n layercache invalidate --redis <url> [--pattern <glob> | --tag <tag>] [--tag-index-prefix <prefix>]\n\nOptions:\n --redis <url> Redis connection URL (e.g. redis://localhost:6379)\n --pattern <glob> Glob pattern to filter keys (default: *)\n --key <key> Exact cache key to inspect\n --tag <tag> Invalidate by tag name\n --tag-index-prefix <prefix> Redis key prefix for tag index (default: layercache:tag-index)\n --require-tls Reject non-TLS (redis://) connections\n"
|
|
519
533
|
);
|
|
520
534
|
}
|
|
521
535
|
function decodeInspectablePayload(payload) {
|
|
@@ -541,6 +555,14 @@ function summarizeInspectableValue(value) {
|
|
|
541
555
|
}
|
|
542
556
|
return value;
|
|
543
557
|
}
|
|
558
|
+
function isPlaintextRedisUrl(url) {
|
|
559
|
+
try {
|
|
560
|
+
const parsed = new URL(url);
|
|
561
|
+
return parsed.protocol === "redis:";
|
|
562
|
+
} catch {
|
|
563
|
+
return true;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
544
566
|
function maskRedisUrl(url) {
|
|
545
567
|
try {
|
|
546
568
|
const parsed = new URL(url);
|
package/dist/cli.js
CHANGED
|
@@ -23,6 +23,18 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
23
23
|
process.exitCode = 1;
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
+
if (isPlaintextRedisUrl(redisUrl)) {
|
|
27
|
+
if (args.requireTls) {
|
|
28
|
+
process.stderr.write(
|
|
29
|
+
"Error: --require-tls is set but the URL uses redis:// (plaintext). Use rediss:// for TLS-encrypted connections.\n"
|
|
30
|
+
);
|
|
31
|
+
process.exitCode = 1;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
process.stderr.write(
|
|
35
|
+
"Warning: connecting to Redis without TLS (redis://). All data including cached values and credentials will be transmitted in plaintext. Use rediss:// in production environments, or set --require-tls.\n"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
26
38
|
const redis = new Redis(redisUrl, {
|
|
27
39
|
connectTimeout: CONNECT_TIMEOUT_MS,
|
|
28
40
|
lazyConnect: true,
|
|
@@ -142,6 +154,8 @@ function parseArgs(argv) {
|
|
|
142
154
|
} else if (token === "--tag-index-prefix") {
|
|
143
155
|
parsed.tagIndexPrefix = value;
|
|
144
156
|
index += 1;
|
|
157
|
+
} else if (token === "--require-tls") {
|
|
158
|
+
parsed.requireTls = true;
|
|
145
159
|
}
|
|
146
160
|
}
|
|
147
161
|
return parsed;
|
|
@@ -173,7 +187,7 @@ async function scanKeys(redis, pattern) {
|
|
|
173
187
|
}
|
|
174
188
|
function printUsage() {
|
|
175
189
|
process.stdout.write(
|
|
176
|
-
"Usage:\n layercache stats --redis <url> [--pattern <glob>]\n layercache keys --redis <url> [--pattern <glob>]\n layercache inspect --redis <url> --key <key>\n layercache invalidate --redis <url> [--pattern <glob> | --tag <tag>] [--tag-index-prefix <prefix>]\n\nOptions:\n --redis <url> Redis connection URL (e.g. redis://localhost:6379)\n --pattern <glob> Glob pattern to filter keys (default: *)\n --key <key> Exact cache key to inspect\n --tag <tag> Invalidate by tag name\n --tag-index-prefix <prefix> Redis key prefix for tag index (default: layercache:tag-index)\n"
|
|
190
|
+
"Usage:\n layercache stats --redis <url> [--pattern <glob>]\n layercache keys --redis <url> [--pattern <glob>]\n layercache inspect --redis <url> --key <key>\n layercache invalidate --redis <url> [--pattern <glob> | --tag <tag>] [--tag-index-prefix <prefix>]\n\nOptions:\n --redis <url> Redis connection URL (e.g. redis://localhost:6379)\n --pattern <glob> Glob pattern to filter keys (default: *)\n --key <key> Exact cache key to inspect\n --tag <tag> Invalidate by tag name\n --tag-index-prefix <prefix> Redis key prefix for tag index (default: layercache:tag-index)\n --require-tls Reject non-TLS (redis://) connections\n"
|
|
177
191
|
);
|
|
178
192
|
}
|
|
179
193
|
function decodeInspectablePayload(payload) {
|
|
@@ -199,6 +213,14 @@ function summarizeInspectableValue(value) {
|
|
|
199
213
|
}
|
|
200
214
|
return value;
|
|
201
215
|
}
|
|
216
|
+
function isPlaintextRedisUrl(url) {
|
|
217
|
+
try {
|
|
218
|
+
const parsed = new URL(url);
|
|
219
|
+
return parsed.protocol === "redis:";
|
|
220
|
+
} catch {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
202
224
|
function maskRedisUrl(url) {
|
|
203
225
|
try {
|
|
204
226
|
const parsed = new URL(url);
|
|
@@ -178,6 +178,8 @@ interface CacheStackOptions {
|
|
|
178
178
|
logger?: CacheLogger | boolean;
|
|
179
179
|
metrics?: boolean;
|
|
180
180
|
stampedePrevention?: boolean;
|
|
181
|
+
stampedeMaxInFlight?: number;
|
|
182
|
+
stampedeEntryTimeoutMs?: number;
|
|
181
183
|
invalidationBus?: InvalidationBus;
|
|
182
184
|
tagIndex?: CacheTagIndex;
|
|
183
185
|
generation?: number;
|
|
@@ -178,6 +178,8 @@ interface CacheStackOptions {
|
|
|
178
178
|
logger?: CacheLogger | boolean;
|
|
179
179
|
metrics?: boolean;
|
|
180
180
|
stampedePrevention?: boolean;
|
|
181
|
+
stampedeMaxInFlight?: number;
|
|
182
|
+
stampedeEntryTimeoutMs?: number;
|
|
181
183
|
invalidationBus?: InvalidationBus;
|
|
182
184
|
tagIndex?: CacheTagIndex;
|
|
183
185
|
generation?: number;
|
package/dist/edge.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-
|
|
1
|
+
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-CUHTP9Bc.cjs';
|
|
2
2
|
import 'node:events';
|
package/dist/edge.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-
|
|
1
|
+
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-CUHTP9Bc.js';
|
|
2
2
|
import 'node:events';
|