@modern-js/runtime-utils 2.65.1 → 2.65.3-alpha.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.
Files changed (29) hide show
  1. package/dist/cjs/browser/nestedRoutes.js +11 -11
  2. package/dist/cjs/node/index.js +3 -6
  3. package/dist/cjs/node/storer/container.js +8 -15
  4. package/dist/cjs/universal/async_storage.js +31 -0
  5. package/dist/cjs/{node/storage.js → universal/async_storage.server.js} +18 -12
  6. package/dist/cjs/universal/cache.js +247 -0
  7. package/dist/esm/browser/nestedRoutes.js +12 -12
  8. package/dist/esm/node/index.js +2 -4
  9. package/dist/esm/node/storer/container.js +8 -5
  10. package/dist/esm/universal/async_storage.js +7 -0
  11. package/dist/esm/{node/storage.js → universal/async_storage.server.js} +13 -8
  12. package/dist/esm/universal/cache.js +355 -0
  13. package/dist/esm-node/browser/nestedRoutes.js +11 -11
  14. package/dist/esm-node/node/index.js +2 -4
  15. package/dist/esm-node/node/storer/container.js +8 -5
  16. package/dist/esm-node/universal/async_storage.js +7 -0
  17. package/dist/esm-node/{node/storage.js → universal/async_storage.server.js} +13 -8
  18. package/dist/esm-node/universal/cache.js +216 -0
  19. package/dist/types/browser/nestedRoutes.d.ts +2 -3
  20. package/dist/types/node/index.d.ts +1 -4
  21. package/dist/types/node/loaderContext/index.d.ts +1 -13
  22. package/dist/types/node/storer/container.d.ts +1 -1
  23. package/dist/types/node/storer/index.d.ts +1 -1
  24. package/dist/types/server/nestedRoutes.d.ts +1 -2
  25. package/dist/types/universal/async_storage.d.ts +2 -0
  26. package/dist/types/universal/async_storage.server.d.ts +18 -0
  27. package/dist/types/universal/cache.d.ts +28 -0
  28. package/package.json +15 -10
  29. package/dist/types/node/storage.d.ts +0 -5
@@ -0,0 +1,355 @@
1
+ import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
2
+ import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
3
+ import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
4
+ import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
5
+ import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
6
+ import { _ as _type_of } from "@swc/helpers/_/_type_of";
7
+ import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
8
+ import { LRUCache } from "lru-cache";
9
+ import { getAsyncLocalStorage } from "./async_storage";
10
+ var CacheSize = {
11
+ KB: 1024,
12
+ MB: 1024 * 1024,
13
+ GB: 1024 * 1024 * 1024
14
+ };
15
+ var CacheTime = {
16
+ SECOND: 1e3,
17
+ MINUTE: 60 * 1e3,
18
+ HOUR: 60 * 60 * 1e3,
19
+ DAY: 24 * 60 * 60 * 1e3,
20
+ WEEK: 7 * 24 * 60 * 60 * 1e3,
21
+ MONTH: 30 * 24 * 60 * 60 * 1e3
22
+ };
23
+ var isServer = typeof window === "undefined";
24
+ var requestCacheMap = /* @__PURE__ */ new WeakMap();
25
+ var lruCache;
26
+ var cacheConfig = {
27
+ maxSize: CacheSize.GB
28
+ };
29
+ var tagFnMap = /* @__PURE__ */ new Map();
30
+ function addTagFnRelation(tag, fn) {
31
+ var fns = tagFnMap.get(tag);
32
+ if (!fns) {
33
+ fns = /* @__PURE__ */ new Set();
34
+ tagFnMap.set(tag, fns);
35
+ }
36
+ fns.add(fn);
37
+ }
38
+ function configureCache(config) {
39
+ cacheConfig = _object_spread({}, cacheConfig, config);
40
+ }
41
+ function getLRUCache() {
42
+ if (!lruCache) {
43
+ lruCache = new LRUCache({
44
+ maxSize: cacheConfig.maxSize,
45
+ sizeCalculation: function(value) {
46
+ if (!value.size) {
47
+ return 1;
48
+ }
49
+ var size = 0;
50
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
51
+ try {
52
+ for (var _iterator = value.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
53
+ var _step_value = _sliced_to_array(_step.value, 2), k = _step_value[0], item = _step_value[1];
54
+ size += k.length * 2;
55
+ size += estimateObjectSize(item.data);
56
+ size += 8;
57
+ }
58
+ } catch (err) {
59
+ _didIteratorError = true;
60
+ _iteratorError = err;
61
+ } finally {
62
+ try {
63
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
64
+ _iterator.return();
65
+ }
66
+ } finally {
67
+ if (_didIteratorError) {
68
+ throw _iteratorError;
69
+ }
70
+ }
71
+ }
72
+ return size;
73
+ },
74
+ updateAgeOnGet: true,
75
+ updateAgeOnHas: true
76
+ });
77
+ }
78
+ return lruCache;
79
+ }
80
+ function estimateObjectSize(data) {
81
+ var type = typeof data === "undefined" ? "undefined" : _type_of(data);
82
+ if (type === "number")
83
+ return 8;
84
+ if (type === "boolean")
85
+ return 4;
86
+ if (type === "string")
87
+ return Math.max(data.length * 2, 1);
88
+ if (data === null || data === void 0)
89
+ return 1;
90
+ if (ArrayBuffer.isView(data)) {
91
+ return Math.max(data.byteLength, 1);
92
+ }
93
+ if (Array.isArray(data)) {
94
+ return Math.max(data.reduce(function(acc, item) {
95
+ return acc + estimateObjectSize(item);
96
+ }, 0), 1);
97
+ }
98
+ if (_instanceof(data, Map) || _instanceof(data, Set)) {
99
+ return 1024;
100
+ }
101
+ if (_instanceof(data, Date)) {
102
+ return 8;
103
+ }
104
+ if (type === "object") {
105
+ return Math.max(Object.entries(data).reduce(function(acc, param) {
106
+ var _param = _sliced_to_array(param, 2), key = _param[0], value = _param[1];
107
+ return acc + key.length * 2 + estimateObjectSize(value);
108
+ }, 0), 1);
109
+ }
110
+ return 1;
111
+ }
112
+ function generateKey(args) {
113
+ return JSON.stringify(args, function(_, value) {
114
+ if (value && (typeof value === "undefined" ? "undefined" : _type_of(value)) === "object" && !Array.isArray(value)) {
115
+ return Object.keys(value).sort().reduce(function(result, key) {
116
+ result[key] = value[key];
117
+ return result;
118
+ }, {});
119
+ }
120
+ return value;
121
+ });
122
+ }
123
+ function cache(fn, options) {
124
+ var _ref = options || {}, _ref_tag = _ref.tag, tag = _ref_tag === void 0 ? "default" : _ref_tag, _ref_maxAge = _ref.maxAge, maxAge = _ref_maxAge === void 0 ? CacheTime.MINUTE * 5 : _ref_maxAge, _ref_revalidate = _ref.revalidate, revalidate = _ref_revalidate === void 0 ? 0 : _ref_revalidate;
125
+ var store = getLRUCache();
126
+ var tags = Array.isArray(tag) ? tag : [
127
+ tag
128
+ ];
129
+ tags.forEach(function(t) {
130
+ return addTagFnRelation(t, fn);
131
+ });
132
+ return /* @__PURE__ */ _async_to_generator(function() {
133
+ var _len, args, _key, _storage_useContext, storage, request, requestCache, key, promise, data, error, tagCache, key1, cached, now, age, data1;
134
+ var _arguments = arguments;
135
+ return _ts_generator(this, function(_state) {
136
+ switch (_state.label) {
137
+ case 0:
138
+ for (_len = _arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
139
+ args[_key] = _arguments[_key];
140
+ }
141
+ if (!(isServer && typeof options === "undefined"))
142
+ return [
143
+ 3,
144
+ 5
145
+ ];
146
+ storage = getAsyncLocalStorage();
147
+ request = storage === null || storage === void 0 ? void 0 : (_storage_useContext = storage.useContext()) === null || _storage_useContext === void 0 ? void 0 : _storage_useContext.request;
148
+ if (!request)
149
+ return [
150
+ 3,
151
+ 4
152
+ ];
153
+ requestCache = requestCacheMap.get(request);
154
+ if (!requestCache) {
155
+ requestCache = /* @__PURE__ */ new Map();
156
+ requestCacheMap.set(request, requestCache);
157
+ }
158
+ key = generateKey(args);
159
+ if (requestCache.has(key)) {
160
+ return [
161
+ 2,
162
+ requestCache.get(key)
163
+ ];
164
+ }
165
+ promise = fn.apply(void 0, _to_consumable_array(args));
166
+ requestCache.set(key, promise);
167
+ _state.label = 1;
168
+ case 1:
169
+ _state.trys.push([
170
+ 1,
171
+ 3,
172
+ ,
173
+ 4
174
+ ]);
175
+ return [
176
+ 4,
177
+ promise
178
+ ];
179
+ case 2:
180
+ data = _state.sent();
181
+ return [
182
+ 2,
183
+ data
184
+ ];
185
+ case 3:
186
+ error = _state.sent();
187
+ requestCache.delete(key);
188
+ throw error;
189
+ case 4:
190
+ return [
191
+ 3,
192
+ 8
193
+ ];
194
+ case 5:
195
+ if (!(typeof options !== "undefined"))
196
+ return [
197
+ 3,
198
+ 7
199
+ ];
200
+ tagCache = store.get(fn);
201
+ if (!tagCache) {
202
+ tagCache = /* @__PURE__ */ new Map();
203
+ }
204
+ key1 = generateKey(args);
205
+ cached = tagCache.get(key1);
206
+ now = Date.now();
207
+ if (cached) {
208
+ age = now - cached.timestamp;
209
+ if (age < maxAge) {
210
+ return [
211
+ 2,
212
+ cached.data
213
+ ];
214
+ }
215
+ if (revalidate > 0 && age < maxAge + revalidate) {
216
+ if (!cached.isRevalidating) {
217
+ cached.isRevalidating = true;
218
+ Promise.resolve().then(/* @__PURE__ */ _async_to_generator(function() {
219
+ var newData, error2, _storage_useContext_monitors, _storage_useContext2, storage2;
220
+ return _ts_generator(this, function(_state2) {
221
+ switch (_state2.label) {
222
+ case 0:
223
+ _state2.trys.push([
224
+ 0,
225
+ 2,
226
+ ,
227
+ 3
228
+ ]);
229
+ return [
230
+ 4,
231
+ fn.apply(void 0, _to_consumable_array(args))
232
+ ];
233
+ case 1:
234
+ newData = _state2.sent();
235
+ tagCache.set(key1, {
236
+ data: newData,
237
+ timestamp: Date.now(),
238
+ isRevalidating: false
239
+ });
240
+ store.set(fn, tagCache);
241
+ return [
242
+ 3,
243
+ 3
244
+ ];
245
+ case 2:
246
+ error2 = _state2.sent();
247
+ cached.isRevalidating = false;
248
+ if (isServer) {
249
+ ;
250
+ storage2 = getAsyncLocalStorage();
251
+ storage2 === null || storage2 === void 0 ? void 0 : (_storage_useContext2 = storage2.useContext()) === null || _storage_useContext2 === void 0 ? void 0 : (_storage_useContext_monitors = _storage_useContext2.monitors) === null || _storage_useContext_monitors === void 0 ? void 0 : _storage_useContext_monitors.error(error2.message);
252
+ } else {
253
+ console.error("Background revalidation failed:", error2);
254
+ }
255
+ return [
256
+ 3,
257
+ 3
258
+ ];
259
+ case 3:
260
+ return [
261
+ 2
262
+ ];
263
+ }
264
+ });
265
+ }));
266
+ }
267
+ return [
268
+ 2,
269
+ cached.data
270
+ ];
271
+ }
272
+ }
273
+ return [
274
+ 4,
275
+ fn.apply(void 0, _to_consumable_array(args))
276
+ ];
277
+ case 6:
278
+ data1 = _state.sent();
279
+ tagCache.set(key1, {
280
+ data: data1,
281
+ timestamp: now,
282
+ isRevalidating: false
283
+ });
284
+ store.set(fn, tagCache);
285
+ return [
286
+ 2,
287
+ data1
288
+ ];
289
+ case 7:
290
+ console.warn("The cache function will not work because it runs on the browser and there are no options are provided.");
291
+ return [
292
+ 2,
293
+ fn.apply(void 0, _to_consumable_array(args))
294
+ ];
295
+ case 8:
296
+ return [
297
+ 2
298
+ ];
299
+ }
300
+ });
301
+ });
302
+ }
303
+ function withRequestCache(handler) {
304
+ if (!isServer) {
305
+ return handler;
306
+ }
307
+ return function() {
308
+ var _ref = _async_to_generator(function(req) {
309
+ var _len, args, _key, storage;
310
+ var _arguments = arguments;
311
+ return _ts_generator(this, function(_state) {
312
+ for (_len = _arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
313
+ args[_key - 1] = _arguments[_key];
314
+ }
315
+ storage = getAsyncLocalStorage();
316
+ return [
317
+ 2,
318
+ storage.run({
319
+ request: req
320
+ }, function() {
321
+ return handler.apply(void 0, [
322
+ req
323
+ ].concat(_to_consumable_array(args)));
324
+ })
325
+ ];
326
+ });
327
+ });
328
+ return function(req) {
329
+ return _ref.apply(this, arguments);
330
+ };
331
+ }();
332
+ }
333
+ function revalidateTag(tag) {
334
+ var fns = tagFnMap.get(tag);
335
+ if (fns) {
336
+ fns.forEach(function(fn) {
337
+ lruCache === null || lruCache === void 0 ? void 0 : lruCache.delete(fn);
338
+ });
339
+ }
340
+ }
341
+ function clearStore() {
342
+ lruCache === null || lruCache === void 0 ? void 0 : lruCache.clear();
343
+ lruCache = void 0;
344
+ tagFnMap.clear();
345
+ }
346
+ export {
347
+ CacheSize,
348
+ CacheTime,
349
+ cache,
350
+ clearStore,
351
+ configureCache,
352
+ generateKey,
353
+ revalidateTag,
354
+ withRequestCache
355
+ };
@@ -3,12 +3,11 @@ import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
3
3
  import { Suspense } from "react";
4
4
  import { Outlet, Route, createRoutesFromElements } from "react-router-dom";
5
5
  import { time } from "../time";
6
- const transformNestedRoutes = (routes, reporter) => {
6
+ import { getAsyncLocalStorage } from "../universal/async_storage";
7
+ const transformNestedRoutes = (routes) => {
7
8
  const routeElements = [];
8
9
  for (const route of routes) {
9
- const routeElement = renderNestedRoute(route, {
10
- reporter
11
- });
10
+ const routeElement = renderNestedRoute(route);
12
11
  routeElements.push(routeElement);
13
12
  }
14
13
  return createRoutesFromElements(routeElements);
@@ -16,12 +15,12 @@ const transformNestedRoutes = (routes, reporter) => {
16
15
  const renderNestedRoute = (nestedRoute, options = {}) => {
17
16
  const { children, index, id, component, isRoot, lazyImport, config, handle } = nestedRoute;
18
17
  const Component = component;
19
- const { parent, props = {}, reporter } = options;
18
+ const { parent, props = {} } = options;
20
19
  const routeProps = {
21
20
  caseSensitive: nestedRoute.caseSensitive,
22
21
  path: nestedRoute.path,
23
22
  id: nestedRoute.id,
24
- loader: createLoader(nestedRoute, reporter),
23
+ loader: createLoader(nestedRoute),
25
24
  action: nestedRoute.action,
26
25
  hasErrorBoundary: nestedRoute.hasErrorBoundary,
27
26
  shouldRevalidate: nestedRoute.shouldRevalidate,
@@ -74,8 +73,7 @@ const renderNestedRoute = (nestedRoute, options = {}) => {
74
73
  }
75
74
  const childElements = children === null || children === void 0 ? void 0 : children.map((childRoute) => {
76
75
  return renderNestedRoute(childRoute, {
77
- parent: nestedRoute,
78
- reporter
76
+ parent: nestedRoute
79
77
  });
80
78
  });
81
79
  const routeElement = index ? /* @__PURE__ */ _jsx(Route, {
@@ -88,7 +86,7 @@ const renderNestedRoute = (nestedRoute, options = {}) => {
88
86
  }, id);
89
87
  return routeElement;
90
88
  };
91
- function createLoader(route, reporter) {
89
+ function createLoader(route) {
92
90
  const { loader } = route;
93
91
  if (loader) {
94
92
  return async (args) => {
@@ -98,8 +96,10 @@ function createLoader(route, reporter) {
98
96
  const end = time();
99
97
  const res = await loader(args);
100
98
  const cost = end();
101
- if (typeof document === "undefined" && reporter) {
102
- reporter === null || reporter === void 0 ? void 0 : reporter.reportTiming(`${LOADER_REPORTER_NAME}-${route.id}`, cost);
99
+ if (typeof document === "undefined") {
100
+ var _storage_useContext_monitors;
101
+ const storage = getAsyncLocalStorage();
102
+ storage === null || storage === void 0 ? void 0 : (_storage_useContext_monitors = storage.useContext().monitors) === null || _storage_useContext_monitors === void 0 ? void 0 : _storage_useContext_monitors.timing(`${LOADER_REPORTER_NAME}-${route.id}`, cost);
103
103
  }
104
104
  return res;
105
105
  };
@@ -1,10 +1,8 @@
1
- import { createStorage } from "./storage";
2
- const { run, useContext: useHeaders } = createStorage();
1
+ import { storage } from "../universal/async_storage.server";
3
2
  import { serializeJson } from "./serialize";
4
3
  export * from "./loaderContext";
5
4
  export * from "./stream";
6
5
  export {
7
- run,
8
6
  serializeJson,
9
- useHeaders
7
+ storage
10
8
  };
@@ -1,4 +1,4 @@
1
- import LRU from "lru-cache";
1
+ import { LRUCache } from "lru-cache";
2
2
  class MemoryContainer {
3
3
  async get(key) {
4
4
  return this.cache.get(key);
@@ -13,7 +13,7 @@ class MemoryContainer {
13
13
  async delete(key) {
14
14
  const exist = await this.has(key);
15
15
  if (exist) {
16
- this.cache.del(key);
16
+ this.cache.delete(key);
17
17
  }
18
18
  return exist;
19
19
  }
@@ -23,9 +23,12 @@ class MemoryContainer {
23
23
  });
24
24
  }
25
25
  constructor({ max, maxAge } = {}) {
26
- this.cache = new LRU({
27
- max: (max || 256) * MemoryContainer.MB,
28
- maxAge: maxAge || MemoryContainer.hour
26
+ this.cache = new LRUCache({
27
+ maxSize: (max || 256) * MemoryContainer.MB,
28
+ ttl: maxAge || MemoryContainer.hour,
29
+ sizeCalculation: (value, key) => {
30
+ return JSON.stringify(value).length;
31
+ }
29
32
  });
30
33
  }
31
34
  }
@@ -0,0 +1,7 @@
1
+ const getAsyncLocalStorage = () => {
2
+ console.error("You should not get async storage in browser");
3
+ return null;
4
+ };
5
+ export {
6
+ getAsyncLocalStorage
7
+ };
@@ -1,16 +1,16 @@
1
1
  import * as ah from "async_hooks";
2
2
  const createStorage = () => {
3
- let storage;
3
+ let storage2;
4
4
  if (typeof ah.AsyncLocalStorage !== "undefined") {
5
- storage = new ah.AsyncLocalStorage();
5
+ storage2 = new ah.AsyncLocalStorage();
6
6
  }
7
7
  const run = (context, cb) => {
8
- if (!storage) {
8
+ if (!storage2) {
9
9
  throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
10
10
  `);
11
11
  }
12
12
  return new Promise((resolve, reject) => {
13
- storage.run(context, () => {
13
+ storage2.run(context, () => {
14
14
  try {
15
15
  return resolve(cb());
16
16
  } catch (error) {
@@ -20,13 +20,13 @@ const createStorage = () => {
20
20
  });
21
21
  };
22
22
  const useContext = () => {
23
- if (!storage) {
23
+ if (!storage2) {
24
24
  throw new Error(`Unable to use async_hook, please confirm the node version >= 12.17
25
25
  `);
26
26
  }
27
- const context = storage.getStore();
27
+ const context = storage2 === null || storage2 === void 0 ? void 0 : storage2.getStore();
28
28
  if (!context) {
29
- throw new Error(`Can't call useContext out of scope, make sure @modern-js/utils is a single version in node_modules`);
29
+ throw new Error(`Can't call useContext out of scope, make sure @modern-js/runtime-utils is a single version in node_modules`);
30
30
  }
31
31
  return context;
32
32
  };
@@ -35,6 +35,11 @@ const createStorage = () => {
35
35
  useContext
36
36
  };
37
37
  };
38
+ const storage = createStorage();
39
+ const getAsyncLocalStorage = () => {
40
+ return storage;
41
+ };
38
42
  export {
39
- createStorage
43
+ getAsyncLocalStorage,
44
+ storage
40
45
  };