@naturalcycles/js-lib 14.85.0 → 14.85.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.
@@ -12,9 +12,12 @@ export interface AsyncMemoOptions {
12
12
  */
13
13
  cacheKeyFn?: (args: any[]) => any;
14
14
  /**
15
- * Set to `true` to cache rejected promises (errors).
15
+ * Default true.
16
16
  *
17
- * Default false.
17
+ * Set to `false` to skip caching rejected promises (errors).
18
+ *
19
+ * True will ensure "max 1 execution", but will "remember" rejection.
20
+ * False will allow >1 execution in case of errors.
18
21
  */
19
22
  cacheRejections?: boolean;
20
23
  /**
@@ -18,7 +18,7 @@ const _AsyncMemo = (opt = {}) => (target, key, descriptor) => {
18
18
  const originalFn = descriptor.value;
19
19
  // Map from "instance" of the Class where @_AsyncMemo is applied to AsyncMemoCache instance.
20
20
  const cache = new Map();
21
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, cacheRejections = false, } = opt;
21
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, cacheRejections = true, } = opt;
22
22
  const keyStr = String(key);
23
23
  const methodSignature = (0, decorator_util_1._getTargetMethodSignature)(target, keyStr);
24
24
  descriptor.value = async function (...args) {
@@ -42,7 +42,10 @@ const _AsyncMemo = (opt = {}) => (target, key, descriptor) => {
42
42
  if (logHit) {
43
43
  logger.log(`${(0, decorator_util_1._getMethodSignature)(ctx, keyStr)}(${(0, decorator_util_1._getArgsSignature)(args, logArgs)}) @_AsyncMemo hit`);
44
44
  }
45
- return value instanceof Error ? Promise.reject(value) : Promise.resolve(value);
45
+ if (value instanceof Error) {
46
+ throw value;
47
+ }
48
+ return value;
46
49
  }
47
50
  // Here we know it's a MISS, let's execute the real method
48
51
  const started = Date.now();
@@ -12,8 +12,11 @@ export interface MemoOptions {
12
12
  */
13
13
  cacheKeyFn?: (args: any[]) => any;
14
14
  /**
15
- * Defaults to false.
16
- * Set to true to cache thrown errors.
15
+ * Defaults to true.
16
+ * Set to false to skip caching errors.
17
+ *
18
+ * True will ensure "max 1 execution", but will "remember" errors.
19
+ * False will allow >1 execution in case of errors.
17
20
  */
18
21
  cacheErrors?: boolean;
19
22
  /**
@@ -37,12 +37,13 @@ const _Memo = (opt = {}) => (target, key, descriptor) => {
37
37
  // UPD: tests show that normal Map also doesn't leak (to be tested further)
38
38
  // Normal Map is needed to allow .dropCache()
39
39
  const cache = new Map();
40
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, cacheErrors = false, } = opt;
40
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, cacheErrors = true, } = opt;
41
41
  const keyStr = String(key);
42
42
  const methodSignature = (0, decorator_util_1._getTargetMethodSignature)(target, keyStr);
43
43
  descriptor.value = function (...args) {
44
44
  const ctx = this;
45
45
  const cacheKey = cacheKeyFn(args);
46
+ let value;
46
47
  if (!cache.has(ctx)) {
47
48
  cache.set(ctx, cacheFactory());
48
49
  }
@@ -50,18 +51,31 @@ const _Memo = (opt = {}) => (target, key, descriptor) => {
50
51
  if (logHit) {
51
52
  logger.log(`${(0, decorator_util_1._getMethodSignature)(ctx, keyStr)}(${(0, decorator_util_1._getArgsSignature)(args, logArgs)}) @_Memo hit`);
52
53
  }
53
- return cache.get(ctx).get(cacheKey);
54
+ value = cache.get(ctx).get(cacheKey);
55
+ if (value instanceof Error) {
56
+ throw value;
57
+ }
58
+ return value;
54
59
  }
55
60
  const started = Date.now();
56
- let value;
57
61
  try {
58
62
  value = originalFn.apply(ctx, args);
59
- cache.get(ctx).set(cacheKey, value);
63
+ try {
64
+ cache.get(ctx).set(cacheKey, value);
65
+ }
66
+ catch (err) {
67
+ logger.error(err);
68
+ }
60
69
  return value;
61
70
  }
62
71
  catch (err) {
63
72
  if (cacheErrors) {
64
- cache.get(ctx).set(cacheKey, err);
73
+ try {
74
+ cache.get(ctx).set(cacheKey, err);
75
+ }
76
+ catch (err) {
77
+ logger.error(err);
78
+ }
65
79
  }
66
80
  throw err;
67
81
  }
@@ -10,28 +10,42 @@ const memo_util_1 = require("./memo.util");
10
10
  * Technically, you can use it with Async functions, but it'll return the Promise without awaiting it.
11
11
  */
12
12
  function _memoFn(fn, opt = {}) {
13
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheErrors = false, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, } = opt;
13
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheErrors = true, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, } = opt;
14
14
  const cache = cacheFactory();
15
15
  const fnName = fn.name;
16
16
  const memoizedFn = function (...args) {
17
17
  const ctx = this;
18
18
  const cacheKey = cacheKeyFn(args);
19
+ let value;
19
20
  if (cache.has(cacheKey)) {
20
21
  if (logHit) {
21
22
  logger.log(`${fnName}(${(0, decorator_util_1._getArgsSignature)(args, logArgs)}) memoFn hit`);
22
23
  }
23
- return cache.get(cacheKey);
24
+ value = cache.get(cacheKey);
25
+ if (value instanceof Error) {
26
+ throw value;
27
+ }
28
+ return value;
24
29
  }
25
30
  const started = Date.now();
26
- let value;
27
31
  try {
28
32
  value = fn.apply(ctx, args);
29
- cache.set(cacheKey, value);
33
+ try {
34
+ cache.set(cacheKey, value);
35
+ }
36
+ catch (err) {
37
+ logger.error(err);
38
+ }
30
39
  return value;
31
40
  }
32
41
  catch (err) {
33
42
  if (cacheErrors) {
34
- cache.set(cacheKey, err);
43
+ try {
44
+ cache.set(cacheKey, err);
45
+ }
46
+ catch (err) {
47
+ logger.error(err);
48
+ }
35
49
  }
36
50
  throw err;
37
51
  }
@@ -9,7 +9,7 @@ const memo_util_1 = require("./memo.util");
9
9
  * To support Async functions - use _memoFnAsync
10
10
  */
11
11
  function _memoFnAsync(fn, opt = {}) {
12
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheRejections = false, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, } = opt;
12
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheRejections = true, cacheFactory = () => new memo_util_1.MapMemoCache(), cacheKeyFn = memo_util_1.jsonMemoSerializer, } = opt;
13
13
  const cache = cacheFactory();
14
14
  const fnName = fn.name;
15
15
  const memoizedFn = async function (...args) {
@@ -26,6 +26,9 @@ function _memoFnAsync(fn, opt = {}) {
26
26
  if (logHit) {
27
27
  logger.log(`${fnName}(${(0, decorator_util_1._getArgsSignature)(args, logArgs)}) memoFnAsync hit`);
28
28
  }
29
+ if (value instanceof Error) {
30
+ throw value;
31
+ }
29
32
  return value;
30
33
  }
31
34
  const started = Date.now();
@@ -15,7 +15,7 @@ export const _AsyncMemo = (opt = {}) => (target, key, descriptor) => {
15
15
  const originalFn = descriptor.value;
16
16
  // Map from "instance" of the Class where @_AsyncMemo is applied to AsyncMemoCache instance.
17
17
  const cache = new Map();
18
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, cacheRejections = false, } = opt;
18
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, cacheRejections = true, } = opt;
19
19
  const keyStr = String(key);
20
20
  const methodSignature = _getTargetMethodSignature(target, keyStr);
21
21
  descriptor.value = async function (...args) {
@@ -39,7 +39,10 @@ export const _AsyncMemo = (opt = {}) => (target, key, descriptor) => {
39
39
  if (logHit) {
40
40
  logger.log(`${_getMethodSignature(ctx, keyStr)}(${_getArgsSignature(args, logArgs)}) @_AsyncMemo hit`);
41
41
  }
42
- return value instanceof Error ? Promise.reject(value) : Promise.resolve(value);
42
+ if (value instanceof Error) {
43
+ throw value;
44
+ }
45
+ return value;
43
46
  }
44
47
  // Here we know it's a MISS, let's execute the real method
45
48
  const started = Date.now();
@@ -34,12 +34,13 @@ export const _Memo = (opt = {}) => (target, key, descriptor) => {
34
34
  // UPD: tests show that normal Map also doesn't leak (to be tested further)
35
35
  // Normal Map is needed to allow .dropCache()
36
36
  const cache = new Map();
37
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, cacheErrors = false, } = opt;
37
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, cacheErrors = true, } = opt;
38
38
  const keyStr = String(key);
39
39
  const methodSignature = _getTargetMethodSignature(target, keyStr);
40
40
  descriptor.value = function (...args) {
41
41
  const ctx = this;
42
42
  const cacheKey = cacheKeyFn(args);
43
+ let value;
43
44
  if (!cache.has(ctx)) {
44
45
  cache.set(ctx, cacheFactory());
45
46
  }
@@ -47,18 +48,31 @@ export const _Memo = (opt = {}) => (target, key, descriptor) => {
47
48
  if (logHit) {
48
49
  logger.log(`${_getMethodSignature(ctx, keyStr)}(${_getArgsSignature(args, logArgs)}) @_Memo hit`);
49
50
  }
50
- return cache.get(ctx).get(cacheKey);
51
+ value = cache.get(ctx).get(cacheKey);
52
+ if (value instanceof Error) {
53
+ throw value;
54
+ }
55
+ return value;
51
56
  }
52
57
  const started = Date.now();
53
- let value;
54
58
  try {
55
59
  value = originalFn.apply(ctx, args);
56
- cache.get(ctx).set(cacheKey, value);
60
+ try {
61
+ cache.get(ctx).set(cacheKey, value);
62
+ }
63
+ catch (err) {
64
+ logger.error(err);
65
+ }
57
66
  return value;
58
67
  }
59
68
  catch (err) {
60
69
  if (cacheErrors) {
61
- cache.get(ctx).set(cacheKey, err);
70
+ try {
71
+ cache.get(ctx).set(cacheKey, err);
72
+ }
73
+ catch (err) {
74
+ logger.error(err);
75
+ }
62
76
  }
63
77
  throw err;
64
78
  }
@@ -7,28 +7,42 @@ import { jsonMemoSerializer, MapMemoCache } from './memo.util';
7
7
  * Technically, you can use it with Async functions, but it'll return the Promise without awaiting it.
8
8
  */
9
9
  export function _memoFn(fn, opt = {}) {
10
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheErrors = false, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, } = opt;
10
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheErrors = true, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, } = opt;
11
11
  const cache = cacheFactory();
12
12
  const fnName = fn.name;
13
13
  const memoizedFn = function (...args) {
14
14
  const ctx = this;
15
15
  const cacheKey = cacheKeyFn(args);
16
+ let value;
16
17
  if (cache.has(cacheKey)) {
17
18
  if (logHit) {
18
19
  logger.log(`${fnName}(${_getArgsSignature(args, logArgs)}) memoFn hit`);
19
20
  }
20
- return cache.get(cacheKey);
21
+ value = cache.get(cacheKey);
22
+ if (value instanceof Error) {
23
+ throw value;
24
+ }
25
+ return value;
21
26
  }
22
27
  const started = Date.now();
23
- let value;
24
28
  try {
25
29
  value = fn.apply(ctx, args);
26
- cache.set(cacheKey, value);
30
+ try {
31
+ cache.set(cacheKey, value);
32
+ }
33
+ catch (err) {
34
+ logger.error(err);
35
+ }
27
36
  return value;
28
37
  }
29
38
  catch (err) {
30
39
  if (cacheErrors) {
31
- cache.set(cacheKey, err);
40
+ try {
41
+ cache.set(cacheKey, err);
42
+ }
43
+ catch (err) {
44
+ logger.error(err);
45
+ }
32
46
  }
33
47
  throw err;
34
48
  }
@@ -6,7 +6,7 @@ import { jsonMemoSerializer, MapMemoCache } from './memo.util';
6
6
  * To support Async functions - use _memoFnAsync
7
7
  */
8
8
  export function _memoFnAsync(fn, opt = {}) {
9
- const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheRejections = false, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, } = opt;
9
+ const { logHit = false, logMiss = false, logArgs = true, logger = console, cacheRejections = true, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, } = opt;
10
10
  const cache = cacheFactory();
11
11
  const fnName = fn.name;
12
12
  const memoizedFn = async function (...args) {
@@ -23,6 +23,9 @@ export function _memoFnAsync(fn, opt = {}) {
23
23
  if (logHit) {
24
24
  logger.log(`${fnName}(${_getArgsSignature(args, logArgs)}) memoFnAsync hit`);
25
25
  }
26
+ if (value instanceof Error) {
27
+ throw value;
28
+ }
26
29
  return value;
27
30
  }
28
31
  const started = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.85.0",
3
+ "version": "14.85.1",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -18,9 +18,12 @@ export interface AsyncMemoOptions {
18
18
  cacheKeyFn?: (args: any[]) => any
19
19
 
20
20
  /**
21
- * Set to `true` to cache rejected promises (errors).
21
+ * Default true.
22
22
  *
23
- * Default false.
23
+ * Set to `false` to skip caching rejected promises (errors).
24
+ *
25
+ * True will ensure "max 1 execution", but will "remember" rejection.
26
+ * False will allow >1 execution in case of errors.
24
27
  */
25
28
  cacheRejections?: boolean
26
29
 
@@ -73,7 +76,7 @@ export const _AsyncMemo =
73
76
  logger = console,
74
77
  cacheFactory = () => new MapMemoCache(),
75
78
  cacheKeyFn = jsonMemoSerializer,
76
- cacheRejections = false,
79
+ cacheRejections = true,
77
80
  } = opt
78
81
 
79
82
  const keyStr = String(key)
@@ -110,7 +113,11 @@ export const _AsyncMemo =
110
113
  )
111
114
  }
112
115
 
113
- return value instanceof Error ? Promise.reject(value) : Promise.resolve(value)
116
+ if (value instanceof Error) {
117
+ throw value
118
+ }
119
+
120
+ return value
114
121
  }
115
122
 
116
123
  // Here we know it's a MISS, let's execute the real method
@@ -18,8 +18,11 @@ export interface MemoOptions {
18
18
  cacheKeyFn?: (args: any[]) => any
19
19
 
20
20
  /**
21
- * Defaults to false.
22
- * Set to true to cache thrown errors.
21
+ * Defaults to true.
22
+ * Set to false to skip caching errors.
23
+ *
24
+ * True will ensure "max 1 execution", but will "remember" errors.
25
+ * False will allow >1 execution in case of errors.
23
26
  */
24
27
  cacheErrors?: boolean
25
28
 
@@ -89,7 +92,7 @@ export const _Memo =
89
92
  logger = console,
90
93
  cacheFactory = () => new MapMemoCache(),
91
94
  cacheKeyFn = jsonMemoSerializer,
92
- cacheErrors = false,
95
+ cacheErrors = true,
93
96
  } = opt
94
97
 
95
98
  const keyStr = String(key)
@@ -97,8 +100,8 @@ export const _Memo =
97
100
 
98
101
  descriptor.value = function (this: typeof target, ...args: any[]): any {
99
102
  const ctx = this
100
-
101
103
  const cacheKey = cacheKeyFn(args)
104
+ let value: any
102
105
 
103
106
  if (!cache.has(ctx)) {
104
107
  cache.set(ctx, cacheFactory())
@@ -109,21 +112,34 @@ export const _Memo =
109
112
  )
110
113
  }
111
114
 
112
- return cache.get(ctx)!.get(cacheKey)
115
+ value = cache.get(ctx)!.get(cacheKey)
116
+
117
+ if (value instanceof Error) {
118
+ throw value
119
+ }
120
+
121
+ return value
113
122
  }
114
123
 
115
124
  const started = Date.now()
116
- let value: any
117
125
 
118
126
  try {
119
127
  value = originalFn.apply(ctx, args)
120
128
 
121
- cache.get(ctx)!.set(cacheKey, value)
129
+ try {
130
+ cache.get(ctx)!.set(cacheKey, value)
131
+ } catch (err) {
132
+ logger.error(err)
133
+ }
122
134
 
123
135
  return value
124
136
  } catch (err) {
125
137
  if (cacheErrors) {
126
- cache.get(ctx)!.set(cacheKey, err)
138
+ try {
139
+ cache.get(ctx)!.set(cacheKey, err)
140
+ } catch (err) {
141
+ logger.error(err)
142
+ }
127
143
  }
128
144
 
129
145
  throw err
@@ -21,7 +21,7 @@ export function _memoFn<T extends (...args: any[]) => any>(
21
21
  logMiss = false,
22
22
  logArgs = true,
23
23
  logger = console,
24
- cacheErrors = false,
24
+ cacheErrors = true,
25
25
  cacheFactory = () => new MapMemoCache(),
26
26
  cacheKeyFn = jsonMemoSerializer,
27
27
  } = opt
@@ -32,28 +32,41 @@ export function _memoFn<T extends (...args: any[]) => any>(
32
32
  const memoizedFn = function (this: any, ...args: any[]): T {
33
33
  const ctx = this
34
34
  const cacheKey = cacheKeyFn(args)
35
+ let value: any
35
36
 
36
37
  if (cache.has(cacheKey)) {
37
38
  if (logHit) {
38
39
  logger.log(`${fnName}(${_getArgsSignature(args, logArgs)}) memoFn hit`)
39
40
  }
40
41
 
41
- return cache.get(cacheKey)
42
+ value = cache.get(cacheKey)
43
+
44
+ if (value instanceof Error) {
45
+ throw value
46
+ }
47
+
48
+ return value
42
49
  }
43
50
 
44
51
  const started = Date.now()
45
52
 
46
- let value: any
47
-
48
53
  try {
49
54
  value = fn.apply(ctx, args)
50
55
 
51
- cache.set(cacheKey, value)
56
+ try {
57
+ cache.set(cacheKey, value)
58
+ } catch (err) {
59
+ logger.error(err)
60
+ }
52
61
 
53
62
  return value
54
63
  } catch (err) {
55
64
  if (cacheErrors) {
56
- cache.set(cacheKey, err)
65
+ try {
66
+ cache.set(cacheKey, err)
67
+ } catch (err) {
68
+ logger.error(err)
69
+ }
57
70
  }
58
71
 
59
72
  throw err
@@ -20,7 +20,7 @@ export function _memoFnAsync<T extends (...args: any[]) => Promise<any>>(
20
20
  logMiss = false,
21
21
  logArgs = true,
22
22
  logger = console,
23
- cacheRejections = false,
23
+ cacheRejections = true,
24
24
  cacheFactory = () => new MapMemoCache(),
25
25
  cacheKeyFn = jsonMemoSerializer,
26
26
  } = opt
@@ -44,6 +44,10 @@ export function _memoFnAsync<T extends (...args: any[]) => Promise<any>>(
44
44
  logger.log(`${fnName}(${_getArgsSignature(args, logArgs)}) memoFnAsync hit`)
45
45
  }
46
46
 
47
+ if (value instanceof Error) {
48
+ throw value
49
+ }
50
+
47
51
  return value
48
52
  }
49
53