@amaster.ai/auth-client 1.1.0-beta.30 → 1.1.0-beta.32
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.d.cts +2 -1
- package/dist/auth.d.ts +2 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.cts +1 -1
- package/dist/oauth.d.ts +1 -1
- package/dist/permissions.d.cts +1 -1
- package/dist/permissions.d.ts +1 -1
- package/dist/sessions.d.cts +1 -1
- package/dist/sessions.d.ts +1 -1
- package/dist/{types-C56GAJKY.d.cts → types-BhHE_geU.d.cts} +19 -0
- package/dist/{types-C56GAJKY.d.ts → types-BhHE_geU.d.ts} +19 -0
- package/dist/user.d.cts +1 -1
- package/dist/user.d.ts +1 -1
- package/package.json +2 -2
package/dist/auth.d.cts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { q as User, i as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, p as SuccessResponse, b as CaptchaResponse, g as OAuthProvider, M as MiniProgramPhoneResponse, R as RefreshTokenResponse } from './types-
|
|
17
|
+
import { q as User, i as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, p as SuccessResponse, b as CaptchaResponse, g as OAuthProvider, M as MiniProgramPhoneResponse, R as RefreshTokenResponse } from './types-BhHE_geU.cjs';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Authentication Module
|
|
@@ -35,6 +35,7 @@ interface AuthModuleDeps {
|
|
|
35
35
|
onLoginSuccess: (user: User, accessToken: string) => void;
|
|
36
36
|
storage: {
|
|
37
37
|
getItem: (key: string) => string | null;
|
|
38
|
+
setItem: (key: string, value: string) => void;
|
|
38
39
|
};
|
|
39
40
|
clearAuth: () => void;
|
|
40
41
|
}
|
package/dist/auth.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { q as User, i as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, p as SuccessResponse, b as CaptchaResponse, g as OAuthProvider, M as MiniProgramPhoneResponse, R as RefreshTokenResponse } from './types-
|
|
17
|
+
import { q as User, i as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, p as SuccessResponse, b as CaptchaResponse, g as OAuthProvider, M as MiniProgramPhoneResponse, R as RefreshTokenResponse } from './types-BhHE_geU.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Authentication Module
|
|
@@ -35,6 +35,7 @@ interface AuthModuleDeps {
|
|
|
35
35
|
onLoginSuccess: (user: User, accessToken: string) => void;
|
|
36
36
|
storage: {
|
|
37
37
|
getItem: (key: string) => string | null;
|
|
38
|
+
setItem: (key: string, value: string) => void;
|
|
38
39
|
};
|
|
39
40
|
clearAuth: () => void;
|
|
40
41
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var httpClient=require('@amaster.ai/http-client');var y=class{constructor(){this.events={};}on(e,s){this.events[e]||(this.events[e]=[]),this.events[e].push(s);}off(e,s){this.events[e]&&(this.events[e]=this.events[e].filter(r=>r!==s));}emit(e,...s){this.events[e]&&this.events[e].forEach(r=>{try{r(...s);}catch(a){console.error(`[AuthClient] Error in event handler for "${e}":`,a);}});}removeAllListeners(){this.events={};}};var d={ACCESS_TOKEN:"amaster_access_token",REFRESH_TOKEN:"amaster_refresh_token",USER:"amaster_user"};function H(){return typeof wx<"u"&&wx.getStorageSync?"wechat-miniprogram":typeof window<"u"&&typeof window.localStorage<"u"?"browser":"node"}function S(){switch(H()){case "wechat-miniprogram":return q();case "browser":return N();case "node":return $()}}function N(){let t=window.localStorage;return {getItem(e){try{return t.getItem(e)}catch(s){return console.error("[AuthClient] Failed to get item from localStorage:",s),null}},setItem(e,s){try{t.setItem(e,s);}catch(r){console.error("[AuthClient] Failed to set item in localStorage:",r);}},removeItem(e){try{t.removeItem(e);}catch(s){console.error("[AuthClient] Failed to remove item from localStorage:",s);}},clear(){try{t.removeItem(d.ACCESS_TOKEN),t.removeItem(d.REFRESH_TOKEN),t.removeItem(d.USER);}catch(e){console.error("[AuthClient] Failed to clear localStorage:",e);}}}}function q(){return {getItem(t){try{return wx.getStorageSync(t)||null}catch(e){return console.error("[AuthClient] Failed to get item from WeChat storage:",e),null}},setItem(t,e){try{wx.setStorageSync(t,e);}catch(s){console.error("[AuthClient] Failed to set item in WeChat storage:",s);}},removeItem(t){try{wx.removeStorageSync(t);}catch(e){console.error("[AuthClient] Failed to remove item from WeChat storage:",e);}},clear(){try{wx.removeStorageSync(d.ACCESS_TOKEN),wx.removeStorageSync(d.REFRESH_TOKEN),wx.removeStorageSync(d.USER);}catch(t){console.error("[AuthClient] Failed to clear WeChat storage:",t);}}}}function $(){let t=new Map;return {getItem(e){return t.get(e)??null},setItem(e,s){t.set(e,s);},removeItem(e){t.delete(e);},clear(){t.clear();}}}function B(t){try{let e=t.split(".");if(e.length!==3)return null;let r=(e[1]||"").replace(/-/g,"+").replace(/_/g,"/");if(typeof atob<"u"){let a=decodeURIComponent(atob(r).split("").map(n=>"%"+("00"+n.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(a)}if(typeof Buffer<"u"){let a=Buffer.from(r,"base64").toString("utf-8");return JSON.parse(a)}return null}catch(e){return console.error("[AuthClient] Failed to parse JWT token:",e),null}}var C=class{constructor(){this.refreshTimer=null;this.isRefreshing=false;this.refreshCallback=null;}setRefreshCallback(e){this.refreshCallback=e;}scheduleRefresh(e){this.clearSchedule(),!(e<=0)&&(this.refreshTimer=setTimeout(()=>{this.refresh();},e));}scheduleRefreshFromToken(e,s=300){let r=B(e);if(!r||!r.exp){console.warn("[AuthClient] Cannot schedule refresh: invalid token or missing exp claim");return}let a=r.exp*1e3,n=Date.now(),c=a-n-s*1e3;c<=0?(console.warn("[AuthClient] Token already expired or expiring soon, refreshing immediately"),this.refresh()):this.scheduleRefresh(c);}async refresh(){if(!this.isRefreshing){if(!this.refreshCallback){console.error("[AuthClient] No refresh callback set");return}this.isRefreshing=true;try{await this.refreshCallback();}catch(e){console.error("[AuthClient] Token refresh failed:",e);}finally{this.isRefreshing=false;}}}clearSchedule(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}isCurrentlyRefreshing(){return this.isRefreshing}destroy(){this.clearSchedule(),this.refreshCallback=null,this.isRefreshing=false;}};function v(t){return t&&typeof t=="object"&&("statusCode"in t||"status"in t)&&"data"in t?t.data:t}var R={transformResponse:v,logErrors:true};function F(t){if(t.email)return "email";if(t.username)return "username";if(t.phone)return "phone"}function z(t){if(t.email)return "email";if(t.phone)return "phone"}function k(t){let{http:e,onLoginSuccess:s,storage:r,clearAuth:a}=t;return {async register(n){let o=await e.request({url:"/api/auth/register",method:"post",headers:{"Content-Type":"application/json"},data:n});return o.data?.user&&o.data?.accessToken&&s(o.data.user,o.data.accessToken),o},async login(n){let o=n.loginType||F(n);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email, username, or phone.",status:400},status:400};let c={...n,loginType:o},u=await e.request({url:"/api/auth/login",method:"post",headers:{"Content-Type":"application/json"},data:c});return u.data?.user&&u.data?.accessToken&&s(u.data.user,u.data.accessToken),u},async loginWithCode(n){let o=n.loginType||z(n);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email or phone.",status:400},status:400};let c={...n,loginType:o},u=await e.request({url:"/api/auth/login-with-code",method:"post",headers:{"Content-Type":"application/json"},data:c});return u.data?.user&&u.data?.accessToken&&s(u.data.user,u.data.accessToken),u},async sendCode(n){return e.request({url:"/api/auth/send-code",method:"post",headers:{"Content-Type":"application/json"},data:n})},async getCaptcha(){return e.request({url:"/api/auth/captcha",method:"get"})},loginWithOAuth(n,o){if(typeof window>"u"){console.error("[AuthClient] OAuth login is only available in browser environment");return}let c=o?`/api/auth/oauth/${n}?redirect_url=${encodeURIComponent(o)}`:`/api/auth/oauth/${n}`;window.location.href=c;},async handleOAuthCallback(){if(typeof window>"u")return {data:null,error:{message:"OAuth callback is only available in browser environment",status:400},status:400};try{let n=window.location.hash.substring(1),o=new URLSearchParams(n),c=o.get("access_token"),u=o.get("user");if(!c||!u)return {data:null,error:{message:"OAuth callback failed: missing token or user data",status:400},status:400};let l=JSON.parse(decodeURIComponent(u));return s(l,c),{data:{user:l,accessToken:c},error:null,status:200}}catch(n){return {data:null,error:{message:`OAuth callback failed: ${n instanceof Error?n.message:String(n)}`,status:400},status:400}}},async loginWithMiniProgram(n){let o=await e.request({url:"/api/auth/miniprogram/login",method:"post",headers:{"Content-Type":"application/json"},data:{code:n}});return o.data?.user&&o.data?.accessToken&&s(o.data.user,o.data.accessToken),o},async getMiniProgramPhoneNumber(n){let o=r.getItem("amaster_access_token");return o?e.request({url:"/api/auth/miniprogram/phone",method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},data:{code:n}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async logout(){let n=r.getItem("amaster_access_token"),o=await e.request({url:"/api/auth/logout",method:"post",headers:n?{Authorization:`Bearer ${n}`}:void 0});return a(),o},async refreshToken(){return e.request({url:"/api/auth/refresh",method:"post"})}}}function T(t){let{getCurrentUser:e}=t;return {hasRole(s){let r=e();return !r||!r.roles?false:r.roles.includes(s)},hasPermission(s,r){let a=e();if(!a||!a.permissions)return false;let n=`${s}:${r}`;return a.permissions.includes(n)},hasAnyPermission(s){return s.some(({resource:r,action:a})=>this.hasPermission(r,a))},hasAllPermissions(s){return s.every(({resource:r,action:a})=>this.hasPermission(r,a))}}}function P(t){let{http:e,storage:s,onUserUpdate:r}=t;return {async getMe(){let a=s.getItem("amaster_access_token");if(!a)return {data:null,error:{message:"Not authenticated",status:401},status:401};let n=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${a}`}});return n.data&&r(n.data),n},async updateMe(a){let n=s.getItem("amaster_access_token");if(!n)return {data:null,error:{message:"Not authenticated",status:401},status:401};let o=await e.request({url:"/api/auth/me",method:"put",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},data:a});return o.data&&r(o.data),o},async changePassword(a){let n=s.getItem("amaster_access_token");return n?e.request({url:"/api/auth/change-password",method:"post",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},data:a}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function w(t){let{http:e,storage:s}=t;return {async getOAuthBindings(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/oauth-bindings",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},bindOAuth(r){if(typeof window>"u"){console.error("[AuthClient] OAuth binding is only available in browser environment");return}window.location.href=`/api/auth/oauth/${r}/bind`;},async unbindOAuth(r){let a=s.getItem("amaster_access_token");return a?e.request({url:`/api/auth/oauth/${r}/unbind`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function E(t){let{http:e,storage:s}=t;return {async getSession(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions/current",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async getSessions(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeSession(r){let a=s.getItem("amaster_access_token");return a?r?e.request({url:`/api/auth/sessions/${r}`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Session ID is required",status:400},status:400}:{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeAllSessions(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"delete",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function J(t={},e){let {baseURL:s,headers:r,onTokenExpired:a,onUnauthorized:n}=t,o=e||httpClient.createHttpClient({...R,baseURL:s,headers:r}),u=300,l=S(),m=new y,f=new C,g=null;try{let i=l.getItem(d.USER);i&&(g=JSON.parse(i));}catch(i){console.error("[AuthClient] Failed to load user from storage:",i);}let p;f.setRefreshCallback(async()=>{let i=await p.refreshToken();i.data?(await p.getMe(),m.emit("tokenRefreshed",i.data.accessToken)):(m.emit("tokenExpired"),a?.());});function M(i,h){l.setItem(d.ACCESS_TOKEN,h),l.setItem(d.USER,JSON.stringify(i)),g=i,f.scheduleRefreshFromToken(h,u),m.emit("login",i);}function O(i){g=i,l.setItem(d.USER,JSON.stringify(i));}function A(){l.clear(),g=null,f.clearSchedule();}function U(){return g}let b=k({http:o,onLoginSuccess:M,storage:l,clearAuth:A}),x=T({getCurrentUser:U}),I=P({http:o,storage:l,onUserUpdate:O}),_=w({http:o,storage:l}),L=E({http:o,storage:l});return p={...b,...x,...I,..._,...L,on(i,h){m.on(i,h);},off(i,h){m.off(i,h);},isAuthenticated(){return !!l.getItem(d.ACCESS_TOKEN)},getAccessToken(){return l.getItem(d.ACCESS_TOKEN)},setAccessToken(i){l.setItem(d.ACCESS_TOKEN,i),f.scheduleRefreshFromToken(i,u);},clearAuth:A},p.on("unauthorized",()=>{n?.();}),p.isAuthenticated()&&p.getMe().catch(i=>{console.warn("[AuthClient] Failed to sync user info on init:",i);}),p}exports.createAuthClient=J;exports.defaultHttpClientOptions=R;exports.transformAmasterResponse=v;//# sourceMappingURL=index.cjs.map
|
|
1
|
+
'use strict';var httpClient=require('@amaster.ai/http-client');var C=class{constructor(){this.events={};}on(e,n){this.events[e]||(this.events[e]=[]),this.events[e].push(n);}off(e,n){this.events[e]&&(this.events[e]=this.events[e].filter(r=>r!==n));}emit(e,...n){this.events[e]&&this.events[e].forEach(r=>{try{r(...n);}catch(a){console.error(`[AuthClient] Error in event handler for "${e}":`,a);}});}removeAllListeners(){this.events={};}};var d={ACCESS_TOKEN:"amaster_access_token",REFRESH_TOKEN:"amaster_refresh_token",USER:"amaster_user"};function N(){return typeof wx<"u"&&wx.getStorageSync?"wechat-miniprogram":typeof window<"u"&&typeof window.localStorage<"u"?"browser":"node"}function v(){switch(N()){case "wechat-miniprogram":return $();case "browser":return q();case "node":return B()}}function q(){let t=window.localStorage;return {getItem(e){try{return t.getItem(e)}catch(n){return console.error("[AuthClient] Failed to get item from localStorage:",n),null}},setItem(e,n){try{t.setItem(e,n);}catch(r){console.error("[AuthClient] Failed to set item in localStorage:",r);}},removeItem(e){try{t.removeItem(e);}catch(n){console.error("[AuthClient] Failed to remove item from localStorage:",n);}},clear(){try{t.removeItem(d.ACCESS_TOKEN),t.removeItem(d.REFRESH_TOKEN),t.removeItem(d.USER);}catch(e){console.error("[AuthClient] Failed to clear localStorage:",e);}}}}function $(){return {getItem(t){try{return wx.getStorageSync(t)||null}catch(e){return console.error("[AuthClient] Failed to get item from WeChat storage:",e),null}},setItem(t,e){try{wx.setStorageSync(t,e);}catch(n){console.error("[AuthClient] Failed to set item in WeChat storage:",n);}},removeItem(t){try{wx.removeStorageSync(t);}catch(e){console.error("[AuthClient] Failed to remove item from WeChat storage:",e);}},clear(){try{wx.removeStorageSync(d.ACCESS_TOKEN),wx.removeStorageSync(d.REFRESH_TOKEN),wx.removeStorageSync(d.USER);}catch(t){console.error("[AuthClient] Failed to clear WeChat storage:",t);}}}}function B(){let t=new Map;return {getItem(e){return t.get(e)??null},setItem(e,n){t.set(e,n);},removeItem(e){t.delete(e);},clear(){t.clear();}}}function F(t){try{let e=t.split(".");if(e.length!==3)return null;let r=(e[1]||"").replace(/-/g,"+").replace(/_/g,"/");if(typeof atob<"u"){let a=decodeURIComponent(atob(r).split("").map(s=>"%"+("00"+s.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(a)}if(typeof Buffer<"u"){let a=Buffer.from(r,"base64").toString("utf-8");return JSON.parse(a)}return null}catch(e){return console.error("[AuthClient] Failed to parse JWT token:",e),null}}var A=class{constructor(){this.refreshTimer=null;this.isRefreshing=false;this.refreshCallback=null;}setRefreshCallback(e){this.refreshCallback=e;}scheduleRefresh(e){this.clearSchedule(),!(e<=0)&&(this.refreshTimer=setTimeout(()=>{this.refresh();},e));}scheduleRefreshFromToken(e,n=300){let r=F(e);if(!r||!r.exp){console.warn("[AuthClient] Cannot schedule refresh: invalid token or missing exp claim");return}let a=r.exp*1e3,s=Date.now(),u=a-s-n*1e3;u<=0?(console.warn("[AuthClient] Token already expired or expiring soon, refreshing immediately"),this.refresh()):this.scheduleRefresh(u);}async refresh(){if(!this.isRefreshing){if(!this.refreshCallback){console.error("[AuthClient] No refresh callback set");return}this.isRefreshing=true;try{await this.refreshCallback();}catch(e){console.error("[AuthClient] Token refresh failed:",e);}finally{this.isRefreshing=false;}}}clearSchedule(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}isCurrentlyRefreshing(){return this.isRefreshing}destroy(){this.clearSchedule(),this.refreshCallback=null,this.isRefreshing=false;}};function k(t){return t&&typeof t=="object"&&("statusCode"in t||"status"in t)&&"data"in t?t.data:t}var R={transformResponse:k,logErrors:true};function z(t){if(t.email)return "email";if(t.username)return "username";if(t.phone)return "phone"}function j(t){if(t.email)return "email";if(t.phone)return "phone"}function T(t){let{http:e,onLoginSuccess:n,storage:r,clearAuth:a}=t;return {async register(s){let o=await e.request({url:"/api/auth/register",method:"post",headers:{"Content-Type":"application/json"},data:s});return o.data?.user&&o.data?.accessToken&&n(o.data.user,o.data.accessToken),o},async login(s){let o=s.loginType||z(s);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email, username, or phone.",status:400},status:400};let u={...s,loginType:o},l=await e.request({url:"/api/auth/login",method:"post",headers:{"Content-Type":"application/json"},data:u});return l.data?.user&&l.data?.accessToken&&n(l.data.user,l.data.accessToken),l},async loginWithCode(s){let o=s.loginType||j(s);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email or phone.",status:400},status:400};let u={...s,loginType:o},l=await e.request({url:"/api/auth/login-with-code",method:"post",headers:{"Content-Type":"application/json"},data:u});return l.data?.user&&l.data?.accessToken&&n(l.data.user,l.data.accessToken),l},async sendCode(s){return e.request({url:"/api/auth/send-code",method:"post",headers:{"Content-Type":"application/json"},data:s})},async getCaptcha(){return e.request({url:"/api/auth/captcha",method:"get"})},loginWithOAuth(s,o){if(typeof window>"u"){console.error("[AuthClient] OAuth login is only available in browser environment");return}let u=o?`/api/auth/oauth/${s}?redirect_url=${encodeURIComponent(o)}`:`/api/auth/oauth/${s}`;window.location.href=u;},async handleOAuthCallback(){if(typeof window>"u")return {data:null,error:{message:"OAuth callback is only available in browser environment",status:400},status:400};try{let s=window.location.hash.substring(1),o=new URLSearchParams(s),u=o.get("access_token"),l=o.get("user");if(!u||!l)return {data:null,error:{message:"OAuth callback failed: missing token or user data",status:400},status:400};let m=JSON.parse(decodeURIComponent(l));if(n(m,u),window.history&&window.history.replaceState){let c=window.location.pathname+window.location.search;window.history.replaceState(null,"",c);}else window.location.hash="";return {data:{user:m,accessToken:u},error:null,status:200}}catch(s){return {data:null,error:{message:`OAuth callback failed: ${s instanceof Error?s.message:String(s)}`,status:400},status:400}}},async loginWithMiniProgram(s){let o=await e.request({url:"/api/auth/miniprogram/login",method:"post",headers:{"Content-Type":"application/json"},data:{code:s}});return o.data?.user&&o.data?.accessToken&&n(o.data.user,o.data.accessToken),o},async getMiniProgramPhoneNumber(s){let o=r.getItem("amaster_access_token");return o?e.request({url:"/api/auth/miniprogram/phone",method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},data:{code:s}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async logout(){let s=r.getItem("amaster_access_token"),o=await e.request({url:"/api/auth/logout",method:"post",headers:s?{Authorization:`Bearer ${s}`}:void 0});return a(),o},async refreshToken(){let s=await e.request({url:"/api/auth/refresh",method:"post"});return s.data?.accessToken&&r.setItem("amaster_access_token",s.data.accessToken),s}}}function w(t){let{getCurrentUser:e}=t;return {hasRole(n){let r=e();return !r||!r.roles?false:r.roles.includes(n)},hasPermission(n,r){let a=e();if(!a||!a.permissions)return false;let s=`${n}:${r}`;return a.permissions.includes(s)},hasAnyPermission(n){return n.some(({resource:r,action:a})=>this.hasPermission(r,a))},hasAllPermissions(n){return n.every(({resource:r,action:a})=>this.hasPermission(r,a))}}}function P(t){let{http:e,storage:n,onUserUpdate:r}=t;return {async getMe(){let a=n.getItem("amaster_access_token");if(!a)return {data:null,error:{message:"Not authenticated",status:401},status:401};let s=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${a}`}});return s.data&&r(s.data),s},async updateMe(a){let s=n.getItem("amaster_access_token");if(!s)return {data:null,error:{message:"Not authenticated",status:401},status:401};let o=await e.request({url:"/api/auth/me",method:"put",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},data:a});return o.data&&r(o.data),o},async changePassword(a){let s=n.getItem("amaster_access_token");return s?e.request({url:"/api/auth/change-password",method:"post",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},data:a}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function E(t){let{http:e,storage:n}=t;return {async getOAuthBindings(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/oauth-bindings",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},bindOAuth(r){if(typeof window>"u"){console.error("[AuthClient] OAuth binding is only available in browser environment");return}window.location.href=`/api/auth/oauth/${r}/bind`;},async unbindOAuth(r){let a=n.getItem("amaster_access_token");return a?e.request({url:`/api/auth/oauth/${r}/unbind`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function M(t){let{http:e,storage:n}=t;return {async getSession(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions/current",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async getSessions(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeSession(r){let a=n.getItem("amaster_access_token");return a?r?e.request({url:`/api/auth/sessions/${r}`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Session ID is required",status:400},status:400}:{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeAllSessions(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"delete",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function K(t={},e){let {baseURL:n,headers:r,onTokenExpired:a,onUnauthorized:s,autoHandleOAuthCallback:o=true}=t,u=e||httpClient.createHttpClient({...R,baseURL:n,headers:r}),m=300,c=v(),g=new C,y=new A,f=null;try{let i=c.getItem(d.USER);i&&(f=JSON.parse(i));}catch(i){console.error("[AuthClient] Failed to load user from storage:",i);}let p;y.setRefreshCallback(async()=>{let i=await p.refreshToken();i.data?(await p.getMe(),g.emit("tokenRefreshed",i.data.accessToken)):(g.emit("tokenExpired"),a?.());});function O(i,h){c.setItem(d.ACCESS_TOKEN,h),c.setItem(d.USER,JSON.stringify(i)),f=i,y.scheduleRefreshFromToken(h,m),g.emit("login",i);}function U(i){f=i,c.setItem(d.USER,JSON.stringify(i));}function S(){c.clear(),f=null,y.clearSchedule();}function b(){return f}let I=T({http:u,onLoginSuccess:O,storage:c,clearAuth:S}),x=w({getCurrentUser:b}),_=P({http:u,storage:c,onUserUpdate:U}),L=E({http:u,storage:c}),H=M({http:u,storage:c});if(p={...I,...x,..._,...L,...H,on(i,h){g.on(i,h);},off(i,h){g.off(i,h);},isAuthenticated(){return !!c.getItem(d.ACCESS_TOKEN)},getAccessToken(){return c.getItem(d.ACCESS_TOKEN)},setAccessToken(i){c.setItem(d.ACCESS_TOKEN,i),y.scheduleRefreshFromToken(i,m);},clearAuth:S},p.on("unauthorized",()=>{s?.();}),p.isAuthenticated()&&p.getMe().catch(i=>{console.warn("[AuthClient] Failed to sync user info on init:",i);}),o&&typeof window<"u"){let i=window.location.hash;i&&i.includes("access_token")&&p.handleOAuthCallback().then(h=>{h.error&&console.error("[AuthClient] Auto OAuth callback failed:",h.error);}).catch(h=>{console.error("[AuthClient] Auto OAuth callback error:",h);});}return p}exports.createAuthClient=K;exports.defaultHttpClientOptions=R;exports.transformAmasterResponse=k;//# sourceMappingURL=index.cjs.map
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event-emitter.ts","../src/storage.ts","../src/token-manager.ts","../src/http-config.ts","../src/modules/auth.ts","../src/modules/permissions.ts","../src/modules/user.ts","../src/modules/oauth.ts","../src/modules/sessions.ts","../src/client.ts"],"names":["EventEmitter","event","handler","h","args","error","STORAGE_KEYS","detectEnvironment","createStorageAdapter","createWeChatMiniProgramStorage","createBrowserStorage","createNoOpStorage","storage","key","value","store","parseJwt","token","parts","base64","jsonPayload","c","TokenManager","callback","delayMs","accessToken","thresholdSeconds","payload","expiresAtMs","nowMs","refreshDelayMs","transformAmasterResponse","responseData","defaultHttpClientOptions","inferLoginType","params","inferCodeLoginType","createAuthModule","deps","http","onLoginSuccess","clearAuth","result","loginType","requestData","provider","redirectUrl","url","hash","userJson","user","code","createPermissionsModule","getCurrentUser","roleCode","resource","action","permissionName","permissions","createUserModule","onUserUpdate","createOAuthModule","createSessionsModule","sessionId","createAuthClient","options","baseURL","headers","onTokenExpired","onUnauthorized","httpClient","createHttpClient","refreshThreshold","eventEmitter","tokenManager","currentUser","authClient","handleLoginSuccess","handleUserUpdate","authModule","permissionsModule","userModule","oauthModule","sessionsModule"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Simple event emitter for auth events\n */\n\nimport type { AuthEvent, EventHandler } from \"./types\";\n\ntype EventMap = Record<string, EventHandler[]>;\n\nexport class EventEmitter {\n private events: EventMap = {};\n\n /**\n * Subscribe to an event\n */\n on(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event] = this.events[event].filter((h) => h !== handler);\n }\n\n /**\n * Emit an event with arguments\n */\n emit(event: AuthEvent, ...args: any[]): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event].forEach((handler) => {\n try {\n handler(...args);\n } catch (error) {\n console.error(`[AuthClient] Error in event handler for \"${event}\":`, error);\n }\n });\n }\n\n /**\n * Remove all event listeners\n */\n removeAllListeners(): void {\n this.events = {};\n }\n}\n","/**\n * Storage adapter for token and user data persistence\n * Auto-detects environment and uses appropriate storage:\n * - Browser: localStorage\n * - WeChat Mini Program: wx.setStorageSync/wx.getStorageSync\n * - SSR/Node.js: No-op (no persistence)\n */\n\nexport interface StorageAdapter {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n clear(): void;\n}\n\n/**\n * Storage keys for auth data\n */\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: \"amaster_access_token\",\n REFRESH_TOKEN: \"amaster_refresh_token\",\n USER: \"amaster_user\",\n} as const;\n\n/**\n * Detect current runtime environment\n */\nfunction detectEnvironment(): \"browser\" | \"wechat-miniprogram\" | \"node\" {\n // WeChat Mini Program\n if (typeof wx !== \"undefined\" && wx.getStorageSync) {\n return \"wechat-miniprogram\";\n }\n \n // Browser\n if (typeof window !== \"undefined\" && typeof window.localStorage !== \"undefined\") {\n return \"browser\";\n }\n \n // Node.js/SSR\n return \"node\";\n}\n\n/**\n * Create a storage adapter that auto-detects environment\n * \n * @returns Storage adapter optimized for current environment\n * \n * @example\n * ```typescript\n * const storage = createStorageAdapter();\n * \n * // Browser → uses localStorage\n * // WeChat Mini Program → uses wx.setStorageSync\n * // SSR/Node.js → uses no-op (no persistence)\n * ```\n */\nexport function createStorageAdapter(): StorageAdapter {\n const env = detectEnvironment();\n \n switch (env) {\n case \"wechat-miniprogram\":\n return createWeChatMiniProgramStorage();\n case \"browser\":\n return createBrowserStorage();\n case \"node\":\n return createNoOpStorage();\n }\n}\n\n/**\n * Create browser storage adapter (localStorage)\n */\nfunction createBrowserStorage(): StorageAdapter {\n const storage = window.localStorage;\n\n return {\n getItem(key: string): string | null {\n try {\n return storage.getItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from localStorage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n storage.setItem(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in localStorage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n storage.removeItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from localStorage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n storage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);\n storage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);\n storage.removeItem(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear localStorage:\", error);\n }\n },\n };\n}\n\n/**\n * Create WeChat Mini Program storage adapter\n * Uses wx.setStorageSync and wx.getStorageSync\n */\nfunction createWeChatMiniProgramStorage(): StorageAdapter {\n return {\n getItem(key: string): string | null {\n try {\n const value = wx.getStorageSync(key);\n return value || null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from WeChat storage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n wx.setStorageSync(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in WeChat storage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n wx.removeStorageSync(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from WeChat storage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n wx.removeStorageSync(STORAGE_KEYS.ACCESS_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.REFRESH_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear WeChat storage:\", error);\n }\n },\n };\n}\n\n/**\n * In-memory storage adapter for SSR/Node.js/test environments\n * Data is stored in memory but not persisted across process restarts\n */\nfunction createNoOpStorage(): StorageAdapter {\n const store = new Map<string, string>();\n \n return {\n getItem(key: string): string | null {\n return store.get(key) ?? null;\n },\n setItem(key: string, value: string): void {\n store.set(key, value);\n },\n removeItem(key: string): void {\n store.delete(key);\n },\n clear(): void {\n store.clear();\n },\n };\n}\n","/**\n * Token manager for automatic token refresh\n */\n\n/**\n * JWT token payload interface\n */\ninterface JwtPayload {\n exp: number; // Expiration timestamp (seconds)\n [key: string]: any;\n}\n\n/**\n * Parse JWT token to extract payload\n * Note: This does NOT verify the token signature, only decodes the payload\n */\nexport function parseJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const base64Url = parts[1] || \"\";\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\n // Decode base64 in browser environment\n if (typeof atob !== \"undefined\") {\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split(\"\")\n .map((c) => \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2))\n .join(\"\")\n );\n return JSON.parse(jsonPayload);\n }\n\n // Fallback for Node.js environment\n if (typeof Buffer !== \"undefined\") {\n const jsonPayload = Buffer.from(base64, \"base64\").toString(\"utf-8\");\n return JSON.parse(jsonPayload);\n }\n\n return null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to parse JWT token:\", error);\n return null;\n }\n}\n\n/**\n * Token manager class for handling automatic token refresh\n */\nexport class TokenManager {\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private isRefreshing = false;\n private refreshCallback: (() => Promise<void>) | null = null;\n\n /**\n * Set the refresh callback function\n */\n setRefreshCallback(callback: () => Promise<void>): void {\n this.refreshCallback = callback;\n }\n\n /**\n * Schedule a token refresh after a delay\n * @param delayMs Delay in milliseconds before refreshing\n */\n scheduleRefresh(delayMs: number): void {\n // Clear existing timer\n this.clearSchedule();\n\n // Don't schedule if delay is negative or zero\n if (delayMs <= 0) {\n return;\n }\n\n this.refreshTimer = setTimeout(() => {\n this.refresh();\n }, delayMs);\n }\n\n /**\n * Schedule token refresh based on token expiration and threshold\n * @param accessToken JWT access token\n * @param thresholdSeconds Refresh threshold in seconds (default: 300)\n */\n scheduleRefreshFromToken(accessToken: string, thresholdSeconds: number = 300): void {\n const payload = parseJwt(accessToken);\n if (!payload || !payload.exp) {\n console.warn(\"[AuthClient] Cannot schedule refresh: invalid token or missing exp claim\");\n return;\n }\n\n const expiresAtMs = payload.exp * 1000; // Convert to milliseconds\n const nowMs = Date.now();\n const expiresInMs = expiresAtMs - nowMs;\n\n // Calculate when to refresh (before expiration by thresholdSeconds)\n const refreshDelayMs = expiresInMs - thresholdSeconds * 1000;\n\n if (refreshDelayMs <= 0) {\n // Token already expired or will expire very soon\n console.warn(\"[AuthClient] Token already expired or expiring soon, refreshing immediately\");\n this.refresh();\n } else {\n this.scheduleRefresh(refreshDelayMs);\n }\n }\n\n /**\n * Manually trigger token refresh\n */\n async refresh(): Promise<void> {\n if (this.isRefreshing) {\n return;\n }\n\n if (!this.refreshCallback) {\n console.error(\"[AuthClient] No refresh callback set\");\n return;\n }\n\n this.isRefreshing = true;\n\n try {\n await this.refreshCallback();\n } catch (error) {\n console.error(\"[AuthClient] Token refresh failed:\", error);\n } finally {\n this.isRefreshing = false;\n }\n }\n\n /**\n * Clear the scheduled refresh timer\n */\n clearSchedule(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /**\n * Check if currently refreshing\n */\n isCurrentlyRefreshing(): boolean {\n return this.isRefreshing;\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.clearSchedule();\n this.refreshCallback = null;\n this.isRefreshing = false;\n }\n}\n","/**\n * HTTP Client Configuration Utilities\n * \n * Provides shared HTTP client configuration for Amaster backend integration\n */\n\nimport { type HttpClientOptions } from \"@amaster.ai/http-client\";\n\n/**\n * Transform Amaster backend response format\n * Backend returns: { statusCode: 200, data: {...}, message: \"...\" }\n * We extract the inner 'data' field for cleaner client usage\n * \n * @param responseData - Raw response data from backend\n * @returns Extracted data or original response if not in Amaster format\n * \n * @example\n * ```typescript\n * const response = { statusCode: 200, data: { userId: \"123\" }, message: \"Success\" };\n * const result = transformAmasterResponse(response);\n * // result = { userId: \"123\" }\n * ```\n */\nexport function transformAmasterResponse<T>(responseData: unknown): T {\n if (\n responseData &&\n typeof responseData === \"object\" &&\n (\"statusCode\" in responseData || \"status\" in responseData)\n ) {\n // If response has 'data' field, extract it\n if (\"data\" in responseData) {\n return (responseData as { data: T }).data;\n }\n // Otherwise return the whole response (e.g., for SuccessResponse without data)\n return responseData as T;\n }\n return responseData as T;\n}\n\n/**\n * Default HTTP client options for Amaster backend\n * Includes response transformation and error logging\n */\nexport const defaultHttpClientOptions: HttpClientOptions = {\n transformResponse: transformAmasterResponse,\n // Enable error logging by default (helps with debugging and AI assistance)\n logErrors: true,\n};\n","/**\n * Authentication Module\n *\n * @module auth\n * @category Authentication\n *\n * Handles user authentication including:\n * - Registration\n * - Login (email/username/phone + password)\n * - Verification code login\n * - OAuth social login\n * - Logout and token refresh\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type {\n RegisterParams,\n LoginParams,\n LoginResponse,\n LoginType,\n CodeLoginParams,\n CodeLoginType,\n SendCodeParams,\n SuccessResponse,\n CaptchaResponse,\n OAuthProvider,\n RefreshTokenResponse,\n User,\n MiniProgramPhoneResponse,\n} from \"../types\";\n\n/**\n * Auto-detect login type based on provided parameters\n */\nfunction inferLoginType(params: LoginParams): LoginType | undefined {\n if (params.email) return \"email\";\n if (params.username) return \"username\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\n/**\n * Auto-detect code login type based on provided parameters\n */\nfunction inferCodeLoginType(params: CodeLoginParams): CodeLoginType | undefined {\n if (params.email) return \"email\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\nexport interface AuthModuleDeps {\n http: HttpClient;\n onLoginSuccess: (user: User, accessToken: string) => void;\n storage: { getItem: (key: string) => string | null };\n clearAuth: () => void;\n}\n\nexport function createAuthModule(deps: AuthModuleDeps) {\n const { http, onLoginSuccess, storage, clearAuth } = deps;\n\n return {\n /**\n * Register a new user account\n *\n * @category Authentication\n * @example\n * ```typescript\n * const result = await auth.register({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * displayName: \"John Doe\",\n * });\n * ```\n */\n async register(params: RegisterParams): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/register\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with username/email/phone and password\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from username\n * await auth.login({\n * username: \"john_doe\",\n * password: \"Password@123\",\n * });\n *\n * // Auto-detect loginType from email\n * await auth.login({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * });\n * ```\n */\n async login(params: LoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email, username, or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with verification code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from email\n * await auth.loginWithCode({\n * email: \"user@example.com\",\n * code: \"123456\",\n * });\n *\n * // Auto-detect loginType from phone\n * await auth.loginWithCode({\n * phone: \"13800138000\",\n * code: \"123456\",\n * });\n * ```\n */\n async loginWithCode(params: CodeLoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferCodeLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login-with-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Send verification code to email or phone\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.sendCode({\n * type: \"email\",\n * email: \"user@example.com\",\n * });\n * ```\n */\n async sendCode(params: SendCodeParams): Promise<ClientResult<SuccessResponse>> {\n return http.request<SuccessResponse>({\n url: \"/api/auth/send-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n },\n\n /**\n * Get captcha image\n *\n * @category Authentication\n */\n async getCaptcha(): Promise<ClientResult<CaptchaResponse>> {\n return http.request<CaptchaResponse>({\n url: \"/api/auth/captcha\",\n method: \"get\",\n });\n },\n\n /**\n * Redirect to OAuth provider for authentication\n *\n * @category Authentication\n * @example\n * ```typescript\n * auth.loginWithOAuth(\"google\");\n * ```\n */\n loginWithOAuth(provider: OAuthProvider, redirectUrl?: string): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth login is only available in browser environment\");\n return;\n }\n\n const url = redirectUrl\n ? `/api/auth/oauth/${provider}?redirect_url=${encodeURIComponent(redirectUrl)}`\n : `/api/auth/oauth/${provider}`;\n\n window.location.href = url;\n },\n\n /**\n * Handle OAuth callback\n *\n * @category Authentication\n */\n async handleOAuthCallback(): Promise<ClientResult<LoginResponse>> {\n if (typeof window === \"undefined\") {\n return {\n data: null,\n error: {\n message: \"OAuth callback is only available in browser environment\",\n status: 400,\n },\n status: 400,\n };\n }\n\n try {\n const hash = window.location.hash.substring(1);\n const params = new URLSearchParams(hash);\n const accessToken = params.get(\"access_token\");\n const userJson = params.get(\"user\");\n\n if (!accessToken || !userJson) {\n return {\n data: null,\n error: { message: \"OAuth callback failed: missing token or user data\", status: 400 },\n status: 400,\n };\n }\n\n const user = JSON.parse(decodeURIComponent(userJson)) as User;\n onLoginSuccess(user, accessToken);\n\n return { data: { user, accessToken }, error: null, status: 200 };\n } catch (error) {\n return {\n data: null,\n error: {\n message: `OAuth callback failed: ${error instanceof Error ? error.message : String(error)}`,\n status: 400,\n },\n status: 400,\n };\n }\n },\n\n /**\n * Login with WeChat Mini Program code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // In WeChat Mini Program\n * wx.login({\n * success: async (res) => {\n * if (res.code) {\n * const result = await auth.loginWithMiniProgram(res.code);\n * if (result.data) {\n * console.log(\"Logged in:\", result.data.user);\n * }\n * }\n * }\n * });\n * ```\n */\n async loginWithMiniProgram(code: string): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/miniprogram/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: { code },\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Get WeChat Mini Program user phone number\n * Requires user authorization via getPhoneNumber button\n *\n * @category Authentication\n * @example\n * ```typescript\n * // WXML\n * <button open-type=\"getPhoneNumber\" bindgetphonenumber=\"onGetPhoneNumber\">\n * Get Phone Number\n * </button>\n *\n * // JS\n * async onGetPhoneNumber(e) {\n * const { code } = e.detail;\n * if (code) {\n * const result = await auth.getMiniProgramPhoneNumber(code);\n * if (result.data) {\n * console.log(\"Phone:\", result.data.phone);\n * }\n * }\n * }\n * ```\n */\n async getMiniProgramPhoneNumber(code: string): Promise<ClientResult<MiniProgramPhoneResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<MiniProgramPhoneResponse>({\n url: \"/api/auth/miniprogram/phone\",\n method: \"post\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n data: { code },\n });\n },\n\n /**\n * Logout current user\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.logout();\n * ```\n */\n async logout(): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n\n const result = await http.request<SuccessResponse>({\n url: \"/api/auth/logout\",\n method: \"post\",\n headers: token ? { Authorization: `Bearer ${token}` } : undefined,\n });\n\n clearAuth();\n return result;\n },\n\n /**\n * Refresh access token\n *\n * @category Authentication\n */\n async refreshToken(): Promise<ClientResult<RefreshTokenResponse>> {\n return http.request<RefreshTokenResponse>({\n url: \"/api/auth/refresh\",\n method: \"post\",\n });\n },\n };\n}\n\nexport type AuthModule = ReturnType<typeof createAuthModule>;\n","/**\n * Permissions Module\n *\n * @module permissions\n * @category Permissions\n *\n * Handles permission and role checks:\n * - Role-based access control (RBAC)\n * - Permission checks (fast, local)\n * - Data scope queries (async, server-side)\n */\n\nimport type { HttpClient } from \"@amaster.ai/http-client\";\nimport type { User } from \"../types\";\n\nexport interface PermissionsModuleDeps {\n http: HttpClient;\n getCurrentUser: () => User | null;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createPermissionsModule(deps: PermissionsModuleDeps) {\n const { getCurrentUser } = deps;\n\n return {\n /**\n * Check if user has a specific role (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasRole(\"admin\")) {\n * showAdminPanel();\n * }\n * ```\n */\n hasRole(roleCode: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.roles) return false;\n return user.roles.includes(roleCode);\n },\n\n /**\n * Check if user has a specific permission (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasPermission(\"user\", \"delete\")) {\n * showDeleteButton();\n * }\n * ```\n */\n hasPermission(resource: string, action: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.permissions) return false;\n const permissionName = `${resource}:${action}`;\n return user.permissions.includes(permissionName);\n },\n\n /**\n * Check if user has ANY of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAnyPermission([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showUserSection();\n * }\n * ```\n */\n hasAnyPermission(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.some(({ resource, action }) => this.hasPermission(resource, action));\n },\n\n /**\n * Check if user has ALL of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAllPermissions([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showFullEditor();\n * }\n * ```\n */\n hasAllPermissions(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.every(({ resource, action }) => this.hasPermission(resource, action));\n },\n };\n}\n\nexport type PermissionsModule = ReturnType<typeof createPermissionsModule>;\n","/**\n * User Management Module\n *\n * @module user\n * @category User\n *\n * Handles user profile and account management:\n * - Get current user info\n * - Update profile\n * - Change password\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { User, UpdateMeParams, ChangePasswordParams, SuccessResponse } from \"../types\";\n\nexport interface UserModuleDeps {\n http: HttpClient;\n storage: {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n };\n onUserUpdate: (user: User) => void;\n}\n\nexport function createUserModule(deps: UserModuleDeps) {\n const { http, storage, onUserUpdate } = deps;\n\n return {\n /**\n * Get current logged-in user information\n *\n * @category User\n * @example\n * ```typescript\n * const result = await user.getMe();\n * if (result.data) {\n * console.log(\"User:\", result.data.displayName);\n * }\n * ```\n */\n async getMe(): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Update current user's profile\n *\n * @category User\n * @example\n * ```typescript\n * await user.updateMe({\n * displayName: \"New Name\",\n * avatarUrl: \"https://example.com/avatar.jpg\",\n * });\n * ```\n */\n async updateMe(params: UpdateMeParams): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"put\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Change current user's password\n *\n * @category User\n * @example\n * ```typescript\n * await user.changePassword({\n * oldPassword: \"OldPass@123\",\n * newPassword: \"NewPass@456\",\n * });\n * ```\n */\n async changePassword(params: ChangePasswordParams): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: \"/api/auth/change-password\",\n method: \"post\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n },\n };\n}\n\nexport type UserModule = ReturnType<typeof createUserModule>;\n","/**\n * OAuth Module\n *\n * @module oauth\n * @category OAuth\n *\n * Handles OAuth account binding management:\n * - List connected OAuth accounts\n * - Bind new OAuth account\n * - Unbind OAuth account\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { OAuthBinding, OAuthProvider, SuccessResponse } from \"../types\";\n\nexport interface OAuthModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createOAuthModule(deps: OAuthModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get list of OAuth accounts bound to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * const result = await oauth.getOAuthBindings();\n * if (result.data) {\n * result.data.forEach(binding => {\n * console.log(`${binding.provider}: ${binding.email}`);\n * });\n * }\n * ```\n */\n async getOAuthBindings(): Promise<ClientResult<OAuthBinding[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<OAuthBinding[]>({\n url: \"/api/auth/oauth-bindings\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Bind an OAuth account to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * oauth.bindOAuth(\"google\"); // Redirects to Google OAuth\n * ```\n */\n bindOAuth(provider: OAuthProvider): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth binding is only available in browser environment\");\n return;\n }\n\n window.location.href = `/api/auth/oauth/${provider}/bind`;\n },\n\n /**\n * Unbind an OAuth account from current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * await oauth.unbindOAuth(\"google\");\n * ```\n */\n async unbindOAuth(provider: OAuthProvider): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/oauth/${provider}/unbind`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type OAuthModule = ReturnType<typeof createOAuthModule>;\n","/**\n * Sessions Module\n *\n * @module sessions\n * @category Sessions\n *\n * Handles multi-device session management:\n * - View all active sessions\n * - Revoke specific session\n * - Revoke all other sessions\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { Session, SuccessResponse, RevokeAllSessionsResponse } from \"../types\";\n\nexport interface SessionsModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createSessionsModule(deps: SessionsModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get current session information\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSession();\n * if (result.data) {\n * console.log(\"Session ID:\", result.data.id);\n * console.log(\"Device:\", result.data.sessionName);\n * console.log(\"IP address:\", result.data.ipAddress);\n * console.log(\"Location:\", result.data.location);\n * }\n * ```\n */\n async getSession(): Promise<ClientResult<Session>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session>({\n url: \"/api/auth/sessions/current\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Get all active sessions for current user\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSessions();\n * if (result.data) {\n * result.data.forEach(session => {\n * const status = session.isCurrent ? \"Current\" : \"Other\";\n * console.log(`${session.sessionName} - ${session.ipAddress} - ${status}`);\n * });\n * }\n * ```\n */\n async getSessions(): Promise<ClientResult<Session[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session[]>({\n url: \"/api/auth/sessions\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke a specific session\n *\n * @category Sessions\n * @example\n * ```typescript\n * await sessions.revokeSession(\"session-id-123\");\n * ```\n */\n async revokeSession(sessionId: string): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n if (!sessionId) {\n return {\n data: null,\n error: { message: \"Session ID is required\", status: 400 },\n status: 400,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/sessions/${sessionId}`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke all sessions except current one\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.revokeAllSessions();\n * if (result.data) {\n * console.log(`Revoked ${result.data.revokedCount} sessions`);\n * }\n * ```\n */\n async revokeAllSessions(): Promise<ClientResult<RevokeAllSessionsResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<RevokeAllSessionsResponse>({\n url: \"/api/auth/sessions\",\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type SessionsModule = ReturnType<typeof createSessionsModule>;\n","/**\n * Main Authentication Client\n *\n * Combines all modules into a unified client interface\n */\n\nimport { createHttpClient, type HttpClient } from \"@amaster.ai/http-client\";\nimport { EventEmitter } from \"./event-emitter\";\nimport { createStorageAdapter, STORAGE_KEYS, type StorageAdapter } from \"./storage\";\nimport { TokenManager } from \"./token-manager\";\nimport { defaultHttpClientOptions } from \"./http-config\";\nimport { createAuthModule } from \"./modules/auth\";\nimport { createPermissionsModule } from \"./modules/permissions\";\nimport { createUserModule } from \"./modules/user\";\nimport { createOAuthModule } from \"./modules/oauth\";\nimport { createSessionsModule } from \"./modules/sessions\";\nimport type { AuthClientOptions, AuthEvent, EventHandler, User } from \"./types\";\n\nexport type AuthClient = ReturnType<typeof createAuthModule> &\n ReturnType<typeof createPermissionsModule> &\n ReturnType<typeof createUserModule> &\n ReturnType<typeof createOAuthModule> &\n ReturnType<typeof createSessionsModule> & {\n // Events\n on(event: AuthEvent, handler: EventHandler): void;\n off(event: AuthEvent, handler: EventHandler): void;\n\n // Utilities\n isAuthenticated(): boolean;\n getAccessToken(): string | null;\n setAccessToken(token: string): void;\n clearAuth(): void;\n };\n\nexport function createAuthClient(\n options: AuthClientOptions = {},\n http?: HttpClient\n): AuthClient {\n const { baseURL, headers, onTokenExpired, onUnauthorized } = options;\n \n // Create HTTP client with user options if not provided\n const httpClient = http || createHttpClient({\n ...defaultHttpClientOptions,\n baseURL,\n headers,\n });\n\n const autoRefresh = true;\n const refreshThreshold = 300;\n\n // Auto-detect environment and use appropriate storage\n const storage: StorageAdapter = createStorageAdapter();\n const eventEmitter = new EventEmitter();\n const tokenManager = new TokenManager();\n\n let currentUser: User | null = null;\n\n // Load user from storage\n try {\n const userJson = storage.getItem(STORAGE_KEYS.USER);\n if (userJson) {\n currentUser = JSON.parse(userJson);\n }\n } catch (error) {\n console.error(\"[AuthClient] Failed to load user from storage:\", error);\n }\n\n // Forward declare for circular dependency\n let authClient: AuthClient;\n\n // Setup token refresh callback\n tokenManager.setRefreshCallback(async () => {\n const result = await authClient.refreshToken();\n if (result.data) {\n await authClient.getMe();\n eventEmitter.emit(\"tokenRefreshed\", result.data.accessToken);\n } else {\n eventEmitter.emit(\"tokenExpired\");\n onTokenExpired?.();\n }\n });\n\n function handleLoginSuccess(user: User, accessToken: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, accessToken);\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n currentUser = user;\n\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(accessToken, refreshThreshold);\n }\n\n eventEmitter.emit(\"login\", user);\n }\n\n function handleUserUpdate(user: User): void {\n currentUser = user;\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n }\n\n function clearAuth(): void {\n storage.clear();\n currentUser = null;\n tokenManager.clearSchedule();\n }\n\n function getCurrentUser(): User | null {\n return currentUser;\n }\n\n // Create modules\n const authModule = createAuthModule({\n http: httpClient,\n onLoginSuccess: handleLoginSuccess,\n storage,\n clearAuth,\n });\n\n const permissionsModule = createPermissionsModule({\n http: httpClient,\n getCurrentUser,\n storage,\n });\n\n const userModule = createUserModule({\n http: httpClient,\n storage,\n onUserUpdate: handleUserUpdate,\n });\n\n const oauthModule = createOAuthModule({\n http: httpClient,\n storage,\n });\n\n const sessionsModule = createSessionsModule({\n http: httpClient,\n storage,\n });\n\n // Combine all modules\n authClient = {\n ...authModule,\n ...permissionsModule,\n ...userModule,\n ...oauthModule,\n ...sessionsModule,\n\n // Events\n on(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.on(event, handler);\n },\n\n off(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.off(event, handler);\n },\n\n // Utilities\n isAuthenticated(): boolean {\n const token = storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n return !!token;\n },\n\n getAccessToken(): string | null {\n return storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n },\n\n setAccessToken(token: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(token, refreshThreshold);\n }\n },\n\n clearAuth,\n };\n\n // Setup unauthorized handler\n authClient.on(\"unauthorized\", () => {\n onUnauthorized?.();\n });\n\n // Auto sync user info on initialization\n if (authClient.isAuthenticated()) {\n authClient.getMe().catch((error) => {\n console.warn(\"[AuthClient] Failed to sync user info on init:\", error);\n });\n }\n\n return authClient;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/event-emitter.ts","../src/storage.ts","../src/token-manager.ts","../src/http-config.ts","../src/modules/auth.ts","../src/modules/permissions.ts","../src/modules/user.ts","../src/modules/oauth.ts","../src/modules/sessions.ts","../src/client.ts"],"names":["EventEmitter","event","handler","h","args","error","STORAGE_KEYS","detectEnvironment","createStorageAdapter","createWeChatMiniProgramStorage","createBrowserStorage","createNoOpStorage","storage","key","value","store","parseJwt","token","parts","base64","jsonPayload","c","TokenManager","callback","delayMs","accessToken","thresholdSeconds","payload","expiresAtMs","nowMs","refreshDelayMs","transformAmasterResponse","responseData","defaultHttpClientOptions","inferLoginType","params","inferCodeLoginType","createAuthModule","deps","http","onLoginSuccess","clearAuth","result","loginType","requestData","provider","redirectUrl","url","hash","userJson","user","urlWithoutHash","code","createPermissionsModule","getCurrentUser","roleCode","resource","action","permissionName","permissions","createUserModule","onUserUpdate","createOAuthModule","createSessionsModule","sessionId","createAuthClient","options","baseURL","headers","onTokenExpired","onUnauthorized","autoHandleOAuthCallback","httpClient","createHttpClient","refreshThreshold","eventEmitter","tokenManager","currentUser","authClient","handleLoginSuccess","handleUserUpdate","authModule","permissionsModule","userModule","oauthModule","sessionsModule"],"mappings":"+DAQO,IAAMA,CAAAA,CAAN,KAAmB,CAAnB,WAAA,EAAA,CACL,IAAA,CAAQ,MAAA,CAAmB,GAAC,CAK5B,GAAGC,CAAAA,CAAkBC,CAAAA,CAA6B,CAC3C,IAAA,CAAK,MAAA,CAAOD,CAAK,CAAA,GACpB,IAAA,CAAK,OAAOA,CAAK,CAAA,CAAI,EAAC,CAAA,CAExB,IAAA,CAAK,MAAA,CAAOA,CAAK,CAAA,CAAE,KAAKC,CAAO,EACjC,CAKA,GAAA,CAAID,CAAAA,CAAkBC,CAAAA,CAA6B,CAC5C,IAAA,CAAK,MAAA,CAAOD,CAAK,CAAA,GAGtB,IAAA,CAAK,MAAA,CAAOA,CAAK,CAAA,CAAI,IAAA,CAAK,OAAOA,CAAK,CAAA,CAAE,MAAA,CAAQE,CAAAA,EAAMA,CAAAA,GAAMD,CAAO,CAAA,EACrE,CAKA,KAAKD,CAAAA,CAAAA,GAAqBG,CAAAA,CAAmB,CACtC,IAAA,CAAK,MAAA,CAAOH,CAAK,CAAA,EAGtB,IAAA,CAAK,OAAOA,CAAK,CAAA,CAAE,OAAA,CAASC,CAAAA,EAAY,CACtC,GAAI,CACFA,CAAAA,CAAQ,GAAGE,CAAI,EACjB,CAAA,MAASC,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,4CAA4CJ,CAAK,CAAA,EAAA,CAAA,CAAMI,CAAK,EAC5E,CACF,CAAC,EACH,CAKA,oBAA2B,CACzB,IAAA,CAAK,MAAA,CAAS,GAChB,CACF,CAAA,CCnCO,IAAMC,EAAe,CAC1B,YAAA,CAAc,sBAAA,CACd,aAAA,CAAe,uBAAA,CACf,IAAA,CAAM,cACR,CAAA,CAKA,SAASC,CAAAA,EAA+D,CAEtE,OAAI,OAAO,EAAA,CAAO,GAAA,EAAe,EAAA,CAAG,cAAA,CAC3B,qBAIL,OAAO,MAAA,CAAW,GAAA,EAAe,OAAO,MAAA,CAAO,YAAA,CAAiB,GAAA,CAC3D,SAAA,CAIF,MACT,CAgBO,SAASC,CAAAA,EAAuC,CAGrD,OAFYD,CAAAA,EAAkB,EAG5B,KAAK,oBAAA,CACH,OAAOE,CAAAA,EAA+B,CACxC,KAAK,SAAA,CACH,OAAOC,CAAAA,EAAqB,CAC9B,KAAK,MAAA,CACH,OAAOC,CAAAA,EACX,CACF,CAKA,SAASD,CAAAA,EAAuC,CAC9C,IAAME,CAAAA,CAAU,MAAA,CAAO,YAAA,CAEvB,OAAO,CACL,QAAQC,CAAAA,CAA4B,CAClC,GAAI,CACF,OAAOD,CAAAA,CAAQ,OAAA,CAAQC,CAAG,CAC5B,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,OAAA,CAAQ,KAAA,CAAM,oDAAA,CAAsDA,CAAK,CAAA,CAClE,IACT,CACF,CAAA,CAEA,OAAA,CAAQQ,CAAAA,CAAaC,CAAAA,CAAqB,CACxC,GAAI,CACFF,EAAQ,OAAA,CAAQC,CAAAA,CAAKC,CAAK,EAC5B,CAAA,MAAST,CAAAA,CAAO,CACd,OAAA,CAAQ,MAAM,kDAAA,CAAoDA,CAAK,EACzE,CACF,CAAA,CAEA,UAAA,CAAWQ,CAAAA,CAAmB,CAC5B,GAAI,CACFD,CAAAA,CAAQ,UAAA,CAAWC,CAAG,EACxB,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,uDAAA,CAAyDA,CAAK,EAC9E,CACF,CAAA,CAEA,KAAA,EAAc,CACZ,GAAI,CAEFO,CAAAA,CAAQ,UAAA,CAAWN,CAAAA,CAAa,YAAY,CAAA,CAC5CM,CAAAA,CAAQ,WAAWN,CAAAA,CAAa,aAAa,CAAA,CAC7CM,CAAAA,CAAQ,UAAA,CAAWN,CAAAA,CAAa,IAAI,EACtC,OAASD,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,4CAAA,CAA8CA,CAAK,EACnE,CACF,CACF,CACF,CAMA,SAASI,CAAAA,EAAiD,CACxD,OAAO,CACL,OAAA,CAAQI,EAA4B,CAClC,GAAI,CAEF,OADc,EAAA,CAAG,cAAA,CAAeA,CAAG,CAAA,EACnB,IAClB,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,OAAA,CAAQ,KAAA,CAAM,sDAAA,CAAwDA,CAAK,CAAA,CACpE,IACT,CACF,CAAA,CAEA,OAAA,CAAQQ,CAAAA,CAAaC,CAAAA,CAAqB,CACxC,GAAI,CACF,EAAA,CAAG,cAAA,CAAeD,CAAAA,CAAKC,CAAK,EAC9B,CAAA,MAAST,CAAAA,CAAO,CACd,QAAQ,KAAA,CAAM,oDAAA,CAAsDA,CAAK,EAC3E,CACF,CAAA,CAEA,UAAA,CAAWQ,CAAAA,CAAmB,CAC5B,GAAI,CACF,EAAA,CAAG,iBAAA,CAAkBA,CAAG,EAC1B,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,yDAAA,CAA2DA,CAAK,EAChF,CACF,CAAA,CAEA,KAAA,EAAc,CACZ,GAAI,CAEF,EAAA,CAAG,iBAAA,CAAkBC,CAAAA,CAAa,YAAY,CAAA,CAC9C,EAAA,CAAG,kBAAkBA,CAAAA,CAAa,aAAa,CAAA,CAC/C,EAAA,CAAG,iBAAA,CAAkBA,CAAAA,CAAa,IAAI,EACxC,OAASD,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,8CAAA,CAAgDA,CAAK,EACrE,CACF,CACF,CACF,CAMA,SAASM,CAAAA,EAAoC,CAC3C,IAAMI,CAAAA,CAAQ,IAAI,GAAA,CAElB,OAAO,CACL,OAAA,CAAQF,CAAAA,CAA4B,CAClC,OAAOE,CAAAA,CAAM,IAAIF,CAAG,CAAA,EAAK,IAC3B,CAAA,CACA,OAAA,CAAQA,CAAAA,CAAaC,CAAAA,CAAqB,CACxCC,EAAM,GAAA,CAAIF,CAAAA,CAAKC,CAAK,EACtB,CAAA,CACA,UAAA,CAAWD,CAAAA,CAAmB,CAC5BE,EAAM,MAAA,CAAOF,CAAG,EAClB,CAAA,CACA,KAAA,EAAc,CACZE,CAAAA,CAAM,KAAA,GACR,CACF,CACF,CCpKO,SAASC,CAAAA,CAASC,CAAAA,CAAkC,CACzD,GAAI,CACF,IAAMC,CAAAA,CAAQD,CAAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAC7B,GAAIC,CAAAA,CAAM,SAAW,CAAA,CACnB,OAAO,IAAA,CAIT,IAAMC,CAAAA,CAAAA,CADYD,CAAAA,CAAM,CAAC,CAAA,EAAK,IACL,OAAA,CAAQ,IAAA,CAAM,GAAG,CAAA,CAAE,OAAA,CAAQ,IAAA,CAAM,GAAG,CAAA,CAG7D,GAAI,OAAO,IAAA,CAAS,GAAA,CAAa,CAC/B,IAAME,CAAAA,CAAc,kBAAA,CAClB,KAAKD,CAAM,CAAA,CACR,KAAA,CAAM,EAAE,CAAA,CACR,GAAA,CAAKE,CAAAA,EAAM,GAAA,CAAA,CAAO,KAAOA,CAAAA,CAAE,UAAA,CAAW,CAAC,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,EAAG,KAAA,CAAM,EAAE,CAAC,CAAA,CAChE,IAAA,CAAK,EAAE,CACZ,CAAA,CACA,OAAO,IAAA,CAAK,MAAMD,CAAW,CAC/B,CAGA,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjC,IAAMA,CAAAA,CAAc,MAAA,CAAO,IAAA,CAAKD,CAAAA,CAAQ,QAAQ,CAAA,CAAE,QAAA,CAAS,OAAO,EAClE,OAAO,IAAA,CAAK,KAAA,CAAMC,CAAW,CAC/B,CAEA,OAAO,IACT,OAASf,CAAAA,CAAO,CACd,OAAA,OAAA,CAAQ,KAAA,CAAM,yCAAA,CAA2CA,CAAK,CAAA,CACvD,IACT,CACF,CAKO,IAAMiB,CAAAA,CAAN,KAAmB,CAAnB,WAAA,EAAA,CACL,IAAA,CAAQ,aAAqD,IAAA,CAC7D,IAAA,CAAQ,YAAA,CAAe,KAAA,CACvB,IAAA,CAAQ,eAAA,CAAgD,KAAA,CAKxD,kBAAA,CAAmBC,EAAqC,CACtD,IAAA,CAAK,eAAA,CAAkBA,EACzB,CAMA,eAAA,CAAgBC,CAAAA,CAAuB,CAErC,KAAK,aAAA,EAAc,CAGf,EAAAA,CAAAA,EAAW,CAAA,CAAA,GAIf,IAAA,CAAK,YAAA,CAAe,UAAA,CAAW,IAAM,CACnC,IAAA,CAAK,OAAA,GACP,CAAA,CAAGA,CAAO,CAAA,EACZ,CAOA,yBAAyBC,CAAAA,CAAqBC,CAAAA,CAA2B,GAAA,CAAW,CAClF,IAAMC,CAAAA,CAAUX,CAAAA,CAASS,CAAW,EACpC,GAAI,CAACE,CAAAA,EAAW,CAACA,CAAAA,CAAQ,GAAA,CAAK,CAC5B,OAAA,CAAQ,KAAK,0EAA0E,CAAA,CACvF,MACF,CAEA,IAAMC,CAAAA,CAAcD,CAAAA,CAAQ,GAAA,CAAM,GAAA,CAC5BE,CAAAA,CAAQ,IAAA,CAAK,GAAA,EAAI,CAIjBC,CAAAA,CAHcF,CAAAA,CAAcC,CAAAA,CAGGH,EAAmB,GAAA,CAEpDI,CAAAA,EAAkB,CAAA,EAEpB,OAAA,CAAQ,IAAA,CAAK,6EAA6E,CAAA,CAC1F,IAAA,CAAK,SAAQ,EAEb,IAAA,CAAK,eAAA,CAAgBA,CAAc,EAEvC,CAKA,MAAM,OAAA,EAAyB,CAC7B,GAAI,CAAA,IAAA,CAAK,YAAA,CAIT,CAAA,GAAI,CAAC,IAAA,CAAK,eAAA,CAAiB,CACzB,QAAQ,KAAA,CAAM,sCAAsC,CAAA,CACpD,MACF,CAEA,IAAA,CAAK,YAAA,CAAe,IAAA,CAEpB,GAAI,CACF,MAAM,IAAA,CAAK,eAAA,GACb,CAAA,MAASzB,CAAAA,CAAO,CACd,QAAQ,KAAA,CAAM,oCAAA,CAAsCA,CAAK,EAC3D,CAAA,OAAE,CACA,IAAA,CAAK,YAAA,CAAe,MACtB,CAAA,CACF,CAKA,aAAA,EAAsB,CAChB,IAAA,CAAK,YAAA,GACP,YAAA,CAAa,IAAA,CAAK,YAAY,CAAA,CAC9B,IAAA,CAAK,YAAA,CAAe,IAAA,EAExB,CAKA,qBAAA,EAAiC,CAC/B,OAAO,IAAA,CAAK,YACd,CAKA,OAAA,EAAgB,CACd,IAAA,CAAK,aAAA,EAAc,CACnB,KAAK,eAAA,CAAkB,IAAA,CACvB,IAAA,CAAK,YAAA,CAAe,MACtB,CACF,CAAA,CCzIO,SAAS0B,EAA4BC,CAAAA,CAA0B,CACpE,OACEA,CAAAA,EACA,OAAOA,CAAAA,EAAiB,QAAA,GACvB,YAAA,GAAgBA,GAAgB,QAAA,GAAYA,CAAAA,CAAAA,EAGzC,MAAA,GAAUA,CAAAA,CACJA,CAAAA,CAA6B,IAAA,CAKlCA,CACT,KAMaC,CAAAA,CAA8C,CACzD,iBAAA,CAAmBF,CAAAA,CAEnB,SAAA,CAAW,IACb,ECbA,SAASG,EAAeC,CAAAA,CAA4C,CAClE,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAAA,CACzB,GAAIA,EAAO,QAAA,CAAU,OAAO,UAAA,CAC5B,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAE3B,CAKA,SAASC,CAAAA,CAAmBD,CAAAA,CAAoD,CAC9E,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAAA,CACzB,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAE3B,CAYO,SAASE,EAAiBC,CAAAA,CAAsB,CACrD,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,cAAA,CAAAC,CAAAA,CAAgB,QAAA5B,CAAAA,CAAS,SAAA,CAAA6B,CAAU,CAAA,CAAIH,CAAAA,CAErD,OAAO,CAcL,MAAM,SAASH,CAAAA,CAA8D,CAC3E,IAAMO,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,IAAK,oBAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,KAAMJ,CACR,CAAC,CAAA,CAED,OAAIO,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,MAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CAqBA,MAAM,KAAA,CAAMP,CAAAA,CAA2D,CAErE,IAAMQ,EAAYR,CAAAA,CAAO,SAAA,EAAaD,CAAAA,CAAeC,CAAM,CAAA,CAE3D,GAAI,CAACQ,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,2EAAA,CACT,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,CAAA,CAIF,IAAMC,CAAAA,CAAc,CAClB,GAAGT,EACH,SAAA,CAAAQ,CACF,CAAA,CAEMD,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,IAAK,iBAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,KAAMK,CACR,CAAC,CAAA,CAED,OAAIF,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,MAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CAqBA,MAAM,aAAA,CAAcP,CAAAA,CAA+D,CAEjF,IAAMQ,EAAYR,CAAAA,CAAO,SAAA,EAAaC,CAAAA,CAAmBD,CAAM,CAAA,CAE/D,GAAI,CAACQ,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,gEAAA,CACT,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,CAAA,CAIF,IAAMC,CAAAA,CAAc,CAClB,GAAGT,EACH,SAAA,CAAAQ,CACF,CAAA,CAEMD,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,IAAK,2BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,KAAMK,CACR,CAAC,CAAA,CAED,OAAIF,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,MAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CAcA,MAAM,QAAA,CAASP,CAAAA,CAAgE,CAC7E,OAAOI,EAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,qBAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,eAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAMJ,CACR,CAAC,CACH,CAAA,CAOA,MAAM,YAAqD,CACzD,OAAOI,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,mBAAA,CACL,MAAA,CAAQ,KACV,CAAC,CACH,CAAA,CAWA,cAAA,CAAeM,CAAAA,CAAyBC,CAAAA,CAA4B,CAClE,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjC,OAAA,CAAQ,KAAA,CAAM,mEAAmE,CAAA,CACjF,MACF,CAEA,IAAMC,CAAAA,CAAMD,CAAAA,CACR,CAAA,gBAAA,EAAmBD,CAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmBC,CAAW,CAAC,CAAA,CAAA,CAC3E,CAAA,gBAAA,EAAmBD,CAAQ,CAAA,CAAA,CAE/B,MAAA,CAAO,QAAA,CAAS,IAAA,CAAOE,EACzB,CAAA,CAOA,MAAM,mBAAA,EAA4D,CAChE,GAAI,OAAO,MAAA,CAAW,GAAA,CACpB,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,yDAAA,CACT,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,CAAA,CAGF,GAAI,CACF,IAAMC,CAAAA,CAAO,OAAO,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CACvCb,CAAAA,CAAS,IAAI,eAAA,CAAgBa,CAAI,CAAA,CACjCvB,CAAAA,CAAcU,CAAAA,CAAO,GAAA,CAAI,cAAc,CAAA,CACvCc,CAAAA,CAAWd,CAAAA,CAAO,IAAI,MAAM,CAAA,CAElC,GAAI,CAACV,CAAAA,EAAe,CAACwB,CAAAA,CACnB,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mDAAA,CAAqD,MAAA,CAAQ,GAAI,EACnF,MAAA,CAAQ,GACV,CAAA,CAGF,IAAMC,CAAAA,CAAO,IAAA,CAAK,KAAA,CAAM,kBAAA,CAAmBD,CAAQ,CAAC,CAAA,CAKpD,GAJAT,CAAAA,CAAeU,CAAAA,CAAMzB,CAAW,CAAA,CAI5B,OAAO,OAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,YAAA,CAAc,CACjD,IAAM0B,CAAAA,CAAiB,MAAA,CAAO,SAAS,QAAA,CAAW,MAAA,CAAO,QAAA,CAAS,MAAA,CAClE,MAAA,CAAO,OAAA,CAAQ,YAAA,CAAa,IAAA,CAAM,GAAIA,CAAc,EACtD,CAAA,KAEE,MAAA,CAAO,QAAA,CAAS,IAAA,CAAO,EAAA,CAGzB,OAAO,CAAE,IAAA,CAAM,CAAE,IAAA,CAAAD,CAAAA,CAAM,WAAA,CAAAzB,CAAY,CAAA,CAAG,KAAA,CAAO,KAAM,MAAA,CAAQ,GAAI,CACjE,CAAA,MAASpB,CAAAA,CAAO,CACd,OAAO,CACL,KAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,CAAA,uBAAA,EAA0BA,CAAAA,YAAiB,KAAA,CAAQA,CAAAA,CAAM,QAAU,MAAA,CAAOA,CAAK,CAAC,CAAA,CAAA,CACzF,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,CACF,CACF,CAAA,CAqBA,MAAM,oBAAA,CAAqB+C,CAAAA,CAAoD,CAC7E,IAAMV,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,GAAA,CAAK,6BAAA,CACL,MAAA,CAAQ,OACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAM,CAAE,IAAA,CAAAa,CAAK,CACf,CAAC,CAAA,CAED,OAAIV,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,MAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,EAGnDA,CACT,CAAA,CA0BA,MAAM,yBAAA,CAA0BU,CAAAA,CAA+D,CAC7F,IAAMnC,CAAAA,CAAQL,EAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAkC,CAC5C,IAAK,6BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAChC,CAAA,CACA,IAAA,CAAM,CAAE,IAAA,CAAAmC,CAAK,CACf,CAAC,CAAA,CAfQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,oBAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAYJ,CAAA,CAWA,MAAM,QAAiD,CACrD,IAAMnC,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CAE9C8B,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAyB,CACjD,GAAA,CAAK,kBAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAStB,EAAQ,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUA,CAAK,CAAA,CAAG,CAAA,CAAI,MAC1D,CAAC,EAED,OAAAwB,CAAAA,EAAU,CACHC,CACT,CAAA,CAOA,MAAM,YAAA,EAA4D,CAChE,IAAMA,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAA8B,CACtD,GAAA,CAAK,mBAAA,CACL,MAAA,CAAQ,MACV,CAAC,CAAA,CAGD,OAAIG,CAAAA,CAAO,IAAA,EAAM,WAAA,EACf9B,CAAAA,CAAQ,QAAQ,sBAAA,CAAwB8B,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAG1DA,CACT,CACF,CACF,CC3ZO,SAASW,CAAAA,CAAwBf,CAAAA,CAA6B,CACnE,GAAM,CAAE,cAAA,CAAAgB,CAAe,EAAIhB,CAAAA,CAE3B,OAAO,CAaL,OAAA,CAAQiB,CAAAA,CAA2B,CACjC,IAAML,CAAAA,CAAOI,GAAe,CAC5B,OAAI,CAACJ,CAAAA,EAAQ,CAACA,CAAAA,CAAK,KAAA,CAAc,KAAA,CAC1BA,EAAK,KAAA,CAAM,QAAA,CAASK,CAAQ,CACrC,CAAA,CAcA,aAAA,CAAcC,CAAAA,CAAkBC,CAAAA,CAAyB,CACvD,IAAMP,CAAAA,CAAOI,CAAAA,EAAe,CAC5B,GAAI,CAACJ,CAAAA,EAAQ,CAACA,EAAK,WAAA,CAAa,OAAO,MAAA,CACvC,IAAMQ,CAAAA,CAAiB,CAAA,EAAGF,CAAQ,CAAA,CAAA,EAAIC,CAAM,CAAA,CAAA,CAC5C,OAAOP,CAAAA,CAAK,WAAA,CAAY,QAAA,CAASQ,CAAc,CACjD,EAcA,gBAAA,CAAiBC,CAAAA,CAAmE,CAClF,OAAOA,CAAAA,CAAY,IAAA,CAAK,CAAC,CAAE,SAAAH,CAAAA,CAAU,MAAA,CAAAC,CAAO,CAAA,GAAM,IAAA,CAAK,aAAA,CAAcD,CAAAA,CAAUC,CAAM,CAAC,CACxF,CAAA,CAcA,iBAAA,CAAkBE,CAAAA,CAAmE,CACnF,OAAOA,CAAAA,CAAY,KAAA,CAAM,CAAC,CAAE,QAAA,CAAAH,CAAAA,CAAU,MAAA,CAAAC,CAAO,CAAA,GAAM,IAAA,CAAK,aAAA,CAAcD,EAAUC,CAAM,CAAC,CACzF,CACF,CACF,CCtEO,SAASG,CAAAA,CAAiBtB,EAAsB,CACrD,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,OAAA,CAAA3B,CAAAA,CAAS,YAAA,CAAAiD,CAAa,CAAA,CAAIvB,CAAAA,CAExC,OAAO,CAaL,MAAM,KAAA,EAAqC,CACzC,IAAMrB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,GAAI,CAACK,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAAA,CAGF,IAAMyB,CAAAA,CAAS,MAAMH,CAAAA,CAAK,QAAc,CACtC,GAAA,CAAK,cAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,UAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAED,OAAIyB,CAAAA,CAAO,IAAA,EACTmB,EAAanB,CAAAA,CAAO,IAAI,CAAA,CAGnBA,CACT,CAAA,CAcA,MAAM,QAAA,CAASP,CAAAA,CAAqD,CAClE,IAAMlB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,GAAI,CAACK,EACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAAA,CAGF,IAAMyB,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAc,CACtC,GAAA,CAAK,cAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CACP,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAA,CAC9B,cAAA,CAAgB,kBAClB,CAAA,CACA,IAAA,CAAMkB,CACR,CAAC,CAAA,CAED,OAAIO,CAAAA,CAAO,IAAA,EACTmB,CAAAA,CAAanB,CAAAA,CAAO,IAAI,EAGnBA,CACT,CAAA,CAcA,MAAM,cAAA,CAAeP,CAAAA,CAAsE,CACzF,IAAMlB,CAAAA,CAAQL,EAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAyB,CACnC,IAAK,2BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,GAC9B,cAAA,CAAgB,kBAClB,CAAA,CACA,IAAA,CAAMkB,CACR,CAAC,CAAA,CAfQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,EACnD,MAAA,CAAQ,GACV,CAYJ,CACF,CACF,CCnHO,SAAS2B,CAAAA,CAAkBxB,EAAuB,CACvD,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,OAAA,CAAA3B,CAAQ,CAAA,CAAI0B,EAE1B,OAAO,CAeL,MAAM,gBAAA,EAA0D,CAC9D,IAAMrB,CAAAA,CAAQL,CAAAA,CAAQ,QAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAwB,CAClC,GAAA,CAAK,2BACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,oBAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CAAA,CAWA,SAAA,CAAU4B,CAAAA,CAA+B,CACvC,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjC,OAAA,CAAQ,MAAM,qEAAqE,CAAA,CACnF,MACF,CAEA,MAAA,CAAO,QAAA,CAAS,IAAA,CAAO,CAAA,gBAAA,EAAmBA,CAAQ,CAAA,KAAA,EACpD,CAAA,CAWA,MAAM,WAAA,CAAYA,CAAAA,CAAiE,CACjF,IAAM5B,CAAAA,CAAQL,EAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAyB,CACnC,IAAK,CAAA,gBAAA,EAAmBM,CAAQ,CAAA,OAAA,CAAA,CAChC,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,UAAU5B,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,IAAA,CACN,MAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CACF,CACF,CC/EO,SAAS8C,CAAAA,CAAqBzB,CAAAA,CAA0B,CAC7D,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,OAAA,CAAA3B,CAAQ,CAAA,CAAI0B,CAAAA,CAE1B,OAAO,CAgBL,MAAM,UAAA,EAA6C,CACjD,IAAMrB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,EACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAiB,CAC3B,GAAA,CAAK,4BAAA,CACL,MAAA,CAAQ,MACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,EAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CAAA,CAiBA,MAAM,WAAA,EAAgD,CACpD,IAAMA,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,QAAmB,CAC7B,GAAA,CAAK,oBAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,KACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CAAA,CAWA,MAAM,aAAA,CAAc+C,CAAAA,CAA2D,CAC7E,IAAM/C,CAAAA,CAAQL,EAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQA+C,CAAAA,CAQEzB,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,CAAA,mBAAA,EAAsByB,CAAS,CAAA,CAAA,CACpC,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,CAAE,cAAe,CAAA,OAAA,EAAU/C,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,KACN,KAAA,CAAO,CAAE,OAAA,CAAS,wBAAA,CAA0B,MAAA,CAAQ,GAAI,CAAA,CACxD,MAAA,CAAQ,GACV,CAAA,CAZO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAgBJ,CAAA,CAcA,MAAM,mBAAsE,CAC1E,IAAMA,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,EAQEsB,CAAAA,CAAK,OAAA,CAAmC,CAC7C,GAAA,CAAK,oBAAA,CACL,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,KAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,OAAQ,GACV,CAQJ,CACF,CACF,CCrHO,SAASgD,CAAAA,CACdC,CAAAA,CAA6B,EAAC,CAC9B3B,CAAAA,CACY,CACZ,IAAM,CAAE,OAAA,CAAA4B,CAAAA,CAAS,OAAA,CAAAC,EAAS,cAAA,CAAAC,CAAAA,CAAgB,cAAA,CAAAC,CAAAA,CAAgB,uBAAA,CAAAC,CAAAA,CAA0B,IAAK,CAAA,CAAIL,CAAAA,CAGvFM,CAAAA,CAAajC,CAAAA,EAAQkC,2BAAAA,CAAiB,CAC1C,GAAGxC,CAAAA,CACH,OAAA,CAAAkC,EACA,OAAA,CAAAC,CACF,CAAC,CAAA,CAGKM,CAAAA,CAAmB,GAAA,CAGnB9D,EAA0BJ,CAAAA,EAAqB,CAC/CmE,CAAAA,CAAe,IAAI3E,CAAAA,CACnB4E,CAAAA,CAAe,IAAItD,CAAAA,CAErBuD,EAA2B,KAG/B,GAAI,CACF,IAAM5B,CAAAA,CAAWrC,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,IAAI,CAAA,CAC9C2C,CAAAA,GACF4B,CAAAA,CAAc,IAAA,CAAK,KAAA,CAAM5B,CAAQ,CAAA,EAErC,CAAA,MAAS5C,EAAO,CACd,OAAA,CAAQ,KAAA,CAAM,gDAAA,CAAkDA,CAAK,EACvE,CAGA,IAAIyE,EAGJF,CAAAA,CAAa,kBAAA,CAAmB,SAAY,CAC1C,IAAMlC,CAAAA,CAAS,MAAMoC,CAAAA,CAAW,cAAa,CACzCpC,CAAAA,CAAO,IAAA,EACT,MAAMoC,CAAAA,CAAW,KAAA,EAAM,CACvBH,CAAAA,CAAa,IAAA,CAAK,gBAAA,CAAkBjC,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,GAE3DiC,CAAAA,CAAa,IAAA,CAAK,cAAc,CAAA,CAChCN,CAAAA,IAAiB,EAErB,CAAC,CAAA,CAED,SAASU,CAAAA,CAAmB7B,CAAAA,CAAYzB,EAA2B,CACjEb,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAA,CAAcmB,CAAW,CAAA,CACtDb,CAAAA,CAAQ,QAAQN,CAAAA,CAAa,IAAA,CAAM,IAAA,CAAK,SAAA,CAAU4C,CAAI,CAAC,CAAA,CACvD2B,CAAAA,CAAc3B,EAGZ0B,CAAAA,CAAa,wBAAA,CAAyBnD,CAAAA,CAAaiD,CAAgB,CAAA,CAGrEC,CAAAA,CAAa,IAAA,CAAK,QAASzB,CAAI,EACjC,CAEA,SAAS8B,CAAAA,CAAiB9B,CAAAA,CAAkB,CAC1C2B,CAAAA,CAAc3B,EACdtC,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,IAAA,CAAM,IAAA,CAAK,SAAA,CAAU4C,CAAI,CAAC,EACzD,CAEA,SAAST,CAAAA,EAAkB,CACzB7B,CAAAA,CAAQ,KAAA,EAAM,CACdiE,CAAAA,CAAc,IAAA,CACdD,CAAAA,CAAa,aAAA,GACf,CAEA,SAAStB,CAAAA,EAA8B,CACrC,OAAOuB,CACT,CAGA,IAAMI,CAAAA,CAAa5C,CAAAA,CAAiB,CAClC,IAAA,CAAMmC,CAAAA,CACN,eAAgBO,CAAAA,CAChB,OAAA,CAAAnE,CAAAA,CACA,SAAA,CAAA6B,CACF,CAAC,CAAA,CAEKyC,CAAAA,CAAoB7B,EAAwB,CAEhD,cAAA,CAAAC,CAEF,CAAC,EAEK6B,CAAAA,CAAavB,CAAAA,CAAiB,CAClC,IAAA,CAAMY,CAAAA,CACN,OAAA,CAAA5D,CAAAA,CACA,YAAA,CAAcoE,CAChB,CAAC,CAAA,CAEKI,CAAAA,CAActB,CAAAA,CAAkB,CACpC,IAAA,CAAMU,CAAAA,CACN,OAAA,CAAA5D,CACF,CAAC,CAAA,CAEKyE,CAAAA,CAAiBtB,CAAAA,CAAqB,CAC1C,IAAA,CAAMS,CAAAA,CACN,OAAA,CAAA5D,CACF,CAAC,CAAA,CAoDD,GAjDAkE,CAAAA,CAAa,CACX,GAAGG,CAAAA,CACH,GAAGC,CAAAA,CACH,GAAGC,CAAAA,CACH,GAAGC,CAAAA,CACH,GAAGC,CAAAA,CAGH,EAAA,CAAGpF,EAAkBC,CAAAA,CAA6B,CAChDyE,CAAAA,CAAa,EAAA,CAAG1E,CAAAA,CAAOC,CAAO,EAChC,CAAA,CAEA,IAAID,CAAAA,CAAkBC,CAAAA,CAA6B,CACjDyE,CAAAA,CAAa,GAAA,CAAI1E,CAAAA,CAAOC,CAAO,EACjC,EAGA,eAAA,EAA2B,CAEzB,OAAO,CAAC,CADMU,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAY,CAEzD,CAAA,CAEA,cAAA,EAAgC,CAC9B,OAAOM,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAY,CAClD,CAAA,CAEA,cAAA,CAAeW,CAAAA,CAAqB,CAClCL,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,aAAcW,CAAK,CAAA,CAE9C2D,CAAAA,CAAa,wBAAA,CAAyB3D,CAAAA,CAAOyD,CAAgB,EAEjE,EAEA,SAAA,CAAAjC,CACF,CAAA,CAGAqC,CAAAA,CAAW,EAAA,CAAG,cAAA,CAAgB,IAAM,CAClCR,CAAAA,KACF,CAAC,CAAA,CAGGQ,CAAAA,CAAW,eAAA,EAAgB,EAC7BA,CAAAA,CAAW,OAAM,CAAE,KAAA,CAAOzE,CAAAA,EAAU,CAClC,OAAA,CAAQ,IAAA,CAAK,gDAAA,CAAkDA,CAAK,EACtE,CAAC,CAAA,CAICkE,CAAAA,EAA2B,OAAO,MAAA,CAAW,GAAA,CAAa,CAC5D,IAAMvB,EAAO,MAAA,CAAO,QAAA,CAAS,IAAA,CACzBA,CAAAA,EAAQA,CAAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAEtC8B,EAAW,mBAAA,EAAoB,CAAE,IAAA,CAAMpC,CAAAA,EAAW,CAC5CA,CAAAA,CAAO,KAAA,EACT,OAAA,CAAQ,MAAM,0CAAA,CAA4CA,CAAAA,CAAO,KAAK,EAE1E,CAAC,CAAA,CAAE,KAAA,CAAOrC,CAAAA,EAAU,CAClB,OAAA,CAAQ,KAAA,CAAM,yCAAA,CAA2CA,CAAK,EAChE,CAAC,EAEL,CAEA,OAAOyE,CACT","file":"index.cjs","sourcesContent":["/**\n * Simple event emitter for auth events\n */\n\nimport type { AuthEvent, EventHandler } from \"./types\";\n\ntype EventMap = Record<string, EventHandler[]>;\n\nexport class EventEmitter {\n private events: EventMap = {};\n\n /**\n * Subscribe to an event\n */\n on(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event] = this.events[event].filter((h) => h !== handler);\n }\n\n /**\n * Emit an event with arguments\n */\n emit(event: AuthEvent, ...args: any[]): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event].forEach((handler) => {\n try {\n handler(...args);\n } catch (error) {\n console.error(`[AuthClient] Error in event handler for \"${event}\":`, error);\n }\n });\n }\n\n /**\n * Remove all event listeners\n */\n removeAllListeners(): void {\n this.events = {};\n }\n}\n","/**\n * Storage adapter for token and user data persistence\n * Auto-detects environment and uses appropriate storage:\n * - Browser: localStorage\n * - WeChat Mini Program: wx.setStorageSync/wx.getStorageSync\n * - SSR/Node.js: No-op (no persistence)\n */\n\nexport interface StorageAdapter {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n clear(): void;\n}\n\n/**\n * Storage keys for auth data\n */\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: \"amaster_access_token\",\n REFRESH_TOKEN: \"amaster_refresh_token\",\n USER: \"amaster_user\",\n} as const;\n\n/**\n * Detect current runtime environment\n */\nfunction detectEnvironment(): \"browser\" | \"wechat-miniprogram\" | \"node\" {\n // WeChat Mini Program\n if (typeof wx !== \"undefined\" && wx.getStorageSync) {\n return \"wechat-miniprogram\";\n }\n \n // Browser\n if (typeof window !== \"undefined\" && typeof window.localStorage !== \"undefined\") {\n return \"browser\";\n }\n \n // Node.js/SSR\n return \"node\";\n}\n\n/**\n * Create a storage adapter that auto-detects environment\n * \n * @returns Storage adapter optimized for current environment\n * \n * @example\n * ```typescript\n * const storage = createStorageAdapter();\n * \n * // Browser → uses localStorage\n * // WeChat Mini Program → uses wx.setStorageSync\n * // SSR/Node.js → uses no-op (no persistence)\n * ```\n */\nexport function createStorageAdapter(): StorageAdapter {\n const env = detectEnvironment();\n \n switch (env) {\n case \"wechat-miniprogram\":\n return createWeChatMiniProgramStorage();\n case \"browser\":\n return createBrowserStorage();\n case \"node\":\n return createNoOpStorage();\n }\n}\n\n/**\n * Create browser storage adapter (localStorage)\n */\nfunction createBrowserStorage(): StorageAdapter {\n const storage = window.localStorage;\n\n return {\n getItem(key: string): string | null {\n try {\n return storage.getItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from localStorage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n storage.setItem(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in localStorage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n storage.removeItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from localStorage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n storage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);\n storage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);\n storage.removeItem(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear localStorage:\", error);\n }\n },\n };\n}\n\n/**\n * Create WeChat Mini Program storage adapter\n * Uses wx.setStorageSync and wx.getStorageSync\n */\nfunction createWeChatMiniProgramStorage(): StorageAdapter {\n return {\n getItem(key: string): string | null {\n try {\n const value = wx.getStorageSync(key);\n return value || null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from WeChat storage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n wx.setStorageSync(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in WeChat storage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n wx.removeStorageSync(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from WeChat storage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n wx.removeStorageSync(STORAGE_KEYS.ACCESS_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.REFRESH_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear WeChat storage:\", error);\n }\n },\n };\n}\n\n/**\n * In-memory storage adapter for SSR/Node.js/test environments\n * Data is stored in memory but not persisted across process restarts\n */\nfunction createNoOpStorage(): StorageAdapter {\n const store = new Map<string, string>();\n \n return {\n getItem(key: string): string | null {\n return store.get(key) ?? null;\n },\n setItem(key: string, value: string): void {\n store.set(key, value);\n },\n removeItem(key: string): void {\n store.delete(key);\n },\n clear(): void {\n store.clear();\n },\n };\n}\n","/**\n * Token manager for automatic token refresh\n */\n\n/**\n * JWT token payload interface\n */\ninterface JwtPayload {\n exp: number; // Expiration timestamp (seconds)\n [key: string]: any;\n}\n\n/**\n * Parse JWT token to extract payload\n * Note: This does NOT verify the token signature, only decodes the payload\n */\nexport function parseJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const base64Url = parts[1] || \"\";\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\n // Decode base64 in browser environment\n if (typeof atob !== \"undefined\") {\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split(\"\")\n .map((c) => \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2))\n .join(\"\")\n );\n return JSON.parse(jsonPayload);\n }\n\n // Fallback for Node.js environment\n if (typeof Buffer !== \"undefined\") {\n const jsonPayload = Buffer.from(base64, \"base64\").toString(\"utf-8\");\n return JSON.parse(jsonPayload);\n }\n\n return null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to parse JWT token:\", error);\n return null;\n }\n}\n\n/**\n * Token manager class for handling automatic token refresh\n */\nexport class TokenManager {\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private isRefreshing = false;\n private refreshCallback: (() => Promise<void>) | null = null;\n\n /**\n * Set the refresh callback function\n */\n setRefreshCallback(callback: () => Promise<void>): void {\n this.refreshCallback = callback;\n }\n\n /**\n * Schedule a token refresh after a delay\n * @param delayMs Delay in milliseconds before refreshing\n */\n scheduleRefresh(delayMs: number): void {\n // Clear existing timer\n this.clearSchedule();\n\n // Don't schedule if delay is negative or zero\n if (delayMs <= 0) {\n return;\n }\n\n this.refreshTimer = setTimeout(() => {\n this.refresh();\n }, delayMs);\n }\n\n /**\n * Schedule token refresh based on token expiration and threshold\n * @param accessToken JWT access token\n * @param thresholdSeconds Refresh threshold in seconds (default: 300)\n */\n scheduleRefreshFromToken(accessToken: string, thresholdSeconds: number = 300): void {\n const payload = parseJwt(accessToken);\n if (!payload || !payload.exp) {\n console.warn(\"[AuthClient] Cannot schedule refresh: invalid token or missing exp claim\");\n return;\n }\n\n const expiresAtMs = payload.exp * 1000; // Convert to milliseconds\n const nowMs = Date.now();\n const expiresInMs = expiresAtMs - nowMs;\n\n // Calculate when to refresh (before expiration by thresholdSeconds)\n const refreshDelayMs = expiresInMs - thresholdSeconds * 1000;\n\n if (refreshDelayMs <= 0) {\n // Token already expired or will expire very soon\n console.warn(\"[AuthClient] Token already expired or expiring soon, refreshing immediately\");\n this.refresh();\n } else {\n this.scheduleRefresh(refreshDelayMs);\n }\n }\n\n /**\n * Manually trigger token refresh\n */\n async refresh(): Promise<void> {\n if (this.isRefreshing) {\n return;\n }\n\n if (!this.refreshCallback) {\n console.error(\"[AuthClient] No refresh callback set\");\n return;\n }\n\n this.isRefreshing = true;\n\n try {\n await this.refreshCallback();\n } catch (error) {\n console.error(\"[AuthClient] Token refresh failed:\", error);\n } finally {\n this.isRefreshing = false;\n }\n }\n\n /**\n * Clear the scheduled refresh timer\n */\n clearSchedule(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /**\n * Check if currently refreshing\n */\n isCurrentlyRefreshing(): boolean {\n return this.isRefreshing;\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.clearSchedule();\n this.refreshCallback = null;\n this.isRefreshing = false;\n }\n}\n","/**\n * HTTP Client Configuration Utilities\n * \n * Provides shared HTTP client configuration for Amaster backend integration\n */\n\nimport { type HttpClientOptions } from \"@amaster.ai/http-client\";\n\n/**\n * Transform Amaster backend response format\n * Backend returns: { statusCode: 200, data: {...}, message: \"...\" }\n * We extract the inner 'data' field for cleaner client usage\n * \n * @param responseData - Raw response data from backend\n * @returns Extracted data or original response if not in Amaster format\n * \n * @example\n * ```typescript\n * const response = { statusCode: 200, data: { userId: \"123\" }, message: \"Success\" };\n * const result = transformAmasterResponse(response);\n * // result = { userId: \"123\" }\n * ```\n */\nexport function transformAmasterResponse<T>(responseData: unknown): T {\n if (\n responseData &&\n typeof responseData === \"object\" &&\n (\"statusCode\" in responseData || \"status\" in responseData)\n ) {\n // If response has 'data' field, extract it\n if (\"data\" in responseData) {\n return (responseData as { data: T }).data;\n }\n // Otherwise return the whole response (e.g., for SuccessResponse without data)\n return responseData as T;\n }\n return responseData as T;\n}\n\n/**\n * Default HTTP client options for Amaster backend\n * Includes response transformation and error logging\n */\nexport const defaultHttpClientOptions: HttpClientOptions = {\n transformResponse: transformAmasterResponse,\n // Enable error logging by default (helps with debugging and AI assistance)\n logErrors: true,\n};\n","/**\n * Authentication Module\n *\n * @module auth\n * @category Authentication\n *\n * Handles user authentication including:\n * - Registration\n * - Login (email/username/phone + password)\n * - Verification code login\n * - OAuth social login\n * - Logout and token refresh\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type {\n RegisterParams,\n LoginParams,\n LoginResponse,\n LoginType,\n CodeLoginParams,\n CodeLoginType,\n SendCodeParams,\n SuccessResponse,\n CaptchaResponse,\n OAuthProvider,\n RefreshTokenResponse,\n User,\n MiniProgramPhoneResponse,\n} from \"../types\";\n\n/**\n * Auto-detect login type based on provided parameters\n */\nfunction inferLoginType(params: LoginParams): LoginType | undefined {\n if (params.email) return \"email\";\n if (params.username) return \"username\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\n/**\n * Auto-detect code login type based on provided parameters\n */\nfunction inferCodeLoginType(params: CodeLoginParams): CodeLoginType | undefined {\n if (params.email) return \"email\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\nexport interface AuthModuleDeps {\n http: HttpClient;\n onLoginSuccess: (user: User, accessToken: string) => void;\n storage: { \n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n };\n clearAuth: () => void;\n}\n\nexport function createAuthModule(deps: AuthModuleDeps) {\n const { http, onLoginSuccess, storage, clearAuth } = deps;\n\n return {\n /**\n * Register a new user account\n *\n * @category Authentication\n * @example\n * ```typescript\n * const result = await auth.register({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * displayName: \"John Doe\",\n * });\n * ```\n */\n async register(params: RegisterParams): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/register\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with username/email/phone and password\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from username\n * await auth.login({\n * username: \"john_doe\",\n * password: \"Password@123\",\n * });\n *\n * // Auto-detect loginType from email\n * await auth.login({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * });\n * ```\n */\n async login(params: LoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email, username, or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with verification code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from email\n * await auth.loginWithCode({\n * email: \"user@example.com\",\n * code: \"123456\",\n * });\n *\n * // Auto-detect loginType from phone\n * await auth.loginWithCode({\n * phone: \"13800138000\",\n * code: \"123456\",\n * });\n * ```\n */\n async loginWithCode(params: CodeLoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferCodeLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login-with-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Send verification code to email or phone\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.sendCode({\n * type: \"email\",\n * email: \"user@example.com\",\n * });\n * ```\n */\n async sendCode(params: SendCodeParams): Promise<ClientResult<SuccessResponse>> {\n return http.request<SuccessResponse>({\n url: \"/api/auth/send-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n },\n\n /**\n * Get captcha image\n *\n * @category Authentication\n */\n async getCaptcha(): Promise<ClientResult<CaptchaResponse>> {\n return http.request<CaptchaResponse>({\n url: \"/api/auth/captcha\",\n method: \"get\",\n });\n },\n\n /**\n * Redirect to OAuth provider for authentication\n *\n * @category Authentication\n * @example\n * ```typescript\n * auth.loginWithOAuth(\"google\");\n * ```\n */\n loginWithOAuth(provider: OAuthProvider, redirectUrl?: string): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth login is only available in browser environment\");\n return;\n }\n\n const url = redirectUrl\n ? `/api/auth/oauth/${provider}?redirect_url=${encodeURIComponent(redirectUrl)}`\n : `/api/auth/oauth/${provider}`;\n\n window.location.href = url;\n },\n\n /**\n * Handle OAuth callback\n *\n * @category Authentication\n */\n async handleOAuthCallback(): Promise<ClientResult<LoginResponse>> {\n if (typeof window === \"undefined\") {\n return {\n data: null,\n error: {\n message: \"OAuth callback is only available in browser environment\",\n status: 400,\n },\n status: 400,\n };\n }\n\n try {\n const hash = window.location.hash.substring(1);\n const params = new URLSearchParams(hash);\n const accessToken = params.get(\"access_token\");\n const userJson = params.get(\"user\");\n\n if (!accessToken || !userJson) {\n return {\n data: null,\n error: { message: \"OAuth callback failed: missing token or user data\", status: 400 },\n status: 400,\n };\n }\n\n const user = JSON.parse(decodeURIComponent(userJson)) as User;\n onLoginSuccess(user, accessToken);\n\n // Clear the hash from URL to avoid security issues and re-processing\n // Use replaceState to avoid adding to browser history\n if (window.history && window.history.replaceState) {\n const urlWithoutHash = window.location.pathname + window.location.search;\n window.history.replaceState(null, '', urlWithoutHash);\n } else {\n // Fallback for older browsers\n window.location.hash = '';\n }\n\n return { data: { user, accessToken }, error: null, status: 200 };\n } catch (error) {\n return {\n data: null,\n error: {\n message: `OAuth callback failed: ${error instanceof Error ? error.message : String(error)}`,\n status: 400,\n },\n status: 400,\n };\n }\n },\n\n /**\n * Login with WeChat Mini Program code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // In WeChat Mini Program\n * wx.login({\n * success: async (res) => {\n * if (res.code) {\n * const result = await auth.loginWithMiniProgram(res.code);\n * if (result.data) {\n * console.log(\"Logged in:\", result.data.user);\n * }\n * }\n * }\n * });\n * ```\n */\n async loginWithMiniProgram(code: string): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/miniprogram/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: { code },\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Get WeChat Mini Program user phone number\n * Requires user authorization via getPhoneNumber button\n *\n * @category Authentication\n * @example\n * ```typescript\n * // WXML\n * <button open-type=\"getPhoneNumber\" bindgetphonenumber=\"onGetPhoneNumber\">\n * Get Phone Number\n * </button>\n *\n * // JS\n * async onGetPhoneNumber(e) {\n * const { code } = e.detail;\n * if (code) {\n * const result = await auth.getMiniProgramPhoneNumber(code);\n * if (result.data) {\n * console.log(\"Phone:\", result.data.phone);\n * }\n * }\n * }\n * ```\n */\n async getMiniProgramPhoneNumber(code: string): Promise<ClientResult<MiniProgramPhoneResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<MiniProgramPhoneResponse>({\n url: \"/api/auth/miniprogram/phone\",\n method: \"post\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n data: { code },\n });\n },\n\n /**\n * Logout current user\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.logout();\n * ```\n */\n async logout(): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n\n const result = await http.request<SuccessResponse>({\n url: \"/api/auth/logout\",\n method: \"post\",\n headers: token ? { Authorization: `Bearer ${token}` } : undefined,\n });\n\n clearAuth();\n return result;\n },\n\n /**\n * Refresh access token\n *\n * @category Authentication\n */\n async refreshToken(): Promise<ClientResult<RefreshTokenResponse>> {\n const result = await http.request<RefreshTokenResponse>({\n url: \"/api/auth/refresh\",\n method: \"post\",\n });\n\n // Save new token to storage if refresh succeeded\n if (result.data?.accessToken) {\n storage.setItem(\"amaster_access_token\", result.data.accessToken);\n }\n\n return result;\n },\n };\n}\n\nexport type AuthModule = ReturnType<typeof createAuthModule>;\n","/**\n * Permissions Module\n *\n * @module permissions\n * @category Permissions\n *\n * Handles permission and role checks:\n * - Role-based access control (RBAC)\n * - Permission checks (fast, local)\n * - Data scope queries (async, server-side)\n */\n\nimport type { HttpClient } from \"@amaster.ai/http-client\";\nimport type { User } from \"../types\";\n\nexport interface PermissionsModuleDeps {\n http: HttpClient;\n getCurrentUser: () => User | null;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createPermissionsModule(deps: PermissionsModuleDeps) {\n const { getCurrentUser } = deps;\n\n return {\n /**\n * Check if user has a specific role (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasRole(\"admin\")) {\n * showAdminPanel();\n * }\n * ```\n */\n hasRole(roleCode: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.roles) return false;\n return user.roles.includes(roleCode);\n },\n\n /**\n * Check if user has a specific permission (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasPermission(\"user\", \"delete\")) {\n * showDeleteButton();\n * }\n * ```\n */\n hasPermission(resource: string, action: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.permissions) return false;\n const permissionName = `${resource}:${action}`;\n return user.permissions.includes(permissionName);\n },\n\n /**\n * Check if user has ANY of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAnyPermission([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showUserSection();\n * }\n * ```\n */\n hasAnyPermission(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.some(({ resource, action }) => this.hasPermission(resource, action));\n },\n\n /**\n * Check if user has ALL of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAllPermissions([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showFullEditor();\n * }\n * ```\n */\n hasAllPermissions(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.every(({ resource, action }) => this.hasPermission(resource, action));\n },\n };\n}\n\nexport type PermissionsModule = ReturnType<typeof createPermissionsModule>;\n","/**\n * User Management Module\n *\n * @module user\n * @category User\n *\n * Handles user profile and account management:\n * - Get current user info\n * - Update profile\n * - Change password\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { User, UpdateMeParams, ChangePasswordParams, SuccessResponse } from \"../types\";\n\nexport interface UserModuleDeps {\n http: HttpClient;\n storage: {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n };\n onUserUpdate: (user: User) => void;\n}\n\nexport function createUserModule(deps: UserModuleDeps) {\n const { http, storage, onUserUpdate } = deps;\n\n return {\n /**\n * Get current logged-in user information\n *\n * @category User\n * @example\n * ```typescript\n * const result = await user.getMe();\n * if (result.data) {\n * console.log(\"User:\", result.data.displayName);\n * }\n * ```\n */\n async getMe(): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Update current user's profile\n *\n * @category User\n * @example\n * ```typescript\n * await user.updateMe({\n * displayName: \"New Name\",\n * avatarUrl: \"https://example.com/avatar.jpg\",\n * });\n * ```\n */\n async updateMe(params: UpdateMeParams): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"put\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Change current user's password\n *\n * @category User\n * @example\n * ```typescript\n * await user.changePassword({\n * oldPassword: \"OldPass@123\",\n * newPassword: \"NewPass@456\",\n * });\n * ```\n */\n async changePassword(params: ChangePasswordParams): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: \"/api/auth/change-password\",\n method: \"post\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n },\n };\n}\n\nexport type UserModule = ReturnType<typeof createUserModule>;\n","/**\n * OAuth Module\n *\n * @module oauth\n * @category OAuth\n *\n * Handles OAuth account binding management:\n * - List connected OAuth accounts\n * - Bind new OAuth account\n * - Unbind OAuth account\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { OAuthBinding, OAuthProvider, SuccessResponse } from \"../types\";\n\nexport interface OAuthModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createOAuthModule(deps: OAuthModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get list of OAuth accounts bound to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * const result = await oauth.getOAuthBindings();\n * if (result.data) {\n * result.data.forEach(binding => {\n * console.log(`${binding.provider}: ${binding.email}`);\n * });\n * }\n * ```\n */\n async getOAuthBindings(): Promise<ClientResult<OAuthBinding[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<OAuthBinding[]>({\n url: \"/api/auth/oauth-bindings\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Bind an OAuth account to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * oauth.bindOAuth(\"google\"); // Redirects to Google OAuth\n * ```\n */\n bindOAuth(provider: OAuthProvider): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth binding is only available in browser environment\");\n return;\n }\n\n window.location.href = `/api/auth/oauth/${provider}/bind`;\n },\n\n /**\n * Unbind an OAuth account from current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * await oauth.unbindOAuth(\"google\");\n * ```\n */\n async unbindOAuth(provider: OAuthProvider): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/oauth/${provider}/unbind`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type OAuthModule = ReturnType<typeof createOAuthModule>;\n","/**\n * Sessions Module\n *\n * @module sessions\n * @category Sessions\n *\n * Handles multi-device session management:\n * - View all active sessions\n * - Revoke specific session\n * - Revoke all other sessions\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { Session, SuccessResponse, RevokeAllSessionsResponse } from \"../types\";\n\nexport interface SessionsModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createSessionsModule(deps: SessionsModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get current session information\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSession();\n * if (result.data) {\n * console.log(\"Session ID:\", result.data.id);\n * console.log(\"Device:\", result.data.sessionName);\n * console.log(\"IP address:\", result.data.ipAddress);\n * console.log(\"Location:\", result.data.location);\n * }\n * ```\n */\n async getSession(): Promise<ClientResult<Session>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session>({\n url: \"/api/auth/sessions/current\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Get all active sessions for current user\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSessions();\n * if (result.data) {\n * result.data.forEach(session => {\n * const status = session.isCurrent ? \"Current\" : \"Other\";\n * console.log(`${session.sessionName} - ${session.ipAddress} - ${status}`);\n * });\n * }\n * ```\n */\n async getSessions(): Promise<ClientResult<Session[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session[]>({\n url: \"/api/auth/sessions\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke a specific session\n *\n * @category Sessions\n * @example\n * ```typescript\n * await sessions.revokeSession(\"session-id-123\");\n * ```\n */\n async revokeSession(sessionId: string): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n if (!sessionId) {\n return {\n data: null,\n error: { message: \"Session ID is required\", status: 400 },\n status: 400,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/sessions/${sessionId}`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke all sessions except current one\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.revokeAllSessions();\n * if (result.data) {\n * console.log(`Revoked ${result.data.revokedCount} sessions`);\n * }\n * ```\n */\n async revokeAllSessions(): Promise<ClientResult<RevokeAllSessionsResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<RevokeAllSessionsResponse>({\n url: \"/api/auth/sessions\",\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type SessionsModule = ReturnType<typeof createSessionsModule>;\n","/**\n * Main Authentication Client\n *\n * Combines all modules into a unified client interface\n */\n\nimport { createHttpClient, type HttpClient } from \"@amaster.ai/http-client\";\nimport { EventEmitter } from \"./event-emitter\";\nimport { createStorageAdapter, STORAGE_KEYS, type StorageAdapter } from \"./storage\";\nimport { TokenManager } from \"./token-manager\";\nimport { defaultHttpClientOptions } from \"./http-config\";\nimport { createAuthModule } from \"./modules/auth\";\nimport { createPermissionsModule } from \"./modules/permissions\";\nimport { createUserModule } from \"./modules/user\";\nimport { createOAuthModule } from \"./modules/oauth\";\nimport { createSessionsModule } from \"./modules/sessions\";\nimport type { AuthClientOptions, AuthEvent, EventHandler, User } from \"./types\";\n\nexport type AuthClient = ReturnType<typeof createAuthModule> &\n ReturnType<typeof createPermissionsModule> &\n ReturnType<typeof createUserModule> &\n ReturnType<typeof createOAuthModule> &\n ReturnType<typeof createSessionsModule> & {\n // Events\n on(event: AuthEvent, handler: EventHandler): void;\n off(event: AuthEvent, handler: EventHandler): void;\n\n // Utilities\n isAuthenticated(): boolean;\n getAccessToken(): string | null;\n setAccessToken(token: string): void;\n clearAuth(): void;\n };\n\nexport function createAuthClient(\n options: AuthClientOptions = {},\n http?: HttpClient\n): AuthClient {\n const { baseURL, headers, onTokenExpired, onUnauthorized, autoHandleOAuthCallback = true } = options;\n \n // Create HTTP client with user options if not provided\n const httpClient = http || createHttpClient({\n ...defaultHttpClientOptions,\n baseURL,\n headers,\n });\n\n const autoRefresh = true;\n const refreshThreshold = 300;\n\n // Auto-detect environment and use appropriate storage\n const storage: StorageAdapter = createStorageAdapter();\n const eventEmitter = new EventEmitter();\n const tokenManager = new TokenManager();\n\n let currentUser: User | null = null;\n\n // Load user from storage\n try {\n const userJson = storage.getItem(STORAGE_KEYS.USER);\n if (userJson) {\n currentUser = JSON.parse(userJson);\n }\n } catch (error) {\n console.error(\"[AuthClient] Failed to load user from storage:\", error);\n }\n\n // Forward declare for circular dependency\n let authClient: AuthClient;\n\n // Setup token refresh callback\n tokenManager.setRefreshCallback(async () => {\n const result = await authClient.refreshToken();\n if (result.data) {\n await authClient.getMe();\n eventEmitter.emit(\"tokenRefreshed\", result.data.accessToken);\n } else {\n eventEmitter.emit(\"tokenExpired\");\n onTokenExpired?.();\n }\n });\n\n function handleLoginSuccess(user: User, accessToken: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, accessToken);\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n currentUser = user;\n\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(accessToken, refreshThreshold);\n }\n\n eventEmitter.emit(\"login\", user);\n }\n\n function handleUserUpdate(user: User): void {\n currentUser = user;\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n }\n\n function clearAuth(): void {\n storage.clear();\n currentUser = null;\n tokenManager.clearSchedule();\n }\n\n function getCurrentUser(): User | null {\n return currentUser;\n }\n\n // Create modules\n const authModule = createAuthModule({\n http: httpClient,\n onLoginSuccess: handleLoginSuccess,\n storage,\n clearAuth,\n });\n\n const permissionsModule = createPermissionsModule({\n http: httpClient,\n getCurrentUser,\n storage,\n });\n\n const userModule = createUserModule({\n http: httpClient,\n storage,\n onUserUpdate: handleUserUpdate,\n });\n\n const oauthModule = createOAuthModule({\n http: httpClient,\n storage,\n });\n\n const sessionsModule = createSessionsModule({\n http: httpClient,\n storage,\n });\n\n // Combine all modules\n authClient = {\n ...authModule,\n ...permissionsModule,\n ...userModule,\n ...oauthModule,\n ...sessionsModule,\n\n // Events\n on(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.on(event, handler);\n },\n\n off(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.off(event, handler);\n },\n\n // Utilities\n isAuthenticated(): boolean {\n const token = storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n return !!token;\n },\n\n getAccessToken(): string | null {\n return storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n },\n\n setAccessToken(token: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(token, refreshThreshold);\n }\n },\n\n clearAuth,\n };\n\n // Setup unauthorized handler\n authClient.on(\"unauthorized\", () => {\n onUnauthorized?.();\n });\n\n // Auto sync user info on initialization\n if (authClient.isAuthenticated()) {\n authClient.getMe().catch((error) => {\n console.warn(\"[AuthClient] Failed to sync user info on init:\", error);\n });\n }\n\n // Auto-handle OAuth callback if enabled (default: true)\n if (autoHandleOAuthCallback && typeof window !== \"undefined\") {\n const hash = window.location.hash;\n if (hash && hash.includes(\"access_token\")) {\n // Automatically process OAuth callback\n authClient.handleOAuthCallback().then((result) => {\n if (result.error) {\n console.error(\"[AuthClient] Auto OAuth callback failed:\", result.error);\n }\n }).catch((error) => {\n console.error(\"[AuthClient] Auto OAuth callback error:\", error);\n });\n }\n }\n\n return authClient;\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -19,8 +19,8 @@ import { createPermissionsModule } from './permissions.cjs';
|
|
|
19
19
|
import { createUserModule } from './user.cjs';
|
|
20
20
|
import { createOAuthModule } from './oauth.cjs';
|
|
21
21
|
import { createSessionsModule } from './sessions.cjs';
|
|
22
|
-
import { A as AuthClientOptions, a as AuthEvent, E as EventHandler } from './types-
|
|
23
|
-
export { b as CaptchaResponse, C as ChangePasswordParams, c as CodeLoginParams, d as CodeLoginType, L as LoginParams, e as LoginResponse, f as LoginType, O as OAuthBinding, g as OAuthProvider, P as Permission, h as PermissionDetail, R as RefreshTokenResponse, i as RegisterParams, j as RegisterResponse, k as RevokeAllSessionsResponse, l as Role, m as RoleDetail, S as SendCodeParams, n as SendCodeType, o as Session, p as SuccessResponse, U as UpdateMeParams, q as User } from './types-
|
|
22
|
+
import { A as AuthClientOptions, a as AuthEvent, E as EventHandler } from './types-BhHE_geU.cjs';
|
|
23
|
+
export { b as CaptchaResponse, C as ChangePasswordParams, c as CodeLoginParams, d as CodeLoginType, L as LoginParams, e as LoginResponse, f as LoginType, O as OAuthBinding, g as OAuthProvider, P as Permission, h as PermissionDetail, R as RefreshTokenResponse, i as RegisterParams, j as RegisterResponse, k as RevokeAllSessionsResponse, l as Role, m as RoleDetail, S as SendCodeParams, n as SendCodeType, o as Session, p as SuccessResponse, U as UpdateMeParams, q as User } from './types-BhHE_geU.cjs';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Main Authentication Client
|
package/dist/index.d.ts
CHANGED
|
@@ -19,8 +19,8 @@ import { createPermissionsModule } from './permissions.js';
|
|
|
19
19
|
import { createUserModule } from './user.js';
|
|
20
20
|
import { createOAuthModule } from './oauth.js';
|
|
21
21
|
import { createSessionsModule } from './sessions.js';
|
|
22
|
-
import { A as AuthClientOptions, a as AuthEvent, E as EventHandler } from './types-
|
|
23
|
-
export { b as CaptchaResponse, C as ChangePasswordParams, c as CodeLoginParams, d as CodeLoginType, L as LoginParams, e as LoginResponse, f as LoginType, O as OAuthBinding, g as OAuthProvider, P as Permission, h as PermissionDetail, R as RefreshTokenResponse, i as RegisterParams, j as RegisterResponse, k as RevokeAllSessionsResponse, l as Role, m as RoleDetail, S as SendCodeParams, n as SendCodeType, o as Session, p as SuccessResponse, U as UpdateMeParams, q as User } from './types-
|
|
22
|
+
import { A as AuthClientOptions, a as AuthEvent, E as EventHandler } from './types-BhHE_geU.js';
|
|
23
|
+
export { b as CaptchaResponse, C as ChangePasswordParams, c as CodeLoginParams, d as CodeLoginType, L as LoginParams, e as LoginResponse, f as LoginType, O as OAuthBinding, g as OAuthProvider, P as Permission, h as PermissionDetail, R as RefreshTokenResponse, i as RegisterParams, j as RegisterResponse, k as RevokeAllSessionsResponse, l as Role, m as RoleDetail, S as SendCodeParams, n as SendCodeType, o as Session, p as SuccessResponse, U as UpdateMeParams, q as User } from './types-BhHE_geU.js';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Main Authentication Client
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {createHttpClient}from'@amaster.ai/http-client';var y=class{constructor(){this.events={};}on(e,s){this.events[e]||(this.events[e]=[]),this.events[e].push(s);}off(e,s){this.events[e]&&(this.events[e]=this.events[e].filter(r=>r!==s));}emit(e,...s){this.events[e]&&this.events[e].forEach(r=>{try{r(...s);}catch(a){console.error(`[AuthClient] Error in event handler for "${e}":`,a);}});}removeAllListeners(){this.events={};}};var d={ACCESS_TOKEN:"amaster_access_token",REFRESH_TOKEN:"amaster_refresh_token",USER:"amaster_user"};function H(){return typeof wx<"u"&&wx.getStorageSync?"wechat-miniprogram":typeof window<"u"&&typeof window.localStorage<"u"?"browser":"node"}function S(){switch(H()){case "wechat-miniprogram":return q();case "browser":return N();case "node":return $()}}function N(){let t=window.localStorage;return {getItem(e){try{return t.getItem(e)}catch(s){return console.error("[AuthClient] Failed to get item from localStorage:",s),null}},setItem(e,s){try{t.setItem(e,s);}catch(r){console.error("[AuthClient] Failed to set item in localStorage:",r);}},removeItem(e){try{t.removeItem(e);}catch(s){console.error("[AuthClient] Failed to remove item from localStorage:",s);}},clear(){try{t.removeItem(d.ACCESS_TOKEN),t.removeItem(d.REFRESH_TOKEN),t.removeItem(d.USER);}catch(e){console.error("[AuthClient] Failed to clear localStorage:",e);}}}}function q(){return {getItem(t){try{return wx.getStorageSync(t)||null}catch(e){return console.error("[AuthClient] Failed to get item from WeChat storage:",e),null}},setItem(t,e){try{wx.setStorageSync(t,e);}catch(s){console.error("[AuthClient] Failed to set item in WeChat storage:",s);}},removeItem(t){try{wx.removeStorageSync(t);}catch(e){console.error("[AuthClient] Failed to remove item from WeChat storage:",e);}},clear(){try{wx.removeStorageSync(d.ACCESS_TOKEN),wx.removeStorageSync(d.REFRESH_TOKEN),wx.removeStorageSync(d.USER);}catch(t){console.error("[AuthClient] Failed to clear WeChat storage:",t);}}}}function $(){let t=new Map;return {getItem(e){return t.get(e)??null},setItem(e,s){t.set(e,s);},removeItem(e){t.delete(e);},clear(){t.clear();}}}function B(t){try{let e=t.split(".");if(e.length!==3)return null;let r=(e[1]||"").replace(/-/g,"+").replace(/_/g,"/");if(typeof atob<"u"){let a=decodeURIComponent(atob(r).split("").map(n=>"%"+("00"+n.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(a)}if(typeof Buffer<"u"){let a=Buffer.from(r,"base64").toString("utf-8");return JSON.parse(a)}return null}catch(e){return console.error("[AuthClient] Failed to parse JWT token:",e),null}}var C=class{constructor(){this.refreshTimer=null;this.isRefreshing=false;this.refreshCallback=null;}setRefreshCallback(e){this.refreshCallback=e;}scheduleRefresh(e){this.clearSchedule(),!(e<=0)&&(this.refreshTimer=setTimeout(()=>{this.refresh();},e));}scheduleRefreshFromToken(e,s=300){let r=B(e);if(!r||!r.exp){console.warn("[AuthClient] Cannot schedule refresh: invalid token or missing exp claim");return}let a=r.exp*1e3,n=Date.now(),c=a-n-s*1e3;c<=0?(console.warn("[AuthClient] Token already expired or expiring soon, refreshing immediately"),this.refresh()):this.scheduleRefresh(c);}async refresh(){if(!this.isRefreshing){if(!this.refreshCallback){console.error("[AuthClient] No refresh callback set");return}this.isRefreshing=true;try{await this.refreshCallback();}catch(e){console.error("[AuthClient] Token refresh failed:",e);}finally{this.isRefreshing=false;}}}clearSchedule(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}isCurrentlyRefreshing(){return this.isRefreshing}destroy(){this.clearSchedule(),this.refreshCallback=null,this.isRefreshing=false;}};function v(t){return t&&typeof t=="object"&&("statusCode"in t||"status"in t)&&"data"in t?t.data:t}var R={transformResponse:v,logErrors:true};function F(t){if(t.email)return "email";if(t.username)return "username";if(t.phone)return "phone"}function z(t){if(t.email)return "email";if(t.phone)return "phone"}function k(t){let{http:e,onLoginSuccess:s,storage:r,clearAuth:a}=t;return {async register(n){let o=await e.request({url:"/api/auth/register",method:"post",headers:{"Content-Type":"application/json"},data:n});return o.data?.user&&o.data?.accessToken&&s(o.data.user,o.data.accessToken),o},async login(n){let o=n.loginType||F(n);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email, username, or phone.",status:400},status:400};let c={...n,loginType:o},u=await e.request({url:"/api/auth/login",method:"post",headers:{"Content-Type":"application/json"},data:c});return u.data?.user&&u.data?.accessToken&&s(u.data.user,u.data.accessToken),u},async loginWithCode(n){let o=n.loginType||z(n);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email or phone.",status:400},status:400};let c={...n,loginType:o},u=await e.request({url:"/api/auth/login-with-code",method:"post",headers:{"Content-Type":"application/json"},data:c});return u.data?.user&&u.data?.accessToken&&s(u.data.user,u.data.accessToken),u},async sendCode(n){return e.request({url:"/api/auth/send-code",method:"post",headers:{"Content-Type":"application/json"},data:n})},async getCaptcha(){return e.request({url:"/api/auth/captcha",method:"get"})},loginWithOAuth(n,o){if(typeof window>"u"){console.error("[AuthClient] OAuth login is only available in browser environment");return}let c=o?`/api/auth/oauth/${n}?redirect_url=${encodeURIComponent(o)}`:`/api/auth/oauth/${n}`;window.location.href=c;},async handleOAuthCallback(){if(typeof window>"u")return {data:null,error:{message:"OAuth callback is only available in browser environment",status:400},status:400};try{let n=window.location.hash.substring(1),o=new URLSearchParams(n),c=o.get("access_token"),u=o.get("user");if(!c||!u)return {data:null,error:{message:"OAuth callback failed: missing token or user data",status:400},status:400};let l=JSON.parse(decodeURIComponent(u));return s(l,c),{data:{user:l,accessToken:c},error:null,status:200}}catch(n){return {data:null,error:{message:`OAuth callback failed: ${n instanceof Error?n.message:String(n)}`,status:400},status:400}}},async loginWithMiniProgram(n){let o=await e.request({url:"/api/auth/miniprogram/login",method:"post",headers:{"Content-Type":"application/json"},data:{code:n}});return o.data?.user&&o.data?.accessToken&&s(o.data.user,o.data.accessToken),o},async getMiniProgramPhoneNumber(n){let o=r.getItem("amaster_access_token");return o?e.request({url:"/api/auth/miniprogram/phone",method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},data:{code:n}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async logout(){let n=r.getItem("amaster_access_token"),o=await e.request({url:"/api/auth/logout",method:"post",headers:n?{Authorization:`Bearer ${n}`}:void 0});return a(),o},async refreshToken(){return e.request({url:"/api/auth/refresh",method:"post"})}}}function T(t){let{getCurrentUser:e}=t;return {hasRole(s){let r=e();return !r||!r.roles?false:r.roles.includes(s)},hasPermission(s,r){let a=e();if(!a||!a.permissions)return false;let n=`${s}:${r}`;return a.permissions.includes(n)},hasAnyPermission(s){return s.some(({resource:r,action:a})=>this.hasPermission(r,a))},hasAllPermissions(s){return s.every(({resource:r,action:a})=>this.hasPermission(r,a))}}}function P(t){let{http:e,storage:s,onUserUpdate:r}=t;return {async getMe(){let a=s.getItem("amaster_access_token");if(!a)return {data:null,error:{message:"Not authenticated",status:401},status:401};let n=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${a}`}});return n.data&&r(n.data),n},async updateMe(a){let n=s.getItem("amaster_access_token");if(!n)return {data:null,error:{message:"Not authenticated",status:401},status:401};let o=await e.request({url:"/api/auth/me",method:"put",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},data:a});return o.data&&r(o.data),o},async changePassword(a){let n=s.getItem("amaster_access_token");return n?e.request({url:"/api/auth/change-password",method:"post",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},data:a}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function w(t){let{http:e,storage:s}=t;return {async getOAuthBindings(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/oauth-bindings",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},bindOAuth(r){if(typeof window>"u"){console.error("[AuthClient] OAuth binding is only available in browser environment");return}window.location.href=`/api/auth/oauth/${r}/bind`;},async unbindOAuth(r){let a=s.getItem("amaster_access_token");return a?e.request({url:`/api/auth/oauth/${r}/unbind`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function E(t){let{http:e,storage:s}=t;return {async getSession(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions/current",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async getSessions(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeSession(r){let a=s.getItem("amaster_access_token");return a?r?e.request({url:`/api/auth/sessions/${r}`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Session ID is required",status:400},status:400}:{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeAllSessions(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"delete",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function J(t={},e){let {baseURL:s,headers:r,onTokenExpired:a,onUnauthorized:n}=t,o=e||createHttpClient({...R,baseURL:s,headers:r}),u=300,l=S(),m=new y,f=new C,g=null;try{let i=l.getItem(d.USER);i&&(g=JSON.parse(i));}catch(i){console.error("[AuthClient] Failed to load user from storage:",i);}let p;f.setRefreshCallback(async()=>{let i=await p.refreshToken();i.data?(await p.getMe(),m.emit("tokenRefreshed",i.data.accessToken)):(m.emit("tokenExpired"),a?.());});function M(i,h){l.setItem(d.ACCESS_TOKEN,h),l.setItem(d.USER,JSON.stringify(i)),g=i,f.scheduleRefreshFromToken(h,u),m.emit("login",i);}function O(i){g=i,l.setItem(d.USER,JSON.stringify(i));}function A(){l.clear(),g=null,f.clearSchedule();}function U(){return g}let b=k({http:o,onLoginSuccess:M,storage:l,clearAuth:A}),x=T({getCurrentUser:U}),I=P({http:o,storage:l,onUserUpdate:O}),_=w({http:o,storage:l}),L=E({http:o,storage:l});return p={...b,...x,...I,..._,...L,on(i,h){m.on(i,h);},off(i,h){m.off(i,h);},isAuthenticated(){return !!l.getItem(d.ACCESS_TOKEN)},getAccessToken(){return l.getItem(d.ACCESS_TOKEN)},setAccessToken(i){l.setItem(d.ACCESS_TOKEN,i),f.scheduleRefreshFromToken(i,u);},clearAuth:A},p.on("unauthorized",()=>{n?.();}),p.isAuthenticated()&&p.getMe().catch(i=>{console.warn("[AuthClient] Failed to sync user info on init:",i);}),p}export{J as createAuthClient,R as defaultHttpClientOptions,v as transformAmasterResponse};//# sourceMappingURL=index.js.map
|
|
1
|
+
import {createHttpClient}from'@amaster.ai/http-client';var C=class{constructor(){this.events={};}on(e,n){this.events[e]||(this.events[e]=[]),this.events[e].push(n);}off(e,n){this.events[e]&&(this.events[e]=this.events[e].filter(r=>r!==n));}emit(e,...n){this.events[e]&&this.events[e].forEach(r=>{try{r(...n);}catch(a){console.error(`[AuthClient] Error in event handler for "${e}":`,a);}});}removeAllListeners(){this.events={};}};var d={ACCESS_TOKEN:"amaster_access_token",REFRESH_TOKEN:"amaster_refresh_token",USER:"amaster_user"};function N(){return typeof wx<"u"&&wx.getStorageSync?"wechat-miniprogram":typeof window<"u"&&typeof window.localStorage<"u"?"browser":"node"}function v(){switch(N()){case "wechat-miniprogram":return $();case "browser":return q();case "node":return B()}}function q(){let t=window.localStorage;return {getItem(e){try{return t.getItem(e)}catch(n){return console.error("[AuthClient] Failed to get item from localStorage:",n),null}},setItem(e,n){try{t.setItem(e,n);}catch(r){console.error("[AuthClient] Failed to set item in localStorage:",r);}},removeItem(e){try{t.removeItem(e);}catch(n){console.error("[AuthClient] Failed to remove item from localStorage:",n);}},clear(){try{t.removeItem(d.ACCESS_TOKEN),t.removeItem(d.REFRESH_TOKEN),t.removeItem(d.USER);}catch(e){console.error("[AuthClient] Failed to clear localStorage:",e);}}}}function $(){return {getItem(t){try{return wx.getStorageSync(t)||null}catch(e){return console.error("[AuthClient] Failed to get item from WeChat storage:",e),null}},setItem(t,e){try{wx.setStorageSync(t,e);}catch(n){console.error("[AuthClient] Failed to set item in WeChat storage:",n);}},removeItem(t){try{wx.removeStorageSync(t);}catch(e){console.error("[AuthClient] Failed to remove item from WeChat storage:",e);}},clear(){try{wx.removeStorageSync(d.ACCESS_TOKEN),wx.removeStorageSync(d.REFRESH_TOKEN),wx.removeStorageSync(d.USER);}catch(t){console.error("[AuthClient] Failed to clear WeChat storage:",t);}}}}function B(){let t=new Map;return {getItem(e){return t.get(e)??null},setItem(e,n){t.set(e,n);},removeItem(e){t.delete(e);},clear(){t.clear();}}}function F(t){try{let e=t.split(".");if(e.length!==3)return null;let r=(e[1]||"").replace(/-/g,"+").replace(/_/g,"/");if(typeof atob<"u"){let a=decodeURIComponent(atob(r).split("").map(s=>"%"+("00"+s.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(a)}if(typeof Buffer<"u"){let a=Buffer.from(r,"base64").toString("utf-8");return JSON.parse(a)}return null}catch(e){return console.error("[AuthClient] Failed to parse JWT token:",e),null}}var A=class{constructor(){this.refreshTimer=null;this.isRefreshing=false;this.refreshCallback=null;}setRefreshCallback(e){this.refreshCallback=e;}scheduleRefresh(e){this.clearSchedule(),!(e<=0)&&(this.refreshTimer=setTimeout(()=>{this.refresh();},e));}scheduleRefreshFromToken(e,n=300){let r=F(e);if(!r||!r.exp){console.warn("[AuthClient] Cannot schedule refresh: invalid token or missing exp claim");return}let a=r.exp*1e3,s=Date.now(),u=a-s-n*1e3;u<=0?(console.warn("[AuthClient] Token already expired or expiring soon, refreshing immediately"),this.refresh()):this.scheduleRefresh(u);}async refresh(){if(!this.isRefreshing){if(!this.refreshCallback){console.error("[AuthClient] No refresh callback set");return}this.isRefreshing=true;try{await this.refreshCallback();}catch(e){console.error("[AuthClient] Token refresh failed:",e);}finally{this.isRefreshing=false;}}}clearSchedule(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}isCurrentlyRefreshing(){return this.isRefreshing}destroy(){this.clearSchedule(),this.refreshCallback=null,this.isRefreshing=false;}};function k(t){return t&&typeof t=="object"&&("statusCode"in t||"status"in t)&&"data"in t?t.data:t}var R={transformResponse:k,logErrors:true};function z(t){if(t.email)return "email";if(t.username)return "username";if(t.phone)return "phone"}function j(t){if(t.email)return "email";if(t.phone)return "phone"}function T(t){let{http:e,onLoginSuccess:n,storage:r,clearAuth:a}=t;return {async register(s){let o=await e.request({url:"/api/auth/register",method:"post",headers:{"Content-Type":"application/json"},data:s});return o.data?.user&&o.data?.accessToken&&n(o.data.user,o.data.accessToken),o},async login(s){let o=s.loginType||z(s);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email, username, or phone.",status:400},status:400};let u={...s,loginType:o},l=await e.request({url:"/api/auth/login",method:"post",headers:{"Content-Type":"application/json"},data:u});return l.data?.user&&l.data?.accessToken&&n(l.data.user,l.data.accessToken),l},async loginWithCode(s){let o=s.loginType||j(s);if(!o)return {data:null,error:{message:"Unable to determine login type. Please provide email or phone.",status:400},status:400};let u={...s,loginType:o},l=await e.request({url:"/api/auth/login-with-code",method:"post",headers:{"Content-Type":"application/json"},data:u});return l.data?.user&&l.data?.accessToken&&n(l.data.user,l.data.accessToken),l},async sendCode(s){return e.request({url:"/api/auth/send-code",method:"post",headers:{"Content-Type":"application/json"},data:s})},async getCaptcha(){return e.request({url:"/api/auth/captcha",method:"get"})},loginWithOAuth(s,o){if(typeof window>"u"){console.error("[AuthClient] OAuth login is only available in browser environment");return}let u=o?`/api/auth/oauth/${s}?redirect_url=${encodeURIComponent(o)}`:`/api/auth/oauth/${s}`;window.location.href=u;},async handleOAuthCallback(){if(typeof window>"u")return {data:null,error:{message:"OAuth callback is only available in browser environment",status:400},status:400};try{let s=window.location.hash.substring(1),o=new URLSearchParams(s),u=o.get("access_token"),l=o.get("user");if(!u||!l)return {data:null,error:{message:"OAuth callback failed: missing token or user data",status:400},status:400};let m=JSON.parse(decodeURIComponent(l));if(n(m,u),window.history&&window.history.replaceState){let c=window.location.pathname+window.location.search;window.history.replaceState(null,"",c);}else window.location.hash="";return {data:{user:m,accessToken:u},error:null,status:200}}catch(s){return {data:null,error:{message:`OAuth callback failed: ${s instanceof Error?s.message:String(s)}`,status:400},status:400}}},async loginWithMiniProgram(s){let o=await e.request({url:"/api/auth/miniprogram/login",method:"post",headers:{"Content-Type":"application/json"},data:{code:s}});return o.data?.user&&o.data?.accessToken&&n(o.data.user,o.data.accessToken),o},async getMiniProgramPhoneNumber(s){let o=r.getItem("amaster_access_token");return o?e.request({url:"/api/auth/miniprogram/phone",method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},data:{code:s}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async logout(){let s=r.getItem("amaster_access_token"),o=await e.request({url:"/api/auth/logout",method:"post",headers:s?{Authorization:`Bearer ${s}`}:void 0});return a(),o},async refreshToken(){let s=await e.request({url:"/api/auth/refresh",method:"post"});return s.data?.accessToken&&r.setItem("amaster_access_token",s.data.accessToken),s}}}function w(t){let{getCurrentUser:e}=t;return {hasRole(n){let r=e();return !r||!r.roles?false:r.roles.includes(n)},hasPermission(n,r){let a=e();if(!a||!a.permissions)return false;let s=`${n}:${r}`;return a.permissions.includes(s)},hasAnyPermission(n){return n.some(({resource:r,action:a})=>this.hasPermission(r,a))},hasAllPermissions(n){return n.every(({resource:r,action:a})=>this.hasPermission(r,a))}}}function P(t){let{http:e,storage:n,onUserUpdate:r}=t;return {async getMe(){let a=n.getItem("amaster_access_token");if(!a)return {data:null,error:{message:"Not authenticated",status:401},status:401};let s=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${a}`}});return s.data&&r(s.data),s},async updateMe(a){let s=n.getItem("amaster_access_token");if(!s)return {data:null,error:{message:"Not authenticated",status:401},status:401};let o=await e.request({url:"/api/auth/me",method:"put",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},data:a});return o.data&&r(o.data),o},async changePassword(a){let s=n.getItem("amaster_access_token");return s?e.request({url:"/api/auth/change-password",method:"post",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},data:a}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function E(t){let{http:e,storage:n}=t;return {async getOAuthBindings(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/oauth-bindings",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},bindOAuth(r){if(typeof window>"u"){console.error("[AuthClient] OAuth binding is only available in browser environment");return}window.location.href=`/api/auth/oauth/${r}/bind`;},async unbindOAuth(r){let a=n.getItem("amaster_access_token");return a?e.request({url:`/api/auth/oauth/${r}/unbind`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function M(t){let{http:e,storage:n}=t;return {async getSession(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions/current",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async getSessions(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeSession(r){let a=n.getItem("amaster_access_token");return a?r?e.request({url:`/api/auth/sessions/${r}`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Session ID is required",status:400},status:400}:{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeAllSessions(){let r=n.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"delete",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function K(t={},e){let {baseURL:n,headers:r,onTokenExpired:a,onUnauthorized:s,autoHandleOAuthCallback:o=true}=t,u=e||createHttpClient({...R,baseURL:n,headers:r}),m=300,c=v(),g=new C,y=new A,f=null;try{let i=c.getItem(d.USER);i&&(f=JSON.parse(i));}catch(i){console.error("[AuthClient] Failed to load user from storage:",i);}let p;y.setRefreshCallback(async()=>{let i=await p.refreshToken();i.data?(await p.getMe(),g.emit("tokenRefreshed",i.data.accessToken)):(g.emit("tokenExpired"),a?.());});function O(i,h){c.setItem(d.ACCESS_TOKEN,h),c.setItem(d.USER,JSON.stringify(i)),f=i,y.scheduleRefreshFromToken(h,m),g.emit("login",i);}function U(i){f=i,c.setItem(d.USER,JSON.stringify(i));}function S(){c.clear(),f=null,y.clearSchedule();}function b(){return f}let I=T({http:u,onLoginSuccess:O,storage:c,clearAuth:S}),x=w({getCurrentUser:b}),_=P({http:u,storage:c,onUserUpdate:U}),L=E({http:u,storage:c}),H=M({http:u,storage:c});if(p={...I,...x,..._,...L,...H,on(i,h){g.on(i,h);},off(i,h){g.off(i,h);},isAuthenticated(){return !!c.getItem(d.ACCESS_TOKEN)},getAccessToken(){return c.getItem(d.ACCESS_TOKEN)},setAccessToken(i){c.setItem(d.ACCESS_TOKEN,i),y.scheduleRefreshFromToken(i,m);},clearAuth:S},p.on("unauthorized",()=>{s?.();}),p.isAuthenticated()&&p.getMe().catch(i=>{console.warn("[AuthClient] Failed to sync user info on init:",i);}),o&&typeof window<"u"){let i=window.location.hash;i&&i.includes("access_token")&&p.handleOAuthCallback().then(h=>{h.error&&console.error("[AuthClient] Auto OAuth callback failed:",h.error);}).catch(h=>{console.error("[AuthClient] Auto OAuth callback error:",h);});}return p}export{K as createAuthClient,R as defaultHttpClientOptions,k as transformAmasterResponse};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event-emitter.ts","../src/storage.ts","../src/token-manager.ts","../src/http-config.ts","../src/modules/auth.ts","../src/modules/permissions.ts","../src/modules/user.ts","../src/modules/oauth.ts","../src/modules/sessions.ts","../src/client.ts"],"names":["EventEmitter","event","handler","h","args","error","STORAGE_KEYS","detectEnvironment","createStorageAdapter","createWeChatMiniProgramStorage","createBrowserStorage","createNoOpStorage","storage","key","value","store","parseJwt","token","parts","base64","jsonPayload","c","TokenManager","callback","delayMs","accessToken","thresholdSeconds","payload","expiresAtMs","nowMs","refreshDelayMs","transformAmasterResponse","responseData","defaultHttpClientOptions","inferLoginType","params","inferCodeLoginType","createAuthModule","deps","http","onLoginSuccess","clearAuth","result","loginType","requestData","provider","redirectUrl","url","hash","userJson","user","code","createPermissionsModule","getCurrentUser","roleCode","resource","action","permissionName","permissions","createUserModule","onUserUpdate","createOAuthModule","createSessionsModule","sessionId","createAuthClient","options","baseURL","headers","onTokenExpired","onUnauthorized","httpClient","createHttpClient","refreshThreshold","eventEmitter","tokenManager","currentUser","authClient","handleLoginSuccess","handleUserUpdate","authModule","permissionsModule","userModule","oauthModule","sessionsModule"],"mappings":"uDAQO,IAAMA,CAAAA,CAAN,KAAmB,CAAnB,WAAA,EAAA,CACL,IAAA,CAAQ,MAAA,CAAmB,GAAC,CAK5B,GAAGC,CAAAA,CAAkBC,CAAAA,CAA6B,CAC3C,IAAA,CAAK,MAAA,CAAOD,CAAK,CAAA,GACpB,IAAA,CAAK,MAAA,CAAOA,CAAK,CAAA,CAAI,EAAC,CAAA,CAExB,IAAA,CAAK,MAAA,CAAOA,CAAK,EAAE,IAAA,CAAKC,CAAO,EACjC,CAKA,GAAA,CAAID,CAAAA,CAAkBC,CAAAA,CAA6B,CAC5C,IAAA,CAAK,MAAA,CAAOD,CAAK,CAAA,GAGtB,IAAA,CAAK,MAAA,CAAOA,CAAK,CAAA,CAAI,KAAK,MAAA,CAAOA,CAAK,CAAA,CAAE,MAAA,CAAQE,CAAAA,EAAMA,CAAAA,GAAMD,CAAO,CAAA,EACrE,CAKA,IAAA,CAAKD,CAAAA,CAAAA,GAAqBG,CAAAA,CAAmB,CACtC,IAAA,CAAK,MAAA,CAAOH,CAAK,GAGtB,IAAA,CAAK,MAAA,CAAOA,CAAK,CAAA,CAAE,OAAA,CAASC,CAAAA,EAAY,CACtC,GAAI,CACFA,CAAAA,CAAQ,GAAGE,CAAI,EACjB,CAAA,MAASC,CAAAA,CAAO,CACd,QAAQ,KAAA,CAAM,CAAA,yCAAA,EAA4CJ,CAAK,CAAA,EAAA,CAAA,CAAMI,CAAK,EAC5E,CACF,CAAC,EACH,CAKA,kBAAA,EAA2B,CACzB,IAAA,CAAK,MAAA,CAAS,GAChB,CACF,CAAA,CCnCO,IAAMC,CAAAA,CAAe,CAC1B,YAAA,CAAc,sBAAA,CACd,aAAA,CAAe,uBAAA,CACf,IAAA,CAAM,cACR,CAAA,CAKA,SAASC,CAAAA,EAA+D,CAEtE,OAAI,OAAO,GAAO,GAAA,EAAe,EAAA,CAAG,cAAA,CAC3B,oBAAA,CAIL,OAAO,MAAA,CAAW,GAAA,EAAe,OAAO,MAAA,CAAO,YAAA,CAAiB,GAAA,CAC3D,SAAA,CAIF,MACT,CAgBO,SAASC,CAAAA,EAAuC,CAGrD,OAFYD,CAAAA,EAAkB,EAG5B,KAAK,oBAAA,CACH,OAAOE,CAAAA,EAA+B,CACxC,KAAK,SAAA,CACH,OAAOC,CAAAA,EAAqB,CAC9B,KAAK,MAAA,CACH,OAAOC,CAAAA,EACX,CACF,CAKA,SAASD,CAAAA,EAAuC,CAC9C,IAAME,CAAAA,CAAU,MAAA,CAAO,YAAA,CAEvB,OAAO,CACL,OAAA,CAAQC,CAAAA,CAA4B,CAClC,GAAI,CACF,OAAOD,CAAAA,CAAQ,OAAA,CAAQC,CAAG,CAC5B,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,OAAA,CAAQ,KAAA,CAAM,oDAAA,CAAsDA,CAAK,CAAA,CAClE,IACT,CACF,EAEA,OAAA,CAAQQ,CAAAA,CAAaC,CAAAA,CAAqB,CACxC,GAAI,CACFF,CAAAA,CAAQ,OAAA,CAAQC,CAAAA,CAAKC,CAAK,EAC5B,CAAA,MAAST,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,mDAAoDA,CAAK,EACzE,CACF,CAAA,CAEA,UAAA,CAAWQ,CAAAA,CAAmB,CAC5B,GAAI,CACFD,CAAAA,CAAQ,UAAA,CAAWC,CAAG,EACxB,CAAA,MAASR,CAAAA,CAAO,CACd,QAAQ,KAAA,CAAM,uDAAA,CAAyDA,CAAK,EAC9E,CACF,CAAA,CAEA,KAAA,EAAc,CACZ,GAAI,CAEFO,CAAAA,CAAQ,UAAA,CAAWN,CAAAA,CAAa,YAAY,CAAA,CAC5CM,CAAAA,CAAQ,WAAWN,CAAAA,CAAa,aAAa,CAAA,CAC7CM,CAAAA,CAAQ,UAAA,CAAWN,CAAAA,CAAa,IAAI,EACtC,CAAA,MAASD,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,4CAAA,CAA8CA,CAAK,EACnE,CACF,CACF,CACF,CAMA,SAASI,CAAAA,EAAiD,CACxD,OAAO,CACL,QAAQI,CAAAA,CAA4B,CAClC,GAAI,CAEF,OADc,EAAA,CAAG,cAAA,CAAeA,CAAG,GACnB,IAClB,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,OAAA,CAAQ,KAAA,CAAM,sDAAA,CAAwDA,CAAK,CAAA,CACpE,IACT,CACF,CAAA,CAEA,OAAA,CAAQQ,CAAAA,CAAaC,CAAAA,CAAqB,CACxC,GAAI,CACF,EAAA,CAAG,cAAA,CAAeD,CAAAA,CAAKC,CAAK,EAC9B,CAAA,MAAST,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,oDAAA,CAAsDA,CAAK,EAC3E,CACF,CAAA,CAEA,WAAWQ,CAAAA,CAAmB,CAC5B,GAAI,CACF,EAAA,CAAG,iBAAA,CAAkBA,CAAG,EAC1B,CAAA,MAASR,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,yDAAA,CAA2DA,CAAK,EAChF,CACF,CAAA,CAEA,KAAA,EAAc,CACZ,GAAI,CAEF,EAAA,CAAG,iBAAA,CAAkBC,CAAAA,CAAa,YAAY,CAAA,CAC9C,EAAA,CAAG,iBAAA,CAAkBA,CAAAA,CAAa,aAAa,CAAA,CAC/C,EAAA,CAAG,kBAAkBA,CAAAA,CAAa,IAAI,EACxC,CAAA,MAASD,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,8CAAA,CAAgDA,CAAK,EACrE,CACF,CACF,CACF,CAMA,SAASM,GAAoC,CAC3C,IAAMI,CAAAA,CAAQ,IAAI,GAAA,CAElB,OAAO,CACL,OAAA,CAAQF,CAAAA,CAA4B,CAClC,OAAOE,CAAAA,CAAM,GAAA,CAAIF,CAAG,CAAA,EAAK,IAC3B,EACA,OAAA,CAAQA,CAAAA,CAAaC,CAAAA,CAAqB,CACxCC,CAAAA,CAAM,GAAA,CAAIF,CAAAA,CAAKC,CAAK,EACtB,CAAA,CACA,UAAA,CAAWD,CAAAA,CAAmB,CAC5BE,CAAAA,CAAM,MAAA,CAAOF,CAAG,EAClB,CAAA,CACA,KAAA,EAAc,CACZE,CAAAA,CAAM,KAAA,GACR,CACF,CACF,CCpKO,SAASC,CAAAA,CAASC,CAAAA,CAAkC,CACzD,GAAI,CACF,IAAMC,EAAQD,CAAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAC7B,GAAIC,CAAAA,CAAM,MAAA,GAAW,CAAA,CACnB,OAAO,IAAA,CAIT,IAAMC,CAAAA,CAAAA,CADYD,CAAAA,CAAM,CAAC,CAAA,EAAK,EAAA,EACL,QAAQ,IAAA,CAAM,GAAG,CAAA,CAAE,OAAA,CAAQ,IAAA,CAAM,GAAG,CAAA,CAG7D,GAAI,OAAO,IAAA,CAAS,GAAA,CAAa,CAC/B,IAAME,CAAAA,CAAc,kBAAA,CAClB,IAAA,CAAKD,CAAM,CAAA,CACR,KAAA,CAAM,EAAE,CAAA,CACR,GAAA,CAAKE,CAAAA,EAAM,GAAA,CAAA,CAAO,IAAA,CAAOA,CAAAA,CAAE,UAAA,CAAW,CAAC,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,EAAG,KAAA,CAAM,EAAE,CAAC,CAAA,CAChE,IAAA,CAAK,EAAE,CACZ,CAAA,CACA,OAAO,IAAA,CAAK,KAAA,CAAMD,CAAW,CAC/B,CAGA,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjC,IAAMA,CAAAA,CAAc,MAAA,CAAO,IAAA,CAAKD,CAAAA,CAAQ,QAAQ,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,CAClE,OAAO,IAAA,CAAK,KAAA,CAAMC,CAAW,CAC/B,CAEA,OAAO,IACT,CAAA,MAASf,CAAAA,CAAO,CACd,OAAA,OAAA,CAAQ,KAAA,CAAM,yCAAA,CAA2CA,CAAK,CAAA,CACvD,IACT,CACF,CAKO,IAAMiB,CAAAA,CAAN,KAAmB,CAAnB,cACL,IAAA,CAAQ,YAAA,CAAqD,IAAA,CAC7D,IAAA,CAAQ,YAAA,CAAe,KAAA,CACvB,IAAA,CAAQ,eAAA,CAAgD,KAAA,CAKxD,kBAAA,CAAmBC,CAAAA,CAAqC,CACtD,IAAA,CAAK,eAAA,CAAkBA,EACzB,CAMA,gBAAgBC,CAAAA,CAAuB,CAErC,IAAA,CAAK,aAAA,EAAc,CAGf,EAAAA,CAAAA,EAAW,CAAA,CAAA,GAIf,KAAK,YAAA,CAAe,UAAA,CAAW,IAAM,CACnC,IAAA,CAAK,OAAA,GACP,CAAA,CAAGA,CAAO,CAAA,EACZ,CAOA,wBAAA,CAAyBC,CAAAA,CAAqBC,CAAAA,CAA2B,GAAA,CAAW,CAClF,IAAMC,CAAAA,CAAUX,CAAAA,CAASS,CAAW,CAAA,CACpC,GAAI,CAACE,CAAAA,EAAW,CAACA,EAAQ,GAAA,CAAK,CAC5B,OAAA,CAAQ,IAAA,CAAK,0EAA0E,CAAA,CACvF,MACF,CAEA,IAAMC,CAAAA,CAAcD,CAAAA,CAAQ,GAAA,CAAM,GAAA,CAC5BE,CAAAA,CAAQ,IAAA,CAAK,GAAA,GAIbC,CAAAA,CAHcF,CAAAA,CAAcC,CAAAA,CAGGH,CAAAA,CAAmB,GAAA,CAEpDI,CAAAA,EAAkB,CAAA,EAEpB,OAAA,CAAQ,IAAA,CAAK,6EAA6E,CAAA,CAC1F,IAAA,CAAK,OAAA,EAAQ,EAEb,IAAA,CAAK,eAAA,CAAgBA,CAAc,EAEvC,CAKA,MAAM,OAAA,EAAyB,CAC7B,GAAI,CAAA,IAAA,CAAK,YAAA,CAIT,CAAA,GAAI,CAAC,IAAA,CAAK,eAAA,CAAiB,CACzB,OAAA,CAAQ,KAAA,CAAM,sCAAsC,EACpD,MACF,CAEA,IAAA,CAAK,YAAA,CAAe,IAAA,CAEpB,GAAI,CACF,MAAM,IAAA,CAAK,eAAA,GACb,CAAA,MAASzB,CAAAA,CAAO,CACd,OAAA,CAAQ,KAAA,CAAM,qCAAsCA,CAAK,EAC3D,CAAA,OAAE,CACA,IAAA,CAAK,YAAA,CAAe,MACtB,CAAA,CACF,CAKA,aAAA,EAAsB,CAChB,IAAA,CAAK,YAAA,GACP,YAAA,CAAa,IAAA,CAAK,YAAY,EAC9B,IAAA,CAAK,YAAA,CAAe,IAAA,EAExB,CAKA,qBAAA,EAAiC,CAC/B,OAAO,IAAA,CAAK,YACd,CAKA,OAAA,EAAgB,CACd,IAAA,CAAK,aAAA,EAAc,CACnB,IAAA,CAAK,gBAAkB,IAAA,CACvB,IAAA,CAAK,YAAA,CAAe,MACtB,CACF,CAAA,CCzIO,SAAS0B,CAAAA,CAA4BC,CAAAA,CAA0B,CACpE,OACEA,CAAAA,EACA,OAAOA,CAAAA,EAAiB,QAAA,GACvB,YAAA,GAAgBA,GAAgB,QAAA,GAAYA,CAAAA,CAAAA,EAGzC,MAAA,GAAUA,CAAAA,CACJA,CAAAA,CAA6B,IAAA,CAKlCA,CACT,CAMO,IAAMC,CAAAA,CAA8C,CACzD,iBAAA,CAAmBF,CAAAA,CAEnB,SAAA,CAAW,IACb,ECbA,SAASG,CAAAA,CAAeC,CAAAA,CAA4C,CAClE,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAAA,CACzB,GAAIA,CAAAA,CAAO,QAAA,CAAU,OAAO,UAAA,CAC5B,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAE3B,CAKA,SAASC,CAAAA,CAAmBD,CAAAA,CAAoD,CAC9E,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAAA,CACzB,GAAIA,CAAAA,CAAO,KAAA,CAAO,OAAO,OAE3B,CASO,SAASE,CAAAA,CAAiBC,CAAAA,CAAsB,CACrD,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,cAAA,CAAAC,CAAAA,CAAgB,OAAA,CAAA5B,CAAAA,CAAS,SAAA,CAAA6B,CAAU,CAAA,CAAIH,CAAAA,CAErD,OAAO,CAcL,MAAM,QAAA,CAASH,CAAAA,CAA8D,CAC3E,IAAMO,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,GAAA,CAAK,oBAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAMJ,CACR,CAAC,CAAA,CAED,OAAIO,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,IAAA,EAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,KAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CAqBA,MAAM,KAAA,CAAMP,CAAAA,CAA2D,CAErE,IAAMQ,CAAAA,CAAYR,CAAAA,CAAO,SAAA,EAAaD,CAAAA,CAAeC,CAAM,CAAA,CAE3D,GAAI,CAACQ,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,MAAO,CACL,OAAA,CAAS,2EAAA,CACT,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,EAIF,IAAMC,CAAAA,CAAc,CAClB,GAAGT,CAAAA,CACH,SAAA,CAAAQ,CACF,CAAA,CAEMD,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,GAAA,CAAK,iBAAA,CACL,MAAA,CAAQ,OACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAMK,CACR,CAAC,CAAA,CAED,OAAIF,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,IAAA,EAAM,WAAA,EACpCF,EAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CAqBA,MAAM,aAAA,CAAcP,CAAAA,CAA+D,CAEjF,IAAMQ,CAAAA,CAAYR,CAAAA,CAAO,WAAaC,CAAAA,CAAmBD,CAAM,CAAA,CAE/D,GAAI,CAACQ,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,gEAAA,CACT,MAAA,CAAQ,GACV,EACA,MAAA,CAAQ,GACV,CAAA,CAIF,IAAMC,CAAAA,CAAc,CAClB,GAAGT,CAAAA,CACH,SAAA,CAAAQ,CACF,CAAA,CAEMD,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,IAAK,2BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAMK,CACR,CAAC,CAAA,CAED,OAAIF,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,EAAO,IAAA,EAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CAcA,MAAM,QAAA,CAASP,CAAAA,CAAgE,CAC7E,OAAOI,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,qBAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAMJ,CACR,CAAC,CACH,EAOA,MAAM,UAAA,EAAqD,CACzD,OAAOI,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,mBAAA,CACL,MAAA,CAAQ,KACV,CAAC,CACH,CAAA,CAWA,cAAA,CAAeM,CAAAA,CAAyBC,EAA4B,CAClE,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjC,OAAA,CAAQ,KAAA,CAAM,mEAAmE,CAAA,CACjF,MACF,CAEA,IAAMC,CAAAA,CAAMD,CAAAA,CACR,CAAA,gBAAA,EAAmBD,CAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmBC,CAAW,CAAC,CAAA,CAAA,CAC3E,CAAA,gBAAA,EAAmBD,CAAQ,CAAA,CAAA,CAE/B,MAAA,CAAO,QAAA,CAAS,IAAA,CAAOE,EACzB,CAAA,CAOA,MAAM,mBAAA,EAA4D,CAChE,GAAI,OAAO,MAAA,CAAW,GAAA,CACpB,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,yDAAA,CACT,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,EAGF,GAAI,CACF,IAAMC,CAAAA,CAAO,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CACvCb,CAAAA,CAAS,IAAI,eAAA,CAAgBa,CAAI,CAAA,CACjCvB,CAAAA,CAAcU,EAAO,GAAA,CAAI,cAAc,CAAA,CACvCc,CAAAA,CAAWd,CAAAA,CAAO,GAAA,CAAI,MAAM,CAAA,CAElC,GAAI,CAACV,CAAAA,EAAe,CAACwB,CAAAA,CACnB,OAAO,CACL,IAAA,CAAM,KACN,KAAA,CAAO,CAAE,OAAA,CAAS,mDAAA,CAAqD,MAAA,CAAQ,GAAI,CAAA,CACnF,MAAA,CAAQ,GACV,CAAA,CAGF,IAAMC,CAAAA,CAAO,IAAA,CAAK,KAAA,CAAM,kBAAA,CAAmBD,CAAQ,CAAC,CAAA,CACpD,OAAAT,CAAAA,CAAeU,CAAAA,CAAMzB,CAAW,CAAA,CAEzB,CAAE,IAAA,CAAM,CAAE,IAAA,CAAAyB,CAAAA,CAAM,WAAA,CAAAzB,CAAY,CAAA,CAAG,KAAA,CAAO,IAAA,CAAM,MAAA,CAAQ,GAAI,CACjE,CAAA,MAASpB,CAAAA,CAAO,CACd,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CACL,OAAA,CAAS,CAAA,uBAAA,EAA0BA,CAAAA,YAAiB,KAAA,CAAQA,CAAAA,CAAM,OAAA,CAAU,OAAOA,CAAK,CAAC,CAAA,CAAA,CACzF,MAAA,CAAQ,GACV,CAAA,CACA,MAAA,CAAQ,GACV,CACF,CACF,CAAA,CAqBA,MAAM,oBAAA,CAAqB8C,CAAAA,CAAoD,CAC7E,IAAMT,EAAS,MAAMH,CAAAA,CAAK,OAAA,CAAuB,CAC/C,GAAA,CAAK,6BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAM,CAAE,IAAA,CAAAY,CAAK,CACf,CAAC,CAAA,CAED,OAAIT,CAAAA,CAAO,IAAA,EAAM,IAAA,EAAQA,CAAAA,CAAO,IAAA,EAAM,WAAA,EACpCF,CAAAA,CAAeE,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAMA,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAGnDA,CACT,CAAA,CA0BA,MAAM,yBAAA,CAA0BS,CAAAA,CAA+D,CAC7F,IAAMlC,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,QAAkC,CAC5C,GAAA,CAAK,6BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAChC,CAAA,CACA,IAAA,CAAM,CAAE,KAAAkC,CAAK,CACf,CAAC,CAAA,CAfQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAYJ,CAAA,CAWA,MAAM,MAAA,EAAiD,CACrD,IAAMlC,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CAE9C8B,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAyB,CACjD,GAAA,CAAK,mBACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAStB,CAAAA,CAAQ,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUA,CAAK,CAAA,CAAG,CAAA,CAAI,MAC1D,CAAC,CAAA,CAED,OAAAwB,CAAAA,EAAU,CACHC,CACT,CAAA,CAOA,MAAM,YAAA,EAA4D,CAChE,OAAOH,CAAAA,CAAK,OAAA,CAA8B,CACxC,GAAA,CAAK,mBAAA,CACL,MAAA,CAAQ,MACV,CAAC,CACH,CACF,CACF,CCvYO,SAASa,CAAAA,CAAwBd,CAAAA,CAA6B,CACnE,GAAM,CAAE,cAAA,CAAAe,CAAe,CAAA,CAAIf,CAAAA,CAE3B,OAAO,CAaL,OAAA,CAAQgB,CAAAA,CAA2B,CACjC,IAAMJ,EAAOG,CAAAA,EAAe,CAC5B,OAAI,CAACH,CAAAA,EAAQ,CAACA,CAAAA,CAAK,KAAA,CAAc,KAAA,CAC1BA,CAAAA,CAAK,KAAA,CAAM,QAAA,CAASI,CAAQ,CACrC,CAAA,CAcA,aAAA,CAAcC,EAAkBC,CAAAA,CAAyB,CACvD,IAAMN,CAAAA,CAAOG,CAAAA,EAAe,CAC5B,GAAI,CAACH,CAAAA,EAAQ,CAACA,CAAAA,CAAK,WAAA,CAAa,OAAO,MAAA,CACvC,IAAMO,CAAAA,CAAiB,GAAGF,CAAQ,CAAA,CAAA,EAAIC,CAAM,CAAA,CAAA,CAC5C,OAAON,CAAAA,CAAK,WAAA,CAAY,QAAA,CAASO,CAAc,CACjD,CAAA,CAcA,gBAAA,CAAiBC,CAAAA,CAAmE,CAClF,OAAOA,CAAAA,CAAY,KAAK,CAAC,CAAE,QAAA,CAAAH,CAAAA,CAAU,MAAA,CAAAC,CAAO,CAAA,GAAM,IAAA,CAAK,aAAA,CAAcD,CAAAA,CAAUC,CAAM,CAAC,CACxF,CAAA,CAcA,iBAAA,CAAkBE,CAAAA,CAAmE,CACnF,OAAOA,CAAAA,CAAY,KAAA,CAAM,CAAC,CAAE,QAAA,CAAAH,CAAAA,CAAU,MAAA,CAAAC,CAAO,CAAA,GAAM,IAAA,CAAK,aAAA,CAAcD,CAAAA,CAAUC,CAAM,CAAC,CACzF,CACF,CACF,CCtEO,SAASG,CAAAA,CAAiBrB,CAAAA,CAAsB,CACrD,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,OAAA,CAAA3B,CAAAA,CAAS,YAAA,CAAAgD,CAAa,CAAA,CAAItB,CAAAA,CAExC,OAAO,CAaL,MAAM,KAAA,EAAqC,CACzC,IAAMrB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,GAAI,CAACK,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,MAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAAA,CAGF,IAAMyB,CAAAA,CAAS,MAAMH,CAAAA,CAAK,OAAA,CAAc,CACtC,GAAA,CAAK,eACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAED,OAAIyB,CAAAA,CAAO,IAAA,EACTkB,CAAAA,CAAalB,CAAAA,CAAO,IAAI,CAAA,CAGnBA,CACT,CAAA,CAcA,MAAM,QAAA,CAASP,CAAAA,CAAqD,CAClE,IAAMlB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,GAAI,CAACK,CAAAA,CACH,OAAO,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAAA,CAGF,IAAMyB,CAAAA,CAAS,MAAMH,EAAK,OAAA,CAAc,CACtC,GAAA,CAAK,cAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CACP,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAA,CAC9B,cAAA,CAAgB,kBAClB,CAAA,CACA,IAAA,CAAMkB,CACR,CAAC,CAAA,CAED,OAAIO,CAAAA,CAAO,IAAA,EACTkB,CAAAA,CAAalB,CAAAA,CAAO,IAAI,CAAA,CAGnBA,CACT,CAAA,CAcA,MAAM,cAAA,CAAeP,CAAAA,CAAsE,CACzF,IAAMlB,EAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,2BAAA,CACL,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,aAAA,CAAe,UAAUtB,CAAK,CAAA,CAAA,CAC9B,cAAA,CAAgB,kBAClB,CAAA,CACA,IAAA,CAAMkB,CACR,CAAC,CAAA,CAfQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,OAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAYJ,CACF,CACF,CCnHO,SAAS0B,CAAAA,CAAkBvB,CAAAA,CAAuB,CACvD,GAAM,CAAE,IAAA,CAAAC,CAAAA,CAAM,QAAA3B,CAAQ,CAAA,CAAI0B,CAAAA,CAE1B,OAAO,CAeL,MAAM,gBAAA,EAA0D,CAC9D,IAAMrB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,EAAK,OAAA,CAAwB,CAClC,GAAA,CAAK,0BAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,KAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CAAA,CAWA,SAAA,CAAU4B,CAAAA,CAA+B,CACvC,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,CACjC,OAAA,CAAQ,KAAA,CAAM,qEAAqE,CAAA,CACnF,MACF,CAEA,MAAA,CAAO,QAAA,CAAS,IAAA,CAAO,CAAA,gBAAA,EAAmBA,CAAQ,CAAA,KAAA,EACpD,CAAA,CAWA,MAAM,WAAA,CAAYA,CAAAA,CAAiE,CACjF,IAAM5B,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,EACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,CAAA,gBAAA,EAAmBM,CAAQ,UAChC,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAU5B,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,QAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CACF,CACF,CC/EO,SAAS6C,CAAAA,CAAqBxB,CAAAA,CAA0B,CAC7D,GAAM,CAAE,KAAAC,CAAAA,CAAM,OAAA,CAAA3B,CAAQ,CAAA,CAAI0B,CAAAA,CAE1B,OAAO,CAgBL,MAAM,UAAA,EAA6C,CACjD,IAAMrB,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAiB,CAC3B,GAAA,CAAK,4BAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,EAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CAAA,CAiBA,MAAM,WAAA,EAAgD,CACpD,IAAMA,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAmB,CAC7B,GAAA,CAAK,oBAAA,CACL,MAAA,CAAQ,KAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,EACnD,MAAA,CAAQ,GACV,CAQJ,CAAA,CAWA,MAAM,aAAA,CAAc8C,CAAAA,CAA2D,CAC7E,IAAM9C,CAAAA,CAAQL,CAAAA,CAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQA8C,EAQExB,CAAAA,CAAK,OAAA,CAAyB,CACnC,GAAA,CAAK,CAAA,mBAAA,EAAsBwB,CAAS,CAAA,CAAA,CACpC,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAU9C,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,wBAAA,CAA0B,MAAA,CAAQ,GAAI,CAAA,CACxD,MAAA,CAAQ,GACV,CAAA,CAZO,CACL,IAAA,CAAM,KACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAgBJ,CAAA,CAcA,MAAM,iBAAA,EAAsE,CAC1E,IAAMA,CAAAA,CAAQL,EAAQ,OAAA,CAAQ,sBAAsB,CAAA,CACpD,OAAKK,CAAAA,CAQEsB,CAAAA,CAAK,OAAA,CAAmC,CAC7C,GAAA,CAAK,oBAAA,CACL,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAUtB,CAAK,CAAA,CAAG,CAC9C,CAAC,CAAA,CAXQ,CACL,IAAA,CAAM,IAAA,CACN,KAAA,CAAO,CAAE,OAAA,CAAS,mBAAA,CAAqB,MAAA,CAAQ,GAAI,CAAA,CACnD,MAAA,CAAQ,GACV,CAQJ,CACF,CACF,CCrHO,SAAS+C,CAAAA,CACdC,CAAAA,CAA6B,EAAC,CAC9B1B,CAAAA,CACY,CACZ,IAAM,CAAE,OAAA,CAAA2B,CAAAA,CAAS,OAAA,CAAAC,CAAAA,CAAS,eAAAC,CAAAA,CAAgB,cAAA,CAAAC,CAAe,CAAA,CAAIJ,CAAAA,CAGvDK,CAAAA,CAAa/B,CAAAA,EAAQgC,gBAAAA,CAAiB,CAC1C,GAAGtC,CAAAA,CACH,OAAA,CAAAiC,CAAAA,CACA,OAAA,CAAAC,CACF,CAAC,EAGKK,CAAAA,CAAmB,GAAA,CAGnB5D,CAAAA,CAA0BJ,CAAAA,EAAqB,CAC/CiE,CAAAA,CAAe,IAAIzE,CAAAA,CACnB0E,CAAAA,CAAe,IAAIpD,CAAAA,CAErBqD,CAAAA,CAA2B,KAG/B,GAAI,CACF,IAAM1B,CAAAA,CAAWrC,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,IAAI,CAAA,CAC9C2C,CAAAA,GACF0B,CAAAA,CAAc,IAAA,CAAK,KAAA,CAAM1B,CAAQ,CAAA,EAErC,CAAA,MAAS5C,CAAAA,CAAO,CACd,OAAA,CAAQ,MAAM,gDAAA,CAAkDA,CAAK,EACvE,CAGA,IAAIuE,CAAAA,CAGJF,CAAAA,CAAa,kBAAA,CAAmB,SAAY,CAC1C,IAAMhC,CAAAA,CAAS,MAAMkC,CAAAA,CAAW,YAAA,EAAa,CACzClC,EAAO,IAAA,EACT,MAAMkC,CAAAA,CAAW,KAAA,EAAM,CACvBH,CAAAA,CAAa,IAAA,CAAK,gBAAA,CAAkB/B,CAAAA,CAAO,IAAA,CAAK,WAAW,CAAA,GAE3D+B,CAAAA,CAAa,IAAA,CAAK,cAAc,CAAA,CAChCL,KAAiB,EAErB,CAAC,CAAA,CAED,SAASS,CAAAA,CAAmB3B,CAAAA,CAAYzB,CAAAA,CAA2B,CACjEb,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAA,CAAcmB,CAAW,CAAA,CACtDb,CAAAA,CAAQ,OAAA,CAAQN,EAAa,IAAA,CAAM,IAAA,CAAK,SAAA,CAAU4C,CAAI,CAAC,CAAA,CACvDyB,CAAAA,CAAczB,CAAAA,CAGZwB,CAAAA,CAAa,wBAAA,CAAyBjD,CAAAA,CAAa+C,CAAgB,CAAA,CAGrEC,CAAAA,CAAa,IAAA,CAAK,QAASvB,CAAI,EACjC,CAEA,SAAS4B,CAAAA,CAAiB5B,CAAAA,CAAkB,CAC1CyB,CAAAA,CAAczB,CAAAA,CACdtC,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,IAAA,CAAM,IAAA,CAAK,SAAA,CAAU4C,CAAI,CAAC,EACzD,CAEA,SAAST,CAAAA,EAAkB,CACzB7B,CAAAA,CAAQ,KAAA,EAAM,CACd+D,CAAAA,CAAc,IAAA,CACdD,CAAAA,CAAa,aAAA,GACf,CAEA,SAASrB,CAAAA,EAA8B,CACrC,OAAOsB,CACT,CAGA,IAAMI,CAAAA,CAAa1C,CAAAA,CAAiB,CAClC,IAAA,CAAMiC,CAAAA,CACN,cAAA,CAAgBO,CAAAA,CAChB,OAAA,CAAAjE,CAAAA,CACA,SAAA,CAAA6B,CACF,CAAC,EAEKuC,CAAAA,CAAoB5B,CAAAA,CAAwB,CAEhD,cAAA,CAAAC,CAEF,CAAC,CAAA,CAEK4B,CAAAA,CAAatB,CAAAA,CAAiB,CAClC,IAAA,CAAMW,CAAAA,CACN,QAAA1D,CAAAA,CACA,YAAA,CAAckE,CAChB,CAAC,CAAA,CAEKI,CAAAA,CAAcrB,CAAAA,CAAkB,CACpC,IAAA,CAAMS,CAAAA,CACN,OAAA,CAAA1D,CACF,CAAC,CAAA,CAEKuE,CAAAA,CAAiBrB,CAAAA,CAAqB,CAC1C,IAAA,CAAMQ,CAAAA,CACN,OAAA,CAAA1D,CACF,CAAC,CAAA,CAGD,OAAAgE,CAAAA,CAAa,CACX,GAAGG,CAAAA,CACH,GAAGC,CAAAA,CACH,GAAGC,CAAAA,CACH,GAAGC,EACH,GAAGC,CAAAA,CAGH,EAAA,CAAGlF,CAAAA,CAAkBC,CAAAA,CAA6B,CAChDuE,CAAAA,CAAa,EAAA,CAAGxE,CAAAA,CAAOC,CAAO,EAChC,CAAA,CAEA,GAAA,CAAID,CAAAA,CAAkBC,CAAAA,CAA6B,CACjDuE,EAAa,GAAA,CAAIxE,CAAAA,CAAOC,CAAO,EACjC,CAAA,CAGA,eAAA,EAA2B,CAEzB,OAAO,CAAC,CADMU,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAY,CAEzD,CAAA,CAEA,gBAAgC,CAC9B,OAAOM,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAY,CAClD,CAAA,CAEA,cAAA,CAAeW,CAAAA,CAAqB,CAClCL,CAAAA,CAAQ,OAAA,CAAQN,CAAAA,CAAa,YAAA,CAAcW,CAAK,EAE9CyD,CAAAA,CAAa,wBAAA,CAAyBzD,CAAAA,CAAOuD,CAAgB,EAEjE,CAAA,CAEA,SAAA,CAAA/B,CACF,CAAA,CAGAmC,CAAAA,CAAW,EAAA,CAAG,cAAA,CAAgB,IAAM,CAClCP,CAAAA,KACF,CAAC,CAAA,CAGGO,CAAAA,CAAW,eAAA,EAAgB,EAC7BA,CAAAA,CAAW,KAAA,EAAM,CAAE,MAAOvE,CAAAA,EAAU,CAClC,OAAA,CAAQ,IAAA,CAAK,gDAAA,CAAkDA,CAAK,EACtE,CAAC,EAGIuE,CACT","file":"index.js","sourcesContent":["/**\n * Simple event emitter for auth events\n */\n\nimport type { AuthEvent, EventHandler } from \"./types\";\n\ntype EventMap = Record<string, EventHandler[]>;\n\nexport class EventEmitter {\n private events: EventMap = {};\n\n /**\n * Subscribe to an event\n */\n on(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event] = this.events[event].filter((h) => h !== handler);\n }\n\n /**\n * Emit an event with arguments\n */\n emit(event: AuthEvent, ...args: any[]): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event].forEach((handler) => {\n try {\n handler(...args);\n } catch (error) {\n console.error(`[AuthClient] Error in event handler for \"${event}\":`, error);\n }\n });\n }\n\n /**\n * Remove all event listeners\n */\n removeAllListeners(): void {\n this.events = {};\n }\n}\n","/**\n * Storage adapter for token and user data persistence\n * Auto-detects environment and uses appropriate storage:\n * - Browser: localStorage\n * - WeChat Mini Program: wx.setStorageSync/wx.getStorageSync\n * - SSR/Node.js: No-op (no persistence)\n */\n\nexport interface StorageAdapter {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n clear(): void;\n}\n\n/**\n * Storage keys for auth data\n */\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: \"amaster_access_token\",\n REFRESH_TOKEN: \"amaster_refresh_token\",\n USER: \"amaster_user\",\n} as const;\n\n/**\n * Detect current runtime environment\n */\nfunction detectEnvironment(): \"browser\" | \"wechat-miniprogram\" | \"node\" {\n // WeChat Mini Program\n if (typeof wx !== \"undefined\" && wx.getStorageSync) {\n return \"wechat-miniprogram\";\n }\n \n // Browser\n if (typeof window !== \"undefined\" && typeof window.localStorage !== \"undefined\") {\n return \"browser\";\n }\n \n // Node.js/SSR\n return \"node\";\n}\n\n/**\n * Create a storage adapter that auto-detects environment\n * \n * @returns Storage adapter optimized for current environment\n * \n * @example\n * ```typescript\n * const storage = createStorageAdapter();\n * \n * // Browser → uses localStorage\n * // WeChat Mini Program → uses wx.setStorageSync\n * // SSR/Node.js → uses no-op (no persistence)\n * ```\n */\nexport function createStorageAdapter(): StorageAdapter {\n const env = detectEnvironment();\n \n switch (env) {\n case \"wechat-miniprogram\":\n return createWeChatMiniProgramStorage();\n case \"browser\":\n return createBrowserStorage();\n case \"node\":\n return createNoOpStorage();\n }\n}\n\n/**\n * Create browser storage adapter (localStorage)\n */\nfunction createBrowserStorage(): StorageAdapter {\n const storage = window.localStorage;\n\n return {\n getItem(key: string): string | null {\n try {\n return storage.getItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from localStorage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n storage.setItem(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in localStorage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n storage.removeItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from localStorage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n storage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);\n storage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);\n storage.removeItem(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear localStorage:\", error);\n }\n },\n };\n}\n\n/**\n * Create WeChat Mini Program storage adapter\n * Uses wx.setStorageSync and wx.getStorageSync\n */\nfunction createWeChatMiniProgramStorage(): StorageAdapter {\n return {\n getItem(key: string): string | null {\n try {\n const value = wx.getStorageSync(key);\n return value || null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from WeChat storage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n wx.setStorageSync(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in WeChat storage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n wx.removeStorageSync(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from WeChat storage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n wx.removeStorageSync(STORAGE_KEYS.ACCESS_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.REFRESH_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear WeChat storage:\", error);\n }\n },\n };\n}\n\n/**\n * In-memory storage adapter for SSR/Node.js/test environments\n * Data is stored in memory but not persisted across process restarts\n */\nfunction createNoOpStorage(): StorageAdapter {\n const store = new Map<string, string>();\n \n return {\n getItem(key: string): string | null {\n return store.get(key) ?? null;\n },\n setItem(key: string, value: string): void {\n store.set(key, value);\n },\n removeItem(key: string): void {\n store.delete(key);\n },\n clear(): void {\n store.clear();\n },\n };\n}\n","/**\n * Token manager for automatic token refresh\n */\n\n/**\n * JWT token payload interface\n */\ninterface JwtPayload {\n exp: number; // Expiration timestamp (seconds)\n [key: string]: any;\n}\n\n/**\n * Parse JWT token to extract payload\n * Note: This does NOT verify the token signature, only decodes the payload\n */\nexport function parseJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const base64Url = parts[1] || \"\";\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\n // Decode base64 in browser environment\n if (typeof atob !== \"undefined\") {\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split(\"\")\n .map((c) => \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2))\n .join(\"\")\n );\n return JSON.parse(jsonPayload);\n }\n\n // Fallback for Node.js environment\n if (typeof Buffer !== \"undefined\") {\n const jsonPayload = Buffer.from(base64, \"base64\").toString(\"utf-8\");\n return JSON.parse(jsonPayload);\n }\n\n return null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to parse JWT token:\", error);\n return null;\n }\n}\n\n/**\n * Token manager class for handling automatic token refresh\n */\nexport class TokenManager {\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private isRefreshing = false;\n private refreshCallback: (() => Promise<void>) | null = null;\n\n /**\n * Set the refresh callback function\n */\n setRefreshCallback(callback: () => Promise<void>): void {\n this.refreshCallback = callback;\n }\n\n /**\n * Schedule a token refresh after a delay\n * @param delayMs Delay in milliseconds before refreshing\n */\n scheduleRefresh(delayMs: number): void {\n // Clear existing timer\n this.clearSchedule();\n\n // Don't schedule if delay is negative or zero\n if (delayMs <= 0) {\n return;\n }\n\n this.refreshTimer = setTimeout(() => {\n this.refresh();\n }, delayMs);\n }\n\n /**\n * Schedule token refresh based on token expiration and threshold\n * @param accessToken JWT access token\n * @param thresholdSeconds Refresh threshold in seconds (default: 300)\n */\n scheduleRefreshFromToken(accessToken: string, thresholdSeconds: number = 300): void {\n const payload = parseJwt(accessToken);\n if (!payload || !payload.exp) {\n console.warn(\"[AuthClient] Cannot schedule refresh: invalid token or missing exp claim\");\n return;\n }\n\n const expiresAtMs = payload.exp * 1000; // Convert to milliseconds\n const nowMs = Date.now();\n const expiresInMs = expiresAtMs - nowMs;\n\n // Calculate when to refresh (before expiration by thresholdSeconds)\n const refreshDelayMs = expiresInMs - thresholdSeconds * 1000;\n\n if (refreshDelayMs <= 0) {\n // Token already expired or will expire very soon\n console.warn(\"[AuthClient] Token already expired or expiring soon, refreshing immediately\");\n this.refresh();\n } else {\n this.scheduleRefresh(refreshDelayMs);\n }\n }\n\n /**\n * Manually trigger token refresh\n */\n async refresh(): Promise<void> {\n if (this.isRefreshing) {\n return;\n }\n\n if (!this.refreshCallback) {\n console.error(\"[AuthClient] No refresh callback set\");\n return;\n }\n\n this.isRefreshing = true;\n\n try {\n await this.refreshCallback();\n } catch (error) {\n console.error(\"[AuthClient] Token refresh failed:\", error);\n } finally {\n this.isRefreshing = false;\n }\n }\n\n /**\n * Clear the scheduled refresh timer\n */\n clearSchedule(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /**\n * Check if currently refreshing\n */\n isCurrentlyRefreshing(): boolean {\n return this.isRefreshing;\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.clearSchedule();\n this.refreshCallback = null;\n this.isRefreshing = false;\n }\n}\n","/**\n * HTTP Client Configuration Utilities\n * \n * Provides shared HTTP client configuration for Amaster backend integration\n */\n\nimport { type HttpClientOptions } from \"@amaster.ai/http-client\";\n\n/**\n * Transform Amaster backend response format\n * Backend returns: { statusCode: 200, data: {...}, message: \"...\" }\n * We extract the inner 'data' field for cleaner client usage\n * \n * @param responseData - Raw response data from backend\n * @returns Extracted data or original response if not in Amaster format\n * \n * @example\n * ```typescript\n * const response = { statusCode: 200, data: { userId: \"123\" }, message: \"Success\" };\n * const result = transformAmasterResponse(response);\n * // result = { userId: \"123\" }\n * ```\n */\nexport function transformAmasterResponse<T>(responseData: unknown): T {\n if (\n responseData &&\n typeof responseData === \"object\" &&\n (\"statusCode\" in responseData || \"status\" in responseData)\n ) {\n // If response has 'data' field, extract it\n if (\"data\" in responseData) {\n return (responseData as { data: T }).data;\n }\n // Otherwise return the whole response (e.g., for SuccessResponse without data)\n return responseData as T;\n }\n return responseData as T;\n}\n\n/**\n * Default HTTP client options for Amaster backend\n * Includes response transformation and error logging\n */\nexport const defaultHttpClientOptions: HttpClientOptions = {\n transformResponse: transformAmasterResponse,\n // Enable error logging by default (helps with debugging and AI assistance)\n logErrors: true,\n};\n","/**\n * Authentication Module\n *\n * @module auth\n * @category Authentication\n *\n * Handles user authentication including:\n * - Registration\n * - Login (email/username/phone + password)\n * - Verification code login\n * - OAuth social login\n * - Logout and token refresh\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type {\n RegisterParams,\n LoginParams,\n LoginResponse,\n LoginType,\n CodeLoginParams,\n CodeLoginType,\n SendCodeParams,\n SuccessResponse,\n CaptchaResponse,\n OAuthProvider,\n RefreshTokenResponse,\n User,\n MiniProgramPhoneResponse,\n} from \"../types\";\n\n/**\n * Auto-detect login type based on provided parameters\n */\nfunction inferLoginType(params: LoginParams): LoginType | undefined {\n if (params.email) return \"email\";\n if (params.username) return \"username\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\n/**\n * Auto-detect code login type based on provided parameters\n */\nfunction inferCodeLoginType(params: CodeLoginParams): CodeLoginType | undefined {\n if (params.email) return \"email\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\nexport interface AuthModuleDeps {\n http: HttpClient;\n onLoginSuccess: (user: User, accessToken: string) => void;\n storage: { getItem: (key: string) => string | null };\n clearAuth: () => void;\n}\n\nexport function createAuthModule(deps: AuthModuleDeps) {\n const { http, onLoginSuccess, storage, clearAuth } = deps;\n\n return {\n /**\n * Register a new user account\n *\n * @category Authentication\n * @example\n * ```typescript\n * const result = await auth.register({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * displayName: \"John Doe\",\n * });\n * ```\n */\n async register(params: RegisterParams): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/register\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with username/email/phone and password\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from username\n * await auth.login({\n * username: \"john_doe\",\n * password: \"Password@123\",\n * });\n *\n * // Auto-detect loginType from email\n * await auth.login({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * });\n * ```\n */\n async login(params: LoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email, username, or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with verification code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from email\n * await auth.loginWithCode({\n * email: \"user@example.com\",\n * code: \"123456\",\n * });\n *\n * // Auto-detect loginType from phone\n * await auth.loginWithCode({\n * phone: \"13800138000\",\n * code: \"123456\",\n * });\n * ```\n */\n async loginWithCode(params: CodeLoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferCodeLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login-with-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Send verification code to email or phone\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.sendCode({\n * type: \"email\",\n * email: \"user@example.com\",\n * });\n * ```\n */\n async sendCode(params: SendCodeParams): Promise<ClientResult<SuccessResponse>> {\n return http.request<SuccessResponse>({\n url: \"/api/auth/send-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n },\n\n /**\n * Get captcha image\n *\n * @category Authentication\n */\n async getCaptcha(): Promise<ClientResult<CaptchaResponse>> {\n return http.request<CaptchaResponse>({\n url: \"/api/auth/captcha\",\n method: \"get\",\n });\n },\n\n /**\n * Redirect to OAuth provider for authentication\n *\n * @category Authentication\n * @example\n * ```typescript\n * auth.loginWithOAuth(\"google\");\n * ```\n */\n loginWithOAuth(provider: OAuthProvider, redirectUrl?: string): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth login is only available in browser environment\");\n return;\n }\n\n const url = redirectUrl\n ? `/api/auth/oauth/${provider}?redirect_url=${encodeURIComponent(redirectUrl)}`\n : `/api/auth/oauth/${provider}`;\n\n window.location.href = url;\n },\n\n /**\n * Handle OAuth callback\n *\n * @category Authentication\n */\n async handleOAuthCallback(): Promise<ClientResult<LoginResponse>> {\n if (typeof window === \"undefined\") {\n return {\n data: null,\n error: {\n message: \"OAuth callback is only available in browser environment\",\n status: 400,\n },\n status: 400,\n };\n }\n\n try {\n const hash = window.location.hash.substring(1);\n const params = new URLSearchParams(hash);\n const accessToken = params.get(\"access_token\");\n const userJson = params.get(\"user\");\n\n if (!accessToken || !userJson) {\n return {\n data: null,\n error: { message: \"OAuth callback failed: missing token or user data\", status: 400 },\n status: 400,\n };\n }\n\n const user = JSON.parse(decodeURIComponent(userJson)) as User;\n onLoginSuccess(user, accessToken);\n\n return { data: { user, accessToken }, error: null, status: 200 };\n } catch (error) {\n return {\n data: null,\n error: {\n message: `OAuth callback failed: ${error instanceof Error ? error.message : String(error)}`,\n status: 400,\n },\n status: 400,\n };\n }\n },\n\n /**\n * Login with WeChat Mini Program code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // In WeChat Mini Program\n * wx.login({\n * success: async (res) => {\n * if (res.code) {\n * const result = await auth.loginWithMiniProgram(res.code);\n * if (result.data) {\n * console.log(\"Logged in:\", result.data.user);\n * }\n * }\n * }\n * });\n * ```\n */\n async loginWithMiniProgram(code: string): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/miniprogram/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: { code },\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Get WeChat Mini Program user phone number\n * Requires user authorization via getPhoneNumber button\n *\n * @category Authentication\n * @example\n * ```typescript\n * // WXML\n * <button open-type=\"getPhoneNumber\" bindgetphonenumber=\"onGetPhoneNumber\">\n * Get Phone Number\n * </button>\n *\n * // JS\n * async onGetPhoneNumber(e) {\n * const { code } = e.detail;\n * if (code) {\n * const result = await auth.getMiniProgramPhoneNumber(code);\n * if (result.data) {\n * console.log(\"Phone:\", result.data.phone);\n * }\n * }\n * }\n * ```\n */\n async getMiniProgramPhoneNumber(code: string): Promise<ClientResult<MiniProgramPhoneResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<MiniProgramPhoneResponse>({\n url: \"/api/auth/miniprogram/phone\",\n method: \"post\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n data: { code },\n });\n },\n\n /**\n * Logout current user\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.logout();\n * ```\n */\n async logout(): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n\n const result = await http.request<SuccessResponse>({\n url: \"/api/auth/logout\",\n method: \"post\",\n headers: token ? { Authorization: `Bearer ${token}` } : undefined,\n });\n\n clearAuth();\n return result;\n },\n\n /**\n * Refresh access token\n *\n * @category Authentication\n */\n async refreshToken(): Promise<ClientResult<RefreshTokenResponse>> {\n return http.request<RefreshTokenResponse>({\n url: \"/api/auth/refresh\",\n method: \"post\",\n });\n },\n };\n}\n\nexport type AuthModule = ReturnType<typeof createAuthModule>;\n","/**\n * Permissions Module\n *\n * @module permissions\n * @category Permissions\n *\n * Handles permission and role checks:\n * - Role-based access control (RBAC)\n * - Permission checks (fast, local)\n * - Data scope queries (async, server-side)\n */\n\nimport type { HttpClient } from \"@amaster.ai/http-client\";\nimport type { User } from \"../types\";\n\nexport interface PermissionsModuleDeps {\n http: HttpClient;\n getCurrentUser: () => User | null;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createPermissionsModule(deps: PermissionsModuleDeps) {\n const { getCurrentUser } = deps;\n\n return {\n /**\n * Check if user has a specific role (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasRole(\"admin\")) {\n * showAdminPanel();\n * }\n * ```\n */\n hasRole(roleCode: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.roles) return false;\n return user.roles.includes(roleCode);\n },\n\n /**\n * Check if user has a specific permission (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasPermission(\"user\", \"delete\")) {\n * showDeleteButton();\n * }\n * ```\n */\n hasPermission(resource: string, action: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.permissions) return false;\n const permissionName = `${resource}:${action}`;\n return user.permissions.includes(permissionName);\n },\n\n /**\n * Check if user has ANY of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAnyPermission([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showUserSection();\n * }\n * ```\n */\n hasAnyPermission(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.some(({ resource, action }) => this.hasPermission(resource, action));\n },\n\n /**\n * Check if user has ALL of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAllPermissions([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showFullEditor();\n * }\n * ```\n */\n hasAllPermissions(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.every(({ resource, action }) => this.hasPermission(resource, action));\n },\n };\n}\n\nexport type PermissionsModule = ReturnType<typeof createPermissionsModule>;\n","/**\n * User Management Module\n *\n * @module user\n * @category User\n *\n * Handles user profile and account management:\n * - Get current user info\n * - Update profile\n * - Change password\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { User, UpdateMeParams, ChangePasswordParams, SuccessResponse } from \"../types\";\n\nexport interface UserModuleDeps {\n http: HttpClient;\n storage: {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n };\n onUserUpdate: (user: User) => void;\n}\n\nexport function createUserModule(deps: UserModuleDeps) {\n const { http, storage, onUserUpdate } = deps;\n\n return {\n /**\n * Get current logged-in user information\n *\n * @category User\n * @example\n * ```typescript\n * const result = await user.getMe();\n * if (result.data) {\n * console.log(\"User:\", result.data.displayName);\n * }\n * ```\n */\n async getMe(): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Update current user's profile\n *\n * @category User\n * @example\n * ```typescript\n * await user.updateMe({\n * displayName: \"New Name\",\n * avatarUrl: \"https://example.com/avatar.jpg\",\n * });\n * ```\n */\n async updateMe(params: UpdateMeParams): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"put\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Change current user's password\n *\n * @category User\n * @example\n * ```typescript\n * await user.changePassword({\n * oldPassword: \"OldPass@123\",\n * newPassword: \"NewPass@456\",\n * });\n * ```\n */\n async changePassword(params: ChangePasswordParams): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: \"/api/auth/change-password\",\n method: \"post\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n },\n };\n}\n\nexport type UserModule = ReturnType<typeof createUserModule>;\n","/**\n * OAuth Module\n *\n * @module oauth\n * @category OAuth\n *\n * Handles OAuth account binding management:\n * - List connected OAuth accounts\n * - Bind new OAuth account\n * - Unbind OAuth account\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { OAuthBinding, OAuthProvider, SuccessResponse } from \"../types\";\n\nexport interface OAuthModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createOAuthModule(deps: OAuthModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get list of OAuth accounts bound to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * const result = await oauth.getOAuthBindings();\n * if (result.data) {\n * result.data.forEach(binding => {\n * console.log(`${binding.provider}: ${binding.email}`);\n * });\n * }\n * ```\n */\n async getOAuthBindings(): Promise<ClientResult<OAuthBinding[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<OAuthBinding[]>({\n url: \"/api/auth/oauth-bindings\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Bind an OAuth account to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * oauth.bindOAuth(\"google\"); // Redirects to Google OAuth\n * ```\n */\n bindOAuth(provider: OAuthProvider): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth binding is only available in browser environment\");\n return;\n }\n\n window.location.href = `/api/auth/oauth/${provider}/bind`;\n },\n\n /**\n * Unbind an OAuth account from current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * await oauth.unbindOAuth(\"google\");\n * ```\n */\n async unbindOAuth(provider: OAuthProvider): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/oauth/${provider}/unbind`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type OAuthModule = ReturnType<typeof createOAuthModule>;\n","/**\n * Sessions Module\n *\n * @module sessions\n * @category Sessions\n *\n * Handles multi-device session management:\n * - View all active sessions\n * - Revoke specific session\n * - Revoke all other sessions\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { Session, SuccessResponse, RevokeAllSessionsResponse } from \"../types\";\n\nexport interface SessionsModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createSessionsModule(deps: SessionsModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get current session information\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSession();\n * if (result.data) {\n * console.log(\"Session ID:\", result.data.id);\n * console.log(\"Device:\", result.data.sessionName);\n * console.log(\"IP address:\", result.data.ipAddress);\n * console.log(\"Location:\", result.data.location);\n * }\n * ```\n */\n async getSession(): Promise<ClientResult<Session>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session>({\n url: \"/api/auth/sessions/current\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Get all active sessions for current user\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSessions();\n * if (result.data) {\n * result.data.forEach(session => {\n * const status = session.isCurrent ? \"Current\" : \"Other\";\n * console.log(`${session.sessionName} - ${session.ipAddress} - ${status}`);\n * });\n * }\n * ```\n */\n async getSessions(): Promise<ClientResult<Session[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session[]>({\n url: \"/api/auth/sessions\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke a specific session\n *\n * @category Sessions\n * @example\n * ```typescript\n * await sessions.revokeSession(\"session-id-123\");\n * ```\n */\n async revokeSession(sessionId: string): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n if (!sessionId) {\n return {\n data: null,\n error: { message: \"Session ID is required\", status: 400 },\n status: 400,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/sessions/${sessionId}`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke all sessions except current one\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.revokeAllSessions();\n * if (result.data) {\n * console.log(`Revoked ${result.data.revokedCount} sessions`);\n * }\n * ```\n */\n async revokeAllSessions(): Promise<ClientResult<RevokeAllSessionsResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<RevokeAllSessionsResponse>({\n url: \"/api/auth/sessions\",\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type SessionsModule = ReturnType<typeof createSessionsModule>;\n","/**\n * Main Authentication Client\n *\n * Combines all modules into a unified client interface\n */\n\nimport { createHttpClient, type HttpClient } from \"@amaster.ai/http-client\";\nimport { EventEmitter } from \"./event-emitter\";\nimport { createStorageAdapter, STORAGE_KEYS, type StorageAdapter } from \"./storage\";\nimport { TokenManager } from \"./token-manager\";\nimport { defaultHttpClientOptions } from \"./http-config\";\nimport { createAuthModule } from \"./modules/auth\";\nimport { createPermissionsModule } from \"./modules/permissions\";\nimport { createUserModule } from \"./modules/user\";\nimport { createOAuthModule } from \"./modules/oauth\";\nimport { createSessionsModule } from \"./modules/sessions\";\nimport type { AuthClientOptions, AuthEvent, EventHandler, User } from \"./types\";\n\nexport type AuthClient = ReturnType<typeof createAuthModule> &\n ReturnType<typeof createPermissionsModule> &\n ReturnType<typeof createUserModule> &\n ReturnType<typeof createOAuthModule> &\n ReturnType<typeof createSessionsModule> & {\n // Events\n on(event: AuthEvent, handler: EventHandler): void;\n off(event: AuthEvent, handler: EventHandler): void;\n\n // Utilities\n isAuthenticated(): boolean;\n getAccessToken(): string | null;\n setAccessToken(token: string): void;\n clearAuth(): void;\n };\n\nexport function createAuthClient(\n options: AuthClientOptions = {},\n http?: HttpClient\n): AuthClient {\n const { baseURL, headers, onTokenExpired, onUnauthorized } = options;\n \n // Create HTTP client with user options if not provided\n const httpClient = http || createHttpClient({\n ...defaultHttpClientOptions,\n baseURL,\n headers,\n });\n\n const autoRefresh = true;\n const refreshThreshold = 300;\n\n // Auto-detect environment and use appropriate storage\n const storage: StorageAdapter = createStorageAdapter();\n const eventEmitter = new EventEmitter();\n const tokenManager = new TokenManager();\n\n let currentUser: User | null = null;\n\n // Load user from storage\n try {\n const userJson = storage.getItem(STORAGE_KEYS.USER);\n if (userJson) {\n currentUser = JSON.parse(userJson);\n }\n } catch (error) {\n console.error(\"[AuthClient] Failed to load user from storage:\", error);\n }\n\n // Forward declare for circular dependency\n let authClient: AuthClient;\n\n // Setup token refresh callback\n tokenManager.setRefreshCallback(async () => {\n const result = await authClient.refreshToken();\n if (result.data) {\n await authClient.getMe();\n eventEmitter.emit(\"tokenRefreshed\", result.data.accessToken);\n } else {\n eventEmitter.emit(\"tokenExpired\");\n onTokenExpired?.();\n }\n });\n\n function handleLoginSuccess(user: User, accessToken: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, accessToken);\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n currentUser = user;\n\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(accessToken, refreshThreshold);\n }\n\n eventEmitter.emit(\"login\", user);\n }\n\n function handleUserUpdate(user: User): void {\n currentUser = user;\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n }\n\n function clearAuth(): void {\n storage.clear();\n currentUser = null;\n tokenManager.clearSchedule();\n }\n\n function getCurrentUser(): User | null {\n return currentUser;\n }\n\n // Create modules\n const authModule = createAuthModule({\n http: httpClient,\n onLoginSuccess: handleLoginSuccess,\n storage,\n clearAuth,\n });\n\n const permissionsModule = createPermissionsModule({\n http: httpClient,\n getCurrentUser,\n storage,\n });\n\n const userModule = createUserModule({\n http: httpClient,\n storage,\n onUserUpdate: handleUserUpdate,\n });\n\n const oauthModule = createOAuthModule({\n http: httpClient,\n storage,\n });\n\n const sessionsModule = createSessionsModule({\n http: httpClient,\n storage,\n });\n\n // Combine all modules\n authClient = {\n ...authModule,\n ...permissionsModule,\n ...userModule,\n ...oauthModule,\n ...sessionsModule,\n\n // Events\n on(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.on(event, handler);\n },\n\n off(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.off(event, handler);\n },\n\n // Utilities\n isAuthenticated(): boolean {\n const token = storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n return !!token;\n },\n\n getAccessToken(): string | null {\n return storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n },\n\n setAccessToken(token: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(token, refreshThreshold);\n }\n },\n\n clearAuth,\n };\n\n // Setup unauthorized handler\n authClient.on(\"unauthorized\", () => {\n onUnauthorized?.();\n });\n\n // Auto sync user info on initialization\n if (authClient.isAuthenticated()) {\n authClient.getMe().catch((error) => {\n console.warn(\"[AuthClient] Failed to sync user info on init:\", error);\n });\n }\n\n return authClient;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/event-emitter.ts","../src/storage.ts","../src/token-manager.ts","../src/http-config.ts","../src/modules/auth.ts","../src/modules/permissions.ts","../src/modules/user.ts","../src/modules/oauth.ts","../src/modules/sessions.ts","../src/client.ts"],"names":["EventEmitter","event","handler","h","args","error","STORAGE_KEYS","detectEnvironment","createStorageAdapter","createWeChatMiniProgramStorage","createBrowserStorage","createNoOpStorage","storage","key","value","store","parseJwt","token","parts","base64","jsonPayload","c","TokenManager","callback","delayMs","accessToken","thresholdSeconds","payload","expiresAtMs","nowMs","refreshDelayMs","transformAmasterResponse","responseData","defaultHttpClientOptions","inferLoginType","params","inferCodeLoginType","createAuthModule","deps","http","onLoginSuccess","clearAuth","result","loginType","requestData","provider","redirectUrl","url","hash","userJson","user","urlWithoutHash","code","createPermissionsModule","getCurrentUser","roleCode","resource","action","permissionName","permissions","createUserModule","onUserUpdate","createOAuthModule","createSessionsModule","sessionId","createAuthClient","options","baseURL","headers","onTokenExpired","onUnauthorized","autoHandleOAuthCallback","httpClient","createHttpClient","refreshThreshold","eventEmitter","tokenManager","currentUser","authClient","handleLoginSuccess","handleUserUpdate","authModule","permissionsModule","userModule","oauthModule","sessionsModule"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Simple event emitter for auth events\n */\n\nimport type { AuthEvent, EventHandler } from \"./types\";\n\ntype EventMap = Record<string, EventHandler[]>;\n\nexport class EventEmitter {\n private events: EventMap = {};\n\n /**\n * Subscribe to an event\n */\n on(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: AuthEvent, handler: EventHandler): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event] = this.events[event].filter((h) => h !== handler);\n }\n\n /**\n * Emit an event with arguments\n */\n emit(event: AuthEvent, ...args: any[]): void {\n if (!this.events[event]) {\n return;\n }\n this.events[event].forEach((handler) => {\n try {\n handler(...args);\n } catch (error) {\n console.error(`[AuthClient] Error in event handler for \"${event}\":`, error);\n }\n });\n }\n\n /**\n * Remove all event listeners\n */\n removeAllListeners(): void {\n this.events = {};\n }\n}\n","/**\n * Storage adapter for token and user data persistence\n * Auto-detects environment and uses appropriate storage:\n * - Browser: localStorage\n * - WeChat Mini Program: wx.setStorageSync/wx.getStorageSync\n * - SSR/Node.js: No-op (no persistence)\n */\n\nexport interface StorageAdapter {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n clear(): void;\n}\n\n/**\n * Storage keys for auth data\n */\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: \"amaster_access_token\",\n REFRESH_TOKEN: \"amaster_refresh_token\",\n USER: \"amaster_user\",\n} as const;\n\n/**\n * Detect current runtime environment\n */\nfunction detectEnvironment(): \"browser\" | \"wechat-miniprogram\" | \"node\" {\n // WeChat Mini Program\n if (typeof wx !== \"undefined\" && wx.getStorageSync) {\n return \"wechat-miniprogram\";\n }\n \n // Browser\n if (typeof window !== \"undefined\" && typeof window.localStorage !== \"undefined\") {\n return \"browser\";\n }\n \n // Node.js/SSR\n return \"node\";\n}\n\n/**\n * Create a storage adapter that auto-detects environment\n * \n * @returns Storage adapter optimized for current environment\n * \n * @example\n * ```typescript\n * const storage = createStorageAdapter();\n * \n * // Browser → uses localStorage\n * // WeChat Mini Program → uses wx.setStorageSync\n * // SSR/Node.js → uses no-op (no persistence)\n * ```\n */\nexport function createStorageAdapter(): StorageAdapter {\n const env = detectEnvironment();\n \n switch (env) {\n case \"wechat-miniprogram\":\n return createWeChatMiniProgramStorage();\n case \"browser\":\n return createBrowserStorage();\n case \"node\":\n return createNoOpStorage();\n }\n}\n\n/**\n * Create browser storage adapter (localStorage)\n */\nfunction createBrowserStorage(): StorageAdapter {\n const storage = window.localStorage;\n\n return {\n getItem(key: string): string | null {\n try {\n return storage.getItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from localStorage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n storage.setItem(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in localStorage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n storage.removeItem(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from localStorage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n storage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);\n storage.removeItem(STORAGE_KEYS.REFRESH_TOKEN);\n storage.removeItem(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear localStorage:\", error);\n }\n },\n };\n}\n\n/**\n * Create WeChat Mini Program storage adapter\n * Uses wx.setStorageSync and wx.getStorageSync\n */\nfunction createWeChatMiniProgramStorage(): StorageAdapter {\n return {\n getItem(key: string): string | null {\n try {\n const value = wx.getStorageSync(key);\n return value || null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to get item from WeChat storage:\", error);\n return null;\n }\n },\n\n setItem(key: string, value: string): void {\n try {\n wx.setStorageSync(key, value);\n } catch (error) {\n console.error(\"[AuthClient] Failed to set item in WeChat storage:\", error);\n }\n },\n\n removeItem(key: string): void {\n try {\n wx.removeStorageSync(key);\n } catch (error) {\n console.error(\"[AuthClient] Failed to remove item from WeChat storage:\", error);\n }\n },\n\n clear(): void {\n try {\n // Only clear auth-related keys, not all storage\n wx.removeStorageSync(STORAGE_KEYS.ACCESS_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.REFRESH_TOKEN);\n wx.removeStorageSync(STORAGE_KEYS.USER);\n } catch (error) {\n console.error(\"[AuthClient] Failed to clear WeChat storage:\", error);\n }\n },\n };\n}\n\n/**\n * In-memory storage adapter for SSR/Node.js/test environments\n * Data is stored in memory but not persisted across process restarts\n */\nfunction createNoOpStorage(): StorageAdapter {\n const store = new Map<string, string>();\n \n return {\n getItem(key: string): string | null {\n return store.get(key) ?? null;\n },\n setItem(key: string, value: string): void {\n store.set(key, value);\n },\n removeItem(key: string): void {\n store.delete(key);\n },\n clear(): void {\n store.clear();\n },\n };\n}\n","/**\n * Token manager for automatic token refresh\n */\n\n/**\n * JWT token payload interface\n */\ninterface JwtPayload {\n exp: number; // Expiration timestamp (seconds)\n [key: string]: any;\n}\n\n/**\n * Parse JWT token to extract payload\n * Note: This does NOT verify the token signature, only decodes the payload\n */\nexport function parseJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n return null;\n }\n\n const base64Url = parts[1] || \"\";\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\n // Decode base64 in browser environment\n if (typeof atob !== \"undefined\") {\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split(\"\")\n .map((c) => \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2))\n .join(\"\")\n );\n return JSON.parse(jsonPayload);\n }\n\n // Fallback for Node.js environment\n if (typeof Buffer !== \"undefined\") {\n const jsonPayload = Buffer.from(base64, \"base64\").toString(\"utf-8\");\n return JSON.parse(jsonPayload);\n }\n\n return null;\n } catch (error) {\n console.error(\"[AuthClient] Failed to parse JWT token:\", error);\n return null;\n }\n}\n\n/**\n * Token manager class for handling automatic token refresh\n */\nexport class TokenManager {\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private isRefreshing = false;\n private refreshCallback: (() => Promise<void>) | null = null;\n\n /**\n * Set the refresh callback function\n */\n setRefreshCallback(callback: () => Promise<void>): void {\n this.refreshCallback = callback;\n }\n\n /**\n * Schedule a token refresh after a delay\n * @param delayMs Delay in milliseconds before refreshing\n */\n scheduleRefresh(delayMs: number): void {\n // Clear existing timer\n this.clearSchedule();\n\n // Don't schedule if delay is negative or zero\n if (delayMs <= 0) {\n return;\n }\n\n this.refreshTimer = setTimeout(() => {\n this.refresh();\n }, delayMs);\n }\n\n /**\n * Schedule token refresh based on token expiration and threshold\n * @param accessToken JWT access token\n * @param thresholdSeconds Refresh threshold in seconds (default: 300)\n */\n scheduleRefreshFromToken(accessToken: string, thresholdSeconds: number = 300): void {\n const payload = parseJwt(accessToken);\n if (!payload || !payload.exp) {\n console.warn(\"[AuthClient] Cannot schedule refresh: invalid token or missing exp claim\");\n return;\n }\n\n const expiresAtMs = payload.exp * 1000; // Convert to milliseconds\n const nowMs = Date.now();\n const expiresInMs = expiresAtMs - nowMs;\n\n // Calculate when to refresh (before expiration by thresholdSeconds)\n const refreshDelayMs = expiresInMs - thresholdSeconds * 1000;\n\n if (refreshDelayMs <= 0) {\n // Token already expired or will expire very soon\n console.warn(\"[AuthClient] Token already expired or expiring soon, refreshing immediately\");\n this.refresh();\n } else {\n this.scheduleRefresh(refreshDelayMs);\n }\n }\n\n /**\n * Manually trigger token refresh\n */\n async refresh(): Promise<void> {\n if (this.isRefreshing) {\n return;\n }\n\n if (!this.refreshCallback) {\n console.error(\"[AuthClient] No refresh callback set\");\n return;\n }\n\n this.isRefreshing = true;\n\n try {\n await this.refreshCallback();\n } catch (error) {\n console.error(\"[AuthClient] Token refresh failed:\", error);\n } finally {\n this.isRefreshing = false;\n }\n }\n\n /**\n * Clear the scheduled refresh timer\n */\n clearSchedule(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /**\n * Check if currently refreshing\n */\n isCurrentlyRefreshing(): boolean {\n return this.isRefreshing;\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this.clearSchedule();\n this.refreshCallback = null;\n this.isRefreshing = false;\n }\n}\n","/**\n * HTTP Client Configuration Utilities\n * \n * Provides shared HTTP client configuration for Amaster backend integration\n */\n\nimport { type HttpClientOptions } from \"@amaster.ai/http-client\";\n\n/**\n * Transform Amaster backend response format\n * Backend returns: { statusCode: 200, data: {...}, message: \"...\" }\n * We extract the inner 'data' field for cleaner client usage\n * \n * @param responseData - Raw response data from backend\n * @returns Extracted data or original response if not in Amaster format\n * \n * @example\n * ```typescript\n * const response = { statusCode: 200, data: { userId: \"123\" }, message: \"Success\" };\n * const result = transformAmasterResponse(response);\n * // result = { userId: \"123\" }\n * ```\n */\nexport function transformAmasterResponse<T>(responseData: unknown): T {\n if (\n responseData &&\n typeof responseData === \"object\" &&\n (\"statusCode\" in responseData || \"status\" in responseData)\n ) {\n // If response has 'data' field, extract it\n if (\"data\" in responseData) {\n return (responseData as { data: T }).data;\n }\n // Otherwise return the whole response (e.g., for SuccessResponse without data)\n return responseData as T;\n }\n return responseData as T;\n}\n\n/**\n * Default HTTP client options for Amaster backend\n * Includes response transformation and error logging\n */\nexport const defaultHttpClientOptions: HttpClientOptions = {\n transformResponse: transformAmasterResponse,\n // Enable error logging by default (helps with debugging and AI assistance)\n logErrors: true,\n};\n","/**\n * Authentication Module\n *\n * @module auth\n * @category Authentication\n *\n * Handles user authentication including:\n * - Registration\n * - Login (email/username/phone + password)\n * - Verification code login\n * - OAuth social login\n * - Logout and token refresh\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type {\n RegisterParams,\n LoginParams,\n LoginResponse,\n LoginType,\n CodeLoginParams,\n CodeLoginType,\n SendCodeParams,\n SuccessResponse,\n CaptchaResponse,\n OAuthProvider,\n RefreshTokenResponse,\n User,\n MiniProgramPhoneResponse,\n} from \"../types\";\n\n/**\n * Auto-detect login type based on provided parameters\n */\nfunction inferLoginType(params: LoginParams): LoginType | undefined {\n if (params.email) return \"email\";\n if (params.username) return \"username\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\n/**\n * Auto-detect code login type based on provided parameters\n */\nfunction inferCodeLoginType(params: CodeLoginParams): CodeLoginType | undefined {\n if (params.email) return \"email\";\n if (params.phone) return \"phone\";\n return undefined;\n}\n\nexport interface AuthModuleDeps {\n http: HttpClient;\n onLoginSuccess: (user: User, accessToken: string) => void;\n storage: { \n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n };\n clearAuth: () => void;\n}\n\nexport function createAuthModule(deps: AuthModuleDeps) {\n const { http, onLoginSuccess, storage, clearAuth } = deps;\n\n return {\n /**\n * Register a new user account\n *\n * @category Authentication\n * @example\n * ```typescript\n * const result = await auth.register({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * displayName: \"John Doe\",\n * });\n * ```\n */\n async register(params: RegisterParams): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/register\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with username/email/phone and password\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from username\n * await auth.login({\n * username: \"john_doe\",\n * password: \"Password@123\",\n * });\n *\n * // Auto-detect loginType from email\n * await auth.login({\n * email: \"user@example.com\",\n * password: \"Password@123\",\n * });\n * ```\n */\n async login(params: LoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email, username, or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Login with verification code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // Auto-detect loginType from email\n * await auth.loginWithCode({\n * email: \"user@example.com\",\n * code: \"123456\",\n * });\n *\n * // Auto-detect loginType from phone\n * await auth.loginWithCode({\n * phone: \"13800138000\",\n * code: \"123456\",\n * });\n * ```\n */\n async loginWithCode(params: CodeLoginParams): Promise<ClientResult<LoginResponse>> {\n // Auto-detect loginType if not provided\n const loginType = params.loginType || inferCodeLoginType(params);\n\n if (!loginType) {\n return {\n data: null,\n error: {\n message: \"Unable to determine login type. Please provide email or phone.\",\n status: 400,\n },\n status: 400,\n };\n }\n\n // Prepare request data with explicit loginType\n const requestData = {\n ...params,\n loginType,\n };\n\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/login-with-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: requestData,\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Send verification code to email or phone\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.sendCode({\n * type: \"email\",\n * email: \"user@example.com\",\n * });\n * ```\n */\n async sendCode(params: SendCodeParams): Promise<ClientResult<SuccessResponse>> {\n return http.request<SuccessResponse>({\n url: \"/api/auth/send-code\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: params,\n });\n },\n\n /**\n * Get captcha image\n *\n * @category Authentication\n */\n async getCaptcha(): Promise<ClientResult<CaptchaResponse>> {\n return http.request<CaptchaResponse>({\n url: \"/api/auth/captcha\",\n method: \"get\",\n });\n },\n\n /**\n * Redirect to OAuth provider for authentication\n *\n * @category Authentication\n * @example\n * ```typescript\n * auth.loginWithOAuth(\"google\");\n * ```\n */\n loginWithOAuth(provider: OAuthProvider, redirectUrl?: string): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth login is only available in browser environment\");\n return;\n }\n\n const url = redirectUrl\n ? `/api/auth/oauth/${provider}?redirect_url=${encodeURIComponent(redirectUrl)}`\n : `/api/auth/oauth/${provider}`;\n\n window.location.href = url;\n },\n\n /**\n * Handle OAuth callback\n *\n * @category Authentication\n */\n async handleOAuthCallback(): Promise<ClientResult<LoginResponse>> {\n if (typeof window === \"undefined\") {\n return {\n data: null,\n error: {\n message: \"OAuth callback is only available in browser environment\",\n status: 400,\n },\n status: 400,\n };\n }\n\n try {\n const hash = window.location.hash.substring(1);\n const params = new URLSearchParams(hash);\n const accessToken = params.get(\"access_token\");\n const userJson = params.get(\"user\");\n\n if (!accessToken || !userJson) {\n return {\n data: null,\n error: { message: \"OAuth callback failed: missing token or user data\", status: 400 },\n status: 400,\n };\n }\n\n const user = JSON.parse(decodeURIComponent(userJson)) as User;\n onLoginSuccess(user, accessToken);\n\n // Clear the hash from URL to avoid security issues and re-processing\n // Use replaceState to avoid adding to browser history\n if (window.history && window.history.replaceState) {\n const urlWithoutHash = window.location.pathname + window.location.search;\n window.history.replaceState(null, '', urlWithoutHash);\n } else {\n // Fallback for older browsers\n window.location.hash = '';\n }\n\n return { data: { user, accessToken }, error: null, status: 200 };\n } catch (error) {\n return {\n data: null,\n error: {\n message: `OAuth callback failed: ${error instanceof Error ? error.message : String(error)}`,\n status: 400,\n },\n status: 400,\n };\n }\n },\n\n /**\n * Login with WeChat Mini Program code\n *\n * @category Authentication\n * @example\n * ```typescript\n * // In WeChat Mini Program\n * wx.login({\n * success: async (res) => {\n * if (res.code) {\n * const result = await auth.loginWithMiniProgram(res.code);\n * if (result.data) {\n * console.log(\"Logged in:\", result.data.user);\n * }\n * }\n * }\n * });\n * ```\n */\n async loginWithMiniProgram(code: string): Promise<ClientResult<LoginResponse>> {\n const result = await http.request<LoginResponse>({\n url: \"/api/auth/miniprogram/login\",\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: { code },\n });\n\n if (result.data?.user && result.data?.accessToken) {\n onLoginSuccess(result.data.user, result.data.accessToken);\n }\n\n return result;\n },\n\n /**\n * Get WeChat Mini Program user phone number\n * Requires user authorization via getPhoneNumber button\n *\n * @category Authentication\n * @example\n * ```typescript\n * // WXML\n * <button open-type=\"getPhoneNumber\" bindgetphonenumber=\"onGetPhoneNumber\">\n * Get Phone Number\n * </button>\n *\n * // JS\n * async onGetPhoneNumber(e) {\n * const { code } = e.detail;\n * if (code) {\n * const result = await auth.getMiniProgramPhoneNumber(code);\n * if (result.data) {\n * console.log(\"Phone:\", result.data.phone);\n * }\n * }\n * }\n * ```\n */\n async getMiniProgramPhoneNumber(code: string): Promise<ClientResult<MiniProgramPhoneResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<MiniProgramPhoneResponse>({\n url: \"/api/auth/miniprogram/phone\",\n method: \"post\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n data: { code },\n });\n },\n\n /**\n * Logout current user\n *\n * @category Authentication\n * @example\n * ```typescript\n * await auth.logout();\n * ```\n */\n async logout(): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n\n const result = await http.request<SuccessResponse>({\n url: \"/api/auth/logout\",\n method: \"post\",\n headers: token ? { Authorization: `Bearer ${token}` } : undefined,\n });\n\n clearAuth();\n return result;\n },\n\n /**\n * Refresh access token\n *\n * @category Authentication\n */\n async refreshToken(): Promise<ClientResult<RefreshTokenResponse>> {\n const result = await http.request<RefreshTokenResponse>({\n url: \"/api/auth/refresh\",\n method: \"post\",\n });\n\n // Save new token to storage if refresh succeeded\n if (result.data?.accessToken) {\n storage.setItem(\"amaster_access_token\", result.data.accessToken);\n }\n\n return result;\n },\n };\n}\n\nexport type AuthModule = ReturnType<typeof createAuthModule>;\n","/**\n * Permissions Module\n *\n * @module permissions\n * @category Permissions\n *\n * Handles permission and role checks:\n * - Role-based access control (RBAC)\n * - Permission checks (fast, local)\n * - Data scope queries (async, server-side)\n */\n\nimport type { HttpClient } from \"@amaster.ai/http-client\";\nimport type { User } from \"../types\";\n\nexport interface PermissionsModuleDeps {\n http: HttpClient;\n getCurrentUser: () => User | null;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createPermissionsModule(deps: PermissionsModuleDeps) {\n const { getCurrentUser } = deps;\n\n return {\n /**\n * Check if user has a specific role (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasRole(\"admin\")) {\n * showAdminPanel();\n * }\n * ```\n */\n hasRole(roleCode: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.roles) return false;\n return user.roles.includes(roleCode);\n },\n\n /**\n * Check if user has a specific permission (fast, local check)\n *\n * @category Permissions\n * @performance O(1) - Fast\n * @example\n * ```typescript\n * if (permissions.hasPermission(\"user\", \"delete\")) {\n * showDeleteButton();\n * }\n * ```\n */\n hasPermission(resource: string, action: string): boolean {\n const user = getCurrentUser();\n if (!user || !user.permissions) return false;\n const permissionName = `${resource}:${action}`;\n return user.permissions.includes(permissionName);\n },\n\n /**\n * Check if user has ANY of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAnyPermission([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showUserSection();\n * }\n * ```\n */\n hasAnyPermission(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.some(({ resource, action }) => this.hasPermission(resource, action));\n },\n\n /**\n * Check if user has ALL of the specified permissions\n *\n * @category Permissions\n * @performance O(n) - Fast\n * @example\n * ```typescript\n * if (permissions.hasAllPermissions([{ resource: \"user\", action: \"read\" }, { resource: \"user\", action: \"write\" }])) {\n * showFullEditor();\n * }\n * ```\n */\n hasAllPermissions(permissions: Array<{ resource: string; action: string }>): boolean {\n return permissions.every(({ resource, action }) => this.hasPermission(resource, action));\n },\n };\n}\n\nexport type PermissionsModule = ReturnType<typeof createPermissionsModule>;\n","/**\n * User Management Module\n *\n * @module user\n * @category User\n *\n * Handles user profile and account management:\n * - Get current user info\n * - Update profile\n * - Change password\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { User, UpdateMeParams, ChangePasswordParams, SuccessResponse } from \"../types\";\n\nexport interface UserModuleDeps {\n http: HttpClient;\n storage: {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n };\n onUserUpdate: (user: User) => void;\n}\n\nexport function createUserModule(deps: UserModuleDeps) {\n const { http, storage, onUserUpdate } = deps;\n\n return {\n /**\n * Get current logged-in user information\n *\n * @category User\n * @example\n * ```typescript\n * const result = await user.getMe();\n * if (result.data) {\n * console.log(\"User:\", result.data.displayName);\n * }\n * ```\n */\n async getMe(): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Update current user's profile\n *\n * @category User\n * @example\n * ```typescript\n * await user.updateMe({\n * displayName: \"New Name\",\n * avatarUrl: \"https://example.com/avatar.jpg\",\n * });\n * ```\n */\n async updateMe(params: UpdateMeParams): Promise<ClientResult<User>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n const result = await http.request<User>({\n url: \"/api/auth/me\",\n method: \"put\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n\n if (result.data) {\n onUserUpdate(result.data);\n }\n\n return result;\n },\n\n /**\n * Change current user's password\n *\n * @category User\n * @example\n * ```typescript\n * await user.changePassword({\n * oldPassword: \"OldPass@123\",\n * newPassword: \"NewPass@456\",\n * });\n * ```\n */\n async changePassword(params: ChangePasswordParams): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: \"/api/auth/change-password\",\n method: \"post\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n data: params,\n });\n },\n };\n}\n\nexport type UserModule = ReturnType<typeof createUserModule>;\n","/**\n * OAuth Module\n *\n * @module oauth\n * @category OAuth\n *\n * Handles OAuth account binding management:\n * - List connected OAuth accounts\n * - Bind new OAuth account\n * - Unbind OAuth account\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { OAuthBinding, OAuthProvider, SuccessResponse } from \"../types\";\n\nexport interface OAuthModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createOAuthModule(deps: OAuthModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get list of OAuth accounts bound to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * const result = await oauth.getOAuthBindings();\n * if (result.data) {\n * result.data.forEach(binding => {\n * console.log(`${binding.provider}: ${binding.email}`);\n * });\n * }\n * ```\n */\n async getOAuthBindings(): Promise<ClientResult<OAuthBinding[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<OAuthBinding[]>({\n url: \"/api/auth/oauth-bindings\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Bind an OAuth account to current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * oauth.bindOAuth(\"google\"); // Redirects to Google OAuth\n * ```\n */\n bindOAuth(provider: OAuthProvider): void {\n if (typeof window === \"undefined\") {\n console.error(\"[AuthClient] OAuth binding is only available in browser environment\");\n return;\n }\n\n window.location.href = `/api/auth/oauth/${provider}/bind`;\n },\n\n /**\n * Unbind an OAuth account from current user\n *\n * @category OAuth\n * @example\n * ```typescript\n * await oauth.unbindOAuth(\"google\");\n * ```\n */\n async unbindOAuth(provider: OAuthProvider): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/oauth/${provider}/unbind`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type OAuthModule = ReturnType<typeof createOAuthModule>;\n","/**\n * Sessions Module\n *\n * @module sessions\n * @category Sessions\n *\n * Handles multi-device session management:\n * - View all active sessions\n * - Revoke specific session\n * - Revoke all other sessions\n */\n\nimport type { HttpClient, ClientResult } from \"@amaster.ai/http-client\";\nimport type { Session, SuccessResponse, RevokeAllSessionsResponse } from \"../types\";\n\nexport interface SessionsModuleDeps {\n http: HttpClient;\n storage: { getItem: (key: string) => string | null };\n}\n\nexport function createSessionsModule(deps: SessionsModuleDeps) {\n const { http, storage } = deps;\n\n return {\n /**\n * Get current session information\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSession();\n * if (result.data) {\n * console.log(\"Session ID:\", result.data.id);\n * console.log(\"Device:\", result.data.sessionName);\n * console.log(\"IP address:\", result.data.ipAddress);\n * console.log(\"Location:\", result.data.location);\n * }\n * ```\n */\n async getSession(): Promise<ClientResult<Session>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session>({\n url: \"/api/auth/sessions/current\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Get all active sessions for current user\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.getSessions();\n * if (result.data) {\n * result.data.forEach(session => {\n * const status = session.isCurrent ? \"Current\" : \"Other\";\n * console.log(`${session.sessionName} - ${session.ipAddress} - ${status}`);\n * });\n * }\n * ```\n */\n async getSessions(): Promise<ClientResult<Session[]>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<Session[]>({\n url: \"/api/auth/sessions\",\n method: \"get\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke a specific session\n *\n * @category Sessions\n * @example\n * ```typescript\n * await sessions.revokeSession(\"session-id-123\");\n * ```\n */\n async revokeSession(sessionId: string): Promise<ClientResult<SuccessResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n if (!sessionId) {\n return {\n data: null,\n error: { message: \"Session ID is required\", status: 400 },\n status: 400,\n };\n }\n\n return http.request<SuccessResponse>({\n url: `/api/auth/sessions/${sessionId}`,\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n\n /**\n * Revoke all sessions except current one\n *\n * @category Sessions\n * @example\n * ```typescript\n * const result = await sessions.revokeAllSessions();\n * if (result.data) {\n * console.log(`Revoked ${result.data.revokedCount} sessions`);\n * }\n * ```\n */\n async revokeAllSessions(): Promise<ClientResult<RevokeAllSessionsResponse>> {\n const token = storage.getItem(\"amaster_access_token\");\n if (!token) {\n return {\n data: null,\n error: { message: \"Not authenticated\", status: 401 },\n status: 401,\n };\n }\n\n return http.request<RevokeAllSessionsResponse>({\n url: \"/api/auth/sessions\",\n method: \"delete\",\n headers: { Authorization: `Bearer ${token}` },\n });\n },\n };\n}\n\nexport type SessionsModule = ReturnType<typeof createSessionsModule>;\n","/**\n * Main Authentication Client\n *\n * Combines all modules into a unified client interface\n */\n\nimport { createHttpClient, type HttpClient } from \"@amaster.ai/http-client\";\nimport { EventEmitter } from \"./event-emitter\";\nimport { createStorageAdapter, STORAGE_KEYS, type StorageAdapter } from \"./storage\";\nimport { TokenManager } from \"./token-manager\";\nimport { defaultHttpClientOptions } from \"./http-config\";\nimport { createAuthModule } from \"./modules/auth\";\nimport { createPermissionsModule } from \"./modules/permissions\";\nimport { createUserModule } from \"./modules/user\";\nimport { createOAuthModule } from \"./modules/oauth\";\nimport { createSessionsModule } from \"./modules/sessions\";\nimport type { AuthClientOptions, AuthEvent, EventHandler, User } from \"./types\";\n\nexport type AuthClient = ReturnType<typeof createAuthModule> &\n ReturnType<typeof createPermissionsModule> &\n ReturnType<typeof createUserModule> &\n ReturnType<typeof createOAuthModule> &\n ReturnType<typeof createSessionsModule> & {\n // Events\n on(event: AuthEvent, handler: EventHandler): void;\n off(event: AuthEvent, handler: EventHandler): void;\n\n // Utilities\n isAuthenticated(): boolean;\n getAccessToken(): string | null;\n setAccessToken(token: string): void;\n clearAuth(): void;\n };\n\nexport function createAuthClient(\n options: AuthClientOptions = {},\n http?: HttpClient\n): AuthClient {\n const { baseURL, headers, onTokenExpired, onUnauthorized, autoHandleOAuthCallback = true } = options;\n \n // Create HTTP client with user options if not provided\n const httpClient = http || createHttpClient({\n ...defaultHttpClientOptions,\n baseURL,\n headers,\n });\n\n const autoRefresh = true;\n const refreshThreshold = 300;\n\n // Auto-detect environment and use appropriate storage\n const storage: StorageAdapter = createStorageAdapter();\n const eventEmitter = new EventEmitter();\n const tokenManager = new TokenManager();\n\n let currentUser: User | null = null;\n\n // Load user from storage\n try {\n const userJson = storage.getItem(STORAGE_KEYS.USER);\n if (userJson) {\n currentUser = JSON.parse(userJson);\n }\n } catch (error) {\n console.error(\"[AuthClient] Failed to load user from storage:\", error);\n }\n\n // Forward declare for circular dependency\n let authClient: AuthClient;\n\n // Setup token refresh callback\n tokenManager.setRefreshCallback(async () => {\n const result = await authClient.refreshToken();\n if (result.data) {\n await authClient.getMe();\n eventEmitter.emit(\"tokenRefreshed\", result.data.accessToken);\n } else {\n eventEmitter.emit(\"tokenExpired\");\n onTokenExpired?.();\n }\n });\n\n function handleLoginSuccess(user: User, accessToken: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, accessToken);\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n currentUser = user;\n\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(accessToken, refreshThreshold);\n }\n\n eventEmitter.emit(\"login\", user);\n }\n\n function handleUserUpdate(user: User): void {\n currentUser = user;\n storage.setItem(STORAGE_KEYS.USER, JSON.stringify(user));\n }\n\n function clearAuth(): void {\n storage.clear();\n currentUser = null;\n tokenManager.clearSchedule();\n }\n\n function getCurrentUser(): User | null {\n return currentUser;\n }\n\n // Create modules\n const authModule = createAuthModule({\n http: httpClient,\n onLoginSuccess: handleLoginSuccess,\n storage,\n clearAuth,\n });\n\n const permissionsModule = createPermissionsModule({\n http: httpClient,\n getCurrentUser,\n storage,\n });\n\n const userModule = createUserModule({\n http: httpClient,\n storage,\n onUserUpdate: handleUserUpdate,\n });\n\n const oauthModule = createOAuthModule({\n http: httpClient,\n storage,\n });\n\n const sessionsModule = createSessionsModule({\n http: httpClient,\n storage,\n });\n\n // Combine all modules\n authClient = {\n ...authModule,\n ...permissionsModule,\n ...userModule,\n ...oauthModule,\n ...sessionsModule,\n\n // Events\n on(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.on(event, handler);\n },\n\n off(event: AuthEvent, handler: EventHandler): void {\n eventEmitter.off(event, handler);\n },\n\n // Utilities\n isAuthenticated(): boolean {\n const token = storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n return !!token;\n },\n\n getAccessToken(): string | null {\n return storage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n },\n\n setAccessToken(token: string): void {\n storage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);\n if (autoRefresh) {\n tokenManager.scheduleRefreshFromToken(token, refreshThreshold);\n }\n },\n\n clearAuth,\n };\n\n // Setup unauthorized handler\n authClient.on(\"unauthorized\", () => {\n onUnauthorized?.();\n });\n\n // Auto sync user info on initialization\n if (authClient.isAuthenticated()) {\n authClient.getMe().catch((error) => {\n console.warn(\"[AuthClient] Failed to sync user info on init:\", error);\n });\n }\n\n // Auto-handle OAuth callback if enabled (default: true)\n if (autoHandleOAuthCallback && typeof window !== \"undefined\") {\n const hash = window.location.hash;\n if (hash && hash.includes(\"access_token\")) {\n // Automatically process OAuth callback\n authClient.handleOAuthCallback().then((result) => {\n if (result.error) {\n console.error(\"[AuthClient] Auto OAuth callback failed:\", result.error);\n }\n }).catch((error) => {\n console.error(\"[AuthClient] Auto OAuth callback error:\", error);\n });\n }\n }\n\n return authClient;\n}\n"]}
|
package/dist/oauth.d.cts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { O as OAuthBinding, g as OAuthProvider, p as SuccessResponse } from './types-
|
|
17
|
+
import { O as OAuthBinding, g as OAuthProvider, p as SuccessResponse } from './types-BhHE_geU.cjs';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* OAuth Module
|
package/dist/oauth.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { O as OAuthBinding, g as OAuthProvider, p as SuccessResponse } from './types-
|
|
17
|
+
import { O as OAuthBinding, g as OAuthProvider, p as SuccessResponse } from './types-BhHE_geU.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* OAuth Module
|
package/dist/permissions.d.cts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient } from '@amaster.ai/http-client';
|
|
17
|
-
import { q as User } from './types-
|
|
17
|
+
import { q as User } from './types-BhHE_geU.cjs';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Permissions Module
|
package/dist/permissions.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient } from '@amaster.ai/http-client';
|
|
17
|
-
import { q as User } from './types-
|
|
17
|
+
import { q as User } from './types-BhHE_geU.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Permissions Module
|
package/dist/sessions.d.cts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { o as Session, p as SuccessResponse, k as RevokeAllSessionsResponse } from './types-
|
|
17
|
+
import { o as Session, p as SuccessResponse, k as RevokeAllSessionsResponse } from './types-BhHE_geU.cjs';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Sessions Module
|
package/dist/sessions.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { o as Session, p as SuccessResponse, k as RevokeAllSessionsResponse } from './types-
|
|
17
|
+
import { o as Session, p as SuccessResponse, k as RevokeAllSessionsResponse } from './types-BhHE_geU.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Sessions Module
|
|
@@ -64,6 +64,25 @@ interface AuthClientOptions {
|
|
|
64
64
|
* @example () => alert("Session expired")
|
|
65
65
|
*/
|
|
66
66
|
onUnauthorized?: () => void;
|
|
67
|
+
/**
|
|
68
|
+
* Automatically handle OAuth callback on initialization
|
|
69
|
+
* When enabled, the client will automatically detect and process OAuth callback URLs with #access_token
|
|
70
|
+
* @default true
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* // Enable auto-handling (default)
|
|
74
|
+
* const authClient = createAuthClient({
|
|
75
|
+
* autoHandleOAuthCallback: true,
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* // Disable if you want to handle OAuth callback manually
|
|
79
|
+
* const authClient = createAuthClient({
|
|
80
|
+
* autoHandleOAuthCallback: false,
|
|
81
|
+
* });
|
|
82
|
+
* await authClient.handleOAuthCallback(); // Call manually when needed
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
autoHandleOAuthCallback?: boolean;
|
|
67
86
|
}
|
|
68
87
|
/**
|
|
69
88
|
* User information with roles and permissions
|
|
@@ -64,6 +64,25 @@ interface AuthClientOptions {
|
|
|
64
64
|
* @example () => alert("Session expired")
|
|
65
65
|
*/
|
|
66
66
|
onUnauthorized?: () => void;
|
|
67
|
+
/**
|
|
68
|
+
* Automatically handle OAuth callback on initialization
|
|
69
|
+
* When enabled, the client will automatically detect and process OAuth callback URLs with #access_token
|
|
70
|
+
* @default true
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* // Enable auto-handling (default)
|
|
74
|
+
* const authClient = createAuthClient({
|
|
75
|
+
* autoHandleOAuthCallback: true,
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* // Disable if you want to handle OAuth callback manually
|
|
79
|
+
* const authClient = createAuthClient({
|
|
80
|
+
* autoHandleOAuthCallback: false,
|
|
81
|
+
* });
|
|
82
|
+
* await authClient.handleOAuthCallback(); // Call manually when needed
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
autoHandleOAuthCallback?: boolean;
|
|
67
86
|
}
|
|
68
87
|
/**
|
|
69
88
|
* User information with roles and permissions
|
package/dist/user.d.cts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { q as User, U as UpdateMeParams, C as ChangePasswordParams, p as SuccessResponse } from './types-
|
|
17
|
+
import { q as User, U as UpdateMeParams, C as ChangePasswordParams, p as SuccessResponse } from './types-BhHE_geU.cjs';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* User Management Module
|
package/dist/user.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ============================================================================
|
|
15
15
|
*/
|
|
16
16
|
import { HttpClient, ClientResult } from '@amaster.ai/http-client';
|
|
17
|
-
import { q as User, U as UpdateMeParams, C as ChangePasswordParams, p as SuccessResponse } from './types-
|
|
17
|
+
import { q as User, U as UpdateMeParams, C as ChangePasswordParams, p as SuccessResponse } from './types-BhHE_geU.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* User Management Module
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amaster.ai/auth-client",
|
|
3
|
-
"version": "1.1.0-beta.
|
|
3
|
+
"version": "1.1.0-beta.32",
|
|
4
4
|
"description": "Authentication SDK for Amaster platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"registry": "https://registry.npmjs.org/"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@amaster.ai/http-client": "1.1.0-beta.
|
|
50
|
+
"@amaster.ai/http-client": "1.1.0-beta.32"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"axios": "^1.11.0"
|