@bymax-one/nest-cache 1.2.6 → 1.2.7
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 +25 -1
- package/dist/server/index.cjs +19 -8
- package/dist/server/index.mjs +19 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,29 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
### Tests
|
|
10
|
+
|
|
11
|
+
- `src/readme-quickstart.spec.ts` runs the README Quick Start as written: the standalone module and the
|
|
12
|
+
`ProfileService` cache-aside flow, over an in-memory Redis, asserting that the value is stored under
|
|
13
|
+
`app:user-profile:<userId>` with a 3600-second TTL and served from the cache on the second call. The
|
|
14
|
+
snippet gate compiles the Quick Start but cannot run it.
|
|
15
|
+
|
|
16
|
+
## [1.2.7] - 2026-11-01
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- A thrown or rejected value that cannot be printed no longer makes the error path throw. Caught values
|
|
21
|
+
were turned into text with `err instanceof Error ? err.message : String(err)`, and
|
|
22
|
+
`String()` throws for an object with no prototype (`Object.create(null)`) or a `toString` that throws.
|
|
23
|
+
A `toJSON` hook that threw such a value escaped `JsonSerializer.serialize` as a `TypeError` instead of
|
|
24
|
+
`cache.serialization_failed`; a Redis script rejection of that kind escaped `ScriptManagerService.eval`
|
|
25
|
+
as a `TypeError` instead of `cache.script_execution_failed`; and a Pub/Sub handler that threw one was
|
|
26
|
+
never reported to `onEvent`, because the reporter threw inside its own guard.
|
|
27
|
+
- Those sites now share a `describeError` helper that never throws. It reads a string `message`
|
|
28
|
+
from the value itself instead of testing `instanceof Error`, which is false for an `Error` created in
|
|
29
|
+
another realm (`vm`, a worker) and for an error-shaped object; otherwise it uses `String()`, and
|
|
30
|
+
falls back to the fixed text `unprintable error`.
|
|
31
|
+
|
|
9
32
|
## [1.2.6] - 2026-10-31
|
|
10
33
|
|
|
11
34
|
### Added
|
|
@@ -496,7 +519,8 @@ type or export moved.
|
|
|
496
519
|
- Published with npm OIDC provenance — no long-lived tokens
|
|
497
520
|
- Zero direct runtime dependencies (`dependencies: {}`) — `ioredis` and NestJS via peer deps
|
|
498
521
|
|
|
499
|
-
[Unreleased]: https://github.com/bymaxone/nest-cache/compare/v1.2.
|
|
522
|
+
[Unreleased]: https://github.com/bymaxone/nest-cache/compare/v1.2.7...HEAD
|
|
523
|
+
[1.2.7]: https://github.com/bymaxone/nest-cache/compare/v1.2.6...v1.2.7
|
|
500
524
|
[1.2.6]: https://github.com/bymaxone/nest-cache/compare/v1.2.5...v1.2.6
|
|
501
525
|
[1.2.5]: https://github.com/bymaxone/nest-cache/compare/v1.2.4...v1.2.5
|
|
502
526
|
[1.2.4]: https://github.com/bymaxone/nest-cache/compare/v1.2.3...v1.2.4
|
package/dist/server/index.cjs
CHANGED
|
@@ -527,9 +527,21 @@ exports.ConnectionManager = __decorateClass([
|
|
|
527
527
|
__decorateParam(1, common.Optional()),
|
|
528
528
|
__decorateParam(1, common.Inject(BYMAX_CACHE_EVENTS))
|
|
529
529
|
], exports.ConnectionManager);
|
|
530
|
+
|
|
531
|
+
// src/server/utils/describe-error.ts
|
|
532
|
+
var UNPRINTABLE = "unprintable error";
|
|
533
|
+
function describeError(reason) {
|
|
534
|
+
try {
|
|
535
|
+
const message = reason?.message;
|
|
536
|
+
return typeof message === "string" ? message : String(reason);
|
|
537
|
+
} catch {
|
|
538
|
+
return UNPRINTABLE;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// src/server/services/script-manager.service.ts
|
|
530
543
|
var SCRIPT_LOAD = "LOAD";
|
|
531
544
|
var NOSCRIPT_MARKER = "NOSCRIPT";
|
|
532
|
-
var toErrorMessage = (err) => err instanceof Error ? err.message : String(err);
|
|
533
545
|
exports.ScriptManagerService = class ScriptManagerService {
|
|
534
546
|
/**
|
|
535
547
|
* @param options - Resolved module options; `options.scripts` seeds the registry.
|
|
@@ -637,7 +649,7 @@ exports.ScriptManagerService = class ScriptManagerService {
|
|
|
637
649
|
} catch (err) {
|
|
638
650
|
throw new CacheException(CACHE_ERROR_CODES.SCRIPT_EXECUTION_FAILED, {
|
|
639
651
|
name,
|
|
640
|
-
originalError:
|
|
652
|
+
originalError: describeError(err)
|
|
641
653
|
});
|
|
642
654
|
}
|
|
643
655
|
}
|
|
@@ -645,10 +657,10 @@ exports.ScriptManagerService = class ScriptManagerService {
|
|
|
645
657
|
const sha = entry.sha ?? await this.load(name);
|
|
646
658
|
return await client.evalsha(sha, keys.length, ...keys, ...args);
|
|
647
659
|
} catch (err) {
|
|
648
|
-
if (!
|
|
660
|
+
if (!describeError(err).includes(NOSCRIPT_MARKER)) {
|
|
649
661
|
throw new CacheException(CACHE_ERROR_CODES.SCRIPT_EXECUTION_FAILED, {
|
|
650
662
|
name,
|
|
651
|
-
originalError:
|
|
663
|
+
originalError: describeError(err)
|
|
652
664
|
});
|
|
653
665
|
}
|
|
654
666
|
try {
|
|
@@ -658,7 +670,7 @@ exports.ScriptManagerService = class ScriptManagerService {
|
|
|
658
670
|
} catch (retryErr) {
|
|
659
671
|
throw new CacheException(CACHE_ERROR_CODES.SCRIPT_EXECUTION_FAILED, {
|
|
660
672
|
name,
|
|
661
|
-
originalError:
|
|
673
|
+
originalError: describeError(retryErr)
|
|
662
674
|
});
|
|
663
675
|
}
|
|
664
676
|
}
|
|
@@ -723,7 +735,6 @@ exports.KeyBuilder = __decorateClass([
|
|
|
723
735
|
__decorateParam(0, common.Inject(BYMAX_CACHE_OPTIONS))
|
|
724
736
|
], exports.KeyBuilder);
|
|
725
737
|
var DESERIALIZATION_ERROR = "stored value is not valid JSON";
|
|
726
|
-
var extractErrorMessage = (err) => err instanceof Error ? err.message : String(err);
|
|
727
738
|
exports.JsonSerializer = class JsonSerializer {
|
|
728
739
|
/**
|
|
729
740
|
* Encodes a value as a JSON string.
|
|
@@ -749,7 +760,7 @@ exports.JsonSerializer = class JsonSerializer {
|
|
|
749
760
|
return JSON.stringify(value);
|
|
750
761
|
} catch (err) {
|
|
751
762
|
throw new CacheException(CACHE_ERROR_CODES.SERIALIZATION_FAILED, {
|
|
752
|
-
error:
|
|
763
|
+
error: describeError(err)
|
|
753
764
|
});
|
|
754
765
|
}
|
|
755
766
|
}
|
|
@@ -1622,7 +1633,7 @@ exports.PubSubService = class PubSubService {
|
|
|
1622
1633
|
role: "subscriber",
|
|
1623
1634
|
reason: "handler_error",
|
|
1624
1635
|
channel,
|
|
1625
|
-
error:
|
|
1636
|
+
error: describeError(error)
|
|
1626
1637
|
});
|
|
1627
1638
|
} catch {
|
|
1628
1639
|
}
|
package/dist/server/index.mjs
CHANGED
|
@@ -525,9 +525,21 @@ ConnectionManager = __decorateClass([
|
|
|
525
525
|
__decorateParam(1, Optional()),
|
|
526
526
|
__decorateParam(1, Inject(BYMAX_CACHE_EVENTS))
|
|
527
527
|
], ConnectionManager);
|
|
528
|
+
|
|
529
|
+
// src/server/utils/describe-error.ts
|
|
530
|
+
var UNPRINTABLE = "unprintable error";
|
|
531
|
+
function describeError(reason) {
|
|
532
|
+
try {
|
|
533
|
+
const message = reason?.message;
|
|
534
|
+
return typeof message === "string" ? message : String(reason);
|
|
535
|
+
} catch {
|
|
536
|
+
return UNPRINTABLE;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/server/services/script-manager.service.ts
|
|
528
541
|
var SCRIPT_LOAD = "LOAD";
|
|
529
542
|
var NOSCRIPT_MARKER = "NOSCRIPT";
|
|
530
|
-
var toErrorMessage = (err) => err instanceof Error ? err.message : String(err);
|
|
531
543
|
var ScriptManagerService = class {
|
|
532
544
|
/**
|
|
533
545
|
* @param options - Resolved module options; `options.scripts` seeds the registry.
|
|
@@ -635,7 +647,7 @@ var ScriptManagerService = class {
|
|
|
635
647
|
} catch (err) {
|
|
636
648
|
throw new CacheException(CACHE_ERROR_CODES.SCRIPT_EXECUTION_FAILED, {
|
|
637
649
|
name,
|
|
638
|
-
originalError:
|
|
650
|
+
originalError: describeError(err)
|
|
639
651
|
});
|
|
640
652
|
}
|
|
641
653
|
}
|
|
@@ -643,10 +655,10 @@ var ScriptManagerService = class {
|
|
|
643
655
|
const sha = entry.sha ?? await this.load(name);
|
|
644
656
|
return await client.evalsha(sha, keys.length, ...keys, ...args);
|
|
645
657
|
} catch (err) {
|
|
646
|
-
if (!
|
|
658
|
+
if (!describeError(err).includes(NOSCRIPT_MARKER)) {
|
|
647
659
|
throw new CacheException(CACHE_ERROR_CODES.SCRIPT_EXECUTION_FAILED, {
|
|
648
660
|
name,
|
|
649
|
-
originalError:
|
|
661
|
+
originalError: describeError(err)
|
|
650
662
|
});
|
|
651
663
|
}
|
|
652
664
|
try {
|
|
@@ -656,7 +668,7 @@ var ScriptManagerService = class {
|
|
|
656
668
|
} catch (retryErr) {
|
|
657
669
|
throw new CacheException(CACHE_ERROR_CODES.SCRIPT_EXECUTION_FAILED, {
|
|
658
670
|
name,
|
|
659
|
-
originalError:
|
|
671
|
+
originalError: describeError(retryErr)
|
|
660
672
|
});
|
|
661
673
|
}
|
|
662
674
|
}
|
|
@@ -721,7 +733,6 @@ KeyBuilder = __decorateClass([
|
|
|
721
733
|
__decorateParam(0, Inject(BYMAX_CACHE_OPTIONS))
|
|
722
734
|
], KeyBuilder);
|
|
723
735
|
var DESERIALIZATION_ERROR = "stored value is not valid JSON";
|
|
724
|
-
var extractErrorMessage = (err) => err instanceof Error ? err.message : String(err);
|
|
725
736
|
var JsonSerializer = class {
|
|
726
737
|
/**
|
|
727
738
|
* Encodes a value as a JSON string.
|
|
@@ -747,7 +758,7 @@ var JsonSerializer = class {
|
|
|
747
758
|
return JSON.stringify(value);
|
|
748
759
|
} catch (err) {
|
|
749
760
|
throw new CacheException(CACHE_ERROR_CODES.SERIALIZATION_FAILED, {
|
|
750
|
-
error:
|
|
761
|
+
error: describeError(err)
|
|
751
762
|
});
|
|
752
763
|
}
|
|
753
764
|
}
|
|
@@ -1620,7 +1631,7 @@ var PubSubService = class {
|
|
|
1620
1631
|
role: "subscriber",
|
|
1621
1632
|
reason: "handler_error",
|
|
1622
1633
|
channel,
|
|
1623
|
-
error:
|
|
1634
|
+
error: describeError(error)
|
|
1624
1635
|
});
|
|
1625
1636
|
} catch {
|
|
1626
1637
|
}
|
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.7",
|
|
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",
|