@meistrari/data-token 0.0.10 → 0.0.12
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/dist/adapters/hono.d.ts +1 -1
- package/dist/adapters/hono.js +2 -1
- package/dist/index.js +7 -5
- package/dist/retry.d.ts +34 -0
- package/dist/retry.js +65 -0
- package/package.json +1 -1
package/dist/adapters/hono.d.ts
CHANGED
|
@@ -23,4 +23,4 @@ export type DataTokenContext = {
|
|
|
23
23
|
* app.get('/', c => c.json({ data: c.get('authData') }))
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export declare function createDataTokenMiddleware<Env extends DataTokenContext>(url: string, skipOnError?: boolean, getToken?: (c: Context<Env>) => string): import("hono").MiddlewareHandler<Env, string, {}>;
|
|
26
|
+
export declare function createDataTokenMiddleware<Env extends DataTokenContext>(url: string | ((c: Context<Env>) => string), skipOnError?: boolean, getToken?: (c: Context<Env>) => string): import("hono").MiddlewareHandler<Env, string, {}>;
|
package/dist/adapters/hono.js
CHANGED
|
@@ -20,7 +20,8 @@ import { getValidator } from '..';
|
|
|
20
20
|
*/
|
|
21
21
|
export function createDataTokenMiddleware(url, skipOnError = false, getToken = c => c.req.header('x-data-token') ?? '') {
|
|
22
22
|
return createMiddleware(async (c, next) => {
|
|
23
|
-
const
|
|
23
|
+
const jwksUrl = typeof url === 'function' ? url(c) : url;
|
|
24
|
+
const validator = getValidator(jwksUrl);
|
|
24
25
|
const token = getToken(c);
|
|
25
26
|
const data = await validator(token).catch(() => {
|
|
26
27
|
if (skipOnError) {
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createRemoteJWKSet, errors, jwtVerify } from 'jose';
|
|
2
|
-
import {
|
|
2
|
+
import { createExponentialBackoff } from './retry';
|
|
3
3
|
import { DataToken } from './types';
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const retry = createExponentialBackoff({
|
|
5
|
+
maxRetries: 3,
|
|
6
|
+
jitter: true,
|
|
7
|
+
});
|
|
6
8
|
export function getValidator(jwksUrl, { algorithms } = { algorithms: ['RS256'] }) {
|
|
7
|
-
const JWKS = createRemoteJWKSet(new URL(jwksUrl));
|
|
9
|
+
const JWKS = createRemoteJWKSet(new URL(jwksUrl), { cacheMaxAge: 0, headers: { 'cache-control': 'no-cache', 'pragma': 'no-cache' } });
|
|
8
10
|
return async (token) => {
|
|
9
|
-
const { payload } = await
|
|
11
|
+
const { payload } = await retry(async () => jwtVerify(token, JWKS, { algorithms }), err => err instanceof errors.JWKSTimeout || (err instanceof Error && err.message.includes('ECONNRESET')));
|
|
10
12
|
return DataToken.parse(payload);
|
|
11
13
|
};
|
|
12
14
|
}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
type BackoffOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Maximum number of retry attempts
|
|
4
|
+
* @default 5
|
|
5
|
+
*/
|
|
6
|
+
maxRetries?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Initial delay in milliseconds
|
|
9
|
+
* @default 1000 (1 second)
|
|
10
|
+
*/
|
|
11
|
+
baseDelay?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Multiplier for exponential backoff
|
|
14
|
+
* @default 2
|
|
15
|
+
*/
|
|
16
|
+
factor?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Maximum delay cap in milliseconds
|
|
19
|
+
* @default 30000 (30 seconds)
|
|
20
|
+
*/
|
|
21
|
+
maxDelay?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Jitter to prevent synchronized retries in distributed systems
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
26
|
+
jitter?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Create an exponential backoff retry function
|
|
30
|
+
* @param userOptions Configuration options for backoff strategy
|
|
31
|
+
* @returns Retry function with exponential backoff
|
|
32
|
+
*/
|
|
33
|
+
declare function createExponentialBackoff(userOptions?: BackoffOptions): <T>(fn: () => Promise<T>, errorFilter?: (error: unknown) => boolean) => Promise<T>;
|
|
34
|
+
export { createExponentialBackoff };
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const sleep = async (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
2
|
+
/**
|
|
3
|
+
* Calculate delay for a specific retry attempt
|
|
4
|
+
* @param options Backoff configuration options
|
|
5
|
+
* @param attempt Current retry attempt (0-indexed)
|
|
6
|
+
* @returns Calculated delay in milliseconds
|
|
7
|
+
*/
|
|
8
|
+
function calculateDelay(options, attempt) {
|
|
9
|
+
// Basic exponential backoff calculation
|
|
10
|
+
let delay = options.baseDelay * options.factor ** attempt;
|
|
11
|
+
// Cap the delay at maxDelay
|
|
12
|
+
delay = Math.min(delay, options.maxDelay);
|
|
13
|
+
// Apply jitter if enabled
|
|
14
|
+
if (options.jitter) {
|
|
15
|
+
// Add random variation between 0.5x and 1.5x of the calculated delay
|
|
16
|
+
const jitterMultiplier = 0.5 + Math.random();
|
|
17
|
+
delay *= jitterMultiplier;
|
|
18
|
+
}
|
|
19
|
+
return Math.round(delay);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create an exponential backoff retry function
|
|
23
|
+
* @param userOptions Configuration options for backoff strategy
|
|
24
|
+
* @returns Retry function with exponential backoff
|
|
25
|
+
*/
|
|
26
|
+
function createExponentialBackoff(userOptions = {}) {
|
|
27
|
+
// Merge default options with user-provided options
|
|
28
|
+
const options = {
|
|
29
|
+
maxRetries: 5,
|
|
30
|
+
baseDelay: 1000,
|
|
31
|
+
factor: 2,
|
|
32
|
+
maxDelay: 30000,
|
|
33
|
+
jitter: true,
|
|
34
|
+
...userOptions,
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Execute a function with exponential backoff retry strategy
|
|
38
|
+
* @param fn Function to execute
|
|
39
|
+
* @param errorFilter Optional function to determine if retry is needed
|
|
40
|
+
* @returns Promise resolving to the result of the function
|
|
41
|
+
*/
|
|
42
|
+
return async function executeWithBackoff(fn, errorFilter) {
|
|
43
|
+
let lastError;
|
|
44
|
+
for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
|
|
45
|
+
try {
|
|
46
|
+
return await fn();
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
// If no error filter is provided, or the error passes the filter
|
|
50
|
+
const shouldRetry = errorFilter
|
|
51
|
+
? errorFilter(error)
|
|
52
|
+
: attempt < options.maxRetries;
|
|
53
|
+
if (!shouldRetry) {
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
lastError = error;
|
|
57
|
+
// Calculate and apply delay
|
|
58
|
+
const delay = calculateDelay(options, attempt);
|
|
59
|
+
await sleep(delay);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw lastError;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export { createExponentialBackoff };
|
package/package.json
CHANGED