@gh-platform/auth-sdk 1.0.6 → 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 +10 -10
- package/dist/auth-sdk.min.js +1 -1
- package/dist/auth-sdk.umd.js +1 -1
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
- package/src/client.js +16 -12
- package/src/index.d.ts +2 -2
package/dist/auth-sdk.es.js
CHANGED
|
@@ -15,25 +15,27 @@ class AuthClient {
|
|
|
15
15
|
*/
|
|
16
16
|
constructor({
|
|
17
17
|
baseUrl,
|
|
18
|
-
|
|
18
|
+
introspectBaseUrl,
|
|
19
19
|
tenant = null,
|
|
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(/\/$/, "");
|
|
27
|
-
if (!
|
|
28
|
-
throw new Error("
|
|
28
|
+
if (!introspectBaseUrl) {
|
|
29
|
+
throw new Error("introspectBaseUrl is required");
|
|
29
30
|
}
|
|
30
31
|
const prefix = tenant ? `/api/v1/${tenant}/auth` : `/api/v1/auth`;
|
|
31
32
|
this.loginUrl = this.baseUrl + (loginPath || `${prefix}/login`);
|
|
32
33
|
this.refreshUrl = this.baseUrl + (refreshPath || `${prefix}/refresh`);
|
|
33
|
-
this.introspectUrl =
|
|
34
|
+
this.introspectUrl = `${introspectBaseUrl}/introspect`;
|
|
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,
|
|
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,
|
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface AuthClientOptions {
|
|
2
2
|
baseUrl: string;
|
|
3
|
-
|
|
3
|
+
introspectBaseUrl: string;
|
|
4
4
|
tenant?: string | null;
|
|
5
5
|
loginPath?: string;
|
|
6
6
|
refreshPath?: string;
|
|
@@ -68,7 +68,7 @@ export class AuthClient {
|
|
|
68
68
|
tenant: string | null;
|
|
69
69
|
headers: Record<string, string>;
|
|
70
70
|
storage: TokenStorage | null;
|
|
71
|
-
|
|
71
|
+
fetcher: AuthFetch | null;
|
|
72
72
|
login(
|
|
73
73
|
identifier: string,
|
|
74
74
|
password: string,
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -11,28 +11,31 @@ export default class AuthClient {
|
|
|
11
11
|
*/
|
|
12
12
|
constructor({
|
|
13
13
|
baseUrl,
|
|
14
|
-
|
|
14
|
+
introspectBaseUrl,
|
|
15
15
|
tenant = null,
|
|
16
16
|
loginPath = null,
|
|
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(/\/$/, "");
|
|
23
|
-
if (!
|
|
24
|
-
throw new Error("
|
|
24
|
+
if (!introspectBaseUrl) {
|
|
25
|
+
throw new Error("introspectBaseUrl is required");
|
|
25
26
|
}
|
|
26
27
|
// default path builder: tenant-aware
|
|
27
28
|
const prefix = tenant ? `/api/v1/${tenant}/auth` : `/api/v1/auth`;
|
|
28
29
|
|
|
29
30
|
this.loginUrl = this.baseUrl + (loginPath || `${prefix}/login`);
|
|
30
31
|
this.refreshUrl = this.baseUrl + (refreshPath || `${prefix}/refresh`);
|
|
31
|
-
|
|
32
|
+
|
|
33
|
+
this.introspectUrl = (`${introspectBaseUrl}/introspect`);
|
|
32
34
|
|
|
33
35
|
this.tenant = tenant;
|
|
34
36
|
this.headers = { "Content-Type": "application/json", ...headers };
|
|
35
37
|
this.storage = storage;
|
|
38
|
+
this.fetcher = fetcher;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/**
|
|
@@ -119,10 +122,9 @@ export default class AuthClient {
|
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
124
|
|
|
125
|
+
// src/client.js
|
|
126
|
+
|
|
122
127
|
async introspect(token = null) {
|
|
123
|
-
// -----------------------------
|
|
124
|
-
// 🔥 Auto-get token from storage
|
|
125
|
-
// -----------------------------
|
|
126
128
|
let finalToken = token;
|
|
127
129
|
|
|
128
130
|
if (this.storage && !finalToken) {
|
|
@@ -135,24 +137,26 @@ export default class AuthClient {
|
|
|
135
137
|
if (!this.introspectUrl) {
|
|
136
138
|
throw new Error("No introspect url config");
|
|
137
139
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
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, {
|
|
141
143
|
method: "GET",
|
|
142
|
-
headers: headers,
|
|
143
144
|
});
|
|
144
145
|
|
|
145
146
|
if (!res.ok) {
|
|
146
147
|
const text = await res.text().catch(() => res.statusText);
|
|
147
148
|
throw new Error(`Introspect failed: ${res.status} ${text}`);
|
|
148
149
|
}
|
|
149
|
-
|
|
150
|
+
|
|
151
|
+
let json;
|
|
150
152
|
try {
|
|
151
153
|
json = await res.json();
|
|
152
154
|
} catch (e) {
|
|
153
155
|
console.error("❌ JSON parse error:", e);
|
|
154
156
|
throw new Error("Invalid JSON response from server");
|
|
155
157
|
}
|
|
158
|
+
|
|
156
159
|
return json;
|
|
157
160
|
}
|
|
161
|
+
|
|
158
162
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface AuthClientOptions {
|
|
2
2
|
baseUrl: string;
|
|
3
|
-
|
|
3
|
+
introspectBaseUrl: string;
|
|
4
4
|
tenant?: string | null;
|
|
5
5
|
loginPath?: string;
|
|
6
6
|
refreshPath?: string;
|
|
@@ -68,7 +68,7 @@ export class AuthClient {
|
|
|
68
68
|
tenant: string | null;
|
|
69
69
|
headers: Record<string, string>;
|
|
70
70
|
storage: TokenStorage | null;
|
|
71
|
-
|
|
71
|
+
fetcher: AuthFetch | null;
|
|
72
72
|
login(
|
|
73
73
|
identifier: string,
|
|
74
74
|
password: string,
|