@gh-platform/auth-sdk 1.0.7 → 1.0.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/dist/auth-sdk.es.js +6 -6
- package/dist/auth-sdk.min.js +1 -1
- package/dist/auth-sdk.umd.js +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/client.js +11 -8
- package/src/index.d.ts +1 -1
package/dist/auth-sdk.es.js
CHANGED
|
@@ -20,7 +20,8 @@ class AuthClient {
|
|
|
20
20
|
loginPath = null,
|
|
21
21
|
refreshPath = null,
|
|
22
22
|
headers = {},
|
|
23
|
-
storage = null
|
|
23
|
+
storage = null,
|
|
24
|
+
fetcher = null
|
|
24
25
|
}) {
|
|
25
26
|
if (!baseUrl) throw new Error("baseUrl is required");
|
|
26
27
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -34,6 +35,7 @@ class AuthClient {
|
|
|
34
35
|
this.tenant = tenant;
|
|
35
36
|
this.headers = { "Content-Type": "application/json", ...headers };
|
|
36
37
|
this.storage = storage;
|
|
38
|
+
this.fetcher = fetcher;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Login payload uses identifier + password (+ optional totp)
|
|
@@ -104,6 +106,7 @@ class AuthClient {
|
|
|
104
106
|
setRefreshPromise(null);
|
|
105
107
|
}
|
|
106
108
|
}
|
|
109
|
+
// src/client.js
|
|
107
110
|
async introspect(token = null) {
|
|
108
111
|
let finalToken = token;
|
|
109
112
|
if (this.storage && !finalToken) {
|
|
@@ -115,11 +118,8 @@ class AuthClient {
|
|
|
115
118
|
if (!this.introspectUrl) {
|
|
116
119
|
throw new Error("No introspect url config");
|
|
117
120
|
}
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
const res = await fetch(this.introspectUrl, {
|
|
121
|
-
method: "GET",
|
|
122
|
-
headers
|
|
121
|
+
const res = await this.fetcher.fetch(this.introspectUrl, {
|
|
122
|
+
method: "GET"
|
|
123
123
|
});
|
|
124
124
|
if (!res.ok) {
|
|
125
125
|
const text = await res.text().catch(() => res.statusText);
|
package/dist/auth-sdk.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,introspectBaseUrl:t,tenant:r=null,loginPath:s=null,refreshPath:o=null,headers:n={},storage:a=null}){if(!e)throw new Error("baseUrl is required");if(this.baseUrl=e.replace(/\/$/,""),!t)throw new Error("introspectBaseUrl is required");const
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,introspectBaseUrl:t,tenant:r=null,loginPath:s=null,refreshPath:o=null,headers:n={},storage:a=null,fetcher:i=null}){if(!e)throw new Error("baseUrl is required");if(this.baseUrl=e.replace(/\/$/,""),!t)throw new Error("introspectBaseUrl is required");const h=r?`/api/v1/${r}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(s||`${h}/login`),this.refreshUrl=this.baseUrl+(o||`${h}/refresh`),this.introspectUrl=`${t}/introspect`,this.tenant=r,this.headers={"Content-Type":"application/json",...n},this.storage=a,this.fetcher=i}async login(e,t,r=null,s={}){const o={identifier:e,password:t,...s};r&&(o.totp=r);const n=await fetch(this.loginUrl,{method:"POST",headers:this.headers,body:JSON.stringify(o)});if(!n.ok){const e=await n.text().catch(()=>n.statusText);throw new Error(`Login failed: ${n.status} ${e}`)}let a;try{a=await n.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}const i=a.data||a;return this.storage&&(i.access_token&&(this.storage.accessToken=i.access_token),i.refresh_token&&(this.storage.refreshToken=i.refresh_token)),a}async refresh(e){if(r())return r();const t=(async()=>{const t=await fetch(this.refreshUrl,{method:"POST",headers:this.headers,body:JSON.stringify({refresh_token:e})});if(!t.ok){const e=await t.text().catch(()=>t.statusText);throw new Error(`Refresh failed: ${t.status} ${e}`)}let r;try{r=await t.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}const s=r.data||r;return this.storage&&(s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token)),r})();s(t);try{return await t}finally{s(null)}}async introspect(e=null){let t=e;if(this.storage&&!t&&(t=this.storage.accessToken),!t)throw new Error("No access token available for introspection");if(!this.introspectUrl)throw new Error("No introspect url config");const r=await this.fetcher.fetch(this.introspectUrl,{method:"GET"});if(!r.ok){const e=await r.text().catch(()=>r.statusText);throw new Error(`Introspect failed: ${r.status} ${e}`)}let s;try{s=await r.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}return s}}class n{constructor(e="auth",t=null){this.prefix=e,this.tenant=t}_key(e){return this.tenant?`${this.prefix}:${this.tenant}_${e}`:`${this.prefix}_${e}`}get accessToken(){return localStorage.getItem(this._key("access_token"))}set accessToken(e){null==e?localStorage.removeItem(this._key("access_token")):localStorage.setItem(this._key("access_token"),e)}get refreshToken(){return localStorage.getItem(this._key("refresh_token"))}set refreshToken(e){null==e?localStorage.removeItem(this._key("refresh_token")):localStorage.setItem(this._key("refresh_token"),e)}clear(){localStorage.removeItem(this._key("access_token")),localStorage.removeItem(this._key("refresh_token"))}}class a{constructor(e,t=null){this.client=e,this.storage=t||new n("auth",e.tenant||null)}async fetch(e,t={},r=null){const s=this.storage.accessToken,o=new Headers(t.headers||{});return s&&o.set("Authorization",`Bearer ${s}`),t.method&&"GET"!==t.method&&t.body?await this._xhrRequest(e,t,o,r):await this._fetchWithDownloadProgress(e,t,o,r)}async _fetchWithDownloadProgress(e,t,r,s){let o=await fetch(e,{...t,headers:r});if(401===o.status&&this.storage.refreshToken)try{const s=await this.client.refresh(this.storage.refreshToken);s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token),r.set("Authorization",`Bearer ${this.storage.accessToken}`),o=await fetch(e,{...t,headers:r})}catch{throw this.storage.clear(),new Error("Unauthorized, please login again")}if(!s||!o.body)return o;const n=o.body.getReader(),a=+o.headers.get("Content-Length")||0;let i=0;const h=[];for(;;){const{done:e,value:t}=await n.read();if(e)break;h.push(t),i+=t.length,a?s(Math.round(i/a*100),i,a):s(null,i,null)}const c=new Blob(h);return new Response(c,o)}_xhrRequest(e,t,r,s){return new Promise((o,n)=>{const a=new XMLHttpRequest;a.open(t.method||"POST",e,!0);for(const[e,t]of r.entries())a.setRequestHeader(e,t);a.upload&&s&&(a.upload.onprogress=e=>{if(e.lengthComputable){const t=Math.round(e.loaded/e.total*100);s(t,e.loaded,e.total)}else s(null,e.loaded,null)}),a.onload=()=>{o(new Response(a.response,{status:a.status}))},a.onerror=()=>n(new Error("Network error")),a.send(t.body)})}}const i={AuthClient:o,AuthFetch:a,TokenStorage:n};e.AuthClient=o,e.AuthFetch=a,e.TokenStorage=n,e.default=i,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/auth-sdk.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,introspectBaseUrl:t,tenant:r=null,loginPath:s=null,refreshPath:o=null,headers:n={},storage:a=null}){if(!e)throw new Error("baseUrl is required");if(this.baseUrl=e.replace(/\/$/,""),!t)throw new Error("introspectBaseUrl is required");const
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,introspectBaseUrl:t,tenant:r=null,loginPath:s=null,refreshPath:o=null,headers:n={},storage:a=null,fetcher:i=null}){if(!e)throw new Error("baseUrl is required");if(this.baseUrl=e.replace(/\/$/,""),!t)throw new Error("introspectBaseUrl is required");const h=r?`/api/v1/${r}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(s||`${h}/login`),this.refreshUrl=this.baseUrl+(o||`${h}/refresh`),this.introspectUrl=`${t}/introspect`,this.tenant=r,this.headers={"Content-Type":"application/json",...n},this.storage=a,this.fetcher=i}async login(e,t,r=null,s={}){const o={identifier:e,password:t,...s};r&&(o.totp=r);const n=await fetch(this.loginUrl,{method:"POST",headers:this.headers,body:JSON.stringify(o)});if(!n.ok){const e=await n.text().catch(()=>n.statusText);throw new Error(`Login failed: ${n.status} ${e}`)}let a;try{a=await n.json()}catch(h){throw console.error("❌ JSON parse error:",h),new Error("Invalid JSON response from server")}const i=a.data||a;return this.storage&&(i.access_token&&(this.storage.accessToken=i.access_token),i.refresh_token&&(this.storage.refreshToken=i.refresh_token)),a}async refresh(e){if(r())return r();const t=(async()=>{const t=await fetch(this.refreshUrl,{method:"POST",headers:this.headers,body:JSON.stringify({refresh_token:e})});if(!t.ok){const e=await t.text().catch(()=>t.statusText);throw new Error(`Refresh failed: ${t.status} ${e}`)}let r;try{r=await t.json()}catch(o){throw console.error("❌ JSON parse error:",o),new Error("Invalid JSON response from server")}const s=r.data||r;return this.storage&&(s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token)),r})();s(t);try{return await t}finally{s(null)}}async introspect(e=null){let t=e;if(this.storage&&!t&&(t=this.storage.accessToken),!t)throw new Error("No access token available for introspection");if(!this.introspectUrl)throw new Error("No introspect url config");const r=await this.fetcher.fetch(this.introspectUrl,{method:"GET"});if(!r.ok){const e=await r.text().catch(()=>r.statusText);throw new Error(`Introspect failed: ${r.status} ${e}`)}let s;try{s=await r.json()}catch(o){throw console.error("❌ JSON parse error:",o),new Error("Invalid JSON response from server")}return s}}class n{constructor(e="auth",t=null){this.prefix=e,this.tenant=t}_key(e){return this.tenant?`${this.prefix}:${this.tenant}_${e}`:`${this.prefix}_${e}`}get accessToken(){return localStorage.getItem(this._key("access_token"))}set accessToken(e){null==e?localStorage.removeItem(this._key("access_token")):localStorage.setItem(this._key("access_token"),e)}get refreshToken(){return localStorage.getItem(this._key("refresh_token"))}set refreshToken(e){null==e?localStorage.removeItem(this._key("refresh_token")):localStorage.setItem(this._key("refresh_token"),e)}clear(){localStorage.removeItem(this._key("access_token")),localStorage.removeItem(this._key("refresh_token"))}}class a{constructor(e,t=null){this.client=e,this.storage=t||new n("auth",e.tenant||null)}async fetch(e,t={},r=null){const s=this.storage.accessToken,o=new Headers(t.headers||{});return s&&o.set("Authorization",`Bearer ${s}`),t.method&&"GET"!==t.method&&t.body?await this._xhrRequest(e,t,o,r):await this._fetchWithDownloadProgress(e,t,o,r)}async _fetchWithDownloadProgress(e,t,r,s){let o=await fetch(e,{...t,headers:r});if(401===o.status&&this.storage.refreshToken)try{const s=await this.client.refresh(this.storage.refreshToken);s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token),r.set("Authorization",`Bearer ${this.storage.accessToken}`),o=await fetch(e,{...t,headers:r})}catch{throw this.storage.clear(),new Error("Unauthorized, please login again")}if(!s||!o.body)return o;const n=o.body.getReader(),a=+o.headers.get("Content-Length")||0;let i=0;const h=[];for(;;){const{done:e,value:t}=await n.read();if(e)break;if(h.push(t),i+=t.length,a){s(Math.round(i/a*100),i,a)}else s(null,i,null)}const c=new Blob(h);return new Response(c,o)}_xhrRequest(e,t,r,s){return new Promise((o,n)=>{const a=new XMLHttpRequest;a.open(t.method||"POST",e,!0);for(const[e,t]of r.entries())a.setRequestHeader(e,t);a.upload&&s&&(a.upload.onprogress=e=>{if(e.lengthComputable){const t=Math.round(e.loaded/e.total*100);s(t,e.loaded,e.total)}else s(null,e.loaded,null)}),a.onload=()=>{o(new Response(a.response,{status:a.status}))},a.onerror=()=>n(new Error("Network error")),a.send(t.body)})}}const i={AuthClient:o,AuthFetch:a,TokenStorage:n};e.AuthClient=o,e.AuthFetch=a,e.TokenStorage=n,e.default=i,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -17,6 +17,7 @@ export default class AuthClient {
|
|
|
17
17
|
refreshPath = null,
|
|
18
18
|
headers = {},
|
|
19
19
|
storage = null,
|
|
20
|
+
fetcher = null,
|
|
20
21
|
}) {
|
|
21
22
|
if (!baseUrl) throw new Error("baseUrl is required");
|
|
22
23
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -34,6 +35,7 @@ export default class AuthClient {
|
|
|
34
35
|
this.tenant = tenant;
|
|
35
36
|
this.headers = { "Content-Type": "application/json", ...headers };
|
|
36
37
|
this.storage = storage;
|
|
38
|
+
this.fetcher = fetcher;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -120,10 +122,9 @@ export default class AuthClient {
|
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
|
|
125
|
+
// src/client.js
|
|
126
|
+
|
|
123
127
|
async introspect(token = null) {
|
|
124
|
-
// -----------------------------
|
|
125
|
-
// 🔥 Auto-get token from storage
|
|
126
|
-
// -----------------------------
|
|
127
128
|
let finalToken = token;
|
|
128
129
|
|
|
129
130
|
if (this.storage && !finalToken) {
|
|
@@ -136,24 +137,26 @@ export default class AuthClient {
|
|
|
136
137
|
if (!this.introspectUrl) {
|
|
137
138
|
throw new Error("No introspect url config");
|
|
138
139
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const res = await fetch(this.introspectUrl, {
|
|
140
|
+
|
|
141
|
+
// ⚠️ KHÔNG fetch trực tiếp nữa
|
|
142
|
+
const res = await this.fetcher.fetch(this.introspectUrl, {
|
|
142
143
|
method: "GET",
|
|
143
|
-
headers: headers,
|
|
144
144
|
});
|
|
145
145
|
|
|
146
146
|
if (!res.ok) {
|
|
147
147
|
const text = await res.text().catch(() => res.statusText);
|
|
148
148
|
throw new Error(`Introspect failed: ${res.status} ${text}`);
|
|
149
149
|
}
|
|
150
|
-
|
|
150
|
+
|
|
151
|
+
let json;
|
|
151
152
|
try {
|
|
152
153
|
json = await res.json();
|
|
153
154
|
} catch (e) {
|
|
154
155
|
console.error("❌ JSON parse error:", e);
|
|
155
156
|
throw new Error("Invalid JSON response from server");
|
|
156
157
|
}
|
|
158
|
+
|
|
157
159
|
return json;
|
|
158
160
|
}
|
|
161
|
+
|
|
159
162
|
}
|