@ls-stack/utils 2.10.0 → 2.12.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/dist/cache.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/cache.ts
21
21
  var cache_exports = {};
22
22
  __export(cache_exports, {
23
+ RejectValue: () => RejectValue,
23
24
  cachedGetter: () => cachedGetter,
24
25
  createCache: () => createCache
25
26
  });
@@ -43,6 +44,12 @@ function cachedGetter(getter) {
43
44
  }
44
45
  };
45
46
  }
47
+ var RejectValue = class {
48
+ value;
49
+ constructor(value) {
50
+ this.value = value;
51
+ }
52
+ };
46
53
  function createCache({
47
54
  maxCacheSize = 1e3,
48
55
  maxItemAge,
@@ -50,7 +57,7 @@ function createCache({
50
57
  } = {}) {
51
58
  const cache = /* @__PURE__ */ new Map();
52
59
  let lastExpirationCheck = 0;
53
- function checkExpiredItems() {
60
+ function cleanExpiredItems() {
54
61
  const now = Date.now();
55
62
  if (!maxItemAge || now - lastExpirationCheck < expirationThrottle) return;
56
63
  lastExpirationCheck = now;
@@ -77,49 +84,103 @@ function createCache({
77
84
  function isExpired(timestamp, now) {
78
85
  return maxItemAge !== void 0 && now - timestamp > maxItemAge * 1e3;
79
86
  }
80
- function getOrInsert(cacheKey, val) {
81
- const now = Date.now();
82
- const entry = cache.get(cacheKey);
83
- if (!entry || isExpired(entry.timestamp, now)) {
84
- const value = val();
85
- cache.set(cacheKey, { value, timestamp: now });
86
- trimToSize();
87
- checkExpiredItems();
88
- return value;
89
- }
90
- return entry.value;
91
- }
92
- async function getOrInsertAsync(cacheKey, val) {
93
- const entry = cache.get(cacheKey);
94
- if (entry && isPromise(entry.value)) {
87
+ const utils = {
88
+ reject: (value) => new RejectValue(value)
89
+ };
90
+ return {
91
+ getOrInsert(cacheKey, val) {
92
+ const now = Date.now();
93
+ const entry = cache.get(cacheKey);
94
+ if (!entry || isExpired(entry.timestamp, now)) {
95
+ const value = val(utils);
96
+ if (value instanceof RejectValue) {
97
+ return value.value;
98
+ }
99
+ cache.set(cacheKey, { value, timestamp: now });
100
+ trimToSize();
101
+ cleanExpiredItems();
102
+ return value;
103
+ }
104
+ if (isPromise(entry.value)) {
105
+ throw new Error(
106
+ "Cache value is a promise, use getOrInsertAsync instead"
107
+ );
108
+ }
95
109
  return entry.value;
96
- }
97
- const now = Date.now();
98
- if (entry && !isExpired(entry.timestamp, now)) {
110
+ },
111
+ async getOrInsertAsync(cacheKey, val) {
112
+ const entry = cache.get(cacheKey);
113
+ if (entry && isPromise(entry.value)) {
114
+ return entry.value;
115
+ }
116
+ const now = Date.now();
117
+ if (entry && !isExpired(entry.timestamp, now)) {
118
+ return entry.value;
119
+ }
120
+ const promise = val(utils).then((result) => {
121
+ if (result instanceof RejectValue) {
122
+ const cacheValue = cache.get(cacheKey);
123
+ if (cacheValue?.value === promise) {
124
+ cache.delete(cacheKey);
125
+ }
126
+ return result.value;
127
+ }
128
+ cache.set(cacheKey, { value: result, timestamp: Date.now() });
129
+ return result;
130
+ }).catch((error) => {
131
+ cache.delete(cacheKey);
132
+ throw error;
133
+ });
134
+ cache.set(cacheKey, { value: promise, timestamp: now });
135
+ trimToSize();
136
+ cleanExpiredItems();
137
+ return promise;
138
+ },
139
+ clear() {
140
+ cache.clear();
141
+ },
142
+ get(cacheKey) {
143
+ const entry = cache.get(cacheKey);
144
+ if (!entry || isExpired(entry.timestamp, Date.now())) {
145
+ return void 0;
146
+ }
147
+ if (isPromise(entry.value)) {
148
+ throw new Error("Cache value is a promise, use getAsync instead");
149
+ }
99
150
  return entry.value;
100
- }
101
- const promise = val().then((result) => {
102
- cache.set(cacheKey, { value: result, timestamp: Date.now() });
103
- return result;
104
- }).catch((error) => {
105
- cache.delete(cacheKey);
106
- throw error;
107
- });
108
- cache.set(cacheKey, { value: promise, timestamp: now });
109
- trimToSize();
110
- checkExpiredItems();
111
- return promise;
112
- }
113
- return {
114
- getOrInsert,
115
- getOrInsertAsync,
116
- clear: () => cache.clear(),
151
+ },
152
+ set(cacheKey, value) {
153
+ cache.set(cacheKey, { value, timestamp: Date.now() });
154
+ trimToSize();
155
+ cleanExpiredItems();
156
+ },
157
+ async getAsync(cacheKey) {
158
+ const entry = cache.get(cacheKey);
159
+ if (!entry || isExpired(entry.timestamp, Date.now())) {
160
+ return void 0;
161
+ }
162
+ return await entry.value;
163
+ },
164
+ setAsync(cacheKey, value) {
165
+ const promise = value().then((result) => {
166
+ cache.set(cacheKey, { value: result, timestamp: Date.now() });
167
+ return result;
168
+ }).catch((error) => {
169
+ cache.delete(cacheKey);
170
+ throw error;
171
+ });
172
+ cache.set(cacheKey, { value: promise, timestamp: Date.now() });
173
+ trimToSize();
174
+ cleanExpiredItems();
175
+ },
176
+ cleanExpiredItems,
117
177
  /** @internal */
118
- "~cache": cache
178
+ " cache": { map: cache }
119
179
  };
120
180
  }
121
181
  // Annotate the CommonJS export names for ESM import in node:
122
182
  0 && (module.exports = {
183
+ RejectValue,
123
184
  cachedGetter,
124
185
  createCache
125
186
  });
package/dist/cache.d.cts CHANGED
@@ -13,19 +13,35 @@ type Options = {
13
13
  maxItemAge?: number;
14
14
  /**
15
15
  * The throttle for checking expired items in milliseconds.
16
- * @default 10_000
16
+ * @default
17
+ * 10_000
17
18
  */
18
19
  expirationThrottle?: number;
19
20
  };
20
- declare function createCache({ maxCacheSize, maxItemAge, expirationThrottle, }?: Options): {
21
- getOrInsert: <T>(cacheKey: string, val: () => T) => T;
22
- getOrInsertAsync: <T>(cacheKey: string, val: () => Promise<T>) => Promise<T>;
21
+ declare class RejectValue<T> {
22
+ value: T;
23
+ constructor(value: T);
24
+ }
25
+ type Cache<T> = {
26
+ getOrInsert: (cacheKey: string, val: (utils: {
27
+ reject: (value: T) => RejectValue<T>;
28
+ }) => T | RejectValue<T>) => T;
29
+ getOrInsertAsync: (cacheKey: string, val: (utils: {
30
+ reject: (value: T) => RejectValue<T>;
31
+ }) => Promise<T | RejectValue<T>>) => Promise<T>;
23
32
  clear: () => void;
24
- /** @internal */
25
- '~cache': Map<string, {
26
- value: unknown;
27
- timestamp: number;
28
- }>;
33
+ get: (cacheKey: string) => T | undefined;
34
+ set: (cacheKey: string, value: T) => void;
35
+ cleanExpiredItems: () => void;
36
+ getAsync: (cacheKey: string) => Promise<T | undefined>;
37
+ setAsync: (cacheKey: string, value: () => Promise<T>) => void;
38
+ [' cache']: {
39
+ map: Map<string, {
40
+ value: T | Promise<T>;
41
+ timestamp: number;
42
+ }>;
43
+ };
29
44
  };
45
+ declare function createCache<T>({ maxCacheSize, maxItemAge, expirationThrottle, }?: Options): Cache<T>;
30
46
 
31
- export { cachedGetter, createCache };
47
+ export { type Cache, RejectValue, cachedGetter, createCache };
package/dist/cache.d.ts CHANGED
@@ -13,19 +13,35 @@ type Options = {
13
13
  maxItemAge?: number;
14
14
  /**
15
15
  * The throttle for checking expired items in milliseconds.
16
- * @default 10_000
16
+ * @default
17
+ * 10_000
17
18
  */
18
19
  expirationThrottle?: number;
19
20
  };
20
- declare function createCache({ maxCacheSize, maxItemAge, expirationThrottle, }?: Options): {
21
- getOrInsert: <T>(cacheKey: string, val: () => T) => T;
22
- getOrInsertAsync: <T>(cacheKey: string, val: () => Promise<T>) => Promise<T>;
21
+ declare class RejectValue<T> {
22
+ value: T;
23
+ constructor(value: T);
24
+ }
25
+ type Cache<T> = {
26
+ getOrInsert: (cacheKey: string, val: (utils: {
27
+ reject: (value: T) => RejectValue<T>;
28
+ }) => T | RejectValue<T>) => T;
29
+ getOrInsertAsync: (cacheKey: string, val: (utils: {
30
+ reject: (value: T) => RejectValue<T>;
31
+ }) => Promise<T | RejectValue<T>>) => Promise<T>;
23
32
  clear: () => void;
24
- /** @internal */
25
- '~cache': Map<string, {
26
- value: unknown;
27
- timestamp: number;
28
- }>;
33
+ get: (cacheKey: string) => T | undefined;
34
+ set: (cacheKey: string, value: T) => void;
35
+ cleanExpiredItems: () => void;
36
+ getAsync: (cacheKey: string) => Promise<T | undefined>;
37
+ setAsync: (cacheKey: string, value: () => Promise<T>) => void;
38
+ [' cache']: {
39
+ map: Map<string, {
40
+ value: T | Promise<T>;
41
+ timestamp: number;
42
+ }>;
43
+ };
29
44
  };
45
+ declare function createCache<T>({ maxCacheSize, maxItemAge, expirationThrottle, }?: Options): Cache<T>;
30
46
 
31
- export { cachedGetter, createCache };
47
+ export { type Cache, RejectValue, cachedGetter, createCache };
package/dist/cache.js CHANGED
@@ -12,6 +12,12 @@ function cachedGetter(getter) {
12
12
  }
13
13
  };
14
14
  }
15
+ var RejectValue = class {
16
+ value;
17
+ constructor(value) {
18
+ this.value = value;
19
+ }
20
+ };
15
21
  function createCache({
16
22
  maxCacheSize = 1e3,
17
23
  maxItemAge,
@@ -19,7 +25,7 @@ function createCache({
19
25
  } = {}) {
20
26
  const cache = /* @__PURE__ */ new Map();
21
27
  let lastExpirationCheck = 0;
22
- function checkExpiredItems() {
28
+ function cleanExpiredItems() {
23
29
  const now = Date.now();
24
30
  if (!maxItemAge || now - lastExpirationCheck < expirationThrottle) return;
25
31
  lastExpirationCheck = now;
@@ -46,48 +52,102 @@ function createCache({
46
52
  function isExpired(timestamp, now) {
47
53
  return maxItemAge !== void 0 && now - timestamp > maxItemAge * 1e3;
48
54
  }
49
- function getOrInsert(cacheKey, val) {
50
- const now = Date.now();
51
- const entry = cache.get(cacheKey);
52
- if (!entry || isExpired(entry.timestamp, now)) {
53
- const value = val();
54
- cache.set(cacheKey, { value, timestamp: now });
55
- trimToSize();
56
- checkExpiredItems();
57
- return value;
58
- }
59
- return entry.value;
60
- }
61
- async function getOrInsertAsync(cacheKey, val) {
62
- const entry = cache.get(cacheKey);
63
- if (entry && isPromise(entry.value)) {
55
+ const utils = {
56
+ reject: (value) => new RejectValue(value)
57
+ };
58
+ return {
59
+ getOrInsert(cacheKey, val) {
60
+ const now = Date.now();
61
+ const entry = cache.get(cacheKey);
62
+ if (!entry || isExpired(entry.timestamp, now)) {
63
+ const value = val(utils);
64
+ if (value instanceof RejectValue) {
65
+ return value.value;
66
+ }
67
+ cache.set(cacheKey, { value, timestamp: now });
68
+ trimToSize();
69
+ cleanExpiredItems();
70
+ return value;
71
+ }
72
+ if (isPromise(entry.value)) {
73
+ throw new Error(
74
+ "Cache value is a promise, use getOrInsertAsync instead"
75
+ );
76
+ }
64
77
  return entry.value;
65
- }
66
- const now = Date.now();
67
- if (entry && !isExpired(entry.timestamp, now)) {
78
+ },
79
+ async getOrInsertAsync(cacheKey, val) {
80
+ const entry = cache.get(cacheKey);
81
+ if (entry && isPromise(entry.value)) {
82
+ return entry.value;
83
+ }
84
+ const now = Date.now();
85
+ if (entry && !isExpired(entry.timestamp, now)) {
86
+ return entry.value;
87
+ }
88
+ const promise = val(utils).then((result) => {
89
+ if (result instanceof RejectValue) {
90
+ const cacheValue = cache.get(cacheKey);
91
+ if (cacheValue?.value === promise) {
92
+ cache.delete(cacheKey);
93
+ }
94
+ return result.value;
95
+ }
96
+ cache.set(cacheKey, { value: result, timestamp: Date.now() });
97
+ return result;
98
+ }).catch((error) => {
99
+ cache.delete(cacheKey);
100
+ throw error;
101
+ });
102
+ cache.set(cacheKey, { value: promise, timestamp: now });
103
+ trimToSize();
104
+ cleanExpiredItems();
105
+ return promise;
106
+ },
107
+ clear() {
108
+ cache.clear();
109
+ },
110
+ get(cacheKey) {
111
+ const entry = cache.get(cacheKey);
112
+ if (!entry || isExpired(entry.timestamp, Date.now())) {
113
+ return void 0;
114
+ }
115
+ if (isPromise(entry.value)) {
116
+ throw new Error("Cache value is a promise, use getAsync instead");
117
+ }
68
118
  return entry.value;
69
- }
70
- const promise = val().then((result) => {
71
- cache.set(cacheKey, { value: result, timestamp: Date.now() });
72
- return result;
73
- }).catch((error) => {
74
- cache.delete(cacheKey);
75
- throw error;
76
- });
77
- cache.set(cacheKey, { value: promise, timestamp: now });
78
- trimToSize();
79
- checkExpiredItems();
80
- return promise;
81
- }
82
- return {
83
- getOrInsert,
84
- getOrInsertAsync,
85
- clear: () => cache.clear(),
119
+ },
120
+ set(cacheKey, value) {
121
+ cache.set(cacheKey, { value, timestamp: Date.now() });
122
+ trimToSize();
123
+ cleanExpiredItems();
124
+ },
125
+ async getAsync(cacheKey) {
126
+ const entry = cache.get(cacheKey);
127
+ if (!entry || isExpired(entry.timestamp, Date.now())) {
128
+ return void 0;
129
+ }
130
+ return await entry.value;
131
+ },
132
+ setAsync(cacheKey, value) {
133
+ const promise = value().then((result) => {
134
+ cache.set(cacheKey, { value: result, timestamp: Date.now() });
135
+ return result;
136
+ }).catch((error) => {
137
+ cache.delete(cacheKey);
138
+ throw error;
139
+ });
140
+ cache.set(cacheKey, { value: promise, timestamp: Date.now() });
141
+ trimToSize();
142
+ cleanExpiredItems();
143
+ },
144
+ cleanExpiredItems,
86
145
  /** @internal */
87
- "~cache": cache
146
+ " cache": { map: cache }
88
147
  };
89
148
  }
90
149
  export {
150
+ RejectValue,
91
151
  cachedGetter,
92
152
  createCache
93
153
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ls-stack/utils",
3
3
  "description": "Typescript utils",
4
- "version": "2.10.0",
4
+ "version": "2.12.0",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "dist"