@satoshibits/functional 1.0.2
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/README.md +242 -0
- package/dist/array-utils.d.mts +317 -0
- package/dist/array-utils.d.mts.map +1 -0
- package/dist/array-utils.mjs +370 -0
- package/dist/array-utils.mjs.map +1 -0
- package/dist/composition.d.mts +603 -0
- package/dist/composition.d.mts.map +1 -0
- package/dist/composition.mjs +516 -0
- package/dist/composition.mjs.map +1 -0
- package/dist/object-utils.d.mts +267 -0
- package/dist/object-utils.d.mts.map +1 -0
- package/dist/object-utils.mjs +258 -0
- package/dist/object-utils.mjs.map +1 -0
- package/dist/option.d.mts +622 -0
- package/dist/option.d.mts.map +1 -0
- package/dist/option.mjs +637 -0
- package/dist/option.mjs.map +1 -0
- package/dist/performance.d.mts +265 -0
- package/dist/performance.d.mts.map +1 -0
- package/dist/performance.mjs +453 -0
- package/dist/performance.mjs.map +1 -0
- package/dist/pipeline.d.mts +431 -0
- package/dist/pipeline.d.mts.map +1 -0
- package/dist/pipeline.mjs +460 -0
- package/dist/pipeline.mjs.map +1 -0
- package/dist/predicates.d.mts +722 -0
- package/dist/predicates.d.mts.map +1 -0
- package/dist/predicates.mjs +802 -0
- package/dist/predicates.mjs.map +1 -0
- package/dist/reader-result.d.mts +422 -0
- package/dist/reader-result.d.mts.map +1 -0
- package/dist/reader-result.mjs +758 -0
- package/dist/reader-result.mjs.map +1 -0
- package/dist/result.d.mts +684 -0
- package/dist/result.d.mts.map +1 -0
- package/dist/result.mjs +814 -0
- package/dist/result.mjs.map +1 -0
- package/dist/types.d.mts +439 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +191 -0
- package/dist/types.mjs.map +1 -0
- package/dist/validation.d.mts +622 -0
- package/dist/validation.d.mts.map +1 -0
- package/dist/validation.mjs +852 -0
- package/dist/validation.mjs.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module performance
|
|
4
|
+
* @description Functional utilities for optimizing performance through timing control,
|
|
5
|
+
* batching, and caching. These utilities help manage expensive operations
|
|
6
|
+
* and prevent performance issues in applications. All utilities are designed
|
|
7
|
+
* to be composable and work well with functional programming patterns.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { debounce, throttle, batch, cache, Performance } from './performance.mts';
|
|
12
|
+
*
|
|
13
|
+
* // debounce user input
|
|
14
|
+
* const search = debounce((query: string) => {
|
|
15
|
+
* performSearch(query);
|
|
16
|
+
* }, 300);
|
|
17
|
+
*
|
|
18
|
+
* // throttle scroll events
|
|
19
|
+
* const handleScroll = throttle(() => {
|
|
20
|
+
* updateScrollPosition();
|
|
21
|
+
* }, 100);
|
|
22
|
+
*
|
|
23
|
+
* // batch API calls
|
|
24
|
+
* const saveItem = batch<Item>(async (items) => {
|
|
25
|
+
* await api.saveMany(items);
|
|
26
|
+
* }, { maxSize: 100, maxWait: 1000 });
|
|
27
|
+
*
|
|
28
|
+
* // cache expensive computations
|
|
29
|
+
* const fibonacci = cache((n: number): number => {
|
|
30
|
+
* if (n <= 1) return n;
|
|
31
|
+
* return fibonacci(n - 1) + fibonacci(n - 2);
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @category Performance
|
|
36
|
+
* @since 2025-07-03
|
|
37
|
+
*/
|
|
38
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
39
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
40
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
41
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
42
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
43
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
44
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
48
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
49
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
50
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
51
|
+
function step(op) {
|
|
52
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
53
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
54
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
55
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
56
|
+
switch (op[0]) {
|
|
57
|
+
case 0: case 1: t = op; break;
|
|
58
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
59
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
60
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
61
|
+
default:
|
|
62
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
63
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
64
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
65
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
66
|
+
if (t[2]) _.ops.pop();
|
|
67
|
+
_.trys.pop(); continue;
|
|
68
|
+
}
|
|
69
|
+
op = body.call(thisArg, _);
|
|
70
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
71
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
75
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
76
|
+
if (ar || !(i in from)) {
|
|
77
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
78
|
+
ar[i] = from[i];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Debounce function execution.
|
|
85
|
+
* @description Delays invoking the function until after the specified delay has elapsed
|
|
86
|
+
* since the last time it was invoked. Useful for expensive operations triggered
|
|
87
|
+
* by user input like search or resize events. Each new call resets the timer.
|
|
88
|
+
*
|
|
89
|
+
* @template T - The types of the function arguments
|
|
90
|
+
* @param {function(...T): void} fn - The function to debounce
|
|
91
|
+
* @param {number} delay - The delay in milliseconds
|
|
92
|
+
* @returns {function(...T): void} The debounced function
|
|
93
|
+
*
|
|
94
|
+
* @category Timing
|
|
95
|
+
* @example
|
|
96
|
+
* // Basic debounce
|
|
97
|
+
* const saveChanges = debounce((text: string) => {
|
|
98
|
+
* console.log('Saving:', text);
|
|
99
|
+
* }, 1000);
|
|
100
|
+
*
|
|
101
|
+
* saveChanges('H');
|
|
102
|
+
* saveChanges('He');
|
|
103
|
+
* saveChanges('Hello'); // Only this will execute after 1 second
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* // Search input debouncing
|
|
107
|
+
* const searchInput = document.getElementById('search');
|
|
108
|
+
* const performSearch = debounce((query: string) => {
|
|
109
|
+
* fetch(`/api/search?q=${query}`)
|
|
110
|
+
* .then(res => res.json())
|
|
111
|
+
* .then(results => displayResults(results));
|
|
112
|
+
* }, 300);
|
|
113
|
+
*
|
|
114
|
+
* searchInput.addEventListener('input', (e) => {
|
|
115
|
+
* performSearch(e.target.value);
|
|
116
|
+
* });
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* // Window resize handler
|
|
120
|
+
* const handleResize = debounce(() => {
|
|
121
|
+
* const width = window.innerWidth;
|
|
122
|
+
* const height = window.innerHeight;
|
|
123
|
+
* console.log(`Resized to ${width}x${height}`);
|
|
124
|
+
* recalculateLayout();
|
|
125
|
+
* }, 250);
|
|
126
|
+
*
|
|
127
|
+
* window.addEventListener('resize', handleResize);
|
|
128
|
+
*
|
|
129
|
+
* @see throttle - Limit execution rate without delaying
|
|
130
|
+
* @since 2025-07-03
|
|
131
|
+
*/
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
|
+
export var debounce = function (fn, delay) {
|
|
134
|
+
var timeoutId;
|
|
135
|
+
return function () {
|
|
136
|
+
var args = [];
|
|
137
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
138
|
+
args[_i] = arguments[_i];
|
|
139
|
+
}
|
|
140
|
+
clearTimeout(timeoutId);
|
|
141
|
+
timeoutId = setTimeout(function () { return fn.apply(void 0, args); }, delay);
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Throttle function execution.
|
|
146
|
+
* @description Ensures the function is called at most once per specified time period.
|
|
147
|
+
* Unlike debounce, throttle guarantees regular execution for continuous events.
|
|
148
|
+
* The first call is executed immediately, then subsequent calls are rate-limited.
|
|
149
|
+
*
|
|
150
|
+
* @template T - The types of the function arguments
|
|
151
|
+
* @param {function(...T): void} fn - The function to throttle
|
|
152
|
+
* @param {number} delay - The minimum delay between calls in milliseconds
|
|
153
|
+
* @returns {function(...T): void} The throttled function
|
|
154
|
+
*
|
|
155
|
+
* @category Timing
|
|
156
|
+
* @example
|
|
157
|
+
* // Basic throttle
|
|
158
|
+
* const logScroll = throttle(() => {
|
|
159
|
+
* console.log('Scroll position:', window.scrollY);
|
|
160
|
+
* }, 100);
|
|
161
|
+
*
|
|
162
|
+
* window.addEventListener('scroll', logScroll);
|
|
163
|
+
* // Logs at most once every 100ms during scrolling
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* // API rate limiting
|
|
167
|
+
* const trackEvent = throttle((event: string, data: any) => {
|
|
168
|
+
* fetch('/api/analytics', {
|
|
169
|
+
* method: 'POST',
|
|
170
|
+
* body: JSON.stringify({ event, data, timestamp: Date.now() })
|
|
171
|
+
* });
|
|
172
|
+
* }, 1000);
|
|
173
|
+
*
|
|
174
|
+
* // Won't exceed 1 request per second
|
|
175
|
+
* button.addEventListener('click', () => trackEvent('button_click', { id: 'submit' }));
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* // Game loop or animation
|
|
179
|
+
* const updateGame = throttle(() => {
|
|
180
|
+
* player.updatePosition();
|
|
181
|
+
* enemies.forEach(e => e.update());
|
|
182
|
+
* renderer.draw();
|
|
183
|
+
* }, 16); // ~60 FPS
|
|
184
|
+
*
|
|
185
|
+
* setInterval(updateGame, 0);
|
|
186
|
+
*
|
|
187
|
+
* @see debounce - Delay execution until activity stops
|
|
188
|
+
* @since 2025-07-03
|
|
189
|
+
*/
|
|
190
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
191
|
+
export var throttle = function (fn, limit) {
|
|
192
|
+
var inThrottle = false;
|
|
193
|
+
return function () {
|
|
194
|
+
var args = [];
|
|
195
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
196
|
+
args[_i] = arguments[_i];
|
|
197
|
+
}
|
|
198
|
+
if (!inThrottle) {
|
|
199
|
+
inThrottle = true;
|
|
200
|
+
setTimeout(function () {
|
|
201
|
+
inThrottle = false;
|
|
202
|
+
}, limit);
|
|
203
|
+
return fn.apply(void 0, args);
|
|
204
|
+
}
|
|
205
|
+
return undefined;
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Batch async operations to avoid overwhelming external services.
|
|
210
|
+
* @description Processes items in chunks with optional delays between batches.
|
|
211
|
+
* Essential for rate-limited APIs or resource-intensive operations.
|
|
212
|
+
* Executes operations in parallel within each batch but sequential between batches.
|
|
213
|
+
*
|
|
214
|
+
* @template T - The type of items to process
|
|
215
|
+
* @template R - The type of results
|
|
216
|
+
* @param {T[]} items - Array of items to process
|
|
217
|
+
* @param {function(T): Promise<R>} fn - Async function to process each item
|
|
218
|
+
* @param {number} batchSize - Maximum number of items to process in parallel
|
|
219
|
+
* @param {number} [delayMs=0] - Delay in milliseconds between batches
|
|
220
|
+
* @returns {Promise<R[]>} Array of results in the same order as input
|
|
221
|
+
*
|
|
222
|
+
* @category Batching
|
|
223
|
+
* @example
|
|
224
|
+
* // Basic batch processing
|
|
225
|
+
* const userIds = Array.from({ length: 100 }, (_, i) => i + 1);
|
|
226
|
+
* const fetchUser = async (id: number) => {
|
|
227
|
+
* const res = await fetch(`/api/users/${id}`);
|
|
228
|
+
* return res.json();
|
|
229
|
+
* };
|
|
230
|
+
*
|
|
231
|
+
* const users = await batchAsync(userIds, fetchUser, 10, 100);
|
|
232
|
+
* // Fetches 10 users at a time with 100ms delay between batches
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* // Email sending with rate limits
|
|
236
|
+
* const recipients = [
|
|
237
|
+
* { email: 'user1@example.com', name: 'User 1' },
|
|
238
|
+
* { email: 'user2@example.com', name: 'User 2' },
|
|
239
|
+
* // ... many more
|
|
240
|
+
* ];
|
|
241
|
+
*
|
|
242
|
+
* const sendEmail = async (recipient: typeof recipients[0]) => {
|
|
243
|
+
* return await emailService.send({
|
|
244
|
+
* to: recipient.email,
|
|
245
|
+
* subject: 'Newsletter',
|
|
246
|
+
* body: `Hello ${recipient.name}!`
|
|
247
|
+
* });
|
|
248
|
+
* };
|
|
249
|
+
*
|
|
250
|
+
* // Send 20 emails per batch with 1 second delay (rate limit compliance)
|
|
251
|
+
* const results = await batchAsync(recipients, sendEmail, 20, 1000);
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* // Image processing
|
|
255
|
+
* const imageUrls = ['img1.jpg', 'img2.jpg', // ... more images, 'img100.jpg'];
|
|
256
|
+
*
|
|
257
|
+
* const processImage = async (url: string) => {
|
|
258
|
+
* const img = await loadImage(url);
|
|
259
|
+
* const processed = await applyFilters(img);
|
|
260
|
+
* return await saveImage(processed);
|
|
261
|
+
* };
|
|
262
|
+
*
|
|
263
|
+
* // Process 5 images at a time to avoid memory issues
|
|
264
|
+
* const processed = await batchAsync(imageUrls, processImage, 5, 200);
|
|
265
|
+
* console.log(`Processed ${processed.length} images`);
|
|
266
|
+
*
|
|
267
|
+
* @see Promise.all - Process all items concurrently without batching
|
|
268
|
+
*/
|
|
269
|
+
export var batchAsync = function (items_1, fn_1) {
|
|
270
|
+
var args_1 = [];
|
|
271
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
272
|
+
args_1[_i - 2] = arguments[_i];
|
|
273
|
+
}
|
|
274
|
+
return __awaiter(void 0, __spreadArray([items_1, fn_1], args_1, true), void 0, function (items, fn, batchSize, delayMs) {
|
|
275
|
+
var results, i, batch, batchResults;
|
|
276
|
+
if (batchSize === void 0) { batchSize = 10; }
|
|
277
|
+
if (delayMs === void 0) { delayMs = 100; }
|
|
278
|
+
return __generator(this, function (_a) {
|
|
279
|
+
switch (_a.label) {
|
|
280
|
+
case 0:
|
|
281
|
+
results = [];
|
|
282
|
+
i = 0;
|
|
283
|
+
_a.label = 1;
|
|
284
|
+
case 1:
|
|
285
|
+
if (!(i < items.length)) return [3 /*break*/, 5];
|
|
286
|
+
batch = items.slice(i, i + batchSize);
|
|
287
|
+
return [4 /*yield*/, Promise.all(batch.map(function (item) { return fn(item); }))];
|
|
288
|
+
case 2:
|
|
289
|
+
batchResults = _a.sent();
|
|
290
|
+
results.push.apply(results, batchResults);
|
|
291
|
+
if (!(i + batchSize < items.length && delayMs > 0)) return [3 /*break*/, 4];
|
|
292
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, delayMs); })];
|
|
293
|
+
case 3:
|
|
294
|
+
_a.sent();
|
|
295
|
+
_a.label = 4;
|
|
296
|
+
case 4:
|
|
297
|
+
i += batchSize;
|
|
298
|
+
return [3 /*break*/, 1];
|
|
299
|
+
case 5: return [2 /*return*/, results];
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Advanced timing utilities for specialized use cases.
|
|
306
|
+
*
|
|
307
|
+
* @category Advanced
|
|
308
|
+
*/
|
|
309
|
+
export var timingUtils = {
|
|
310
|
+
/**
|
|
311
|
+
* Debounce with immediate option.
|
|
312
|
+
* Optionally invokes the function immediately on the leading edge.
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* // Execute immediately on first call, then debounce
|
|
316
|
+
* const saveWithFeedback = timingUtils.debounceWithImmediate(
|
|
317
|
+
* (data: string) => {
|
|
318
|
+
* showSaveIndicator();
|
|
319
|
+
* saveToServer(data);
|
|
320
|
+
* },
|
|
321
|
+
* 1000,
|
|
322
|
+
* true // immediate
|
|
323
|
+
* );
|
|
324
|
+
*
|
|
325
|
+
* // First call executes immediately, subsequent calls are debounced
|
|
326
|
+
* saveWithFeedback('data1'); // Executes immediately
|
|
327
|
+
* saveWithFeedback('data2'); // Debounced
|
|
328
|
+
* saveWithFeedback('data3'); // Debounced, only this executes after 1s
|
|
329
|
+
*/
|
|
330
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
331
|
+
debounceWithImmediate: function (fn, delay, immediate) {
|
|
332
|
+
if (immediate === void 0) { immediate = false; }
|
|
333
|
+
var timeoutId = null;
|
|
334
|
+
return function () {
|
|
335
|
+
var args = [];
|
|
336
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
337
|
+
args[_i] = arguments[_i];
|
|
338
|
+
}
|
|
339
|
+
var callNow = immediate && !timeoutId;
|
|
340
|
+
if (timeoutId) {
|
|
341
|
+
clearTimeout(timeoutId);
|
|
342
|
+
}
|
|
343
|
+
timeoutId = setTimeout(function () {
|
|
344
|
+
timeoutId = null;
|
|
345
|
+
if (!immediate) {
|
|
346
|
+
fn.apply(void 0, args);
|
|
347
|
+
}
|
|
348
|
+
}, delay);
|
|
349
|
+
if (callNow) {
|
|
350
|
+
fn.apply(void 0, args);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
},
|
|
354
|
+
/**
|
|
355
|
+
* Throttle with trailing call option.
|
|
356
|
+
* Ensures the last call is always executed.
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* // Progress updates with final state guarantee
|
|
360
|
+
* const updateProgress = timingUtils.throttleWithTrailing(
|
|
361
|
+
* (percent: number) => {
|
|
362
|
+
* progressBar.style.width = `${percent}%`;
|
|
363
|
+
* if (percent === 100) {
|
|
364
|
+
* showCompletionMessage();
|
|
365
|
+
* }
|
|
366
|
+
* },
|
|
367
|
+
* 100,
|
|
368
|
+
* true // trailing
|
|
369
|
+
* );
|
|
370
|
+
*
|
|
371
|
+
* // Updates at most every 100ms, but guarantees the final 100% is shown
|
|
372
|
+
* for (let i = 0; i <= 100; i++) {
|
|
373
|
+
* updateProgress(i);
|
|
374
|
+
* }
|
|
375
|
+
*/
|
|
376
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
377
|
+
throttleWithTrailing: function (fn, limit, trailing) {
|
|
378
|
+
if (trailing === void 0) { trailing = true; }
|
|
379
|
+
var lastArgs = null;
|
|
380
|
+
var lastCallTime = 0;
|
|
381
|
+
var timeoutId = null;
|
|
382
|
+
return function () {
|
|
383
|
+
var args = [];
|
|
384
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
385
|
+
args[_i] = arguments[_i];
|
|
386
|
+
}
|
|
387
|
+
var now = Date.now();
|
|
388
|
+
var timeSinceLastCall = now - lastCallTime;
|
|
389
|
+
if (timeSinceLastCall >= limit) {
|
|
390
|
+
fn.apply(void 0, args);
|
|
391
|
+
lastCallTime = now;
|
|
392
|
+
lastArgs = null;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
lastArgs = args;
|
|
396
|
+
if (trailing && !timeoutId) {
|
|
397
|
+
var remainingTime = limit - timeSinceLastCall;
|
|
398
|
+
timeoutId = setTimeout(function () {
|
|
399
|
+
if (lastArgs) {
|
|
400
|
+
fn.apply(void 0, lastArgs);
|
|
401
|
+
lastCallTime = Date.now();
|
|
402
|
+
lastArgs = null;
|
|
403
|
+
}
|
|
404
|
+
timeoutId = null;
|
|
405
|
+
}, remainingTime);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
},
|
|
410
|
+
/**
|
|
411
|
+
* Create a function that measures its execution time.
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* const timedFetch = timingUtils.measureTime(
|
|
415
|
+
* async (url: string) => {
|
|
416
|
+
* const response = await fetch(url);
|
|
417
|
+
* return response.json();
|
|
418
|
+
* },
|
|
419
|
+
* (duration, result) => {
|
|
420
|
+
* console.log(`Fetch took ${duration}ms`);
|
|
421
|
+
* analytics.track('api_call_duration', { duration, url: result.url });
|
|
422
|
+
* }
|
|
423
|
+
* );
|
|
424
|
+
*
|
|
425
|
+
* const data = await timedFetch('/api/data');
|
|
426
|
+
*/
|
|
427
|
+
measureTime: function (fn, onComplete) {
|
|
428
|
+
return function () {
|
|
429
|
+
var args = [];
|
|
430
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
431
|
+
args[_i] = arguments[_i];
|
|
432
|
+
}
|
|
433
|
+
var start = performance.now();
|
|
434
|
+
var result = fn.apply(void 0, args);
|
|
435
|
+
if (onComplete) {
|
|
436
|
+
if (result instanceof Promise) {
|
|
437
|
+
// Handle async functions
|
|
438
|
+
var promiseWithTiming = result.then(function (value) {
|
|
439
|
+
var totalDuration = performance.now() - start;
|
|
440
|
+
onComplete(totalDuration, value);
|
|
441
|
+
return value;
|
|
442
|
+
});
|
|
443
|
+
return promiseWithTiming;
|
|
444
|
+
}
|
|
445
|
+
// Handle sync functions
|
|
446
|
+
var duration = performance.now() - start;
|
|
447
|
+
onComplete(duration, result);
|
|
448
|
+
}
|
|
449
|
+
return result;
|
|
450
|
+
};
|
|
451
|
+
},
|
|
452
|
+
};
|
|
453
|
+
//# sourceMappingURL=performance.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.mjs","sourceRoot":"","sources":["../src/performance.mts"],"names":[],"mappings":"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"}
|