mentie 0.3.16 → 0.3.17
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/modules/cache.js +5 -0
- package/modules/environment.js +6 -2
- package/modules/network.js +17 -12
- package/modules/promises.js +18 -9
- package/package.json +1 -1
package/modules/cache.js
CHANGED
|
@@ -29,6 +29,11 @@ export function cache( key, value, expires_in_ms=Infinity ) {
|
|
|
29
29
|
log.warn( `The cache key is ${ key }, this may indicate a bug in your cache logic` )
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
if( typeof expires_in_ms !== 'number' ) {
|
|
33
|
+
log.warn( `cache() expires_in_ms must be a number, got ${ typeof expires_in_ms }` )
|
|
34
|
+
expires_in_ms = Infinity
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
// If value is provided, save value and expiration
|
|
33
38
|
if( value !== undefined ) _cache[key] = { value, expires: Date.now() + expires_in_ms }
|
|
34
39
|
|
package/modules/environment.js
CHANGED
|
@@ -117,10 +117,14 @@ env.is_android = () => env.is_web() && navigator.userAgent?.toUpperCase().includ
|
|
|
117
117
|
* Checks if the code is running in a web browser and the platform is iOS.
|
|
118
118
|
* @returns {boolean} True if the code is running in a web browser and the platform is made by Apple
|
|
119
119
|
*/
|
|
120
|
-
env.is_apple = () =>
|
|
120
|
+
env.is_apple = () => {
|
|
121
|
+
if( !env.is_web() ) return false
|
|
122
|
+
const userAgent = navigator.userAgent?.toUpperCase()
|
|
123
|
+
return userAgent?.includes( 'MAC OS X' ) || userAgent?.includes( 'IPHONE' ) || userAgent?.includes( 'IPAD' )
|
|
124
|
+
}
|
|
121
125
|
|
|
122
126
|
/**
|
|
123
|
-
* Checks if the code is running in a web browser and the platform is
|
|
127
|
+
* Checks if the code is running in a web browser and the platform is Linux.
|
|
124
128
|
* @returns {boolean} True if the code is running in a web browser and the platform is Linux, otherwise false.
|
|
125
129
|
*/
|
|
126
130
|
env.is_linux = () => env.is_web() && navigator.userAgent?.toUpperCase().includes( 'LINUX' )
|
package/modules/network.js
CHANGED
|
@@ -6,32 +6,37 @@
|
|
|
6
6
|
* @returns {Object} signal_data - Object containing fetch options and abort signal
|
|
7
7
|
* @returns {Object} signal_data.fetch_options - Options for usage with fetch requests
|
|
8
8
|
* @returns {AbortController} signal_data.controller - Raw abort controller
|
|
9
|
-
* @returns {
|
|
10
|
-
* @
|
|
11
|
-
*
|
|
9
|
+
* @returns {number|null} signal_data.timeout_id - Timeout ID, or null if no timeout was set
|
|
10
|
+
* @example
|
|
11
|
+
* const { fetch_options, controller } = abort_controller( { timeout_ms: 5000 } )
|
|
12
|
+
* fetch( 'https://api.example.com/data', fetch_options )
|
|
13
|
+
* controller.abort() // Abort the request
|
|
12
14
|
*/
|
|
13
15
|
export const abort_controller = ( { timeout_ms }={} ) => {
|
|
14
16
|
|
|
17
|
+
// Input validation
|
|
18
|
+
if( timeout_ms !== undefined && ( typeof timeout_ms !== 'number' || timeout_ms < 0 ) ) {
|
|
19
|
+
throw new Error( 'timeout_ms must be a non-negative number' )
|
|
20
|
+
}
|
|
21
|
+
|
|
15
22
|
// Request with timeout
|
|
16
23
|
const controller = new AbortController()
|
|
17
|
-
const timeout_id = timeout_ms
|
|
24
|
+
const timeout_id = timeout_ms !== undefined ? setTimeout( () => {
|
|
18
25
|
controller.abort()
|
|
19
|
-
}, timeout_ms )
|
|
26
|
+
}, timeout_ms ) : null
|
|
27
|
+
|
|
28
|
+
// Clear timeout when controller is aborted
|
|
29
|
+
controller.signal.addEventListener( 'abort', () => {
|
|
30
|
+
if( timeout_id !== null ) clearTimeout( timeout_id )
|
|
31
|
+
} )
|
|
20
32
|
|
|
21
33
|
const fetch_options = {
|
|
22
34
|
signal: controller.signal
|
|
23
35
|
}
|
|
24
36
|
|
|
25
|
-
const abort = () => {
|
|
26
|
-
if( timeout_ms ) clearTimeout( timeout_id )
|
|
27
|
-
controller.abort()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
37
|
return {
|
|
31
38
|
fetch_options,
|
|
32
39
|
controller,
|
|
33
|
-
abort_signal: abort,
|
|
34
|
-
abort,
|
|
35
40
|
timeout_id
|
|
36
41
|
}
|
|
37
42
|
|
package/modules/promises.js
CHANGED
|
@@ -60,7 +60,7 @@ export async function make_retryable( async_function, { retry_times = 5, cooldow
|
|
|
60
60
|
*
|
|
61
61
|
* @param {Array<Function>} async_function_array - Array of async functions to be throttled and retried.
|
|
62
62
|
* @param {Object} options - Options for throttling and retrying.
|
|
63
|
-
* @param {number} [options.
|
|
63
|
+
* @param {number} [options.max_parallel=2] - Maximum number of functions to run in parallel.
|
|
64
64
|
* @param {number} [options.retry_times] - Number of times to retry each function.
|
|
65
65
|
* @param {number} [options.cooldown_in_s] - Cooldown time in seconds between retries.
|
|
66
66
|
* @param {number} [options.cooldown_entropy] - Random factor to add to the cooldown time.
|
|
@@ -112,17 +112,26 @@ export async function throttle_and_retry( async_function_array = [], { max_paral
|
|
|
112
112
|
*/
|
|
113
113
|
export async function promise_timeout( promise, timeout_in_ms=60_000, throw_on_timeout=true ) {
|
|
114
114
|
|
|
115
|
-
// Timeout
|
|
116
|
-
|
|
115
|
+
// Timeout id placeholder
|
|
116
|
+
let timeout_id
|
|
117
|
+
|
|
118
|
+
// Timeout function that stores the timeout ID so we can clear it
|
|
119
|
+
const timeout = () => new Promise( ( res, rej ) => {
|
|
120
|
+
timeout_id = setTimeout( throw_on_timeout ? rej : () => res( 'timed out' ), timeout_in_ms )
|
|
121
|
+
} )
|
|
117
122
|
|
|
118
123
|
// Race the promise against the timeout
|
|
119
|
-
|
|
124
|
+
try {
|
|
125
|
+
const result = await Promise.race( [
|
|
126
|
+
promise,
|
|
127
|
+
timeout()
|
|
128
|
+
] )
|
|
120
129
|
|
|
121
|
-
|
|
122
|
-
promise,
|
|
130
|
+
return result
|
|
123
131
|
|
|
124
|
-
|
|
125
|
-
timeout
|
|
126
|
-
|
|
132
|
+
} finally {
|
|
133
|
+
// Clear the timeout
|
|
134
|
+
clearTimeout( timeout_id )
|
|
135
|
+
}
|
|
127
136
|
|
|
128
137
|
}
|