@gh-platform/auth-sdk 1.0.2 → 1.0.4

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/README.md CHANGED
@@ -22,7 +22,7 @@ Mọi API của GH Platform Authenticate đều sử dụng dạng:
22
22
  ```
23
23
  /api/v1/{tenant}/auth/login
24
24
  /api/v1/{tenant}/auth/refresh
25
- /api/v1/{tenant}/auth/introspect
25
+ {service_url}/introspect
26
26
  ```
27
27
 
28
28
  JavaScript SDK tự động truyền tenant trong mọi request.
@@ -15,20 +15,22 @@ class AuthClient {
15
15
  */
16
16
  constructor({
17
17
  baseUrl,
18
+ introspectPath,
18
19
  tenant = null,
19
20
  loginPath = null,
20
21
  refreshPath = null,
21
- introspectPath = null,
22
22
  headers = {},
23
23
  storage = null
24
- // <-- thêm storage vào constructor
25
24
  }) {
26
25
  if (!baseUrl) throw new Error("baseUrl is required");
27
26
  this.baseUrl = baseUrl.replace(/\/$/, "");
27
+ if (!introspectUrl) {
28
+ throw new Error("introspectUrl is required");
29
+ }
28
30
  const prefix = tenant ? `/api/v1/${tenant}/auth` : `/api/v1/auth`;
29
31
  this.loginUrl = this.baseUrl + (loginPath || `${prefix}/login`);
30
32
  this.refreshUrl = this.baseUrl + (refreshPath || `${prefix}/refresh`);
31
- this.introspectUrl = this.baseUrl + (introspectPath || `${prefix}/me`);
33
+ this.introspectUrl = introspectPath;
32
34
  this.tenant = tenant;
33
35
  this.headers = { "Content-Type": "application/json", ...headers };
34
36
  this.storage = storage;
@@ -110,6 +112,9 @@ class AuthClient {
110
112
  if (!finalToken) {
111
113
  throw new Error("No access token available for introspection");
112
114
  }
115
+ if (!this.introspectUrl) {
116
+ throw new Error("No introspect url config");
117
+ }
113
118
  const headers = new Headers(this.headers);
114
119
  headers.set("Authorization", `Bearer ${finalToken}`);
115
120
  const res = await fetch(this.introspectUrl, {
@@ -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,tenant:t=null,loginPath:r=null,refreshPath:s=null,introspectPath:o=null,headers:n={},storage:a=null}){if(!e)throw new Error("baseUrl is required");this.baseUrl=e.replace(/\/$/,"");const h=t?`/api/v1/${t}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(r||`${h}/login`),this.refreshUrl=this.baseUrl+(s||`${h}/refresh`),this.introspectUrl=this.baseUrl+(o||`${h}/me`),this.tenant=t,this.headers={"Content-Type":"application/json",...n},this.storage=a}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 h=a.data||a;return this.storage&&(h.access_token&&(this.storage.accessToken=h.access_token),h.refresh_token&&(this.storage.refreshToken=h.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");const r=new Headers(this.headers);r.set("Authorization",`Bearer ${t}`);const s=await fetch(this.introspectUrl,{method:"GET",headers:r});if(!s.ok){const e=await s.text().catch(()=>s.statusText);throw new Error(`Introspect failed: ${s.status} ${e}`)}let o;try{o=await s.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}return o}}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 h=0;const i=[];for(;;){const{done:e,value:t}=await n.read();if(e)break;i.push(t),h+=t.length,a?s(Math.round(h/a*100),h,a):s(null,h,null)}const l=new Blob(i);return new Response(l,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 h={AuthClient:o,AuthFetch:a,TokenStorage:n};e.AuthClient=o,e.AuthFetch=a,e.TokenStorage=n,e.default=h,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
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,introspectPath: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(/\/$/,""),!introspectUrl)throw new Error("introspectUrl is required");const i=r?`/api/v1/${r}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(s||`${i}/login`),this.refreshUrl=this.baseUrl+(o||`${i}/refresh`),this.introspectUrl=t,this.tenant=r,this.headers={"Content-Type":"application/json",...n},this.storage=a}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=new Headers(this.headers);r.set("Authorization",`Bearer ${t}`);const s=await fetch(this.introspectUrl,{method:"GET",headers:r});if(!s.ok){const e=await s.text().catch(()=>s.statusText);throw new Error(`Introspect failed: ${s.status} ${e}`)}let o;try{o=await s.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}return o}}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"}})});
@@ -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,tenant:t=null,loginPath:r=null,refreshPath:s=null,introspectPath:o=null,headers:n={},storage:a=null}){if(!e)throw new Error("baseUrl is required");this.baseUrl=e.replace(/\/$/,"");const h=t?`/api/v1/${t}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(r||`${h}/login`),this.refreshUrl=this.baseUrl+(s||`${h}/refresh`),this.introspectUrl=this.baseUrl+(o||`${h}/me`),this.tenant=t,this.headers={"Content-Type":"application/json",...n},this.storage=a}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(i){throw console.error("❌ JSON parse error:",i),new Error("Invalid JSON response from server")}const h=a.data||a;return this.storage&&(h.access_token&&(this.storage.accessToken=h.access_token),h.refresh_token&&(this.storage.refreshToken=h.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");const r=new Headers(this.headers);r.set("Authorization",`Bearer ${t}`);const s=await fetch(this.introspectUrl,{method:"GET",headers:r});if(!s.ok){const e=await s.text().catch(()=>s.statusText);throw new Error(`Introspect failed: ${s.status} ${e}`)}let o;try{o=await s.json()}catch(n){throw console.error("❌ JSON parse error:",n),new Error("Invalid JSON response from server")}return o}}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 h=0;const i=[];for(;;){const{done:e,value:t}=await n.read();if(e)break;if(i.push(t),h+=t.length,a){s(Math.round(h/a*100),h,a)}else s(null,h,null)}const l=new Blob(i);return new Response(l,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 h={AuthClient:o,AuthFetch:a,TokenStorage:n};e.AuthClient=o,e.AuthFetch=a,e.TokenStorage=n,e.default=h,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
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,introspectPath: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(/\/$/,""),!introspectUrl)throw new Error("introspectUrl is required");const i=r?`/api/v1/${r}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(s||`${i}/login`),this.refreshUrl=this.baseUrl+(o||`${i}/refresh`),this.introspectUrl=t,this.tenant=r,this.headers={"Content-Type":"application/json",...n},this.storage=a}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=new Headers(this.headers);r.set("Authorization",`Bearer ${t}`);const s=await fetch(this.introspectUrl,{method:"GET",headers:r});if(!s.ok){const e=await s.text().catch(()=>s.statusText);throw new Error(`Introspect failed: ${s.status} ${e}`)}let o;try{o=await s.json()}catch(n){throw console.error("❌ JSON parse error:",n),new Error("Invalid JSON response from server")}return o}}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,9 +1,9 @@
1
1
  export interface AuthClientOptions {
2
2
  baseUrl: string;
3
+ introspectPath: string;
3
4
  tenant?: string | null;
4
5
  loginPath?: string;
5
6
  refreshPath?: string;
6
- introspectPath?: string;
7
7
  headers?: Record<string, string>;
8
8
  storage?: TokenStorage | null;
9
9
  }
@@ -24,14 +24,47 @@ export interface TokenData {
24
24
  message?: string;
25
25
  [key: string]: any;
26
26
  }
27
-
27
+ export interface UserMetadata {
28
+ address?: string;
29
+ phone?: string;
30
+ telegram?: string;
31
+ theme?: string;
32
+ [key: string]: any; // cho phép mở rộng metadata
33
+ }
34
+ export interface UserInfo {
35
+ id: string;
36
+ email: string;
37
+ username: string;
38
+ display_name: number;
39
+ metadata?: UserMetadata;
40
+ roles: string[];
41
+ }
28
42
  export interface AuthResponse {
29
43
  status: string; // "success" | "error"
30
44
  code: number; // HTTP-like status code
31
45
  message: string;
32
- data: TokenData;
46
+ data: TokenData | UserInfo;
33
47
  }
34
48
 
49
+
50
+ {
51
+ "status": "success",
52
+ "code": 200,
53
+ "message": "Fetched successfully",
54
+ "data": {
55
+ "id": "2000131553252282368",
56
+ "email": "admin@wraplink.klexpress.net",
57
+ "username": "admin",
58
+ "display_name": "Admin WrapLink",
59
+ "metadata": {
60
+ "address": "",
61
+ "phone": "0948001590",
62
+ "telegram": "@kyle.it",
63
+ "theme": "red"
64
+ },
65
+ "roles": []
66
+ }
67
+ }
35
68
  export class TokenStorage {
36
69
  constructor(prefix?: string, tenant?: string | null);
37
70
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gh-platform/auth-sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "VanillaJS Auth SDK for GH Platform",
5
5
  "type": "module",
6
6
  "main": "dist/auth-sdk.umd.js",
package/src/client.js CHANGED
@@ -11,26 +11,28 @@ export default class AuthClient {
11
11
  */
12
12
  constructor({
13
13
  baseUrl,
14
+ introspectPath,
14
15
  tenant = null,
15
16
  loginPath = null,
16
17
  refreshPath = null,
17
- introspectPath = null,
18
18
  headers = {},
19
- storage = null, // <-- thêm storage vào constructor
19
+ storage = null,
20
20
  }) {
21
21
  if (!baseUrl) throw new Error("baseUrl is required");
22
22
  this.baseUrl = baseUrl.replace(/\/$/, "");
23
-
23
+ if (!introspectUrl) {
24
+ throw new Error("introspectUrl is required");
25
+ }
24
26
  // default path builder: tenant-aware
25
27
  const prefix = tenant ? `/api/v1/${tenant}/auth` : `/api/v1/auth`;
26
28
 
27
29
  this.loginUrl = this.baseUrl + (loginPath || `${prefix}/login`);
28
30
  this.refreshUrl = this.baseUrl + (refreshPath || `${prefix}/refresh`);
29
- this.introspectUrl = this.baseUrl + (introspectPath || `${prefix}/me`);
31
+ this.introspectUrl = introspectPath;
30
32
 
31
- this.tenant = tenant; // keep for storage prefix
33
+ this.tenant = tenant;
32
34
  this.headers = { "Content-Type": "application/json", ...headers };
33
- this.storage = storage; // <-- store storage instance
35
+ this.storage = storage;
34
36
  }
35
37
 
36
38
  /**
@@ -130,7 +132,9 @@ export default class AuthClient {
130
132
  if (!finalToken) {
131
133
  throw new Error("No access token available for introspection");
132
134
  }
133
-
135
+ if (!this.introspectUrl) {
136
+ throw new Error("No introspect url config");
137
+ }
134
138
  const headers = new Headers(this.headers);
135
139
  headers.set("Authorization", `Bearer ${finalToken}`);
136
140
  const res = await fetch(this.introspectUrl, {
package/src/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export interface AuthClientOptions {
2
2
  baseUrl: string;
3
+ introspectPath: string;
3
4
  tenant?: string | null;
4
5
  loginPath?: string;
5
6
  refreshPath?: string;
6
- introspectPath?: string;
7
7
  headers?: Record<string, string>;
8
8
  storage?: TokenStorage | null;
9
9
  }
@@ -24,14 +24,47 @@ export interface TokenData {
24
24
  message?: string;
25
25
  [key: string]: any;
26
26
  }
27
-
27
+ export interface UserMetadata {
28
+ address?: string;
29
+ phone?: string;
30
+ telegram?: string;
31
+ theme?: string;
32
+ [key: string]: any; // cho phép mở rộng metadata
33
+ }
34
+ export interface UserInfo {
35
+ id: string;
36
+ email: string;
37
+ username: string;
38
+ display_name: number;
39
+ metadata?: UserMetadata;
40
+ roles: string[];
41
+ }
28
42
  export interface AuthResponse {
29
43
  status: string; // "success" | "error"
30
44
  code: number; // HTTP-like status code
31
45
  message: string;
32
- data: TokenData;
46
+ data: TokenData | UserInfo;
33
47
  }
34
48
 
49
+
50
+ {
51
+ "status": "success",
52
+ "code": 200,
53
+ "message": "Fetched successfully",
54
+ "data": {
55
+ "id": "2000131553252282368",
56
+ "email": "admin@wraplink.klexpress.net",
57
+ "username": "admin",
58
+ "display_name": "Admin WrapLink",
59
+ "metadata": {
60
+ "address": "",
61
+ "phone": "0948001590",
62
+ "telegram": "@kyle.it",
63
+ "theme": "red"
64
+ },
65
+ "roles": []
66
+ }
67
+ }
35
68
  export class TokenStorage {
36
69
  constructor(prefix?: string, tenant?: string | null);
37
70