@bymax-one/nest-cache 1.2.0 → 1.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/CHANGELOG.md +22 -0
- package/README.md +41 -0
- package/dist/admin/index.cjs +5 -1
- package/dist/admin/index.d.cts +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.mjs +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ All notable changes to this project are documented in this file. The format is
|
|
|
4
4
|
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
|
|
5
5
|
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.2.1] - 2026-08-21
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **`RevealedValue`'s hash arm now names each entry `field`, not `name`**
|
|
12
|
+
(`{ field, value }`). Redis's own vocabulary for a hash is field/value —
|
|
13
|
+
`HSET key field value`, `HDEL key field`, and `HGETALL` returns field-value
|
|
14
|
+
pairs — so a generic `name` lost the domain term in the one place a reader
|
|
15
|
+
would check the shape against the server's documentation.
|
|
16
|
+
|
|
17
|
+
This is a **type-level breaking change** shipped as a patch, deliberately and
|
|
18
|
+
with the trade-off stated: `RevealedValue` was published in 1.2.0 roughly an
|
|
19
|
+
hour earlier, no consumer had wired it yet, and correcting a freshly published
|
|
20
|
+
name is cheaper than carrying a permanent vocabulary mismatch or maintaining
|
|
21
|
+
two names for one concept. A consumer that already destructured `name` gets a
|
|
22
|
+
compile error, not a silent behaviour change.
|
|
23
|
+
|
|
24
|
+
The library emits **one** name. Aliasing `field` and `name` together would have
|
|
25
|
+
been two names for one idea, which is the defect this corrects rather than a
|
|
26
|
+
softer way to ship it.
|
|
27
|
+
|
|
7
28
|
## [1.2.0] - 2026-08-21
|
|
8
29
|
|
|
9
30
|
### Security
|
|
@@ -280,6 +301,7 @@ type or export moved.
|
|
|
280
301
|
- Published with npm OIDC provenance — no long-lived tokens
|
|
281
302
|
- Zero direct runtime dependencies (`dependencies: {}`) — `ioredis` and NestJS via peer deps
|
|
282
303
|
|
|
304
|
+
[1.2.1]: https://github.com/bymaxone/nest-cache/compare/v1.2.0...v1.2.1
|
|
283
305
|
[1.2.0]: https://github.com/bymaxone/nest-cache/compare/v1.1.0...v1.2.0
|
|
284
306
|
[1.1.0]: https://github.com/bymaxone/nest-cache/compare/v1.0.6...v1.1.0
|
|
285
307
|
[1.0.6]: https://github.com/bymaxone/nest-cache/compare/v1.0.5...v1.0.6
|
package/README.md
CHANGED
|
@@ -473,6 +473,47 @@ Do not relax this to be helpful. Widening it later is compatible; a leak is not
|
|
|
473
473
|
|
|
474
474
|
`mode`, `isScanSupported` and `degradedAboveMs` sit **outside** the health union: a cluster deployment that is down should still report that scanning was never going to work.
|
|
475
475
|
|
|
476
|
+
### Reading a value: `revealed` / `withheld` / `missing`
|
|
477
|
+
|
|
478
|
+
`revealValue()` answers with a discriminated union, not a nullable value, because **"I may not tell you" and "there is nothing here" are different answers** and rendering them identically is the defect this whole surface exists to avoid.
|
|
479
|
+
|
|
480
|
+
```ts
|
|
481
|
+
import type { CacheAdminService } from '@bymax-one/nest-cache/admin'
|
|
482
|
+
|
|
483
|
+
async function describeValue(admin: CacheAdminService, scope: string, key: string) {
|
|
484
|
+
const result = await admin.revealValue(scope, key)
|
|
485
|
+
|
|
486
|
+
switch (result.status) {
|
|
487
|
+
case 'revealed':
|
|
488
|
+
// `result.type` is the Redis type; `result.value` is shaped by it.
|
|
489
|
+
return { type: result.type, value: result.value }
|
|
490
|
+
case 'withheld':
|
|
491
|
+
// The scope declares `isReadable: false`. `origin` explains why, verbatim.
|
|
492
|
+
// Listing, types, TTLs and sizes for this key remain available.
|
|
493
|
+
return { refusedBecause: result.origin }
|
|
494
|
+
case 'missing':
|
|
495
|
+
return { gone: true }
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
A withheld value is **not an authorization failure**. The caller is allowed to ask; the deployment declared the keyspace unreadable at wiring, and no credential changes that — so serving it as `403` would tell a client that some other permission would unlock it, which is false.
|
|
501
|
+
|
|
502
|
+
The revealed value is shaped by the key's type:
|
|
503
|
+
|
|
504
|
+
| `value.kind` | Shape | Notes |
|
|
505
|
+
| ------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
506
|
+
| `string` | `{ value: string }` | Truncated to `revealStringLimit` |
|
|
507
|
+
| `hash` | `{ fields: { field, value }[] }` | `field`, matching Redis's own vocabulary (`HSET key field value`) |
|
|
508
|
+
| `members` | `{ members: string[] }` | **Sets and lists both.** The enclosing `type` says which — see the ordering caveat below |
|
|
509
|
+
| `scored` | `{ members: { member, score }[] }` | Sorted sets. `score` is a **string**: parsing to a number would round large integers |
|
|
510
|
+
| `unsupported` | `{ type: RedisKeyType }` | Streams and module types — says so, rather than returning an empty value |
|
|
511
|
+
|
|
512
|
+
Every arm except `unsupported` carries `isComplete`. It is deliberately **positive polarity**: an absent boolean reads as `false`, and under a name like `truncated` that default would be the _reassuring_ answer — a value silently claiming nothing was cut.
|
|
513
|
+
|
|
514
|
+
> [!IMPORTANT]
|
|
515
|
+
> **List order is meaningful; set order is not**, and both arrive in the same `members` array. Nothing in the type stops a renderer from sorting either one. Sorting a set for display is fine; sorting a list is a lie about the data — an `LPUSH` queue shown alphabetically misreports what pops next. Gate any client-side ordering on `type === 'set'`.
|
|
516
|
+
|
|
476
517
|
### Costs the surface does not hide
|
|
477
518
|
|
|
478
519
|
- **`sampledCount` / `sampledBytes`** are sums over a capped `SCAN`, not measurements of the keyspace. `isComplete` is the fact; the names are the guard.
|
package/dist/admin/index.cjs
CHANGED
|
@@ -391,7 +391,11 @@ exports.CacheAdminService = class CacheAdminService {
|
|
|
391
391
|
const kept = all.slice(0, limit);
|
|
392
392
|
return {
|
|
393
393
|
kind: "hash",
|
|
394
|
-
|
|
394
|
+
// `field`, not `name`: Redis's own vocabulary for a hash is field/value
|
|
395
|
+
// (`HSET key field value`, `HDEL key field`). A generic `name` loses the
|
|
396
|
+
// domain term in the one place a reader would check it against the
|
|
397
|
+
// server's documentation.
|
|
398
|
+
fields: kept.map(([field, value]) => ({ field, value })),
|
|
395
399
|
isComplete: kept.length === all.length
|
|
396
400
|
};
|
|
397
401
|
}
|
package/dist/admin/index.d.cts
CHANGED
package/dist/admin/index.d.ts
CHANGED
package/dist/admin/index.mjs
CHANGED
|
@@ -389,7 +389,11 @@ var CacheAdminService = class {
|
|
|
389
389
|
const kept = all.slice(0, limit);
|
|
390
390
|
return {
|
|
391
391
|
kind: "hash",
|
|
392
|
-
|
|
392
|
+
// `field`, not `name`: Redis's own vocabulary for a hash is field/value
|
|
393
|
+
// (`HSET key field value`, `HDEL key field`). A generic `name` loses the
|
|
394
|
+
// domain term in the one place a reader would check it against the
|
|
395
|
+
// server's documentation.
|
|
396
|
+
fields: kept.map(([field, value]) => ({ field, value })),
|
|
393
397
|
isComplete: kept.length === all.length
|
|
394
398
|
};
|
|
395
399
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-cache",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Typed Redis cache for NestJS based on ioredis 6, with namespace strategy, Pub/Sub and Lua script management.",
|
|
5
5
|
"author": "Bymax One <support@bymax.one>",
|
|
6
6
|
"license": "MIT",
|