@zajno/common 2.8.6 → 2.8.8
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/cjs/api/call.config.js +10 -0
- package/cjs/api/call.config.js.map +1 -1
- package/cjs/api/extensions/formData.js +115 -0
- package/cjs/api/extensions/formData.js.map +1 -0
- package/cjs/api/extensions/index.js +1 -0
- package/cjs/api/extensions/index.js.map +1 -1
- package/cjs/structures/promiseCache/cache.js +286 -0
- package/cjs/structures/promiseCache/cache.js.map +1 -0
- package/cjs/structures/promiseCache/core.js +301 -0
- package/cjs/structures/promiseCache/core.js.map +1 -0
- package/cjs/structures/promiseCache/index.js +7 -0
- package/cjs/structures/promiseCache/index.js.map +1 -0
- package/cjs/structures/promiseCache/types.js +15 -0
- package/cjs/structures/promiseCache/types.js.map +1 -0
- package/cjs/types/index.js +1 -0
- package/cjs/types/index.js.map +1 -1
- package/cjs/types/isPlainObject.js +15 -0
- package/cjs/types/isPlainObject.js.map +1 -0
- package/esm/api/call.config.js +10 -0
- package/esm/api/call.config.js.map +1 -1
- package/esm/api/extensions/formData.js +111 -0
- package/esm/api/extensions/formData.js.map +1 -0
- package/esm/api/extensions/index.js +1 -0
- package/esm/api/extensions/index.js.map +1 -1
- package/esm/structures/promiseCache/cache.js +282 -0
- package/esm/structures/promiseCache/cache.js.map +1 -0
- package/esm/structures/promiseCache/core.js +297 -0
- package/esm/structures/promiseCache/core.js.map +1 -0
- package/esm/structures/promiseCache/index.js +4 -0
- package/esm/structures/promiseCache/index.js.map +1 -0
- package/esm/structures/promiseCache/types.js +12 -0
- package/esm/structures/promiseCache/types.js.map +1 -0
- package/esm/types/index.js +1 -0
- package/esm/types/index.js.map +1 -1
- package/esm/types/isPlainObject.js +12 -0
- package/esm/types/isPlainObject.js.map +1 -0
- package/package.json +7 -1
- package/tsconfig.cjs.tsbuildinfo +1 -1
- package/tsconfig.esm.tsbuildinfo +1 -1
- package/tsconfig.types.tsbuildinfo +1 -1
- package/types/api/extensions/formData.d.ts +89 -0
- package/types/api/extensions/index.d.ts +1 -0
- package/types/structures/promiseCache/cache.d.ts +95 -0
- package/types/structures/promiseCache/core.d.ts +157 -0
- package/types/structures/promiseCache/index.d.ts +3 -0
- package/types/structures/promiseCache/types.d.ts +55 -0
- package/types/types/index.d.ts +1 -0
- package/types/types/isPlainObject.d.ts +5 -0
- package/cjs/structures/promiseCache.js +0 -399
- package/cjs/structures/promiseCache.js.map +0 -1
- package/esm/structures/promiseCache.js +0 -395
- package/esm/structures/promiseCache.js.map +0 -1
- package/types/structures/promiseCache.d.ts +0 -206
package/cjs/api/call.config.js
CHANGED
|
@@ -2,9 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RequestMeta = void 0;
|
|
4
4
|
exports.createConfig = createConfig;
|
|
5
|
+
const isPlainObject_js_1 = require("../types/isPlainObject.js");
|
|
5
6
|
const config_js_1 = require("./config.js");
|
|
6
7
|
function createConfig(endpointsConfig, api, data, extra) {
|
|
7
8
|
const { headers, log = 'res', noLoader, ...restExtra } = extra || {};
|
|
9
|
+
// Guard against non-plain objects (e.g. FormData, Blob) that would be destroyed by spread.
|
|
10
|
+
// Only plain objects can be spread for path/query extraction.
|
|
11
|
+
if (data != null && typeof data === 'object' && !(0, isPlainObject_js_1.isPlainObject)(data)) {
|
|
12
|
+
const name = data.constructor?.name ?? typeof data;
|
|
13
|
+
throw new TypeError(`API caller received a non-plain object as data (got ${name}). `
|
|
14
|
+
+ 'Only plain objects are supported because data is spread for path/query extraction. '
|
|
15
|
+
+ 'For FormData/multipart uploads, pass a plain object and use the IEndpointFormData extension '
|
|
16
|
+
+ 'with .asFormData(), or use a beforeRequest hook to replace config.data.');
|
|
17
|
+
}
|
|
8
18
|
const resultInput = data && { ...data };
|
|
9
19
|
const pathInputs = {};
|
|
10
20
|
const queryInputs = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call.config.js","sourceRoot":"","sources":["../../../src/api/call.config.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"call.config.js","sourceRoot":"","sources":["../../../src/api/call.config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IEndpointFormData = void 0;
|
|
4
|
+
exports.createFormDataSerializer = createFormDataSerializer;
|
|
5
|
+
const isPlainObject_js_1 = require("../../types/isPlainObject.js");
|
|
6
|
+
/**
|
|
7
|
+
* Creates a default FormData serializer.
|
|
8
|
+
*
|
|
9
|
+
* Iterates over own enumerable properties of the data object and appends them to a new FormData instance.
|
|
10
|
+
*
|
|
11
|
+
* - `Blob`/`File` values are appended as-is
|
|
12
|
+
* - `null`/`undefined` values are skipped
|
|
13
|
+
* - Primitive values are converted to strings
|
|
14
|
+
* - Objects/arrays are JSON-stringified by default (configurable via `serializeValue`)
|
|
15
|
+
*/
|
|
16
|
+
function createFormDataSerializer(options) {
|
|
17
|
+
const Ctor = options?.FormData ?? globalThis.FormData;
|
|
18
|
+
if (typeof Ctor !== 'function') {
|
|
19
|
+
throw new TypeError('FormData is not available in this environment. '
|
|
20
|
+
+ 'Pass a FormData constructor via options.FormData (e.g., from the `form-data` npm package).');
|
|
21
|
+
}
|
|
22
|
+
const serializeValue = options?.serializeValue ?? 'json';
|
|
23
|
+
return (data) => {
|
|
24
|
+
const fd = new Ctor();
|
|
25
|
+
for (const [key, value] of Object.entries(data)) {
|
|
26
|
+
if (value == null) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (typeof Blob !== 'undefined' && value instanceof Blob) {
|
|
30
|
+
fd.append(key, value);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (typeof value !== 'object') {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
35
|
+
fd.append(key, String(value));
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (typeof serializeValue === 'function') {
|
|
39
|
+
const serialized = serializeValue(key, value);
|
|
40
|
+
if (typeof Blob !== 'undefined' && serialized instanceof Blob) {
|
|
41
|
+
fd.append(key, serialized);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
fd.append(key, serialized);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
fd.append(key, JSON.stringify(value));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return fd;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
var IEndpointFormData;
|
|
55
|
+
(function (IEndpointFormData) {
|
|
56
|
+
IEndpointFormData.extender = (base) => {
|
|
57
|
+
const ext = {
|
|
58
|
+
formData: undefined,
|
|
59
|
+
asFormData(serializer) {
|
|
60
|
+
this.formData = serializer ?? true;
|
|
61
|
+
return this;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
return Object.assign(base, ext);
|
|
65
|
+
};
|
|
66
|
+
function guard(api) {
|
|
67
|
+
return 'formData' in api && !!api.formData;
|
|
68
|
+
}
|
|
69
|
+
IEndpointFormData.guard = guard;
|
|
70
|
+
/**
|
|
71
|
+
* Creates caller hooks for FormData serialization.
|
|
72
|
+
*
|
|
73
|
+
* The hook converts `config.data` (plain object) into a FormData instance using the provided serializer.
|
|
74
|
+
*
|
|
75
|
+
* @param serializer - Default serializer used when endpoint has `.asFormData()` without a custom serializer.
|
|
76
|
+
* Use {@link createFormDataSerializer} for the built-in one, or provide a fully custom function.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // Simplest setup (global FormData, JSON-stringify objects)
|
|
81
|
+
* IEndpointFormData.createHooks(createFormDataSerializer())
|
|
82
|
+
*
|
|
83
|
+
* // Custom FormData constructor
|
|
84
|
+
* import FormDataNode from 'form-data';
|
|
85
|
+
* IEndpointFormData.createHooks(createFormDataSerializer({ FormData: FormDataNode as any }))
|
|
86
|
+
*
|
|
87
|
+
* // Fully custom serializer
|
|
88
|
+
* IEndpointFormData.createHooks((data) => {
|
|
89
|
+
* const fd = new FormData();
|
|
90
|
+
* // custom logic...
|
|
91
|
+
* return fd;
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
function createHooks(serializer) {
|
|
96
|
+
return {
|
|
97
|
+
beforeRequest: (config) => {
|
|
98
|
+
if (!guard(config._meta.api) || !config.data) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Skip if data was already transformed by a previous hook (e.g., to FormData, Blob, string)
|
|
102
|
+
if (!(0, isPlainObject_js_1.isPlainObject)(config.data)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const endpoint = config._meta.api;
|
|
106
|
+
const ser = typeof endpoint.formData === 'function'
|
|
107
|
+
? endpoint.formData
|
|
108
|
+
: serializer;
|
|
109
|
+
config.data = ser(config.data);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
IEndpointFormData.createHooks = createHooks;
|
|
114
|
+
})(IEndpointFormData || (exports.IEndpointFormData = IEndpointFormData = {}));
|
|
115
|
+
//# sourceMappingURL=formData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formData.js","sourceRoot":"","sources":["../../../../src/api/extensions/formData.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./contentType.js"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./formData.js"), exports);
|
|
5
6
|
tslib_1.__exportStar(require("./validation.js"), exports);
|
|
6
7
|
tslib_1.__exportStar(require("./endpointHooks.js"), exports);
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/api/extensions/index.ts"],"names":[],"mappings":";;;AAAA,2DAAiC;AACjC,0DAAgC;AAChC,6DAAmC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/api/extensions/index.ts"],"names":[],"mappings":";;;AAAA,2DAAiC;AACjC,wDAA8B;AAC9B,0DAAgC;AAChC,6DAAmC"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PromiseCache = void 0;
|
|
4
|
+
const debounce_js_1 = require("../../functions/debounce.js");
|
|
5
|
+
const core_js_1 = require("./core.js");
|
|
6
|
+
const BATCHING_DELAY = 200;
|
|
7
|
+
/**
|
|
8
|
+
* Caches items by a key (string or another type) which are resolved by an async fetcher (`Promise`).
|
|
9
|
+
*
|
|
10
|
+
* Supports:
|
|
11
|
+
* - custom key adapter and parser for non-string keys.
|
|
12
|
+
* - direct manual cache manipulation.
|
|
13
|
+
* - batching of fetches.
|
|
14
|
+
* - auto-invalidation of cached items (time-based, callback-based, max items).
|
|
15
|
+
* - error tracking per key.
|
|
16
|
+
*/
|
|
17
|
+
class PromiseCache extends core_js_1.PromiseCacheCore {
|
|
18
|
+
fetcher;
|
|
19
|
+
_batch = null;
|
|
20
|
+
_invalidationConfig = null;
|
|
21
|
+
_onError = null;
|
|
22
|
+
/**
|
|
23
|
+
* Creates an instance of PromiseCache.
|
|
24
|
+
* @param fetcher Function to fetch data by key.
|
|
25
|
+
* @param keyAdapter Optional function to adapt non-string keys to strings.
|
|
26
|
+
* @param keyParser Optional function to parse string keys back to their original type.
|
|
27
|
+
*/
|
|
28
|
+
constructor(fetcher, keyAdapter, keyParser) {
|
|
29
|
+
super(keyAdapter, keyParser);
|
|
30
|
+
this.fetcher = fetcher;
|
|
31
|
+
}
|
|
32
|
+
// ─── Configuration ───────────────────────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Provide a fetcher function that takes multiple ids and returns multiple results at once. Will be called with a slight delay to allow multiple ids to be collected.
|
|
35
|
+
*
|
|
36
|
+
* Warning: resolved array should have the same order as the input array.
|
|
37
|
+
*
|
|
38
|
+
* When provided, effectively replaces the main fetcher; but in case of fail, fallbacks to the main fetcher.
|
|
39
|
+
*/
|
|
40
|
+
useBatching(fetcher, delay = BATCHING_DELAY) {
|
|
41
|
+
this._batch = fetcher ? new debounce_js_1.DebounceProcessor(fetcher, delay) : null;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Enables auto-invalidation of cached items by time.
|
|
46
|
+
*
|
|
47
|
+
* This is a convenience wrapper around {@link useInvalidation}.
|
|
48
|
+
*
|
|
49
|
+
* @param ms Time in milliseconds after which the item will be considered invalid. If null, auto-invalidation is disabled.
|
|
50
|
+
* @param keepInstance If true, the cached item will not be removed during invalidation, but the old instance is kept. Defaults to false.
|
|
51
|
+
*/
|
|
52
|
+
useInvalidationTime(ms, keepInstance = false) {
|
|
53
|
+
return this.useInvalidation(ms != null ? { expirationMs: ms, keepInstance } : null);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Configures advanced invalidation policy.
|
|
57
|
+
*
|
|
58
|
+
* The config object is stored as-is (not destructured), so getter-based fields will be re-evaluated on each access.
|
|
59
|
+
* This allows consumers to provide dynamic invalidation policies.
|
|
60
|
+
*
|
|
61
|
+
* @param config The invalidation configuration. See {@link InvalidationConfig} for details.
|
|
62
|
+
*/
|
|
63
|
+
useInvalidation(config) {
|
|
64
|
+
this._invalidationConfig = config;
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sets an error callback that is called when a fetcher fails.
|
|
69
|
+
*
|
|
70
|
+
* @param callback The callback to call on error. Receives the original key and the raw error.
|
|
71
|
+
*/
|
|
72
|
+
useOnError(callback) {
|
|
73
|
+
this._onError = callback;
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
// ─── Core implementation ─────────────────────────────────────────────
|
|
77
|
+
/**
|
|
78
|
+
* Returns a promise that resolves to the cached value of the item if loaded already, otherwise starts fetching and the promise will be resolved to the final value.
|
|
79
|
+
*
|
|
80
|
+
* Consequent calls will return the same promise until it resolves.
|
|
81
|
+
*
|
|
82
|
+
* @param id The id of the item.
|
|
83
|
+
* @returns A promise that resolves to the result, whether it's cached or freshly fetched.
|
|
84
|
+
*/
|
|
85
|
+
get(id) {
|
|
86
|
+
const { item, key, isInvalid } = this._getCurrent(id);
|
|
87
|
+
// return cached item if it's not invalidated
|
|
88
|
+
if (item !== undefined && !isInvalid) {
|
|
89
|
+
this.logger.log(key, 'get: item resolved to', item, isInvalid ? '(invalidated)' : '');
|
|
90
|
+
return Promise.resolve(item);
|
|
91
|
+
}
|
|
92
|
+
let promise = this._fetchCache.get(key);
|
|
93
|
+
if (promise != null) {
|
|
94
|
+
this.logger.log(key, 'get: item resolved to <promise>');
|
|
95
|
+
return promise;
|
|
96
|
+
}
|
|
97
|
+
this.setStatus(key, true);
|
|
98
|
+
promise = this._doFetchAsync(id, key);
|
|
99
|
+
this.setPromise(key, promise);
|
|
100
|
+
return promise;
|
|
101
|
+
}
|
|
102
|
+
/** Clears the cache and resets the loading state. */
|
|
103
|
+
clear() {
|
|
104
|
+
this._batch?.clear();
|
|
105
|
+
super.clear();
|
|
106
|
+
}
|
|
107
|
+
// ─── Protected overrides ─────────────────────────────────────────────
|
|
108
|
+
_getCurrent(id) {
|
|
109
|
+
const key = this._pk(id);
|
|
110
|
+
const isInvalid = this.getIsInvalidated(key);
|
|
111
|
+
// make sure current item is hooked here from the cache (required by observers)
|
|
112
|
+
const item = this._itemsCache.get(key);
|
|
113
|
+
const keepInstance = !!this._invalidationConfig?.keepInstance;
|
|
114
|
+
if (isInvalid) {
|
|
115
|
+
this.logger.log(key, 'item is invalidated');
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
item: (isInvalid && !keepInstance) ? undefined : item,
|
|
119
|
+
key,
|
|
120
|
+
isInvalid,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
getIsInvalidated(key) {
|
|
124
|
+
const config = this._invalidationConfig;
|
|
125
|
+
if (!config) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
const ts = this._timestamps.get(key);
|
|
129
|
+
// Check time-based expiration
|
|
130
|
+
const expirationMs = config.expirationMs;
|
|
131
|
+
if (expirationMs != null && expirationMs > 0 && ts != null) {
|
|
132
|
+
if (Date.now() - ts > expirationMs) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Check callback-based invalidation
|
|
137
|
+
if (config.invalidationCheck) {
|
|
138
|
+
const value = this._itemsCache.get(key);
|
|
139
|
+
if (value !== undefined && config.invalidationCheck(key, value, ts ?? 0)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
/** @override Stores the result for the specified key, enforcing max items. */
|
|
146
|
+
storeResult(key, res) {
|
|
147
|
+
this._enforceMaxItems(key);
|
|
148
|
+
super.storeResult(key, res);
|
|
149
|
+
}
|
|
150
|
+
// ─── Private ─────────────────────────────────────────────────────────
|
|
151
|
+
/**
|
|
152
|
+
* Fetches the item asynchronously.
|
|
153
|
+
* @param id The id of the item.
|
|
154
|
+
* @param key The cache key.
|
|
155
|
+
* @returns A promise that resolves to the fetched item.
|
|
156
|
+
*/
|
|
157
|
+
async _doFetchAsync(id, key) {
|
|
158
|
+
let isInSameVersion = true;
|
|
159
|
+
try {
|
|
160
|
+
this.onBeforeFetch(key);
|
|
161
|
+
const v = this._version;
|
|
162
|
+
let res;
|
|
163
|
+
let fetchFailed = false;
|
|
164
|
+
try {
|
|
165
|
+
res = await this.tryFetchInBatch(id);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
this._handleError(id, err);
|
|
169
|
+
fetchFailed = true;
|
|
170
|
+
res = null;
|
|
171
|
+
}
|
|
172
|
+
if (v !== this._version) {
|
|
173
|
+
isInSameVersion = false;
|
|
174
|
+
// resolve with actual result but don't store it
|
|
175
|
+
return res;
|
|
176
|
+
}
|
|
177
|
+
if (this._fetchCache.get(key) != null) {
|
|
178
|
+
this.logger.log(key, 'item\'s <promise> resolved to', res);
|
|
179
|
+
res = this.prepareResult(res);
|
|
180
|
+
if (!fetchFailed) {
|
|
181
|
+
this.storeResult(key, res);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return res;
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
if (isInSameVersion) {
|
|
188
|
+
this.onFetchComplete(key);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
this.logger.log(key, 'skipping item\'s resolve due to version change ("clear()" has been called)');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** Performs a fetch operation in batch mode if available, otherwise uses the regular fetch. Throws on error. */
|
|
196
|
+
async tryFetchInBatch(id) {
|
|
197
|
+
if (!this._batch) {
|
|
198
|
+
return this.fetcher(id);
|
|
199
|
+
}
|
|
200
|
+
const res = await this._batch.push(id)
|
|
201
|
+
.catch(err => {
|
|
202
|
+
this.logger.warn('batch fetch failed', id, err);
|
|
203
|
+
return null;
|
|
204
|
+
});
|
|
205
|
+
if (!res || !res.result || res.result[res.index] === undefined) {
|
|
206
|
+
// batch call failed or returned no result — fallback to the direct fetcher
|
|
207
|
+
return this.fetcher(id);
|
|
208
|
+
}
|
|
209
|
+
return res.result[res.index];
|
|
210
|
+
}
|
|
211
|
+
/** Handles a fetch error: stores it, logs it, and calls the onError callback. */
|
|
212
|
+
_handleError(id, err) {
|
|
213
|
+
const key = this._pk(id);
|
|
214
|
+
this._errorsMap.set(key, err);
|
|
215
|
+
this.logger.warn('fetcher failed', id, err);
|
|
216
|
+
if (this._onError) {
|
|
217
|
+
try {
|
|
218
|
+
this._onError(id, err);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
// ignore errors in the callback
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Enforces the max items limit by removing items to make room.
|
|
227
|
+
* Strategy: first removes invalid items, then oldest valid items.
|
|
228
|
+
* Items currently being fetched (in-flight) are not evicted.
|
|
229
|
+
*
|
|
230
|
+
* @param incomingKey The key of the item about to be stored (excluded from eviction).
|
|
231
|
+
*/
|
|
232
|
+
_enforceMaxItems(incomingKey) {
|
|
233
|
+
const maxItems = this._invalidationConfig?.maxItems;
|
|
234
|
+
if (maxItems == null || maxItems <= 0) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
// If we're under the limit, nothing to do
|
|
238
|
+
if (this._itemsCache.size < maxItems) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
// Phase 1: Remove invalid items first (they're garbage anyway)
|
|
242
|
+
const invalidKeys = [];
|
|
243
|
+
for (const key of this._itemsCache.keys()) {
|
|
244
|
+
if (key === incomingKey)
|
|
245
|
+
continue;
|
|
246
|
+
if (this.getIsInvalidated(key)) {
|
|
247
|
+
invalidKeys.push(key);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
for (const key of invalidKeys) {
|
|
251
|
+
this._set(key, undefined, undefined, undefined);
|
|
252
|
+
this._errorsMap.delete(key);
|
|
253
|
+
this._timestamps.delete(key);
|
|
254
|
+
if (this._itemsCache.size < maxItems) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Phase 2: Remove oldest valid items (skip in-flight items)
|
|
259
|
+
while (this._itemsCache.size >= maxItems) {
|
|
260
|
+
let oldestKey = null;
|
|
261
|
+
let oldestTs = Infinity;
|
|
262
|
+
for (const [key, ts] of this._timestamps.entries()) {
|
|
263
|
+
// Don't evict the incoming key or items currently being fetched
|
|
264
|
+
if (key === incomingKey)
|
|
265
|
+
continue;
|
|
266
|
+
if (this._fetchCache.has(key))
|
|
267
|
+
continue;
|
|
268
|
+
if (ts < oldestTs) {
|
|
269
|
+
oldestTs = ts;
|
|
270
|
+
oldestKey = key;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (oldestKey != null) {
|
|
274
|
+
this._set(oldestKey, undefined, undefined, undefined);
|
|
275
|
+
this._timestamps.delete(oldestKey);
|
|
276
|
+
this._errorsMap.delete(oldestKey);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// No evictable items found (all are in-flight or incoming)
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
exports.PromiseCache = PromiseCache;
|
|
286
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../src/structures/promiseCache/cache.ts"],"names":[],"mappings":"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"}
|