@ahoo-wang/fetcher-cosec 0.8.2 → 0.8.3
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.
|
@@ -8,6 +8,12 @@ import { CoSecOptions } from './types';
|
|
|
8
8
|
* - CoSec-App-Id: Application identifier
|
|
9
9
|
* - Authorization: Bearer token
|
|
10
10
|
* - CoSec-Request-Id: Unique request identifier for each request
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* This interceptor runs after the basic request processing interceptors but before
|
|
14
|
+
* the actual HTTP request is made. The order is set to Number.MIN_SAFE_INTEGER + 1000
|
|
15
|
+
* to allow for other authentication or preprocessing interceptors to run earlier
|
|
16
|
+
* while ensuring it runs before FetchInterceptor.
|
|
11
17
|
*/
|
|
12
18
|
export declare class CoSecRequestInterceptor implements Interceptor {
|
|
13
19
|
name: string;
|
|
@@ -16,6 +22,15 @@ export declare class CoSecRequestInterceptor implements Interceptor {
|
|
|
16
22
|
constructor(options: CoSecOptions);
|
|
17
23
|
/**
|
|
18
24
|
* Intercept requests to add CoSec authentication headers
|
|
25
|
+
*
|
|
26
|
+
* This method adds the following headers to each request:
|
|
27
|
+
* - CoSec-App-Id: The application identifier from the CoSec options
|
|
28
|
+
* - CoSec-Device-Id: A unique device identifier, either retrieved from storage or generated
|
|
29
|
+
* - CoSec-Request-Id: A unique identifier for this specific request
|
|
30
|
+
* - Authorization: Bearer token if available in token storage
|
|
31
|
+
*
|
|
32
|
+
* @param exchange - The fetch exchange containing the request to be processed
|
|
33
|
+
* @returns The modified exchange with CoSec authentication headers added
|
|
19
34
|
*/
|
|
20
35
|
intercept(exchange: FetchExchange): FetchExchange;
|
|
21
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosecRequestInterceptor.d.ts","sourceRoot":"","sources":["../src/cosecRequestInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAkB,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAgB,YAAY,EAAE,MAAM,SAAS,CAAC;AAGrD
|
|
1
|
+
{"version":3,"file":"cosecRequestInterceptor.d.ts","sourceRoot":"","sources":["../src/cosecRequestInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAkB,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAgB,YAAY,EAAE,MAAM,SAAS,CAAC;AAGrD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,uBAAwB,YAAW,WAAW;IACzD,IAAI,SAA6B;IACjC,KAAK,SAAkC;IACvC,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE,YAAY;IAIjC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa;CAwBlD"}
|
|
@@ -4,12 +4,31 @@ import { FetchExchange, Interceptor } from '@ahoo-wang/fetcher';
|
|
|
4
4
|
* CoSec Response Interceptor
|
|
5
5
|
*
|
|
6
6
|
* Handles automatic token refresh based on response codes
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* This interceptor runs near the end of the response processing chain, just before
|
|
10
|
+
* the final response is returned. The order is set to Number.MAX_SAFE_INTEGER - 100
|
|
11
|
+
* to ensure it runs after most other response interceptors but still allows for
|
|
12
|
+
* final processing interceptors to run afterward. This order aligns with other
|
|
13
|
+
* response enhancement interceptors like EventStreamInterceptor.
|
|
7
14
|
*/
|
|
8
15
|
export declare class CoSecResponseInterceptor implements Interceptor {
|
|
9
16
|
name: string;
|
|
10
17
|
order: number;
|
|
11
18
|
private options;
|
|
12
19
|
constructor(options: CoSecOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Intercept responses to handle token refresh for unauthorized responses
|
|
22
|
+
*
|
|
23
|
+
* This method checks if a response has a 401 (UNAUTHORIZED) status code and attempts
|
|
24
|
+
* to refresh the authentication token if one is available. If token refresh is successful,
|
|
25
|
+
* the original request is retried with the new token. If token refresh fails, stored
|
|
26
|
+
* tokens are cleared and the original error is re-thrown.
|
|
27
|
+
*
|
|
28
|
+
* @param exchange - The fetch exchange containing the response to be processed
|
|
29
|
+
* @returns Promise<FetchExchange> The processed exchange, either with a refreshed token or original error
|
|
30
|
+
* @throws Error if token refresh fails or other errors occur during processing
|
|
31
|
+
*/
|
|
13
32
|
intercept(exchange: FetchExchange): Promise<FetchExchange>;
|
|
14
33
|
}
|
|
15
34
|
//# sourceMappingURL=cosecResponseInterceptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosecResponseInterceptor.d.ts","sourceRoot":"","sources":["../src/cosecResponseInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAiB,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEhE
|
|
1
|
+
{"version":3,"file":"cosecResponseInterceptor.d.ts","sourceRoot":"","sources":["../src/cosecResponseInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAiB,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,qBAAa,wBAAyB,YAAW,WAAW;IAC1D,IAAI,SAA8B;IAClC,KAAK,SAAiC;IACtC,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE,YAAY;IAIjC;;;;;;;;;;;OAWG;IACG,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;CAsBjE"}
|
package/dist/index.es.js
CHANGED
|
@@ -23,10 +23,19 @@ class l {
|
|
|
23
23
|
const I = new l();
|
|
24
24
|
class T {
|
|
25
25
|
constructor(e) {
|
|
26
|
-
this.name = "CoSecRequestInterceptor", this.order = Number.MIN_SAFE_INTEGER, this.options = e;
|
|
26
|
+
this.name = "CoSecRequestInterceptor", this.order = Number.MIN_SAFE_INTEGER + 1e3, this.options = e;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Intercept requests to add CoSec authentication headers
|
|
30
|
+
*
|
|
31
|
+
* This method adds the following headers to each request:
|
|
32
|
+
* - CoSec-App-Id: The application identifier from the CoSec options
|
|
33
|
+
* - CoSec-Device-Id: A unique device identifier, either retrieved from storage or generated
|
|
34
|
+
* - CoSec-Request-Id: A unique identifier for this specific request
|
|
35
|
+
* - Authorization: Bearer token if available in token storage
|
|
36
|
+
*
|
|
37
|
+
* @param exchange - The fetch exchange containing the request to be processed
|
|
38
|
+
* @returns The modified exchange with CoSec authentication headers added
|
|
30
39
|
*/
|
|
31
40
|
intercept(e) {
|
|
32
41
|
const r = I.generateId(), n = this.options.deviceIdStorage.getOrCreate(), s = this.options.tokenStorage.get(), a = {
|
|
@@ -40,8 +49,20 @@ class T {
|
|
|
40
49
|
}
|
|
41
50
|
class D {
|
|
42
51
|
constructor(e) {
|
|
43
|
-
this.name = "CoSecResponseInterceptor", this.order = Number.MAX_SAFE_INTEGER, this.options = e;
|
|
52
|
+
this.name = "CoSecResponseInterceptor", this.order = Number.MAX_SAFE_INTEGER - 100, this.options = e;
|
|
44
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Intercept responses to handle token refresh for unauthorized responses
|
|
56
|
+
*
|
|
57
|
+
* This method checks if a response has a 401 (UNAUTHORIZED) status code and attempts
|
|
58
|
+
* to refresh the authentication token if one is available. If token refresh is successful,
|
|
59
|
+
* the original request is retried with the new token. If token refresh fails, stored
|
|
60
|
+
* tokens are cleared and the original error is re-thrown.
|
|
61
|
+
*
|
|
62
|
+
* @param exchange - The fetch exchange containing the response to be processed
|
|
63
|
+
* @returns Promise<FetchExchange> The processed exchange, either with a refreshed token or original error
|
|
64
|
+
* @throws Error if token refresh fails or other errors occur during processing
|
|
65
|
+
*/
|
|
45
66
|
async intercept(e) {
|
|
46
67
|
const r = e.response;
|
|
47
68
|
if (!r || r.status !== c.UNAUTHORIZED)
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(r,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(r=typeof globalThis<"u"?globalThis:r||self,s(r.FetcherCoSec={}))})(this,(function(r){"use strict";var s=(t=>(t.DEVICE_ID="CoSec-Device-Id",t.APP_ID="CoSec-App-Id",t.AUTHORIZATION="Authorization",t.REQUEST_ID="CoSec-Request-Id",t))(s||{}),c=(t=>(t[t.UNAUTHORIZED=401]="UNAUTHORIZED",t))(c||{});const g={ALLOW:{authorized:!0,reason:"Allow"},EXPLICIT_DENY:{authorized:!1,reason:"Explicit Deny"},IMPLICIT_DENY:{authorized:!1,reason:"Implicit Deny"},TOKEN_EXPIRED:{authorized:!1,reason:"Token Expired"},TOO_MANY_REQUESTS:{authorized:!1,reason:"Too Many Requests"}},T="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";let f=(t=21)=>{let e="",o=crypto.getRandomValues(new Uint8Array(t|=0));for(;t--;)e+=T[o[t]&63];return e};class d{generateId(){return f()}}const u=new d;class p{constructor(e){this.name="CoSecRequestInterceptor",this.order=Number.MIN_SAFE_INTEGER,this.options=e}intercept(e){const o=u.generateId(),i=this.options.deviceIdStorage.getOrCreate(),n=this.options.tokenStorage.get(),S={...e.request,headers:{...e.request.headers}},a=S.headers;return a[s.APP_ID]=this.options.appId,a[s.DEVICE_ID]=i,a[s.REQUEST_ID]=o,n&&(a[s.AUTHORIZATION]=`Bearer ${n.accessToken}`),e.request=S,e}}class D{constructor(e){this.name="CoSecResponseInterceptor",this.order=Number.MAX_SAFE_INTEGER,this.options=e}async intercept(e){const o=e.response;if(!o||o.status!==c.UNAUTHORIZED)return e;const i=this.options.tokenStorage.get();if(!i)return e;try{const n=await this.options.tokenRefresher.refresh(i);return this.options.tokenStorage.set(n),e.fetcher.request(e.url,e.request)}catch(n){throw this.options.tokenStorage.clear(),n}}}class h{constructor(){this.store=new Map}get length(){return this.store.size}clear(){this.store.clear()}getItem(e){const o=this.store.get(e);return o!==void 0?o:null}key(e){return Array.from(this.store.keys())[e]||null}removeItem(e){this.store.has(e)&&this.store.delete(e)}setItem(e,o){this.store.set(e,o)}}function I(){return typeof window<"u"&&window.localStorage?window.localStorage:new h}const l="cosec-device-id";class _{constructor(e=l,o=I()){this.deviceIdKey=e,this.storage=o}get(){return this.storage.getItem(this.deviceIdKey)}set(e){this.storage.setItem(this.deviceIdKey,e)}generateDeviceId(){return u.generateId()}getOrCreate(){let e=this.get();return e||(e=this.generateDeviceId(),this.set(e)),e}clear(){this.storage.removeItem(this.deviceIdKey)}}const E="cosec-token";class y{constructor(e=E,o=I()){this.tokenKey=e,this.storage=o}get(){const e=this.storage.getItem(this.tokenKey);return e?JSON.parse(e):null}set(e){const o=JSON.stringify(e);this.storage.setItem(this.tokenKey,o)}clear(){this.storage.removeItem(this.tokenKey)}}r.AuthorizeResults=g,r.CoSecHeaders=s,r.CoSecRequestInterceptor=p,r.CoSecResponseInterceptor=D,r.DEFAULT_COSEC_DEVICE_ID_KEY=l,r.DEFAULT_COSEC_TOKEN_KEY=E,r.DeviceIdStorage=_,r.InMemoryStorage=h,r.NanoIdGenerator=d,r.ResponseCodes=c,r.TokenStorage=y,r.getStorage=I,r.idGenerator=u,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(r,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(r=typeof globalThis<"u"?globalThis:r||self,s(r.FetcherCoSec={}))})(this,(function(r){"use strict";var s=(t=>(t.DEVICE_ID="CoSec-Device-Id",t.APP_ID="CoSec-App-Id",t.AUTHORIZATION="Authorization",t.REQUEST_ID="CoSec-Request-Id",t))(s||{}),c=(t=>(t[t.UNAUTHORIZED=401]="UNAUTHORIZED",t))(c||{});const g={ALLOW:{authorized:!0,reason:"Allow"},EXPLICIT_DENY:{authorized:!1,reason:"Explicit Deny"},IMPLICIT_DENY:{authorized:!1,reason:"Implicit Deny"},TOKEN_EXPIRED:{authorized:!1,reason:"Token Expired"},TOO_MANY_REQUESTS:{authorized:!1,reason:"Too Many Requests"}},T="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";let f=(t=21)=>{let e="",o=crypto.getRandomValues(new Uint8Array(t|=0));for(;t--;)e+=T[o[t]&63];return e};class d{generateId(){return f()}}const u=new d;class p{constructor(e){this.name="CoSecRequestInterceptor",this.order=Number.MIN_SAFE_INTEGER+1e3,this.options=e}intercept(e){const o=u.generateId(),i=this.options.deviceIdStorage.getOrCreate(),n=this.options.tokenStorage.get(),S={...e.request,headers:{...e.request.headers}},a=S.headers;return a[s.APP_ID]=this.options.appId,a[s.DEVICE_ID]=i,a[s.REQUEST_ID]=o,n&&(a[s.AUTHORIZATION]=`Bearer ${n.accessToken}`),e.request=S,e}}class D{constructor(e){this.name="CoSecResponseInterceptor",this.order=Number.MAX_SAFE_INTEGER-100,this.options=e}async intercept(e){const o=e.response;if(!o||o.status!==c.UNAUTHORIZED)return e;const i=this.options.tokenStorage.get();if(!i)return e;try{const n=await this.options.tokenRefresher.refresh(i);return this.options.tokenStorage.set(n),e.fetcher.request(e.url,e.request)}catch(n){throw this.options.tokenStorage.clear(),n}}}class h{constructor(){this.store=new Map}get length(){return this.store.size}clear(){this.store.clear()}getItem(e){const o=this.store.get(e);return o!==void 0?o:null}key(e){return Array.from(this.store.keys())[e]||null}removeItem(e){this.store.has(e)&&this.store.delete(e)}setItem(e,o){this.store.set(e,o)}}function I(){return typeof window<"u"&&window.localStorage?window.localStorage:new h}const l="cosec-device-id";class _{constructor(e=l,o=I()){this.deviceIdKey=e,this.storage=o}get(){return this.storage.getItem(this.deviceIdKey)}set(e){this.storage.setItem(this.deviceIdKey,e)}generateDeviceId(){return u.generateId()}getOrCreate(){let e=this.get();return e||(e=this.generateDeviceId(),this.set(e)),e}clear(){this.storage.removeItem(this.deviceIdKey)}}const E="cosec-token";class y{constructor(e=E,o=I()){this.tokenKey=e,this.storage=o}get(){const e=this.storage.getItem(this.tokenKey);return e?JSON.parse(e):null}set(e){const o=JSON.stringify(e);this.storage.setItem(this.tokenKey,o)}clear(){this.storage.removeItem(this.tokenKey)}}r.AuthorizeResults=g,r.CoSecHeaders=s,r.CoSecRequestInterceptor=p,r.CoSecResponseInterceptor=D,r.DEFAULT_COSEC_DEVICE_ID_KEY=l,r.DEFAULT_COSEC_TOKEN_KEY=E,r.DeviceIdStorage=_,r.InMemoryStorage=h,r.NanoIdGenerator=d,r.ResponseCodes=c,r.TokenStorage=y,r.getStorage=I,r.idGenerator=u,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahoo-wang/fetcher-cosec",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "CoSec authentication integration for Fetcher HTTP client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fetch",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"nanoid": "^5.1.5",
|
|
38
|
-
"@ahoo-wang/fetcher": "0.8.
|
|
38
|
+
"@ahoo-wang/fetcher": "0.8.3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@vitest/coverage-v8": "^3.2.4",
|