@raketa-cloud/next 1.0.2 → 1.0.4

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.
Files changed (2) hide show
  1. package/package.json +7 -5
  2. package/src/Cache.js +85 -8
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@raketa-cloud/next",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "main": "src/index.js",
5
5
  "scripts": {
6
- "check-types": "tsc --noEmit"
6
+ "check-types": "tsc --noEmit",
7
+ "format": "prettier --write src/**/*.js"
7
8
  },
8
9
  "devDependencies": {
9
10
  "@repo/typescript-config": "*",
@@ -11,12 +12,13 @@
11
12
  "@types/node": "^20.11.24",
12
13
  "@types/react": "18.3.0",
13
14
  "@types/react-dom": "18.3.1",
15
+ "prettier": "^3.8.3",
14
16
  "typescript": "5.5.4"
15
17
  },
16
18
  "dependencies": {
17
- "react": "^19.0.0",
18
- "react-dom": "^19.0.0",
19
19
  "graphql-request": "7.1.2",
20
- "lru-cache": "11.0.2"
20
+ "lru-cache": "11.0.2",
21
+ "react": "^19.0.0",
22
+ "react-dom": "^19.0.0"
21
23
  }
22
24
  }
package/src/Cache.js CHANGED
@@ -1,20 +1,67 @@
1
1
  import { LRUCache } from "lru-cache";
2
2
 
3
- const UNDEFINED_VALUE = Symbol("udef");
3
+ const NULL_SENTINEL = Symbol.for("raketa_cache_null");
4
+
5
+ function getApproximateMemoryUsage(obj) {
6
+ // Use a WeakSet to track objects we've already seen to avoid infinite loops on circular references
7
+ const seen = new WeakSet();
8
+
9
+ function sizeOf(value) {
10
+ // 1. Handle null and undefined explicitly (This fixes your error!)
11
+ if (value === null || value === undefined) return 0;
12
+
13
+ // 2. Handle primitives based on JS specs
14
+ if (typeof value === 'boolean') return 4;
15
+ if (typeof value === 'number') return 8; // Double-precision floats
16
+ if (typeof value === 'string') return value.length * 2; // UTF-16 strings take 2 bytes per char
17
+
18
+ // 3. Skip functions and symbols (they live in a shared memory pool)
19
+ if (typeof value !== 'object') return 0;
20
+
21
+ // 4. Handle circular references
22
+ if (seen.has(value)) return 0;
23
+
24
+ seen.add(value);
25
+
26
+ let bytes = 0;
27
+
28
+ // 5. Traverse the object's keys and values
29
+ for (const key in value) {
30
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
31
+ bytes += key.length * 2; // Add the size of the key itself
32
+ bytes += sizeOf(value[key]); // Recursively add the size of the value
33
+ }
34
+ }
35
+
36
+ return bytes;
37
+ }
38
+
39
+ return sizeOf(obj);
40
+ }
4
41
 
5
42
  export default class Cache {
6
43
  constructor(opts = {}) {
44
+ const self = this;
45
+
7
46
  const cacheOptions = {
8
- max: opts.max || 5000,
9
- ttl: opts.ttl || 1000 * 60 * 2,
47
+ max: opts.max || 5000, // Items count
48
+ ttl: opts.ttl || 1000 * 60 * 5, // 5 minutes
10
49
  allowStale: true,
11
50
  noDeleteOnStaleGet: true,
12
51
  };
13
52
 
53
+ // Conditionally use the memrory calculation since it is veery flaky and inaccurate...
54
+ if (opts.maxSize) {
55
+ cacheOptions.maxSize = opts.maxSize;
56
+
57
+ cacheOptions.sizeCalculation = (value, key) => {
58
+ return getApproximateMemoryUsage(key) + getApproximateMemoryUsage(value);
59
+ };
60
+
61
+ }
62
+
14
63
  this.debugMode = opts.debugMode || false;
15
- this.cacheInstance = new LRUCache({
16
- ...cacheOptions,
17
- });
64
+ this.cacheInstance = new LRUCache(cacheOptions);
18
65
  }
19
66
 
20
67
  _debug(msg) {
@@ -29,12 +76,22 @@ export default class Cache {
29
76
  const cachedValue = this.cacheInstance.get(key, { status });
30
77
 
31
78
  return {
32
- cachedValue: cachedValue === UNDEFINED_VALUE ? null : cachedValue,
79
+ cachedValue: cachedValue === NULL_SENTINEL ? null : cachedValue,
33
80
  status,
34
81
  };
35
82
  }
36
83
 
37
84
  _cloneObject(obj) {
85
+ if (obj === null || obj === undefined) {
86
+ return obj;
87
+ }
88
+
89
+ const type = typeof obj;
90
+
91
+ if (type !== "function" || type !== "obj") {
92
+ return obj;
93
+ }
94
+
38
95
  // Ah the JS world! See the official docs https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy.
39
96
  // Important note - this works only for objects with primitive types to copy. If an object property is
40
97
  // a function - well it will not work correctly...
@@ -44,10 +101,30 @@ export default class Cache {
44
101
  _setInCache(key, value) {
45
102
  this.cacheInstance.set(
46
103
  key,
47
- value ? this._cloneObject(value) : UNDEFINED_VALUE
104
+ value ? this._cloneObject(value) : NULL_SENTINEL
48
105
  );
49
106
  }
50
107
 
108
+ clear() {
109
+ this.cacheInstance.clear();
110
+ }
111
+
112
+ forEach(callback) {
113
+ this.cacheInstance.forEach(callback);
114
+ }
115
+
116
+ getRemainingTTL(key) {
117
+ return this.cacheInstance.getRemainingTTL(key);
118
+ }
119
+
120
+ get calculatedSize() {
121
+ return this.cacheInstance.calculatedSize;
122
+ }
123
+
124
+ get maxSize() {
125
+ return this.cacheInstance.maxSize;
126
+ }
127
+
51
128
  async fetch(cacheKey, fetcher) {
52
129
  const { cachedValue, status } = this._fetchFromCache(cacheKey);
53
130