@dainprotocol/oauth2-token-manager 0.1.8-alpha.2 → 0.2.0

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/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var crypto=require('crypto'),ironSession=require('iron-session');var m=class{buildUrlParams(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,o])=>`${r}=${encodeURIComponent(o)}`).join("&")}generateAuthorizationUrl(e,t,r){let o={client_id:e.clientId,redirect_uri:e.redirectUri,response_type:"code",scope:e.scopes.join(" "),state:t};(e.usePKCE||e.pkce)&&r&&(o.code_challenge=r,o.code_challenge_method="S256");let i={...e.additionalParams,...e.extraAuthParams};return Object.assign(o,i),`${e.authorizationUrl}?${this.buildUrlParams(o)}`}};var g=class{buildUrlParams(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,o])=>`${r}=${encodeURIComponent(o)}`).join("&")}async exchangeCodeForToken(e,t,r){let o={grant_type:"authorization_code",code:e,redirect_uri:t.redirectUri,client_id:t.clientId};(t.usePKCE||t.pkce)&&r?o.code_verifier=r:t.clientSecret&&(o.client_secret=t.clientSecret);let i=await fetch(t.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(o)});if(!i.ok){let x=await i.text();throw new Error(`Token exchange failed: ${i.statusText} - ${x}`)}let s=await i.json(),a=t.responseRootKey?s[t.responseRootKey]:s,p=Date.now(),c=a.expires_in||3600;return {accessToken:a.access_token,refreshToken:a.refresh_token,expiresAt:new Date(p+c*1e3),expiresIn:c,tokenType:a.token_type||"Bearer",scope:a.scope,createdAt:p,raw:s}}async refreshToken(e,t){let r={grant_type:"refresh_token",refresh_token:e,client_id:t.clientId};!(t.usePKCE||t.pkce)&&t.clientSecret&&(r.client_secret=t.clientSecret);let o=await fetch(t.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(r)});if(!o.ok){let c=await o.text();throw new Error(`Token refresh failed: ${o.statusText} - ${c}`)}let i=await o.json(),s=t.responseRootKey?i[t.responseRootKey]:i,a=Date.now(),p=s.expires_in||3600;return {accessToken:s.access_token,refreshToken:s.refresh_token||e,expiresAt:new Date(a+p*1e3),expiresIn:p,tokenType:s.token_type||"Bearer",scope:s.scope,createdAt:a,raw:i}}};var u=class{constructor(e,t,r,o){this.config=e;this.authUrlStrategy=t||this.createAuthorizationUrlStrategy(),this.tokenStrategy=r||this.createTokenExchangeStrategy(),this.profileFetcher=o;}authUrlStrategy;tokenStrategy;profileFetcher;async fetchProfile(e){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.fetchUserInfo(e)}getProfileEndpoint(){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.getEndpoint()}setProfileFetcher(e){this.profileFetcher=e;}hasProfileFetcher(){return !!this.profileFetcher}generateAuthorizationUrl(e,t){return this.authUrlStrategy.generateAuthorizationUrl(this.config,e,t)}async exchangeCodeForToken(e,t){return this.tokenStrategy.exchangeCodeForToken(e,this.config,t)}async refreshToken(e){return this.tokenStrategy.refreshToken(e,this.config)}};var k=class extends u{constructor(e,t,r,o){super(e,t,r,o);}createAuthorizationUrlStrategy(){return new m}createTokenExchangeStrategy(){return new g}};var d=class{constructor(e){this.profileEndpoint=e;}async fetchUserInfo(e){let t=await fetch(this.profileEndpoint,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json",...this.getAdditionalHeaders()}});if(!t.ok)throw new Error(`Failed to fetch profile from ${this.profileEndpoint}: ${t.statusText}`);let r=await t.json();return this.mapToUserProfile(r)}getAdditionalHeaders(){return {}}getEndpoint(){return this.profileEndpoint}};var P=class extends d{constructor(){super("https://www.googleapis.com/oauth2/v2/userinfo");}mapToUserProfile(e){return {email:e.email,name:e.name,id:e.id,avatar:e.picture,username:e.email,raw:e}}};var T=class extends d{constructor(){super("https://api.github.com/user");}mapToUserProfile(e){var t;return {email:e.email,name:e.name||e.login,id:(t=e.id)==null?void 0:t.toString(),avatar:e.avatar_url,username:e.login,raw:e}}getAdditionalHeaders(){return {"User-Agent":"OAuth2-Token-Manager"}}};var v=class extends d{constructor(){super("https://graph.microsoft.com/v1.0/me");}mapToUserProfile(e){return {email:e.mail||e.userPrincipalName,name:e.displayName,id:e.id,avatar:void 0,username:e.userPrincipalName,raw:e}}};var l=class extends d{constructor(t,r,o){super(t);this.mapping=r;this.additionalHeaders=o;}mapToUserProfile(t){return this.mapping?{email:this.getNestedProperty(t,this.mapping.email),name:this.mapping.name?this.getNestedProperty(t,this.mapping.name):void 0,id:this.mapping.id?this.getNestedProperty(t,this.mapping.id):void 0,avatar:this.mapping.avatar?this.getNestedProperty(t,this.mapping.avatar):void 0,username:this.mapping.username?this.getNestedProperty(t,this.mapping.username):void 0,raw:t}:{email:t.email||t.mail||t.emailAddress,name:t.name||t.displayName||t.full_name,id:t.id||t.sub||t.user_id,avatar:t.avatar||t.picture||t.avatar_url,username:t.username||t.login||t.preferred_username,raw:t}}getAdditionalHeaders(){return this.additionalHeaders||{}}getNestedProperty(t,r){return r.split(".").reduce((o,i)=>o==null?void 0:o[i],t)}};var y=class{static createProfileFetcher(e,t,r){if(r!=null&&r.profileUrl)return new l(r.profileUrl,r.profileMapping,r.profileHeaders);switch(e){case "google":return new P;case "github":return new T;case "microsoft":case "outlook":return new v;case "facebook":return new l("https://graph.facebook.com/me?fields=id,name,email,picture");case "generic":default:let o=t.profileUrl||t.userInfoUrl;if(!o)throw new Error(`Profile URL must be provided for ${e} provider`);return new l(o)}}static registerCustomProfileFetcher(e,t){this.customFetchers.set(e,t);}static customFetchers=new Map;static getCustomProfileFetcher(e){return this.customFetchers.get(e)}};var A=class n{static presetConfigs={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",profileUrl:"https://www.googleapis.com/oauth2/v2/userinfo",usePKCE:true,extraAuthParams:{access_type:"offline",prompt:"consent"}},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",profileUrl:"https://api.github.com/user"},microsoft:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true},outlook:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true,extraAuthParams:{prompt:"select_account"}},facebook:{authorizationUrl:"https://www.facebook.com/v12.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v12.0/oauth/access_token",profileUrl:"https://graph.facebook.com/me?fields=id,name,email,picture"}};createProvider(e,t){let r=e!=="generic"?n.presetConfigs[e]||{}:{},o={...r,...t,authorizationUrl:t.authorizationUrl||r.authorizationUrl||"",tokenUrl:t.tokenUrl||r.tokenUrl||"",profileUrl:t.profileUrl||r.profileUrl,extraAuthParams:{...r.extraAuthParams||{},...t.extraAuthParams||{}}},i=y.createProfileFetcher(e,o);return new k(o,void 0,void 0,i)}static registerPreset(e,t){n.presetConfigs[e]=t;}static getPresetConfig(e){return n.presetConfigs[e]}};var h=class{tokens=new Map;states=new Map;profileFetchers=new Map;generateId(){return Math.random().toString(36).substring(2)+Date.now().toString(36)}async saveToken(e){let t=await this.getToken(e.provider,e.email);if(t){let o={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date};return this.tokens.set(t.id,o),o}let r={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.tokens.set(r.id,r),r}async queryTokens(e){let t=Array.from(this.tokens.values());if(e.id&&(t=t.filter(r=>r.id===e.id)),e.provider&&(t=t.filter(r=>r.provider===e.provider)),e.userId&&(t=t.filter(r=>r.userId===e.userId)),e.email&&(t=t.filter(r=>r.email===e.email)),!e.includeExpired){let r=new Date().getTime();t=t.filter(o=>new Date(o.token.expiresAt).getTime()>=r);}return e.offset!==void 0&&(t=t.slice(e.offset)),e.limit!==void 0&&(t=t.slice(0,e.limit)),t}async getToken(e,t){return (await this.queryTokens({provider:e,email:t,includeExpired:true}))[0]||null}async getTokenById(e){return (await this.queryTokens({id:e,includeExpired:true}))[0]||null}async getTokensByUserId(e){return this.queryTokens({userId:e})}async getTokensByEmail(e){return this.queryTokens({email:e})}async getTokensByProvider(e){return this.queryTokens({provider:e})}async getAccounts(e,t){return this.queryTokens({userId:e,provider:t})}async getTokensForEmail(e,t,r){return (await this.queryTokens({userId:e,provider:t,email:r}))[0]||null}async getTokens(e,t){return this.queryTokens({userId:e,provider:t})}async updateToken(e,t){let r=this.tokens.get(e);if(!r)return null;let o={...r,...t.token&&{token:t.token},...t.metadata&&{metadata:{...r.metadata,...t.metadata}},updatedAt:new Date};return this.tokens.set(e,o),o}async deleteToken(e){return this.tokens.delete(e)}async deleteTokenByProviderEmail(e,t){let r=await this.getToken(e,t);return r?this.tokens.delete(r.id):false}async deleteExpiredTokens(){let e=new Date().getTime(),t=Array.from(this.tokens.entries()).filter(([,r])=>new Date(r.token.expiresAt).getTime()<e).map(([r])=>r);return t.forEach(r=>this.tokens.delete(r)),t.length}async saveAuthorizationState(e){let t={...e,createdAt:new Date(Date.now())};return this.states.set(e.state,t),t}async getAuthorizationState(e){return this.states.get(e)||null}async deleteAuthorizationState(e){return this.states.delete(e)}async cleanupExpiredStates(){let e=new Date().getTime(),t=10*60*1e3,r=Array.from(this.states.entries()).filter(([,o])=>e-o.createdAt.getTime()>t).map(([o])=>o);return r.forEach(o=>this.states.delete(o)),r.length}registerProfileFetcher(e,t){this.profileFetchers.set(e,t);}getProfileFetcher(e){return this.profileFetchers.get(e)}getProfileFetchers(){return new Map(this.profileFetchers)}};var E=()=>crypto.randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),b=n=>crypto.createHash("sha256").update(n).digest("base64url"),O=()=>crypto.randomBytes(16).toString("base64url");var S=class{storage;providerFactory;providers=new Map;providerConfigs=new Map;now;constructor(e={}){this.storage=e.storage||new h,this.providerFactory=new A,this.now=Date.now,e.providers&&Object.entries(e.providers).forEach(([t,r])=>{this.registerProvider(t,r);});}registerProvider(e,t){this.providerConfigs.set(e,t);let r=this.detectProviderType(e,t),o=this.providerFactory.createProvider(r,t),i=this.storage.getProfileFetcher(e);i&&o.setProfileFetcher(i),this.providers.set(e,o);}async authorize(e){var a;let t=this.providers.get(e.provider);if(!t)throw new Error(`Provider ${e.provider} not found`);let r=O(),o,i;if(((a=this.providerConfigs.get(e.provider))==null?void 0:a.usePKCE)||e.usePKCE){let p=E(),c=b(p);o=t.generateAuthorizationUrl(r,c),i={state:r,codeVerifier:p,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};}else o=t.generateAuthorizationUrl(r),i={state:r,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};return await this.storage.saveAuthorizationState(i),{url:o,state:r}}async handleCallback(e,t){var U,w,C;let r=await this.storage.getAuthorizationState(t);if(!r)throw new Error("Invalid or expired state");let o=(U=r.metadata)==null?void 0:U.provider;if(!o)throw new Error("Provider not found in authorization state");let i=this.providers.get(o);if(!i)throw new Error(`Provider ${o} not found`);let s=await i.exchangeCodeForToken(e,r.codeVerifier),a=(w=r.metadata)==null?void 0:w.userId,p=(C=r.metadata)==null?void 0:C.email;if(!a||!p)throw new Error("User ID and email are required in authorization state");let c;if(i.hasProfileFetcher())try{c=await i.fetchProfile(s.accessToken);}catch(z){console.warn("Failed to fetch user profile:",z);}let x=await this.storage.saveToken({provider:o,userId:a,email:(c==null?void 0:c.email)||p,token:s,metadata:{...r.metadata,profileFetched:!!c}});await this.storage.deleteAuthorizationState(t);let f=this.providerConfigs.get(o);return f!=null&&f.onSuccess&&await f.onSuccess(a,s),{token:x,profile:c}}async getAccessToken(e,t,r={}){return (await this.getValidToken(e,t,r)).accessToken}async getValidToken(e,t,r={}){let o=await this.storage.getToken(e,t);if(!o)throw new Error(`No token found for provider ${e} and email ${t}`);if(!(r.autoRefresh!==false&&this.isTokenExpired(o.token,r)))return o.token;if(!o.token.refreshToken)throw new Error("Token expired and no refresh token available");let s=this.providers.get(e);if(!s)throw new Error(`Provider ${e} not found`);let a=await s.refreshToken(o.token.refreshToken);return await this.storage.updateToken(o.id,{token:a}),a}async getTokensByUserId(e){return this.storage.getTokensByUserId(e)}async getTokensByEmail(e){return this.storage.getTokensByEmail(e)}async deleteToken(e,t){return this.storage.deleteTokenByProviderEmail(e,t)}async cleanupExpiredTokens(){return this.storage.deleteExpiredTokens()}async cleanupExpiredStates(){return this.storage.cleanupExpiredStates()}isTokenExpired(e,t={}){let{expirationBuffer:r=300}=t;if(e.createdAt&&e.expiresIn!==void 0){let s=e.createdAt+e.expiresIn*1e3;return this.now()+r*1e3>=s}let o=new Date(e.expiresAt).getTime();return this.now()+r*1e3>=o}detectProviderType(e,t){var o;let r=t.authorizationUrl.toLowerCase();return r.includes("accounts.google.com")?"google":r.includes("github.com")?"github":r.includes("facebook.com")?"facebook":r.includes("microsoft.com")||r.includes("microsoftonline.com")?e.toLowerCase().includes("outlook")||(o=t.scopes)!=null&&o.some(i=>i.includes("outlook"))?"outlook":"microsoft":"generic"}};var ge=(n,e)=>ironSession.sealData(n,{password:e}),ke=(n,e)=>ironSession.unsealData(n,{password:e});
2
- exports.BaseProfileFetcher=d;exports.GenericOAuth2Provider=k;exports.GenericProfileFetcher=l;exports.GitHubProfileFetcher=T;exports.GoogleProfileFetcher=P;exports.InMemoryStorageAdapter=h;exports.MicrosoftProfileFetcher=v;exports.OAuth2Client=S;exports.OAuth2Provider=u;exports.ProfileFetcherFactory=y;exports.StandardAuthorizationUrlStrategy=m;exports.StandardTokenExchangeStrategy=g;exports.createCodeChallenge=b;exports.createCodeVerifier=E;exports.generateState=O;exports.seal=ge;exports.unseal=ke;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var crypto=require('crypto'),ironSession=require('iron-session');var m=class{buildUrlParams(e){return Object.entries(e).filter(([,t])=>t!==void 0).map(([t,o])=>`${t}=${encodeURIComponent(o)}`).join("&")}generateAuthorizationUrl(e,r,t){let o={client_id:e.clientId,redirect_uri:e.redirectUri,response_type:"code",scope:e.scopes.join(" "),state:r};(e.usePKCE||e.pkce)&&t&&(o.code_challenge=t,o.code_challenge_method="S256");let i={...e.additionalParams,...e.extraAuthParams};return Object.assign(o,i),`${e.authorizationUrl}?${this.buildUrlParams(o)}`}};var g=class{buildUrlParams(e){return Object.entries(e).filter(([,t])=>t!==void 0).map(([t,o])=>`${t}=${encodeURIComponent(o)}`).join("&")}async exchangeCodeForToken(e,r,t){let o={grant_type:"authorization_code",code:e,redirect_uri:r.redirectUri,client_id:r.clientId};(r.usePKCE||r.pkce)&&t?o.code_verifier=t:r.clientSecret&&(o.client_secret=r.clientSecret);let i=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(o)});if(!i.ok){let x=await i.text();throw new Error(`Token exchange failed: ${i.statusText} - ${x}`)}let n=await i.json(),a=r.responseRootKey?n[r.responseRootKey]:n,p=Date.now(),c=a.expires_in||3600;return {accessToken:a.access_token,refreshToken:a.refresh_token,expiresAt:new Date(p+c*1e3),expiresIn:c,tokenType:a.token_type||"Bearer",scope:a.scope,createdAt:p,raw:n}}async refreshToken(e,r){let t={grant_type:"refresh_token",refresh_token:e,client_id:r.clientId};!(r.usePKCE||r.pkce)&&r.clientSecret&&(t.client_secret=r.clientSecret);let o=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(t)});if(!o.ok){let c=await o.text();throw new Error(`Token refresh failed: ${o.statusText} - ${c}`)}let i=await o.json(),n=r.responseRootKey?i[r.responseRootKey]:i,a=Date.now(),p=n.expires_in||3600;return {accessToken:n.access_token,refreshToken:n.refresh_token||e,expiresAt:new Date(a+p*1e3),expiresIn:p,tokenType:n.token_type||"Bearer",scope:n.scope,createdAt:a,raw:i}}};var u=class{constructor(e,r,t,o){this.config=e;this.authUrlStrategy=r||this.createAuthorizationUrlStrategy(),this.tokenStrategy=t||this.createTokenExchangeStrategy(),this.profileFetcher=o;}authUrlStrategy;tokenStrategy;profileFetcher;async fetchProfile(e){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.fetchUserInfo(e)}getProfileEndpoint(){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.getEndpoint()}setProfileFetcher(e){this.profileFetcher=e;}hasProfileFetcher(){return !!this.profileFetcher}generateAuthorizationUrl(e,r){return this.authUrlStrategy.generateAuthorizationUrl(this.config,e,r)}async exchangeCodeForToken(e,r){return this.tokenStrategy.exchangeCodeForToken(e,this.config,r)}async refreshToken(e){return this.tokenStrategy.refreshToken(e,this.config)}};var k=class extends u{constructor(e,r,t,o){super(e,r,t,o);}createAuthorizationUrlStrategy(){return new m}createTokenExchangeStrategy(){return new g}};var d=class{constructor(e){this.profileEndpoint=e;}async fetchUserInfo(e){let r=await fetch(this.profileEndpoint,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json",...this.getAdditionalHeaders()}});if(!r.ok)throw new Error(`Failed to fetch profile from ${this.profileEndpoint}: ${r.statusText}`);let t=await r.json();return this.mapToUserProfile(t)}getAdditionalHeaders(){return {}}getEndpoint(){return this.profileEndpoint}};var T=class extends d{constructor(){super("https://www.googleapis.com/oauth2/v2/userinfo");}mapToUserProfile(e){return {email:e.email,name:e.name,id:e.id,avatar:e.picture,username:e.email,raw:e}}};var P=class extends d{constructor(){super("https://api.github.com/user");}mapToUserProfile(e){var r;return {email:e.email,name:e.name||e.login,id:(r=e.id)==null?void 0:r.toString(),avatar:e.avatar_url,username:e.login,raw:e}}getAdditionalHeaders(){return {"User-Agent":"OAuth2-Token-Manager"}}};var v=class extends d{constructor(){super("https://graph.microsoft.com/v1.0/me");}mapToUserProfile(e){return {email:e.mail||e.userPrincipalName,name:e.displayName,id:e.id,avatar:void 0,username:e.userPrincipalName,raw:e}}};var h=class extends d{constructor(r,t,o){super(r);this.mapping=t;this.additionalHeaders=o;}mapToUserProfile(r){return this.mapping?{email:this.getNestedProperty(r,this.mapping.email),name:this.mapping.name?this.getNestedProperty(r,this.mapping.name):void 0,id:this.mapping.id?this.getNestedProperty(r,this.mapping.id):void 0,avatar:this.mapping.avatar?this.getNestedProperty(r,this.mapping.avatar):void 0,username:this.mapping.username?this.getNestedProperty(r,this.mapping.username):void 0,raw:r}:{email:r.email||r.mail||r.emailAddress,name:r.name||r.displayName||r.full_name,id:r.id||r.sub||r.user_id,avatar:r.avatar||r.picture||r.avatar_url,username:r.username||r.login||r.preferred_username,raw:r}}getAdditionalHeaders(){return this.additionalHeaders||{}}getNestedProperty(r,t){return t.split(".").reduce((o,i)=>o==null?void 0:o[i],r)}};var A=class{static createProfileFetcher(e,r,t){if(t!=null&&t.profileUrl)return new h(t.profileUrl,t.profileMapping,t.profileHeaders);switch(e){case "google":return new T;case "github":return new P;case "microsoft":case "outlook":return new v;case "facebook":return new h("https://graph.facebook.com/me?fields=id,name,email,picture");case "generic":default:let o=r.profileUrl||r.userInfoUrl;if(!o)throw new Error(`Profile URL must be provided for ${e} provider`);return new h(o)}}static registerCustomProfileFetcher(e,r){this.customFetchers.set(e,r);}static customFetchers=new Map;static getCustomProfileFetcher(e){return this.customFetchers.get(e)}};var y=class s{static presetConfigs={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",profileUrl:"https://www.googleapis.com/oauth2/v2/userinfo",usePKCE:true,extraAuthParams:{access_type:"offline",prompt:"consent"}},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",profileUrl:"https://api.github.com/user"},microsoft:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true},outlook:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true,extraAuthParams:{prompt:"select_account"}},facebook:{authorizationUrl:"https://www.facebook.com/v12.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v12.0/oauth/access_token",profileUrl:"https://graph.facebook.com/me?fields=id,name,email,picture"}};createProvider(e,r){let t=e!=="generic"?s.presetConfigs[e]||{}:{},o={...t,...r,authorizationUrl:r.authorizationUrl||t.authorizationUrl||"",tokenUrl:r.tokenUrl||t.tokenUrl||"",profileUrl:r.profileUrl||t.profileUrl,extraAuthParams:{...t.extraAuthParams||{},...r.extraAuthParams||{}}},i=A.createProfileFetcher(e,o);return new k(o,void 0,void 0,i)}static registerPreset(e,r){s.presetConfigs[e]=r;}static getPresetConfig(e){return s.presetConfigs[e]}};var l=class{tokens=new Map;states=new Map;profileFetchers=new Map;generateId(){return Math.random().toString(36).substring(2)+Date.now().toString(36)}async saveToken(e){let r=await this.getToken(e.provider,e.email);if(r){let o={...r,...e,id:r.id,createdAt:r.createdAt,updatedAt:new Date};return this.tokens.set(r.id,o),o}let t={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.tokens.set(t.id,t),t}async queryTokens(e){let r=Array.from(this.tokens.values());if(e.id&&(r=r.filter(t=>t.id===e.id)),e.provider&&(r=r.filter(t=>t.provider===e.provider)),e.userId&&(r=r.filter(t=>t.userId===e.userId)),e.email&&(r=r.filter(t=>t.email===e.email)),!e.includeExpired){let t=new Date().getTime();r=r.filter(o=>new Date(o.token.expiresAt).getTime()>=t);}return e.offset!==void 0&&(r=r.slice(e.offset)),e.limit!==void 0&&(r=r.slice(0,e.limit)),r}async getToken(e,r){return (await this.queryTokens({provider:e,email:r,includeExpired:true}))[0]||null}async getTokenById(e){return (await this.queryTokens({id:e,includeExpired:true}))[0]||null}async getTokensByUserId(e){return this.queryTokens({userId:e})}async getTokensByEmail(e){return this.queryTokens({email:e})}async getTokensByProvider(e){return this.queryTokens({provider:e})}async getAccounts(e,r){return this.queryTokens({userId:e,provider:r})}async getTokensForEmail(e,r,t){return (await this.queryTokens({userId:e,provider:r,email:t}))[0]||null}async getTokens(e,r){return this.queryTokens({userId:e,provider:r})}async updateToken(e,r){let t=this.tokens.get(e);if(!t)return null;let o={...t,...r.token&&{token:r.token},...r.metadata&&{metadata:{...t.metadata,...r.metadata}},updatedAt:new Date};return this.tokens.set(e,o),o}async deleteToken(e){return this.tokens.delete(e)}async deleteTokenByProviderEmail(e,r){let t=await this.getToken(e,r);return t?this.tokens.delete(t.id):false}async deleteExpiredTokens(){let e=new Date().getTime(),r=Array.from(this.tokens.entries()).filter(([,t])=>new Date(t.token.expiresAt).getTime()<e).map(([t])=>t);return r.forEach(t=>this.tokens.delete(t)),r.length}async saveAuthorizationState(e){let r={...e,createdAt:new Date(Date.now())};return this.states.set(e.state,r),r}async getAuthorizationState(e){return this.states.get(e)||null}async deleteAuthorizationState(e){return this.states.delete(e)}async cleanupExpiredStates(){let e=new Date().getTime(),r=10*60*1e3,t=Array.from(this.states.entries()).filter(([,o])=>e-o.createdAt.getTime()>r).map(([o])=>o);return t.forEach(o=>this.states.delete(o)),t.length}registerProfileFetcher(e,r){this.profileFetchers.set(e,r);}getProfileFetcher(e){return this.profileFetchers.get(e)}getProfileFetchers(){return new Map(this.profileFetchers)}};var b=()=>crypto.randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),F=s=>crypto.createHash("sha256").update(s).digest("base64url"),C=()=>crypto.randomBytes(16).toString("base64url");var w=class{storage;providerFactory;providers=new Map;providerConfigs=new Map;now;autoRefreshOptions;constructor(e={}){var r,t,o;this.storage=e.storage||new l,this.providerFactory=new y,this.now=Date.now,this.autoRefreshOptions={enabled:((r=e.autoRefresh)==null?void 0:r.enabled)??true,refreshBuffer:((t=e.autoRefresh)==null?void 0:t.refreshBuffer)??10,onRefreshError:(o=e.autoRefresh)==null?void 0:o.onRefreshError},e.providers&&Object.entries(e.providers).forEach(([i,n])=>{this.registerProvider(i,n);});}registerProvider(e,r){this.providerConfigs.set(e,r);let t=this.detectProviderType(e,r),o=this.providerFactory.createProvider(t,r),i=this.storage.getProfileFetcher(e);i&&o.setProfileFetcher(i),this.providers.set(e,o);}async authorize(e){var a;let r=this.providers.get(e.provider);if(!r)throw new Error(`Provider ${e.provider} not found`);let t=C(),o,i;if(((a=this.providerConfigs.get(e.provider))==null?void 0:a.usePKCE)||e.usePKCE){let p=b(),c=F(p);o=r.generateAuthorizationUrl(t,c),i={state:t,codeVerifier:p,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};}else o=r.generateAuthorizationUrl(t),i={state:t,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};return await this.storage.saveAuthorizationState(i),{url:o,state:t}}async handleCallback(e,r){var S,U,O;let t=await this.storage.getAuthorizationState(r);if(!t)throw new Error("Invalid or expired state");let o=(S=t.metadata)==null?void 0:S.provider;if(!o)throw new Error("Provider not found in authorization state");let i=this.providers.get(o);if(!i)throw new Error(`Provider ${o} not found`);let n=await i.exchangeCodeForToken(e,t.codeVerifier),a=(U=t.metadata)==null?void 0:U.userId,p=(O=t.metadata)==null?void 0:O.email;if(!a||!p)throw new Error("User ID and email are required in authorization state");let c;if(i.hasProfileFetcher())try{c=await i.fetchProfile(n.accessToken);}catch(R){console.warn("Failed to fetch user profile:",R);}let x=await this.storage.saveToken({provider:o,userId:a,email:(c==null?void 0:c.email)||p,token:n,metadata:{...t.metadata,profileFetched:!!c}});await this.storage.deleteAuthorizationState(r);let f=this.providerConfigs.get(o);return f!=null&&f.onSuccess&&await f.onSuccess(a,n),{token:x,profile:c}}async getAccessToken(e,r,t={}){return (await this.getValidToken(e,r,t)).accessToken}async getValidToken(e,r,t={}){let o=await this.storage.getToken(e,r);if(!o)throw new Error(`No token found for provider ${e} and email ${r}`);if(!(t.autoRefresh!==false&&this.isTokenExpired(o.token,t)))return o.token;if(!o.token.refreshToken)throw new Error("Token expired and no refresh token available");let n=this.providers.get(e);if(!n)throw new Error(`Provider ${e} not found`);let a=await n.refreshToken(o.token.refreshToken);return await this.storage.updateToken(o.id,{token:a}),a}async queryTokens(e){let r=this.autoRefreshOptions.enabled&&!e.includeExpired?{...e,includeExpired:true}:e,t=await this.storage.queryTokens(r);return this.autoRefreshOptions.enabled&&!e.includeExpired?(await this.refreshTokensIfNeeded(t)).filter(i=>new Date(i.token.expiresAt).getTime()>this.now()):t}async getTokensByUserId(e){return this.queryTokens({userId:e})}async getTokensByEmail(e){return this.queryTokens({email:e})}async deleteToken(e,r){return this.storage.deleteTokenByProviderEmail(e,r)}async cleanupExpiredTokens(){return this.storage.deleteExpiredTokens()}async cleanupExpiredStates(){return this.storage.cleanupExpiredStates()}isTokenExpired(e,r={}){let{expirationBuffer:t=300}=r;if(e.createdAt&&e.expiresIn!==void 0){let n=e.createdAt+e.expiresIn*1e3;return this.now()+t*1e3>=n}let o=new Date(e.expiresAt).getTime();return this.now()+t*1e3>=o}detectProviderType(e,r){var o;let t=r.authorizationUrl.toLowerCase();return t.includes("accounts.google.com")?"google":t.includes("github.com")?"github":t.includes("facebook.com")?"facebook":t.includes("microsoft.com")||t.includes("microsoftonline.com")?e.toLowerCase().includes("outlook")||(o=r.scopes)!=null&&o.some(i=>i.includes("outlook"))?"outlook":"microsoft":"generic"}async refreshTokensIfNeeded(e){let r=e.map(async t=>{if(this.shouldRefreshToken(t))try{let o=this.providers.get(t.provider);if(!o)return console.warn(`Provider ${t.provider} not found for token refresh`),t;if(!t.token.refreshToken)return console.warn(`No refresh token available for ${t.provider}:${t.email}`),t;let i=await o.refreshToken(t.token.refreshToken);return await this.storage.updateToken(t.id,{token:i})||t}catch(o){return this.autoRefreshOptions.onRefreshError&&this.autoRefreshOptions.onRefreshError(o,t),console.error(`Failed to refresh token for ${t.provider}:${t.email}:`,o),t}return t});return Promise.all(r)}shouldRefreshToken(e){if(!e.token.refreshToken)return false;let r=new Date(e.token.expiresAt).getTime(),t=this.now();if(t>=r)return true;let o=this.autoRefreshOptions.refreshBuffer*60*1e3,i=r-o;return t>=i}updateAutoRefreshOptions(e){this.autoRefreshOptions={...this.autoRefreshOptions,...e};}};var ge=(s,e)=>ironSession.sealData(s,{password:e}),ke=(s,e)=>ironSession.unsealData(s,{password:e});
2
+ exports.BaseProfileFetcher=d;exports.GenericOAuth2Provider=k;exports.GenericProfileFetcher=h;exports.GitHubProfileFetcher=P;exports.GoogleProfileFetcher=T;exports.InMemoryStorageAdapter=l;exports.MicrosoftProfileFetcher=v;exports.OAuth2Client=w;exports.OAuth2Provider=u;exports.ProfileFetcherFactory=A;exports.StandardAuthorizationUrlStrategy=m;exports.StandardTokenExchangeStrategy=g;exports.createCodeChallenge=F;exports.createCodeVerifier=b;exports.generateState=C;exports.seal=ge;exports.unseal=ke;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","query","tokens","t","provider","email","id","userId","update","token","expiredTokens","newState","maxAge","expiredStates","fetcher","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","customFetcher","authUrl","authState","_b","_c","providerInstance","profile","error","savedToken","storedToken","expirationBuffer","expiresAt","s","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.cjs","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport {\n StorageAdapter,\n StoredToken,\n SaveTokenInput,\n UpdateTokenInput,\n TokenQuery,\n} from './interfaces';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n private profileFetchers: Map<string, BaseProfileFetcher> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async queryTokens(query: TokenQuery): Promise<StoredToken[]> {\n let tokens = Array.from(this.tokens.values());\n\n // Apply filters\n if (query.id) {\n tokens = tokens.filter((t) => t.id === query.id);\n }\n if (query.provider) {\n tokens = tokens.filter((t) => t.provider === query.provider);\n }\n if (query.userId) {\n tokens = tokens.filter((t) => t.userId === query.userId);\n }\n if (query.email) {\n tokens = tokens.filter((t) => t.email === query.email);\n }\n\n // Filter out expired tokens unless explicitly requested\n if (!query.includeExpired) {\n const now = new Date().getTime();\n tokens = tokens.filter((t) => {\n const expiresAt = new Date(t.token.expiresAt).getTime();\n return expiresAt >= now;\n });\n }\n\n // Apply pagination\n if (query.offset !== undefined) {\n tokens = tokens.slice(query.offset);\n }\n if (query.limit !== undefined) {\n tokens = tokens.slice(0, query.limit);\n }\n\n return tokens;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ provider, email, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ id, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId });\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.queryTokens({ email });\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ provider });\n }\n\n async getAccounts(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async getTokensForEmail(\n userId: string,\n provider: string,\n email: string,\n ): Promise<StoredToken | null> {\n const results = await this.queryTokens({ userId, provider, email });\n return results[0] || null;\n }\n\n async getTokens(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n\n // Profile fetcher operations\n registerProfileFetcher(providerName: string, fetcher: BaseProfileFetcher): void {\n this.profileFetchers.set(providerName, fetcher);\n }\n\n getProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.profileFetchers.get(providerName);\n }\n\n getProfileFetchers(): Map<string, BaseProfileFetcher> {\n return new Map(this.profileFetchers);\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n\n // Check if storage has a custom profile fetcher for this provider\n const customFetcher = this.storage.getProfileFetcher(name);\n if (customFetcher) {\n provider.setProfileFetcher(customFetcher);\n }\n\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email: profile?.email || email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.storage.getTokensByUserId(userId);\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.storage.getTokensByEmail(email);\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
1
+ {"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","query","tokens","t","provider","email","id","userId","update","token","expiredTokens","newState","maxAge","expiredStates","fetcher","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","_b","_c","customFetcher","authUrl","authState","providerInstance","profile","error","savedToken","storedToken","queryWithExpired","expirationBuffer","expiresAt","s","refreshPromises","bufferMs","shouldRefreshAt","seal","d","sealData","unseal","unsealData"],"mappings":"8EAGO,IAAMA,EAAN,KAA2E,CACtE,cAAA,CAAeC,CAAAA,CAAoD,CAM3E,OALiB,MAAA,CAAO,OAAA,CAAQA,CAAM,EACnC,MAAA,CAAO,CAAC,EAAGC,CAAK,IAAMA,CAAAA,GAAU,MAAS,CAAA,CAEzC,GAAA,CAAI,CAAC,CAACC,CAAAA,CAAKD,CAAK,CAAA,GAAM,CAAA,EAAGC,CAAG,CAAA,CAAA,EAAI,kBAAA,CAAmBD,CAAe,CAAC,EAAE,CAAA,CAExD,IAAA,CAAK,GAAG,CAC1B,CAEA,yBAAyBE,CAAAA,CAAsBC,CAAAA,CAAeC,CAAAA,CAAgC,CAC5F,IAAML,CAAAA,CAA6C,CACjD,UAAWG,CAAAA,CAAO,QAAA,CAClB,aAAcA,CAAAA,CAAO,WAAA,CACrB,aAAA,CAAe,MAAA,CACf,MAAOA,CAAAA,CAAO,MAAA,CAAO,KAAK,GAAG,CAAA,CAC7B,MAAAC,CACF,CAAA,CAAA,CAGKD,CAAAA,CAAO,OAAA,EAAWA,EAAO,IAAA,GAASE,CAAAA,GACrCL,EAAO,cAAA,CAAiBK,CAAAA,CACxBL,EAAO,qBAAA,CAAwB,MAAA,CAAA,CAIjC,IAAMM,CAAAA,CAAc,CAClB,GAAGH,CAAAA,CAAO,iBACV,GAAGA,CAAAA,CAAO,eACZ,CAAA,CAEA,OAAA,MAAA,CAAO,MAAA,CAAOH,CAAAA,CAAQM,CAAW,CAAA,CAE1B,CAAA,EAAGH,EAAO,gBAAgB,CAAA,CAAA,EAAI,KAAK,cAAA,CAAeH,CAAM,CAAC,CAAA,CAClE,CACF,ECnCO,IAAMO,EAAN,KAAqE,CAChE,eAAeP,CAAAA,CAAoD,CAK3E,OAJiB,MAAA,CAAO,QAAQA,CAAM,CAAA,CACnC,OAAO,CAAC,EAAGC,CAAK,CAAA,GAAMA,CAAAA,GAAU,MAAS,EACzC,GAAA,CAAI,CAAC,CAACC,CAAAA,CAAKD,CAAK,IAAM,CAAA,EAAGC,CAAG,CAAA,CAAA,EAAI,kBAAA,CAAmBD,CAAe,CAAC,CAAA,CAAE,EAExD,IAAA,CAAK,GAAG,CAC1B,CAEA,MAAM,oBAAA,CACJO,CAAAA,CACAL,EACAM,CAAAA,CACsB,CACtB,IAAMT,CAAAA,CAA6C,CACjD,WAAY,oBAAA,CACZ,IAAA,CAAAQ,CAAAA,CACA,YAAA,CAAcL,EAAO,WAAA,CACrB,SAAA,CAAWA,EAAO,QACpB,CAAA,CAAA,CAGKA,EAAO,OAAA,EAAWA,CAAAA,CAAO,IAAA,GAASM,CAAAA,CACrCT,EAAO,aAAA,CAAgBS,CAAAA,CACdN,EAAO,YAAA,GAChBH,CAAAA,CAAO,cAAgBG,CAAAA,CAAO,YAAA,CAAA,CAGhC,IAAMO,CAAAA,CAAW,MAAM,KAAA,CAAMP,CAAAA,CAAO,QAAA,CAAU,CAC5C,OAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,mCAClB,CAAA,CACA,IAAA,CAAM,KAAK,cAAA,CAAeH,CAAM,CAClC,CAAC,CAAA,CAED,GAAI,CAACU,EAAS,EAAA,CAAI,CAChB,IAAMC,CAAAA,CAAY,MAAMD,EAAS,IAAA,EAAK,CACtC,MAAM,IAAI,MAAM,CAAA,uBAAA,EAA0BA,CAAAA,CAAS,UAAU,CAAA,GAAA,EAAMC,CAAS,EAAE,CAChF,CAEA,IAAMC,CAAAA,CAAO,MAAMF,CAAAA,CAAS,IAAA,GAGtBG,CAAAA,CAAYV,CAAAA,CAAO,gBAAkBS,CAAAA,CAAKT,CAAAA,CAAO,eAAe,CAAA,CAAIS,EAEpEE,CAAAA,CAAM,IAAA,CAAK,KAAI,CACfC,CAAAA,CAAYF,EAAU,UAAA,EAAc,IAAA,CAE1C,OAAO,CACL,YAAaA,CAAAA,CAAU,YAAA,CACvB,aAAcA,CAAAA,CAAU,aAAA,CACxB,UAAW,IAAI,IAAA,CAAKC,CAAAA,CAAMC,CAAAA,CAAY,GAAI,CAAA,CAC1C,SAAA,CAAWA,EACX,SAAA,CAAWF,CAAAA,CAAU,YAAc,QAAA,CACnC,KAAA,CAAOA,CAAAA,CAAU,KAAA,CACjB,UAAWC,CAAAA,CACX,GAAA,CAAKF,CACP,CACF,CAEA,MAAM,YAAA,CAAaI,CAAAA,CAAsBb,CAAAA,CAA4C,CACnF,IAAMH,CAAAA,CAA6C,CACjD,WAAY,eAAA,CACZ,aAAA,CAAegB,EACf,SAAA,CAAWb,CAAAA,CAAO,QACpB,CAAA,CAGI,EAAEA,CAAAA,CAAO,OAAA,EAAWA,EAAO,IAAA,CAAA,EAASA,CAAAA,CAAO,eAC7CH,CAAAA,CAAO,aAAA,CAAgBG,CAAAA,CAAO,YAAA,CAAA,CAGhC,IAAMO,CAAAA,CAAW,MAAM,MAAMP,CAAAA,CAAO,QAAA,CAAU,CAC5C,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,eAAgB,mCAClB,CAAA,CACA,KAAM,IAAA,CAAK,cAAA,CAAeH,CAAM,CAClC,CAAC,CAAA,CAED,GAAI,CAACU,CAAAA,CAAS,EAAA,CAAI,CAChB,IAAMC,CAAAA,CAAY,MAAMD,CAAAA,CAAS,IAAA,EAAK,CACtC,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyBA,EAAS,UAAU,CAAA,GAAA,EAAMC,CAAS,CAAA,CAAE,CAC/E,CAEA,IAAMC,EAAO,MAAMF,CAAAA,CAAS,MAAK,CAC3BG,CAAAA,CAAYV,EAAO,eAAA,CAAkBS,CAAAA,CAAKT,CAAAA,CAAO,eAAe,EAAIS,CAAAA,CAEpEE,CAAAA,CAAM,IAAA,CAAK,GAAA,GACXC,CAAAA,CAAYF,CAAAA,CAAU,UAAA,EAAc,IAAA,CAE1C,OAAO,CACL,WAAA,CAAaA,EAAU,YAAA,CACvB,YAAA,CAAcA,EAAU,aAAA,EAAiBG,CAAAA,CACzC,SAAA,CAAW,IAAI,KAAKF,CAAAA,CAAMC,CAAAA,CAAY,GAAI,CAAA,CAC1C,SAAA,CAAWA,EACX,SAAA,CAAWF,CAAAA,CAAU,UAAA,EAAc,QAAA,CACnC,MAAOA,CAAAA,CAAU,KAAA,CACjB,UAAWC,CAAAA,CACX,GAAA,CAAKF,CACP,CACF,CACF,ECnGO,IAAeK,EAAf,KAA8B,CAKnC,YACYd,CAAAA,CACVe,CAAAA,CACAC,EACAC,CAAAA,CACA,CAJU,IAAA,CAAA,MAAA,CAAAjB,CAAAA,CAKV,KAAK,eAAA,CAAkBe,CAAAA,EAAmB,KAAK,8BAAA,EAA+B,CAC9E,KAAK,aAAA,CAAgBC,CAAAA,EAAiB,IAAA,CAAK,2BAAA,GAC3C,IAAA,CAAK,cAAA,CAAiBC,EACxB,CAbU,eAAA,CACA,cACA,cAAA,CAkBV,MAAM,YAAA,CAAaC,CAAAA,CAA2C,CAC5D,GAAI,CAAC,KAAK,cAAA,CACR,MAAM,IAAI,KAAA,CAAM,kDAAkD,CAAA,CAEpE,OAAO,KAAK,cAAA,CAAe,aAAA,CAAcA,CAAW,CACtD,CAEA,oBAA6B,CAC3B,GAAI,CAAC,IAAA,CAAK,eACR,MAAM,IAAI,MAAM,kDAAkD,CAAA,CAEpE,OAAO,IAAA,CAAK,cAAA,CAAe,WAAA,EAC7B,CAEA,iBAAA,CAAkBD,CAAAA,CAA0C,CAC1D,IAAA,CAAK,cAAA,CAAiBA,EACxB,CAEA,iBAAA,EAA6B,CAC3B,OAAO,CAAC,CAAC,IAAA,CAAK,cAChB,CAEA,wBAAA,CAAyBhB,EAAeC,CAAAA,CAAgC,CACtE,OAAO,IAAA,CAAK,gBAAgB,wBAAA,CAAyB,IAAA,CAAK,OAAQD,CAAAA,CAAOC,CAAa,CACxF,CAEA,MAAM,oBAAA,CAAqBG,CAAAA,CAAcC,EAA6C,CACpF,OAAO,KAAK,aAAA,CAAc,oBAAA,CAAqBD,EAAM,IAAA,CAAK,MAAA,CAAQC,CAAY,CAChF,CAEA,MAAM,YAAA,CAAaO,EAA4C,CAC7D,OAAO,KAAK,aAAA,CAAc,YAAA,CAAaA,CAAAA,CAAc,IAAA,CAAK,MAAM,CAClE,CACF,ECtDO,IAAMM,CAAAA,CAAN,cAAoCL,CAAe,CACxD,WAAA,CACEd,CAAAA,CACAe,EACAC,CAAAA,CACAC,CAAAA,CACA,CACA,KAAA,CAAMjB,EAAQe,CAAAA,CAAiBC,CAAAA,CAAeC,CAAc,EAC9D,CAEU,8BAAA,EAA2D,CACnE,OAAO,IAAIrB,CACb,CAEU,2BAAA,EAAqD,CAC7D,OAAO,IAAIQ,CACb,CACF,MCtBsBgB,CAAAA,CAAf,KAAkC,CACvC,WAAA,CAAsBC,CAAAA,CAAyB,CAAzB,IAAA,CAAA,eAAA,CAAAA,EAA0B,CAOhD,MAAM,cAAcH,CAAAA,CAA2C,CAC7D,IAAMX,CAAAA,CAAW,MAAM,KAAA,CAAM,IAAA,CAAK,gBAAiB,CACjD,OAAA,CAAS,CACP,aAAA,CAAe,CAAA,OAAA,EAAUW,CAAW,CAAA,CAAA,CACpC,MAAA,CAAQ,kBAAA,CACR,GAAG,KAAK,oBAAA,EACV,CACF,CAAC,CAAA,CAED,GAAI,CAACX,CAAAA,CAAS,EAAA,CACZ,MAAM,IAAI,KAAA,CACR,CAAA,6BAAA,EAAgC,KAAK,eAAe,CAAA,EAAA,EAAKA,EAAS,UAAU,CAAA,CAC9E,CAAA,CAGF,IAAMe,EAAU,MAAMf,CAAAA,CAAS,MAAK,CACpC,OAAO,KAAK,gBAAA,CAAiBe,CAAO,CACtC,CAYU,sBAA+C,CACvD,OAAO,EACT,CAKA,aAAsB,CACpB,OAAO,IAAA,CAAK,eACd,CACF,EC9CO,IAAMC,EAAN,cAAmCH,CAAmB,CAC3D,WAAA,EAAc,CACZ,KAAA,CAAM,+CAA+C,EACvD,CAEA,gBAAA,CAAiBE,EAA2B,CAC1C,OAAO,CACL,KAAA,CAAOA,CAAAA,CAAQ,KAAA,CACf,IAAA,CAAMA,EAAQ,IAAA,CACd,EAAA,CAAIA,EAAQ,EAAA,CACZ,MAAA,CAAQA,EAAQ,OAAA,CAChB,QAAA,CAAUA,CAAAA,CAAQ,KAAA,CAClB,IAAKA,CACP,CACF,CACF,ECfO,IAAME,EAAN,cAAmCJ,CAAmB,CAC3D,WAAA,EAAc,CACZ,KAAA,CAAM,6BAA6B,EACrC,CAEU,gBAAA,CAAiBE,EAA2B,CARxD,IAAAG,CAAAA,CASI,OAAO,CACL,KAAA,CAAOH,CAAAA,CAAQ,MACf,IAAA,CAAMA,CAAAA,CAAQ,MAAQA,CAAAA,CAAQ,KAAA,CAC9B,EAAA,CAAA,CAAIG,CAAAA,CAAAH,EAAQ,EAAA,GAAR,IAAA,CAAA,MAAA,CAAAG,EAAY,QAAA,EAAA,CAChB,MAAA,CAAQH,EAAQ,UAAA,CAChB,QAAA,CAAUA,CAAAA,CAAQ,KAAA,CAClB,IAAKA,CACP,CACF,CAEU,oBAAA,EAA+C,CACvD,OAAO,CACL,YAAA,CAAc,sBAChB,CACF,CACF,MCrBaI,CAAAA,CAAN,cAAsCN,CAAmB,CAC9D,WAAA,EAAc,CACZ,KAAA,CAAM,qCAAqC,EAC7C,CAEU,iBAAiBE,CAAAA,CAA2B,CACpD,OAAO,CACL,KAAA,CAAOA,CAAAA,CAAQ,IAAA,EAAQA,EAAQ,iBAAA,CAC/B,IAAA,CAAMA,EAAQ,WAAA,CACd,EAAA,CAAIA,EAAQ,EAAA,CACZ,MAAA,CAAQ,MAAA,CACR,QAAA,CAAUA,EAAQ,iBAAA,CAClB,GAAA,CAAKA,CACP,CACF,CACF,ECPO,IAAMK,CAAAA,CAAN,cAAoCP,CAAmB,CAC5D,WAAA,CACEC,CAAAA,CACQO,EACAC,CAAAA,CACR,CACA,MAAMR,CAAe,CAAA,CAHb,IAAA,CAAA,OAAA,CAAAO,CAAAA,CACA,uBAAAC,EAGV,CAEU,iBAAiBP,CAAAA,CAA2B,CACpD,OAAI,IAAA,CAAK,OAAA,CACA,CACL,KAAA,CAAO,KAAK,iBAAA,CAAkBA,CAAAA,CAAS,KAAK,OAAA,CAAQ,KAAK,EACzD,IAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAO,KAAK,iBAAA,CAAkBA,CAAAA,CAAS,KAAK,OAAA,CAAQ,IAAI,EAAI,MAAA,CAC/E,EAAA,CAAI,IAAA,CAAK,OAAA,CAAQ,GAAK,IAAA,CAAK,iBAAA,CAAkBA,EAAS,IAAA,CAAK,OAAA,CAAQ,EAAE,CAAA,CAAI,MAAA,CACzE,MAAA,CAAQ,IAAA,CAAK,QAAQ,MAAA,CACjB,IAAA,CAAK,kBAAkBA,CAAAA,CAAS,IAAA,CAAK,QAAQ,MAAM,CAAA,CACnD,MAAA,CACJ,QAAA,CAAU,KAAK,OAAA,CAAQ,QAAA,CACnB,KAAK,iBAAA,CAAkBA,CAAAA,CAAS,KAAK,OAAA,CAAQ,QAAQ,CAAA,CACrD,MAAA,CACJ,IAAKA,CACP,CAAA,CAIK,CACL,KAAA,CAAOA,CAAAA,CAAQ,OAASA,CAAAA,CAAQ,IAAA,EAAQA,CAAAA,CAAQ,YAAA,CAChD,KAAMA,CAAAA,CAAQ,IAAA,EAAQA,EAAQ,WAAA,EAAeA,CAAAA,CAAQ,UACrD,EAAA,CAAIA,CAAAA,CAAQ,EAAA,EAAMA,CAAAA,CAAQ,KAAOA,CAAAA,CAAQ,OAAA,CACzC,OAAQA,CAAAA,CAAQ,MAAA,EAAUA,EAAQ,OAAA,EAAWA,CAAAA,CAAQ,UAAA,CACrD,QAAA,CAAUA,EAAQ,QAAA,EAAYA,CAAAA,CAAQ,OAASA,CAAAA,CAAQ,kBAAA,CACvD,IAAKA,CACP,CACF,CAEU,oBAAA,EAA+C,CACvD,OAAO,IAAA,CAAK,iBAAA,EAAqB,EACnC,CAEQ,iBAAA,CAAkBQ,CAAAA,CAAUC,CAAAA,CAAmB,CACrD,OAAOA,CAAAA,CAAK,MAAM,GAAG,CAAA,CAAE,OAAO,CAACC,CAAAA,CAASjC,CAAAA,GAAQiC,CAAAA,EAAA,YAAAA,CAAAA,CAAUjC,CAAAA,CAAAA,CAAM+B,CAAG,CACrE,CACF,ECxCO,IAAMG,CAAAA,CAAN,KAA4B,CACjC,OAAO,oBAAA,CACLC,CAAAA,CACAlC,EACAmC,CAAAA,CACoB,CAEpB,GAAIA,CAAAA,EAAA,IAAA,EAAAA,CAAAA,CAAS,UAAA,CACX,OAAO,IAAIR,CAAAA,CACTQ,EAAQ,UAAA,CACRA,CAAAA,CAAQ,eACRA,CAAAA,CAAQ,cACV,CAAA,CAIF,OAAQD,GACN,KAAK,SACH,OAAO,IAAIX,EACb,KAAK,QAAA,CACH,OAAO,IAAIC,EACb,KAAK,WAAA,CACL,KAAK,SAAA,CACH,OAAO,IAAIE,CAAAA,CACb,KAAK,UAAA,CACH,OAAO,IAAIC,CAAAA,CACT,4DACF,EACF,KAAK,SAAA,CACL,QAEE,IAAMS,CAAAA,CAAapC,CAAAA,CAAO,UAAA,EAAcA,EAAO,WAAA,CAC/C,GAAI,CAACoC,CAAAA,CACH,MAAM,IAAI,KAAA,CAAM,CAAA,iCAAA,EAAoCF,CAAY,CAAA,SAAA,CAAW,EAE7E,OAAO,IAAIP,EAAsBS,CAAU,CAC/C,CACF,CAEA,OAAO,4BAAA,CACLC,CAAAA,CACApB,EACM,CAEN,IAAA,CAAK,eAAe,GAAA,CAAIoB,CAAAA,CAAcpB,CAAc,EACtD,CAEA,OAAe,cAAA,CAAiB,IAAI,GAAA,CAEpC,OAAO,wBAAwBoB,CAAAA,CAAsD,CACnF,OAAO,IAAA,CAAK,cAAA,CAAe,GAAA,CAAIA,CAAY,CAC7C,CACF,ECvDO,IAAMC,CAAAA,CAAN,MAAMC,CAAiD,CAC5D,OAAe,aAAA,CAAuD,CACpE,OAAQ,CACN,gBAAA,CAAkB,+CAClB,QAAA,CAAU,qCAAA,CACV,WAAY,+CAAA,CACZ,OAAA,CAAS,IAAA,CACT,eAAA,CAAiB,CACf,WAAA,CAAa,SAAA,CACb,OAAQ,SACV,CACF,EACA,MAAA,CAAQ,CACN,gBAAA,CAAkB,0CAAA,CAClB,SAAU,6CAAA,CACV,UAAA,CAAY,6BACd,CAAA,CACA,SAAA,CAAW,CACT,gBAAA,CAAkB,gEAAA,CAClB,QAAA,CAAU,4DAAA,CACV,WAAY,qCAAA,CACZ,OAAA,CAAS,IACX,CAAA,CACA,QAAS,CACP,gBAAA,CAAkB,gEAAA,CAClB,QAAA,CAAU,6DACV,UAAA,CAAY,qCAAA,CACZ,QAAS,IAAA,CACT,eAAA,CAAiB,CACf,MAAA,CAAQ,gBACV,CACF,CAAA,CACA,SAAU,CACR,gBAAA,CAAkB,8CAClB,QAAA,CAAU,qDAAA,CACV,WAAY,4DACd,CACF,CAAA,CAEA,cAAA,CAAeC,EAAoBxC,CAAAA,CAAsC,CACvE,IAAMyC,CAAAA,CAAeD,CAAAA,GAAS,UAAYD,CAAAA,CAAsB,aAAA,CAAcC,CAAI,CAAA,EAAK,EAAC,CAAI,GAGtFE,CAAAA,CAA6B,CACjC,GAAGD,CAAAA,CACH,GAAGzC,CAAAA,CAEH,gBAAA,CAAkBA,EAAO,gBAAA,EAAoByC,CAAAA,CAAa,kBAAoB,EAAA,CAC9E,QAAA,CAAUzC,EAAO,QAAA,EAAYyC,CAAAA,CAAa,QAAA,EAAY,EAAA,CACtD,WAAYzC,CAAAA,CAAO,UAAA,EAAcyC,EAAa,UAAA,CAC9C,eAAA,CAAiB,CACf,GAAIA,CAAAA,CAAa,eAAA,EAAmB,GACpC,GAAIzC,CAAAA,CAAO,iBAAmB,EAChC,CACF,CAAA,CAEMiB,CAAAA,CAAiBgB,CAAAA,CAAsB,oBAAA,CAAqBO,EAAME,CAAY,CAAA,CAEpF,OAAO,IAAIvB,CAAAA,CAAsBuB,EAAc,MAAA,CAAW,MAAA,CAAWzB,CAAc,CACrF,CAEA,OAAO,cAAA,CAAe0B,EAAc3C,CAAAA,CAAqC,CACvEuC,EAAsB,aAAA,CAAcI,CAAI,CAAA,CAAI3C,EAC9C,CAEA,OAAO,eAAA,CAAgB2C,EAAiD,CACtE,OAAOJ,EAAsB,aAAA,CAAcI,CAAI,CACjD,CACF,ECrEO,IAAMC,CAAAA,CAAN,KAAuD,CACpD,MAAA,CAAmC,IAAI,GAAA,CACvC,MAAA,CAA0C,IAAI,GAAA,CAC9C,gBAAmD,IAAI,GAAA,CAEvD,YAAqB,CAC3B,OAAO,KAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,EAAE,SAAA,CAAU,CAAC,EAAI,IAAA,CAAK,GAAA,GAAM,QAAA,CAAS,EAAE,CACzE,CAGA,MAAM,SAAA,CAAUC,CAAAA,CAA6C,CAE3D,IAAMC,CAAAA,CAAgB,MAAM,IAAA,CAAK,QAAA,CAASD,CAAAA,CAAM,QAAA,CAAUA,EAAM,KAAK,CAAA,CAErE,GAAIC,CAAAA,CAAe,CAEjB,IAAMC,CAAAA,CAA4B,CAChC,GAAGD,CAAAA,CACH,GAAGD,CAAAA,CACH,EAAA,CAAIC,CAAAA,CAAc,EAAA,CAClB,UAAWA,CAAAA,CAAc,SAAA,CACzB,SAAA,CAAW,IAAI,IACjB,CAAA,CACA,OAAA,IAAA,CAAK,OAAO,GAAA,CAAIA,CAAAA,CAAc,GAAIC,CAAY,CAAA,CACvCA,CACT,CAGA,IAAMC,CAAAA,CAAwB,CAC5B,GAAGH,CAAAA,CACH,EAAA,CAAI,KAAK,UAAA,EAAW,CACpB,SAAA,CAAW,IAAI,KACf,SAAA,CAAW,IAAI,IACjB,CAAA,CACA,OAAA,IAAA,CAAK,OAAO,GAAA,CAAIG,CAAAA,CAAS,EAAA,CAAIA,CAAQ,EAC9BA,CACT,CAEA,MAAM,WAAA,CAAYC,CAAAA,CAA2C,CAC3D,IAAIC,CAAAA,CAAS,KAAA,CAAM,IAAA,CAAK,KAAK,MAAA,CAAO,MAAA,EAAQ,CAAA,CAiB5C,GAdID,EAAM,EAAA,GACRC,CAAAA,CAASA,CAAAA,CAAO,MAAA,CAAQ,GAAM,CAAA,CAAE,EAAA,GAAOD,EAAM,EAAE,CAAA,CAAA,CAE7CA,EAAM,QAAA,GACRC,CAAAA,CAASA,CAAAA,CAAO,MAAA,CAAQ,GAAM,CAAA,CAAE,QAAA,GAAaD,EAAM,QAAQ,CAAA,CAAA,CAEzDA,EAAM,MAAA,GACRC,CAAAA,CAASA,CAAAA,CAAO,MAAA,CAAQ,GAAM,CAAA,CAAE,MAAA,GAAWD,EAAM,MAAM,CAAA,CAAA,CAErDA,EAAM,KAAA,GACRC,CAAAA,CAASA,CAAAA,CAAO,MAAA,CAAQ,GAAM,CAAA,CAAE,KAAA,GAAUD,EAAM,KAAK,CAAA,CAAA,CAInD,CAACA,CAAAA,CAAM,cAAA,CAAgB,CACzB,IAAMtC,EAAM,IAAI,IAAA,GAAO,OAAA,EAAQ,CAC/BuC,EAASA,CAAAA,CAAO,MAAA,CAAQC,CAAAA,EACJ,IAAI,KAAKA,CAAAA,CAAE,KAAA,CAAM,SAAS,CAAA,CAAE,OAAA,IAC1BxC,CACrB,EACH,CAGA,OAAIsC,EAAM,MAAA,GAAW,MAAA,GACnBC,EAASA,CAAAA,CAAO,KAAA,CAAMD,EAAM,MAAM,CAAA,CAAA,CAEhCA,CAAAA,CAAM,KAAA,GAAU,SAClBC,CAAAA,CAASA,CAAAA,CAAO,MAAM,CAAA,CAAGD,CAAAA,CAAM,KAAK,CAAA,CAAA,CAG/BC,CACT,CAEA,MAAM,SAASE,CAAAA,CAAkBC,CAAAA,CAA4C,CAE3E,OAAA,CADgB,MAAM,KAAK,WAAA,CAAY,CAAE,QAAA,CAAAD,CAAAA,CAAU,MAAAC,CAAAA,CAAO,cAAA,CAAgB,IAAK,CAAC,CAAA,EACjE,CAAC,CAAA,EAAK,IACvB,CAEA,MAAM,aAAaC,CAAAA,CAAyC,CAE1D,OAAA,CADgB,MAAM,KAAK,WAAA,CAAY,CAAE,EAAA,CAAAA,CAAAA,CAAI,eAAgB,IAAK,CAAC,GACpD,CAAC,CAAA,EAAK,IACvB,CAEA,MAAM,iBAAA,CAAkBC,CAAAA,CAAwC,CAC9D,OAAO,IAAA,CAAK,YAAY,CAAE,MAAA,CAAAA,CAAO,CAAC,CACpC,CAEA,MAAM,iBAAiBF,CAAAA,CAAuC,CAC5D,OAAO,IAAA,CAAK,WAAA,CAAY,CAAE,KAAA,CAAAA,CAAM,CAAC,CACnC,CAEA,MAAM,mBAAA,CAAoBD,EAA0C,CAClE,OAAO,KAAK,WAAA,CAAY,CAAE,QAAA,CAAAA,CAAS,CAAC,CACtC,CAEA,MAAM,WAAA,CAAYG,CAAAA,CAAgBH,EAA0C,CAC1E,OAAO,IAAA,CAAK,WAAA,CAAY,CAAE,MAAA,CAAAG,CAAAA,CAAQ,SAAAH,CAAS,CAAC,CAC9C,CAEA,MAAM,iBAAA,CACJG,CAAAA,CACAH,EACAC,CAAAA,CAC6B,CAE7B,QADgB,MAAM,IAAA,CAAK,YAAY,CAAE,MAAA,CAAAE,CAAAA,CAAQ,QAAA,CAAAH,EAAU,KAAA,CAAAC,CAAM,CAAC,CAAA,EACnD,CAAC,GAAK,IACvB,CAEA,MAAM,SAAA,CAAUE,EAAgBH,CAAAA,CAA0C,CACxE,OAAO,IAAA,CAAK,WAAA,CAAY,CAAE,MAAA,CAAAG,CAAAA,CAAQ,QAAA,CAAAH,CAAS,CAAC,CAC9C,CAEA,MAAM,WAAA,CAAYE,CAAAA,CAAYE,EAAuD,CACnF,IAAMC,CAAAA,CAAQ,IAAA,CAAK,OAAO,GAAA,CAAIH,CAAE,EAChC,GAAI,CAACG,EAAO,OAAO,IAAA,CAEnB,IAAMV,CAAAA,CAA4B,CAChC,GAAGU,CAAAA,CACH,GAAID,CAAAA,CAAO,KAAA,EAAS,CAAE,KAAA,CAAOA,CAAAA,CAAO,KAAM,CAAA,CAC1C,GAAIA,CAAAA,CAAO,QAAA,EAAY,CAAE,QAAA,CAAU,CAAE,GAAGC,CAAAA,CAAM,QAAA,CAAU,GAAGD,CAAAA,CAAO,QAAS,CAAE,CAAA,CAC7E,UAAW,IAAI,IACjB,EACA,OAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAIF,CAAAA,CAAIP,CAAY,CAAA,CACzBA,CACT,CAEA,MAAM,WAAA,CAAYO,EAA8B,CAC9C,OAAO,IAAA,CAAK,MAAA,CAAO,OAAOA,CAAE,CAC9B,CAEA,MAAM,2BAA2BF,CAAAA,CAAkBC,CAAAA,CAAiC,CAClF,IAAMI,EAAQ,MAAM,IAAA,CAAK,SAASL,CAAAA,CAAUC,CAAK,EACjD,OAAKI,CAAAA,CACE,IAAA,CAAK,MAAA,CAAO,OAAOA,CAAAA,CAAM,EAAE,EADf,KAErB,CAEA,MAAM,mBAAA,EAAuC,CAC3C,IAAM9C,CAAAA,CAAM,IAAI,IAAA,EAAK,CAAE,SAAQ,CACzB+C,CAAAA,CAAgB,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,CAAA,CACnD,MAAA,CAAO,CAAC,EAAGD,CAAK,CAAA,GACG,IAAI,IAAA,CAAKA,CAAAA,CAAM,MAAM,SAAS,CAAA,CAAE,SAAQ,CACvC9C,CACpB,EACA,GAAA,CAAI,CAAC,CAAC2C,CAAE,IAAMA,CAAE,CAAA,CAEnB,OAAAI,CAAAA,CAAc,OAAA,CAASJ,GAAO,IAAA,CAAK,MAAA,CAAO,MAAA,CAAOA,CAAE,CAAC,CAAA,CAC7CI,CAAAA,CAAc,MACvB,CAGA,MAAM,uBACJzD,CAAAA,CAC6B,CAC7B,IAAM0D,CAAAA,CAA+B,CACnC,GAAG1D,CAAAA,CACH,UAAW,IAAI,IAAA,CAAK,KAAK,GAAA,EAAK,CAChC,CAAA,CACA,YAAK,MAAA,CAAO,GAAA,CAAIA,EAAM,KAAA,CAAO0D,CAAQ,EAC9BA,CACT,CAEA,MAAM,qBAAA,CAAsB1D,EAAmD,CAC7E,OAAO,KAAK,MAAA,CAAO,GAAA,CAAIA,CAAK,CAAA,EAAK,IACnC,CAEA,MAAM,yBAAyBA,CAAAA,CAAiC,CAC9D,OAAO,IAAA,CAAK,MAAA,CAAO,OAAOA,CAAK,CACjC,CAEA,MAAM,sBAAwC,CAC5C,IAAMU,EAAM,IAAI,IAAA,GAAO,OAAA,EAAQ,CACzBiD,CAAAA,CAAS,EAAA,CAAK,GAAK,GAAA,CAEnBC,CAAAA,CAAgB,MAAM,IAAA,CAAK,IAAA,CAAK,OAAO,OAAA,EAAS,CAAA,CACnD,MAAA,CAAO,CAAC,EAAG5D,CAAK,CAAA,GACEU,CAAAA,CAAMV,EAAM,SAAA,CAAU,OAAA,EAAQ,CAC7B2D,CACnB,EACA,GAAA,CAAI,CAAC,CAAC7D,CAAG,CAAA,GAAMA,CAAG,CAAA,CAErB,OAAA8D,CAAAA,CAAc,OAAA,CAAS9D,GAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAOA,CAAG,CAAC,CAAA,CAC/C8D,CAAAA,CAAc,MACvB,CAGA,uBAAuBxB,CAAAA,CAAsByB,CAAAA,CAAmC,CAC9E,IAAA,CAAK,eAAA,CAAgB,IAAIzB,CAAAA,CAAcyB,CAAO,EAChD,CAEA,kBAAkBzB,CAAAA,CAAsD,CACtE,OAAO,IAAA,CAAK,eAAA,CAAgB,IAAIA,CAAY,CAC9C,CAEA,kBAAA,EAAsD,CACpD,OAAO,IAAI,IAAI,IAAA,CAAK,eAAe,CACrC,CACF,EC9MO,IAAM0B,CAAAA,CAAqB,IAChCC,kBAAAA,CAAY,EAAE,CAAA,CACX,QAAA,CAAS,QAAQ,CAAA,CACjB,OAAA,CAAQ,gBAAiB,EAAE,CAAA,CAC3B,UAAU,CAAA,CAAG,GAAG,CAAA,CAERC,CAAAA,CAAuBC,GAC3BC,iBAAAA,CAAW,QAAQ,EAAE,MAAA,CAAOD,CAAQ,EAAE,MAAA,CAAO,WAAW,CAAA,CAGpDE,CAAAA,CAAgB,IACpBJ,kBAAAA,CAAY,EAAE,EAAE,QAAA,CAAS,WAAW,EC6BtC,IAAMK,CAAAA,CAAN,KAAmB,CAChB,QACA,eAAA,CACA,SAAA,CAAyC,IAAI,GAAA,CAC7C,eAAA,CAA6C,IAAI,GAAA,CACjD,GAAA,CACA,kBAAA,CAER,WAAA,CAAYlC,EAAyB,EAAC,CAAG,CAlD3C,IAAAV,CAAAA,CAAA6C,EAAAC,CAAAA,CAmDI,IAAA,CAAK,OAAA,CAAUpC,CAAAA,CAAQ,SAAW,IAAIS,CAAAA,CACtC,KAAK,eAAA,CAAkB,IAAIN,EAC3B,IAAA,CAAK,GAAA,CAAM,IAAA,CAAK,GAAA,CAGhB,KAAK,kBAAA,CAAqB,CACxB,UAASb,CAAAA,CAAAU,CAAAA,CAAQ,cAAR,IAAA,CAAA,MAAA,CAAAV,CAAAA,CAAqB,OAAA,GAAW,IAAA,CACzC,gBAAe6C,CAAAA,CAAAnC,CAAAA,CAAQ,cAAR,IAAA,CAAA,MAAA,CAAAmC,CAAAA,CAAqB,gBAAiB,EAAA,CACrD,cAAA,CAAA,CAAgBC,CAAAA,CAAApC,CAAAA,CAAQ,cAAR,IAAA,CAAA,MAAA,CAAAoC,CAAAA,CAAqB,cACvC,CAAA,CAGIpC,CAAAA,CAAQ,WACV,MAAA,CAAO,OAAA,CAAQA,CAAAA,CAAQ,SAAS,EAAE,OAAA,CAAQ,CAAC,CAACQ,CAAAA,CAAM3C,CAAM,IAAM,CAC5D,IAAA,CAAK,gBAAA,CAAiB2C,CAAAA,CAAM3C,CAAM,EACpC,CAAC,EAEL,CAKA,gBAAA,CAAiB2C,EAAc3C,CAAAA,CAA4B,CACzD,IAAA,CAAK,eAAA,CAAgB,IAAI2C,CAAAA,CAAM3C,CAAM,CAAA,CAGrC,IAAMkC,EAAe,IAAA,CAAK,kBAAA,CAAmBS,CAAAA,CAAM3C,CAAM,EACnDoD,CAAAA,CAAW,IAAA,CAAK,gBAAgB,cAAA,CAAelB,CAAAA,CAAclC,CAAM,CAAA,CAGnEwE,CAAAA,CAAgB,IAAA,CAAK,OAAA,CAAQ,kBAAkB7B,CAAI,CAAA,CACrD6B,GACFpB,CAAAA,CAAS,iBAAA,CAAkBoB,CAAa,CAAA,CAG1C,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI7B,EAAMS,CAAQ,EACnC,CAKA,MAAM,SAAA,CAAUjB,EAAwE,CA5F1F,IAAAV,CAAAA,CA6FI,IAAM2B,EAAW,IAAA,CAAK,SAAA,CAAU,IAAIjB,CAAAA,CAAQ,QAAQ,EACpD,GAAI,CAACiB,CAAAA,CAAU,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAYjB,EAAQ,QAAQ,CAAA,UAAA,CAAY,EAEvE,IAAMlC,CAAAA,CAAQmE,CAAAA,EAAc,CACxBK,EACAC,CAAAA,CAIJ,GAAA,CAAA,CAFqBjD,EAAA,IAAA,CAAK,eAAA,CAAgB,IAAIU,CAAAA,CAAQ,QAAQ,CAAA,GAAzC,IAAA,CAAA,MAAA,CAAAV,EAA4C,OAAA,GAAWU,CAAAA,CAAQ,QAElE,CAChB,IAAM7B,EAAeyD,CAAAA,EAAmB,CAClC7D,CAAAA,CAAgB+D,CAAAA,CAAoB3D,CAAY,CAAA,CACtDmE,CAAAA,CAAUrB,EAAS,wBAAA,CAAyBnD,CAAAA,CAAOC,CAAa,CAAA,CAChEwE,CAAAA,CAAY,CACV,KAAA,CAAAzE,EACA,YAAA,CAAAK,CAAAA,CACA,OAAQ,IAAA,CAAK,eAAA,CAAgB,IAAI6B,CAAAA,CAAQ,QAAQ,CAAA,CACjD,QAAA,CAAU,CACR,GAAGA,CAAAA,CAAQ,SACX,MAAA,CAAQA,CAAAA,CAAQ,OAChB,KAAA,CAAOA,CAAAA,CAAQ,KAAA,CACf,QAAA,CAAUA,EAAQ,QACpB,CACF,EACF,CAAA,KACEsC,CAAAA,CAAUrB,EAAS,wBAAA,CAAyBnD,CAAK,CAAA,CACjDyE,CAAAA,CAAY,CACV,KAAA,CAAAzE,CAAAA,CACA,OAAQ,IAAA,CAAK,eAAA,CAAgB,IAAIkC,CAAAA,CAAQ,QAAQ,CAAA,CACjD,QAAA,CAAU,CACR,GAAGA,CAAAA,CAAQ,SACX,MAAA,CAAQA,CAAAA,CAAQ,OAChB,KAAA,CAAOA,CAAAA,CAAQ,KAAA,CACf,QAAA,CAAUA,EAAQ,QACpB,CACF,EAGF,OAAA,MAAM,IAAA,CAAK,QAAQ,sBAAA,CAAuBuC,CAAS,CAAA,CAC5C,CAAE,IAAKD,CAAAA,CAAS,KAAA,CAAAxE,CAAM,CAC/B,CAKA,MAAM,cAAA,CAAeI,CAAAA,CAAcJ,CAAAA,CAAwC,CA1I7E,IAAAwB,CAAAA,CAAA6C,CAAAA,CAAAC,CAAAA,CA2II,IAAMG,EAAY,MAAM,IAAA,CAAK,OAAA,CAAQ,qBAAA,CAAsBzE,CAAK,CAAA,CAChE,GAAI,CAACyE,CAAAA,CAAW,MAAM,IAAI,KAAA,CAAM,0BAA0B,CAAA,CAE1D,IAAMtB,GAAW3B,CAAAA,CAAAiD,CAAAA,CAAU,WAAV,IAAA,CAAA,MAAA,CAAAjD,CAAAA,CAAoB,SACrC,GAAI,CAAC2B,CAAAA,CAAU,MAAM,IAAI,KAAA,CAAM,2CAA2C,EAE1E,IAAMuB,CAAAA,CAAmB,KAAK,SAAA,CAAU,GAAA,CAAIvB,CAAQ,CAAA,CACpD,GAAI,CAACuB,CAAAA,CAAkB,MAAM,IAAI,KAAA,CAAM,YAAYvB,CAAQ,CAAA,UAAA,CAAY,CAAA,CAGvE,IAAMF,EAAS,MAAMyB,CAAAA,CAAiB,qBAAqBtE,CAAAA,CAAMqE,CAAAA,CAAU,YAAY,CAAA,CAGjFnB,CAAAA,CAAAA,CAASe,CAAAA,CAAAI,CAAAA,CAAU,WAAV,IAAA,CAAA,MAAA,CAAAJ,CAAAA,CAAoB,OAC7BjB,CAAAA,CAAAA,CAAQkB,CAAAA,CAAAG,EAAU,QAAA,GAAV,IAAA,CAAA,MAAA,CAAAH,CAAAA,CAAoB,KAAA,CAElC,GAAI,CAAChB,CAAAA,EAAU,CAACF,CAAAA,CACd,MAAM,IAAI,KAAA,CAAM,uDAAuD,CAAA,CAIzE,IAAIuB,EACJ,GAAID,CAAAA,CAAiB,mBAAkB,CACrC,GAAI,CACFC,CAAAA,CAAU,MAAMD,CAAAA,CAAiB,YAAA,CAAazB,EAAO,WAAW,EAClE,OAAS2B,CAAAA,CAAO,CACd,QAAQ,IAAA,CAAK,+BAAA,CAAiCA,CAAK,EACrD,CAIF,IAAMC,CAAAA,CAAa,MAAM,IAAA,CAAK,OAAA,CAAQ,UAAU,CAC9C,QAAA,CAAA1B,CAAAA,CACA,MAAA,CAAAG,EACA,KAAA,CAAA,CAAOqB,CAAAA,EAAA,YAAAA,CAAAA,CAAS,KAAA,GAASvB,EACzB,KAAA,CAAOH,CAAAA,CACP,QAAA,CAAU,CACR,GAAGwB,CAAAA,CAAU,QAAA,CACb,eAAgB,CAAC,CAACE,CACpB,CACF,CAAC,CAAA,CAGD,MAAM,KAAK,OAAA,CAAQ,wBAAA,CAAyB3E,CAAK,CAAA,CAGjD,IAAMD,EAAS,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAIoD,CAAQ,EAChD,OAAIpD,CAAAA,EAAA,MAAAA,CAAAA,CAAQ,SAAA,EACV,MAAMA,CAAAA,CAAO,SAAA,CAAUuD,CAAAA,CAAQL,CAAM,EAGhC,CACL,KAAA,CAAO4B,EACP,OAAA,CAAAF,CACF,CACF,CAKA,MAAM,cAAA,CACJxB,CAAAA,CACAC,EACAlB,CAAAA,CAAwB,EAAC,CACR,CAEjB,QADc,MAAM,IAAA,CAAK,aAAA,CAAciB,CAAAA,CAAUC,EAAOlB,CAAO,CAAA,EAClD,WACf,CAKA,MAAM,cACJiB,CAAAA,CACAC,CAAAA,CACAlB,CAAAA,CAAwB,GACF,CACtB,IAAM4C,EAAc,MAAM,IAAA,CAAK,QAAQ,QAAA,CAAS3B,CAAAA,CAAUC,CAAK,CAAA,CAC/D,GAAI,CAAC0B,CAAAA,CACH,MAAM,IAAI,KAAA,CAAM,+BAA+B3B,CAAQ,CAAA,WAAA,EAAcC,CAAK,CAAA,CAAE,EAM9E,GAAI,EAFFlB,EAAQ,WAAA,GAAgB,KAAA,EAAS,KAAK,cAAA,CAAe4C,CAAAA,CAAY,KAAA,CAAO5C,CAAO,GAG/E,OAAO4C,CAAAA,CAAY,MAIrB,GAAI,CAACA,EAAY,KAAA,CAAM,YAAA,CACrB,MAAM,IAAI,MAAM,8CAA8C,CAAA,CAGhE,IAAMJ,CAAAA,CAAmB,IAAA,CAAK,UAAU,GAAA,CAAIvB,CAAQ,CAAA,CACpD,GAAI,CAACuB,CAAAA,CAAkB,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAYvB,CAAQ,CAAA,UAAA,CAAY,CAAA,CAEvE,IAAMJ,CAAAA,CAAW,MAAM2B,CAAAA,CAAiB,YAAA,CAAaI,EAAY,KAAA,CAAM,YAAY,EACnF,OAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAYA,EAAY,EAAA,CAAI,CAAE,MAAO/B,CAAS,CAAC,EAE3DA,CACT,CAKA,MAAM,WAAA,CAAYC,EAA2C,CAG3D,IAAM+B,EACJ,IAAA,CAAK,kBAAA,CAAmB,SAAW,CAAC/B,CAAAA,CAAM,cAAA,CACtC,CAAE,GAAGA,CAAAA,CAAO,cAAA,CAAgB,IAAK,CAAA,CACjCA,CAAAA,CAEAC,EAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY8B,CAAgB,CAAA,CAE9D,OAAI,KAAK,kBAAA,CAAmB,OAAA,EAAW,CAAC/B,CAAAA,CAAM,cAAA,CAAA,CACpB,MAAM,IAAA,CAAK,sBAAsBC,CAAM,CAAA,EAExC,OAAQO,CAAAA,EACX,IAAI,KAAKA,CAAAA,CAAM,KAAA,CAAM,SAAS,CAAA,CAAE,SAAQ,CACvC,IAAA,CAAK,KACzB,CAAA,CAGIP,CACT,CAKA,MAAM,iBAAA,CAAkBK,CAAAA,CAAwC,CAC9D,OAAO,IAAA,CAAK,YAAY,CAAE,MAAA,CAAAA,CAAO,CAAC,CACpC,CAKA,MAAM,iBAAiBF,CAAAA,CAAuC,CAC5D,OAAO,IAAA,CAAK,YAAY,CAAE,KAAA,CAAAA,CAAM,CAAC,CACnC,CAKA,MAAM,YAAYD,CAAAA,CAAkBC,CAAAA,CAAiC,CACnE,OAAO,IAAA,CAAK,OAAA,CAAQ,0BAAA,CAA2BD,EAAUC,CAAK,CAChE,CAKA,MAAM,oBAAA,EAAwC,CAC5C,OAAO,IAAA,CAAK,OAAA,CAAQ,mBAAA,EACtB,CAKA,MAAM,sBAAwC,CAC5C,OAAO,KAAK,OAAA,CAAQ,oBAAA,EACtB,CAGQ,eAAeI,CAAAA,CAAoBtB,CAAAA,CAAwB,EAAC,CAAY,CAC9E,GAAM,CAAE,gBAAA,CAAA8C,CAAAA,CAAmB,GAAI,EAAI9C,CAAAA,CAEnC,GAAIsB,EAAM,SAAA,EAAaA,CAAAA,CAAM,YAAc,MAAA,CAAW,CACpD,IAAMyB,CAAAA,CAAYzB,EAAM,SAAA,CAAYA,CAAAA,CAAM,UAAY,GAAA,CAEtD,OADqB,KAAK,GAAA,EAAI,CAAIwB,CAAAA,CAAmB,GAAA,EAC9BC,CACzB,CAEA,IAAMA,EAAY,IAAI,IAAA,CAAKzB,EAAM,SAAS,CAAA,CAAE,OAAA,EAAQ,CAEpD,OADqB,IAAA,CAAK,GAAA,GAAQwB,CAAAA,CAAmB,GAAA,EAC9BC,CACzB,CAEQ,kBAAA,CAAmBvC,CAAAA,CAAc3C,CAAAA,CAAoC,CA7T/E,IAAAyB,CAAAA,CA+TI,IAAMgD,CAAAA,CAAUzE,CAAAA,CAAO,iBAAiB,WAAA,EAAY,CAGpD,OAAIyE,CAAAA,CAAQ,SAAS,qBAAqB,CAAA,CAAU,SAChDA,CAAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,CAAU,QAAA,CACvCA,CAAAA,CAAQ,QAAA,CAAS,cAAc,CAAA,CAAU,UAAA,CACzCA,EAAQ,QAAA,CAAS,eAAe,GAAKA,CAAAA,CAAQ,QAAA,CAAS,qBAAqB,CAAA,CAG3E9B,EAAK,WAAA,EAAY,CAAE,SAAS,SAAS,CAAA,EAAA,CACrClB,EAAAzB,CAAAA,CAAO,MAAA,GAAP,IAAA,EAAAyB,CAAAA,CAAe,KAAM0D,CAAAA,EAAMA,CAAAA,CAAE,SAAS,SAAS,CAAA,CAAA,CAExC,UAEF,WAAA,CAIF,SACT,CAKA,MAAc,sBAAsBjC,CAAAA,CAA+C,CACjF,IAAMkC,CAAAA,CAAkBlC,CAAAA,CAAO,IAAI,MAAOO,CAAAA,EAAU,CAClD,GAAI,KAAK,kBAAA,CAAmBA,CAAK,EAC/B,GAAI,CACF,IAAML,CAAAA,CAAW,IAAA,CAAK,SAAA,CAAU,GAAA,CAAIK,EAAM,QAAQ,CAAA,CAClD,GAAI,CAACL,CAAAA,CACH,eAAQ,IAAA,CAAK,CAAA,SAAA,EAAYK,CAAAA,CAAM,QAAQ,8BAA8B,CAAA,CAC9DA,CAAAA,CAGT,GAAI,CAACA,CAAAA,CAAM,MAAM,YAAA,CACf,OAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,+BAAA,EAAkCA,EAAM,QAAQ,CAAA,CAAA,EAAIA,EAAM,KAAK,CAAA,CAAE,EACvEA,CAAAA,CAGT,IAAMT,CAAAA,CAAW,MAAMI,EAAS,YAAA,CAAaK,CAAAA,CAAM,MAAM,YAAY,CAAA,CAErE,OADgB,MAAM,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAYA,EAAM,EAAA,CAAI,CAAE,MAAOT,CAAS,CAAC,GAC1DS,CACpB,CAAA,MAASoB,CAAAA,CAAO,CACd,OAAI,IAAA,CAAK,kBAAA,CAAmB,gBAC1B,IAAA,CAAK,kBAAA,CAAmB,eAAeA,CAAAA,CAAgBpB,CAAK,CAAA,CAE9D,OAAA,CAAQ,MAAM,CAAA,4BAAA,EAA+BA,CAAAA,CAAM,QAAQ,CAAA,CAAA,EAAIA,CAAAA,CAAM,KAAK,CAAA,CAAA,CAAA,CAAKoB,CAAK,CAAA,CAC7EpB,CACT,CAEF,OAAOA,CACT,CAAC,CAAA,CAED,OAAO,QAAQ,GAAA,CAAI2B,CAAe,CACpC,CAKQ,mBAAmBL,CAAAA,CAAmC,CAE5D,GAAI,CAACA,CAAAA,CAAY,MAAM,YAAA,CACrB,OAAO,MAAA,CAIT,IAAMG,EAAY,IAAI,IAAA,CAAKH,EAAY,KAAA,CAAM,SAAS,EAAE,OAAA,EAAQ,CAC1DpE,CAAAA,CAAM,IAAA,CAAK,KAAI,CAGrB,GAAIA,GAAOuE,CAAAA,CACT,OAAO,MAIT,IAAMG,CAAAA,CAAW,IAAA,CAAK,kBAAA,CAAmB,cAAiB,EAAA,CAAK,GAAA,CACzDC,EAAkBJ,CAAAA,CAAYG,CAAAA,CAEpC,OAAO1E,CAAAA,EAAO2E,CAChB,CAKA,wBAAA,CAAyBnD,EAA4C,CACnE,IAAA,CAAK,mBAAqB,CAAE,GAAG,KAAK,kBAAA,CAAoB,GAAGA,CAAQ,EACrE,CACF,ECpZO,IAAMoD,EAAAA,CAAO,CAAIC,EAAMzF,CAAAA,GAAgB0F,oBAAAA,CAASD,EAAG,CAAE,QAAA,CAAUzF,CAAI,CAAC,CAAA,CAC9D2F,EAAAA,CAAS,CAAI,EAAW3F,CAAAA,GAAgB4F,sBAAAA,CAAc,EAAG,CAAE,QAAA,CAAU5F,CAAI,CAAC","file":"index.cjs","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport {\n StorageAdapter,\n StoredToken,\n SaveTokenInput,\n UpdateTokenInput,\n TokenQuery,\n} from './interfaces';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n private profileFetchers: Map<string, BaseProfileFetcher> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async queryTokens(query: TokenQuery): Promise<StoredToken[]> {\n let tokens = Array.from(this.tokens.values());\n\n // Apply filters\n if (query.id) {\n tokens = tokens.filter((t) => t.id === query.id);\n }\n if (query.provider) {\n tokens = tokens.filter((t) => t.provider === query.provider);\n }\n if (query.userId) {\n tokens = tokens.filter((t) => t.userId === query.userId);\n }\n if (query.email) {\n tokens = tokens.filter((t) => t.email === query.email);\n }\n\n // Filter out expired tokens unless explicitly requested\n if (!query.includeExpired) {\n const now = new Date().getTime();\n tokens = tokens.filter((t) => {\n const expiresAt = new Date(t.token.expiresAt).getTime();\n return expiresAt >= now;\n });\n }\n\n // Apply pagination\n if (query.offset !== undefined) {\n tokens = tokens.slice(query.offset);\n }\n if (query.limit !== undefined) {\n tokens = tokens.slice(0, query.limit);\n }\n\n return tokens;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ provider, email, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ id, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId });\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.queryTokens({ email });\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ provider });\n }\n\n async getAccounts(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async getTokensForEmail(\n userId: string,\n provider: string,\n email: string,\n ): Promise<StoredToken | null> {\n const results = await this.queryTokens({ userId, provider, email });\n return results[0] || null;\n }\n\n async getTokens(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n\n // Profile fetcher operations\n registerProfileFetcher(providerName: string, fetcher: BaseProfileFetcher): void {\n this.profileFetchers.set(providerName, fetcher);\n }\n\n getProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.profileFetchers.get(providerName);\n }\n\n getProfileFetchers(): Map<string, BaseProfileFetcher> {\n return new Map(this.profileFetchers);\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken, TokenQuery } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n autoRefresh?: AutoRefreshOptions;\n}\n\nexport interface AutoRefreshOptions {\n enabled?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n onRefreshError?: (error: Error, token: StoredToken) => void;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n private autoRefreshOptions: AutoRefreshOptions;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Set default auto-refresh options - enabled by default\n this.autoRefreshOptions = {\n enabled: options.autoRefresh?.enabled ?? true, // Enabled by default\n refreshBuffer: options.autoRefresh?.refreshBuffer ?? 10, // 10 minutes before expiry (safe for Google's 1-hour tokens)\n onRefreshError: options.autoRefresh?.onRefreshError,\n };\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n\n // Check if storage has a custom profile fetcher for this provider\n const customFetcher = this.storage.getProfileFetcher(name);\n if (customFetcher) {\n provider.setProfileFetcher(customFetcher);\n }\n\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email: profile?.email || email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Query tokens with automatic refresh\n */\n async queryTokens(query: TokenQuery): Promise<StoredToken[]> {\n // When auto-refresh is enabled, we need to include expired tokens\n // so we can attempt to refresh them\n const queryWithExpired =\n this.autoRefreshOptions.enabled && !query.includeExpired\n ? { ...query, includeExpired: true }\n : query;\n\n const tokens = await this.storage.queryTokens(queryWithExpired);\n\n if (this.autoRefreshOptions.enabled && !query.includeExpired) {\n const refreshedTokens = await this.refreshTokensIfNeeded(tokens);\n // Filter out tokens that are still expired after refresh attempt\n return refreshedTokens.filter((token) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt > this.now();\n });\n }\n\n return tokens;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId });\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.queryTokens({ email });\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n\n /**\n * Refresh tokens if they are near expiration\n */\n private async refreshTokensIfNeeded(tokens: StoredToken[]): Promise<StoredToken[]> {\n const refreshPromises = tokens.map(async (token) => {\n if (this.shouldRefreshToken(token)) {\n try {\n const provider = this.providers.get(token.provider);\n if (!provider) {\n console.warn(`Provider ${token.provider} not found for token refresh`);\n return token;\n }\n\n if (!token.token.refreshToken) {\n console.warn(`No refresh token available for ${token.provider}:${token.email}`);\n return token;\n }\n\n const newToken = await provider.refreshToken(token.token.refreshToken);\n const updated = await this.storage.updateToken(token.id, { token: newToken });\n return updated || token;\n } catch (error) {\n if (this.autoRefreshOptions.onRefreshError) {\n this.autoRefreshOptions.onRefreshError(error as Error, token);\n }\n console.error(`Failed to refresh token for ${token.provider}:${token.email}:`, error);\n return token;\n }\n }\n return token;\n });\n\n return Promise.all(refreshPromises);\n }\n\n /**\n * Check if a token should be refreshed\n */\n private shouldRefreshToken(storedToken: StoredToken): boolean {\n // Skip if no refresh token\n if (!storedToken.token.refreshToken) {\n return false;\n }\n\n // Check if token is expired or near expiration\n const expiresAt = new Date(storedToken.token.expiresAt).getTime();\n const now = this.now();\n\n // If already expired, definitely try to refresh\n if (now >= expiresAt) {\n return true;\n }\n\n // Otherwise, check if within refresh buffer\n const bufferMs = this.autoRefreshOptions.refreshBuffer! * 60 * 1000;\n const shouldRefreshAt = expiresAt - bufferMs;\n\n return now >= shouldRefreshAt;\n }\n\n /**\n * Update auto-refresh options\n */\n updateAutoRefreshOptions(options: Partial<AutoRefreshOptions>): void {\n this.autoRefreshOptions = { ...this.autoRefreshOptions, ...options };\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
package/dist/index.d.cts CHANGED
@@ -146,6 +146,12 @@ interface ProfileBasedTokenOptions {
146
146
  interface OAuth2Options {
147
147
  storage?: StorageAdapter;
148
148
  providers?: Record<string, OAuth2Config>;
149
+ autoRefresh?: AutoRefreshOptions;
150
+ }
151
+ interface AutoRefreshOptions {
152
+ enabled?: boolean;
153
+ refreshBuffer?: number;
154
+ onRefreshError?: (error: Error, token: StoredToken) => void;
149
155
  }
150
156
  interface AuthorizationOptions {
151
157
  provider: string;
@@ -171,6 +177,7 @@ declare class OAuth2Client {
171
177
  private providers;
172
178
  private providerConfigs;
173
179
  private now;
180
+ private autoRefreshOptions;
174
181
  constructor(options?: OAuth2Options);
175
182
  /**
176
183
  * Register a provider configuration
@@ -195,6 +202,10 @@ declare class OAuth2Client {
195
202
  * Get a valid token (auto-refresh if needed)
196
203
  */
197
204
  getValidToken(provider: string, email: string, options?: TokenOptions): Promise<OAuth2Token>;
205
+ /**
206
+ * Query tokens with automatic refresh
207
+ */
208
+ queryTokens(query: TokenQuery): Promise<StoredToken[]>;
198
209
  /**
199
210
  * Get all tokens for a user
200
211
  */
@@ -217,6 +228,18 @@ declare class OAuth2Client {
217
228
  cleanupExpiredStates(): Promise<number>;
218
229
  private isTokenExpired;
219
230
  private detectProviderType;
231
+ /**
232
+ * Refresh tokens if they are near expiration
233
+ */
234
+ private refreshTokensIfNeeded;
235
+ /**
236
+ * Check if a token should be refreshed
237
+ */
238
+ private shouldRefreshToken;
239
+ /**
240
+ * Update auto-refresh options
241
+ */
242
+ updateAutoRefreshOptions(options: Partial<AutoRefreshOptions>): void;
220
243
  }
221
244
 
222
245
  declare class InMemoryStorageAdapter implements StorageAdapter {
@@ -346,4 +369,4 @@ declare const generateState: () => string;
346
369
  declare const seal: <T>(d: T, key: string) => Promise<string>;
347
370
  declare const unseal: <T>(s: string, key: string) => Promise<T>;
348
371
 
349
- export { type AuthorizationOptions, type AuthorizationState, type AuthorizationUrlStrategy, BaseProfileFetcher, type CallbackResult, GenericOAuth2Provider, GenericProfileFetcher, GitHubProfileFetcher, GoogleProfileFetcher, InMemoryStorageAdapter, MicrosoftProfileFetcher, OAuth2Client, type OAuth2Config, type OAuth2Options, OAuth2Provider, type OAuth2Token, type ProfileBasedTokenOptions, type ProfileFetcher, ProfileFetcherFactory, type ProfileFetcherOptions, type ProfileMapping, type ProviderFactory, type ProviderType, type SaveTokenInput, StandardAuthorizationUrlStrategy, StandardTokenExchangeStrategy, type StorageAdapter, type StoredToken, type TokenExchangeStrategy, type TokenOptions, type TokenQuery, type UpdateTokenInput, type UserProfile, createCodeChallenge, createCodeVerifier, generateState, seal, unseal };
372
+ export { type AuthorizationOptions, type AuthorizationState, type AuthorizationUrlStrategy, type AutoRefreshOptions, BaseProfileFetcher, type CallbackResult, GenericOAuth2Provider, GenericProfileFetcher, GitHubProfileFetcher, GoogleProfileFetcher, InMemoryStorageAdapter, MicrosoftProfileFetcher, OAuth2Client, type OAuth2Config, type OAuth2Options, OAuth2Provider, type OAuth2Token, type ProfileBasedTokenOptions, type ProfileFetcher, ProfileFetcherFactory, type ProfileFetcherOptions, type ProfileMapping, type ProviderFactory, type ProviderType, type SaveTokenInput, StandardAuthorizationUrlStrategy, StandardTokenExchangeStrategy, type StorageAdapter, type StoredToken, type TokenExchangeStrategy, type TokenOptions, type TokenQuery, type UpdateTokenInput, type UserProfile, createCodeChallenge, createCodeVerifier, generateState, seal, unseal };
package/dist/index.d.ts CHANGED
@@ -146,6 +146,12 @@ interface ProfileBasedTokenOptions {
146
146
  interface OAuth2Options {
147
147
  storage?: StorageAdapter;
148
148
  providers?: Record<string, OAuth2Config>;
149
+ autoRefresh?: AutoRefreshOptions;
150
+ }
151
+ interface AutoRefreshOptions {
152
+ enabled?: boolean;
153
+ refreshBuffer?: number;
154
+ onRefreshError?: (error: Error, token: StoredToken) => void;
149
155
  }
150
156
  interface AuthorizationOptions {
151
157
  provider: string;
@@ -171,6 +177,7 @@ declare class OAuth2Client {
171
177
  private providers;
172
178
  private providerConfigs;
173
179
  private now;
180
+ private autoRefreshOptions;
174
181
  constructor(options?: OAuth2Options);
175
182
  /**
176
183
  * Register a provider configuration
@@ -195,6 +202,10 @@ declare class OAuth2Client {
195
202
  * Get a valid token (auto-refresh if needed)
196
203
  */
197
204
  getValidToken(provider: string, email: string, options?: TokenOptions): Promise<OAuth2Token>;
205
+ /**
206
+ * Query tokens with automatic refresh
207
+ */
208
+ queryTokens(query: TokenQuery): Promise<StoredToken[]>;
198
209
  /**
199
210
  * Get all tokens for a user
200
211
  */
@@ -217,6 +228,18 @@ declare class OAuth2Client {
217
228
  cleanupExpiredStates(): Promise<number>;
218
229
  private isTokenExpired;
219
230
  private detectProviderType;
231
+ /**
232
+ * Refresh tokens if they are near expiration
233
+ */
234
+ private refreshTokensIfNeeded;
235
+ /**
236
+ * Check if a token should be refreshed
237
+ */
238
+ private shouldRefreshToken;
239
+ /**
240
+ * Update auto-refresh options
241
+ */
242
+ updateAutoRefreshOptions(options: Partial<AutoRefreshOptions>): void;
220
243
  }
221
244
 
222
245
  declare class InMemoryStorageAdapter implements StorageAdapter {
@@ -346,4 +369,4 @@ declare const generateState: () => string;
346
369
  declare const seal: <T>(d: T, key: string) => Promise<string>;
347
370
  declare const unseal: <T>(s: string, key: string) => Promise<T>;
348
371
 
349
- export { type AuthorizationOptions, type AuthorizationState, type AuthorizationUrlStrategy, BaseProfileFetcher, type CallbackResult, GenericOAuth2Provider, GenericProfileFetcher, GitHubProfileFetcher, GoogleProfileFetcher, InMemoryStorageAdapter, MicrosoftProfileFetcher, OAuth2Client, type OAuth2Config, type OAuth2Options, OAuth2Provider, type OAuth2Token, type ProfileBasedTokenOptions, type ProfileFetcher, ProfileFetcherFactory, type ProfileFetcherOptions, type ProfileMapping, type ProviderFactory, type ProviderType, type SaveTokenInput, StandardAuthorizationUrlStrategy, StandardTokenExchangeStrategy, type StorageAdapter, type StoredToken, type TokenExchangeStrategy, type TokenOptions, type TokenQuery, type UpdateTokenInput, type UserProfile, createCodeChallenge, createCodeVerifier, generateState, seal, unseal };
372
+ export { type AuthorizationOptions, type AuthorizationState, type AuthorizationUrlStrategy, type AutoRefreshOptions, BaseProfileFetcher, type CallbackResult, GenericOAuth2Provider, GenericProfileFetcher, GitHubProfileFetcher, GoogleProfileFetcher, InMemoryStorageAdapter, MicrosoftProfileFetcher, OAuth2Client, type OAuth2Config, type OAuth2Options, OAuth2Provider, type OAuth2Token, type ProfileBasedTokenOptions, type ProfileFetcher, ProfileFetcherFactory, type ProfileFetcherOptions, type ProfileMapping, type ProviderFactory, type ProviderType, type SaveTokenInput, StandardAuthorizationUrlStrategy, StandardTokenExchangeStrategy, type StorageAdapter, type StoredToken, type TokenExchangeStrategy, type TokenOptions, type TokenQuery, type UpdateTokenInput, type UserProfile, createCodeChallenge, createCodeVerifier, generateState, seal, unseal };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import {createHash,randomBytes}from'crypto';import {sealData,unsealData}from'iron-session';var m=class{buildUrlParams(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,o])=>`${r}=${encodeURIComponent(o)}`).join("&")}generateAuthorizationUrl(e,t,r){let o={client_id:e.clientId,redirect_uri:e.redirectUri,response_type:"code",scope:e.scopes.join(" "),state:t};(e.usePKCE||e.pkce)&&r&&(o.code_challenge=r,o.code_challenge_method="S256");let i={...e.additionalParams,...e.extraAuthParams};return Object.assign(o,i),`${e.authorizationUrl}?${this.buildUrlParams(o)}`}};var g=class{buildUrlParams(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r,o])=>`${r}=${encodeURIComponent(o)}`).join("&")}async exchangeCodeForToken(e,t,r){let o={grant_type:"authorization_code",code:e,redirect_uri:t.redirectUri,client_id:t.clientId};(t.usePKCE||t.pkce)&&r?o.code_verifier=r:t.clientSecret&&(o.client_secret=t.clientSecret);let i=await fetch(t.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(o)});if(!i.ok){let x=await i.text();throw new Error(`Token exchange failed: ${i.statusText} - ${x}`)}let s=await i.json(),a=t.responseRootKey?s[t.responseRootKey]:s,p=Date.now(),c=a.expires_in||3600;return {accessToken:a.access_token,refreshToken:a.refresh_token,expiresAt:new Date(p+c*1e3),expiresIn:c,tokenType:a.token_type||"Bearer",scope:a.scope,createdAt:p,raw:s}}async refreshToken(e,t){let r={grant_type:"refresh_token",refresh_token:e,client_id:t.clientId};!(t.usePKCE||t.pkce)&&t.clientSecret&&(r.client_secret=t.clientSecret);let o=await fetch(t.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(r)});if(!o.ok){let c=await o.text();throw new Error(`Token refresh failed: ${o.statusText} - ${c}`)}let i=await o.json(),s=t.responseRootKey?i[t.responseRootKey]:i,a=Date.now(),p=s.expires_in||3600;return {accessToken:s.access_token,refreshToken:s.refresh_token||e,expiresAt:new Date(a+p*1e3),expiresIn:p,tokenType:s.token_type||"Bearer",scope:s.scope,createdAt:a,raw:i}}};var u=class{constructor(e,t,r,o){this.config=e;this.authUrlStrategy=t||this.createAuthorizationUrlStrategy(),this.tokenStrategy=r||this.createTokenExchangeStrategy(),this.profileFetcher=o;}authUrlStrategy;tokenStrategy;profileFetcher;async fetchProfile(e){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.fetchUserInfo(e)}getProfileEndpoint(){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.getEndpoint()}setProfileFetcher(e){this.profileFetcher=e;}hasProfileFetcher(){return !!this.profileFetcher}generateAuthorizationUrl(e,t){return this.authUrlStrategy.generateAuthorizationUrl(this.config,e,t)}async exchangeCodeForToken(e,t){return this.tokenStrategy.exchangeCodeForToken(e,this.config,t)}async refreshToken(e){return this.tokenStrategy.refreshToken(e,this.config)}};var k=class extends u{constructor(e,t,r,o){super(e,t,r,o);}createAuthorizationUrlStrategy(){return new m}createTokenExchangeStrategy(){return new g}};var d=class{constructor(e){this.profileEndpoint=e;}async fetchUserInfo(e){let t=await fetch(this.profileEndpoint,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json",...this.getAdditionalHeaders()}});if(!t.ok)throw new Error(`Failed to fetch profile from ${this.profileEndpoint}: ${t.statusText}`);let r=await t.json();return this.mapToUserProfile(r)}getAdditionalHeaders(){return {}}getEndpoint(){return this.profileEndpoint}};var P=class extends d{constructor(){super("https://www.googleapis.com/oauth2/v2/userinfo");}mapToUserProfile(e){return {email:e.email,name:e.name,id:e.id,avatar:e.picture,username:e.email,raw:e}}};var T=class extends d{constructor(){super("https://api.github.com/user");}mapToUserProfile(e){var t;return {email:e.email,name:e.name||e.login,id:(t=e.id)==null?void 0:t.toString(),avatar:e.avatar_url,username:e.login,raw:e}}getAdditionalHeaders(){return {"User-Agent":"OAuth2-Token-Manager"}}};var v=class extends d{constructor(){super("https://graph.microsoft.com/v1.0/me");}mapToUserProfile(e){return {email:e.mail||e.userPrincipalName,name:e.displayName,id:e.id,avatar:void 0,username:e.userPrincipalName,raw:e}}};var l=class extends d{constructor(t,r,o){super(t);this.mapping=r;this.additionalHeaders=o;}mapToUserProfile(t){return this.mapping?{email:this.getNestedProperty(t,this.mapping.email),name:this.mapping.name?this.getNestedProperty(t,this.mapping.name):void 0,id:this.mapping.id?this.getNestedProperty(t,this.mapping.id):void 0,avatar:this.mapping.avatar?this.getNestedProperty(t,this.mapping.avatar):void 0,username:this.mapping.username?this.getNestedProperty(t,this.mapping.username):void 0,raw:t}:{email:t.email||t.mail||t.emailAddress,name:t.name||t.displayName||t.full_name,id:t.id||t.sub||t.user_id,avatar:t.avatar||t.picture||t.avatar_url,username:t.username||t.login||t.preferred_username,raw:t}}getAdditionalHeaders(){return this.additionalHeaders||{}}getNestedProperty(t,r){return r.split(".").reduce((o,i)=>o==null?void 0:o[i],t)}};var y=class{static createProfileFetcher(e,t,r){if(r!=null&&r.profileUrl)return new l(r.profileUrl,r.profileMapping,r.profileHeaders);switch(e){case "google":return new P;case "github":return new T;case "microsoft":case "outlook":return new v;case "facebook":return new l("https://graph.facebook.com/me?fields=id,name,email,picture");case "generic":default:let o=t.profileUrl||t.userInfoUrl;if(!o)throw new Error(`Profile URL must be provided for ${e} provider`);return new l(o)}}static registerCustomProfileFetcher(e,t){this.customFetchers.set(e,t);}static customFetchers=new Map;static getCustomProfileFetcher(e){return this.customFetchers.get(e)}};var A=class n{static presetConfigs={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",profileUrl:"https://www.googleapis.com/oauth2/v2/userinfo",usePKCE:true,extraAuthParams:{access_type:"offline",prompt:"consent"}},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",profileUrl:"https://api.github.com/user"},microsoft:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true},outlook:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true,extraAuthParams:{prompt:"select_account"}},facebook:{authorizationUrl:"https://www.facebook.com/v12.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v12.0/oauth/access_token",profileUrl:"https://graph.facebook.com/me?fields=id,name,email,picture"}};createProvider(e,t){let r=e!=="generic"?n.presetConfigs[e]||{}:{},o={...r,...t,authorizationUrl:t.authorizationUrl||r.authorizationUrl||"",tokenUrl:t.tokenUrl||r.tokenUrl||"",profileUrl:t.profileUrl||r.profileUrl,extraAuthParams:{...r.extraAuthParams||{},...t.extraAuthParams||{}}},i=y.createProfileFetcher(e,o);return new k(o,void 0,void 0,i)}static registerPreset(e,t){n.presetConfigs[e]=t;}static getPresetConfig(e){return n.presetConfigs[e]}};var h=class{tokens=new Map;states=new Map;profileFetchers=new Map;generateId(){return Math.random().toString(36).substring(2)+Date.now().toString(36)}async saveToken(e){let t=await this.getToken(e.provider,e.email);if(t){let o={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date};return this.tokens.set(t.id,o),o}let r={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.tokens.set(r.id,r),r}async queryTokens(e){let t=Array.from(this.tokens.values());if(e.id&&(t=t.filter(r=>r.id===e.id)),e.provider&&(t=t.filter(r=>r.provider===e.provider)),e.userId&&(t=t.filter(r=>r.userId===e.userId)),e.email&&(t=t.filter(r=>r.email===e.email)),!e.includeExpired){let r=new Date().getTime();t=t.filter(o=>new Date(o.token.expiresAt).getTime()>=r);}return e.offset!==void 0&&(t=t.slice(e.offset)),e.limit!==void 0&&(t=t.slice(0,e.limit)),t}async getToken(e,t){return (await this.queryTokens({provider:e,email:t,includeExpired:true}))[0]||null}async getTokenById(e){return (await this.queryTokens({id:e,includeExpired:true}))[0]||null}async getTokensByUserId(e){return this.queryTokens({userId:e})}async getTokensByEmail(e){return this.queryTokens({email:e})}async getTokensByProvider(e){return this.queryTokens({provider:e})}async getAccounts(e,t){return this.queryTokens({userId:e,provider:t})}async getTokensForEmail(e,t,r){return (await this.queryTokens({userId:e,provider:t,email:r}))[0]||null}async getTokens(e,t){return this.queryTokens({userId:e,provider:t})}async updateToken(e,t){let r=this.tokens.get(e);if(!r)return null;let o={...r,...t.token&&{token:t.token},...t.metadata&&{metadata:{...r.metadata,...t.metadata}},updatedAt:new Date};return this.tokens.set(e,o),o}async deleteToken(e){return this.tokens.delete(e)}async deleteTokenByProviderEmail(e,t){let r=await this.getToken(e,t);return r?this.tokens.delete(r.id):false}async deleteExpiredTokens(){let e=new Date().getTime(),t=Array.from(this.tokens.entries()).filter(([,r])=>new Date(r.token.expiresAt).getTime()<e).map(([r])=>r);return t.forEach(r=>this.tokens.delete(r)),t.length}async saveAuthorizationState(e){let t={...e,createdAt:new Date(Date.now())};return this.states.set(e.state,t),t}async getAuthorizationState(e){return this.states.get(e)||null}async deleteAuthorizationState(e){return this.states.delete(e)}async cleanupExpiredStates(){let e=new Date().getTime(),t=10*60*1e3,r=Array.from(this.states.entries()).filter(([,o])=>e-o.createdAt.getTime()>t).map(([o])=>o);return r.forEach(o=>this.states.delete(o)),r.length}registerProfileFetcher(e,t){this.profileFetchers.set(e,t);}getProfileFetcher(e){return this.profileFetchers.get(e)}getProfileFetchers(){return new Map(this.profileFetchers)}};var E=()=>randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),b=n=>createHash("sha256").update(n).digest("base64url"),O=()=>randomBytes(16).toString("base64url");var S=class{storage;providerFactory;providers=new Map;providerConfigs=new Map;now;constructor(e={}){this.storage=e.storage||new h,this.providerFactory=new A,this.now=Date.now,e.providers&&Object.entries(e.providers).forEach(([t,r])=>{this.registerProvider(t,r);});}registerProvider(e,t){this.providerConfigs.set(e,t);let r=this.detectProviderType(e,t),o=this.providerFactory.createProvider(r,t),i=this.storage.getProfileFetcher(e);i&&o.setProfileFetcher(i),this.providers.set(e,o);}async authorize(e){var a;let t=this.providers.get(e.provider);if(!t)throw new Error(`Provider ${e.provider} not found`);let r=O(),o,i;if(((a=this.providerConfigs.get(e.provider))==null?void 0:a.usePKCE)||e.usePKCE){let p=E(),c=b(p);o=t.generateAuthorizationUrl(r,c),i={state:r,codeVerifier:p,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};}else o=t.generateAuthorizationUrl(r),i={state:r,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};return await this.storage.saveAuthorizationState(i),{url:o,state:r}}async handleCallback(e,t){var U,w,C;let r=await this.storage.getAuthorizationState(t);if(!r)throw new Error("Invalid or expired state");let o=(U=r.metadata)==null?void 0:U.provider;if(!o)throw new Error("Provider not found in authorization state");let i=this.providers.get(o);if(!i)throw new Error(`Provider ${o} not found`);let s=await i.exchangeCodeForToken(e,r.codeVerifier),a=(w=r.metadata)==null?void 0:w.userId,p=(C=r.metadata)==null?void 0:C.email;if(!a||!p)throw new Error("User ID and email are required in authorization state");let c;if(i.hasProfileFetcher())try{c=await i.fetchProfile(s.accessToken);}catch(z){console.warn("Failed to fetch user profile:",z);}let x=await this.storage.saveToken({provider:o,userId:a,email:(c==null?void 0:c.email)||p,token:s,metadata:{...r.metadata,profileFetched:!!c}});await this.storage.deleteAuthorizationState(t);let f=this.providerConfigs.get(o);return f!=null&&f.onSuccess&&await f.onSuccess(a,s),{token:x,profile:c}}async getAccessToken(e,t,r={}){return (await this.getValidToken(e,t,r)).accessToken}async getValidToken(e,t,r={}){let o=await this.storage.getToken(e,t);if(!o)throw new Error(`No token found for provider ${e} and email ${t}`);if(!(r.autoRefresh!==false&&this.isTokenExpired(o.token,r)))return o.token;if(!o.token.refreshToken)throw new Error("Token expired and no refresh token available");let s=this.providers.get(e);if(!s)throw new Error(`Provider ${e} not found`);let a=await s.refreshToken(o.token.refreshToken);return await this.storage.updateToken(o.id,{token:a}),a}async getTokensByUserId(e){return this.storage.getTokensByUserId(e)}async getTokensByEmail(e){return this.storage.getTokensByEmail(e)}async deleteToken(e,t){return this.storage.deleteTokenByProviderEmail(e,t)}async cleanupExpiredTokens(){return this.storage.deleteExpiredTokens()}async cleanupExpiredStates(){return this.storage.cleanupExpiredStates()}isTokenExpired(e,t={}){let{expirationBuffer:r=300}=t;if(e.createdAt&&e.expiresIn!==void 0){let s=e.createdAt+e.expiresIn*1e3;return this.now()+r*1e3>=s}let o=new Date(e.expiresAt).getTime();return this.now()+r*1e3>=o}detectProviderType(e,t){var o;let r=t.authorizationUrl.toLowerCase();return r.includes("accounts.google.com")?"google":r.includes("github.com")?"github":r.includes("facebook.com")?"facebook":r.includes("microsoft.com")||r.includes("microsoftonline.com")?e.toLowerCase().includes("outlook")||(o=t.scopes)!=null&&o.some(i=>i.includes("outlook"))?"outlook":"microsoft":"generic"}};var ge=(n,e)=>sealData(n,{password:e}),ke=(n,e)=>unsealData(n,{password:e});
2
- export{d as BaseProfileFetcher,k as GenericOAuth2Provider,l as GenericProfileFetcher,T as GitHubProfileFetcher,P as GoogleProfileFetcher,h as InMemoryStorageAdapter,v as MicrosoftProfileFetcher,S as OAuth2Client,u as OAuth2Provider,y as ProfileFetcherFactory,m as StandardAuthorizationUrlStrategy,g as StandardTokenExchangeStrategy,b as createCodeChallenge,E as createCodeVerifier,O as generateState,ge as seal,ke as unseal};//# sourceMappingURL=index.js.map
1
+ import {createHash,randomBytes}from'crypto';import {sealData,unsealData}from'iron-session';var m=class{buildUrlParams(e){return Object.entries(e).filter(([,t])=>t!==void 0).map(([t,o])=>`${t}=${encodeURIComponent(o)}`).join("&")}generateAuthorizationUrl(e,r,t){let o={client_id:e.clientId,redirect_uri:e.redirectUri,response_type:"code",scope:e.scopes.join(" "),state:r};(e.usePKCE||e.pkce)&&t&&(o.code_challenge=t,o.code_challenge_method="S256");let i={...e.additionalParams,...e.extraAuthParams};return Object.assign(o,i),`${e.authorizationUrl}?${this.buildUrlParams(o)}`}};var g=class{buildUrlParams(e){return Object.entries(e).filter(([,t])=>t!==void 0).map(([t,o])=>`${t}=${encodeURIComponent(o)}`).join("&")}async exchangeCodeForToken(e,r,t){let o={grant_type:"authorization_code",code:e,redirect_uri:r.redirectUri,client_id:r.clientId};(r.usePKCE||r.pkce)&&t?o.code_verifier=t:r.clientSecret&&(o.client_secret=r.clientSecret);let i=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(o)});if(!i.ok){let x=await i.text();throw new Error(`Token exchange failed: ${i.statusText} - ${x}`)}let n=await i.json(),a=r.responseRootKey?n[r.responseRootKey]:n,p=Date.now(),c=a.expires_in||3600;return {accessToken:a.access_token,refreshToken:a.refresh_token,expiresAt:new Date(p+c*1e3),expiresIn:c,tokenType:a.token_type||"Bearer",scope:a.scope,createdAt:p,raw:n}}async refreshToken(e,r){let t={grant_type:"refresh_token",refresh_token:e,client_id:r.clientId};!(r.usePKCE||r.pkce)&&r.clientSecret&&(t.client_secret=r.clientSecret);let o=await fetch(r.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:this.buildUrlParams(t)});if(!o.ok){let c=await o.text();throw new Error(`Token refresh failed: ${o.statusText} - ${c}`)}let i=await o.json(),n=r.responseRootKey?i[r.responseRootKey]:i,a=Date.now(),p=n.expires_in||3600;return {accessToken:n.access_token,refreshToken:n.refresh_token||e,expiresAt:new Date(a+p*1e3),expiresIn:p,tokenType:n.token_type||"Bearer",scope:n.scope,createdAt:a,raw:i}}};var u=class{constructor(e,r,t,o){this.config=e;this.authUrlStrategy=r||this.createAuthorizationUrlStrategy(),this.tokenStrategy=t||this.createTokenExchangeStrategy(),this.profileFetcher=o;}authUrlStrategy;tokenStrategy;profileFetcher;async fetchProfile(e){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.fetchUserInfo(e)}getProfileEndpoint(){if(!this.profileFetcher)throw new Error("Profile fetcher not configured for this provider");return this.profileFetcher.getEndpoint()}setProfileFetcher(e){this.profileFetcher=e;}hasProfileFetcher(){return !!this.profileFetcher}generateAuthorizationUrl(e,r){return this.authUrlStrategy.generateAuthorizationUrl(this.config,e,r)}async exchangeCodeForToken(e,r){return this.tokenStrategy.exchangeCodeForToken(e,this.config,r)}async refreshToken(e){return this.tokenStrategy.refreshToken(e,this.config)}};var k=class extends u{constructor(e,r,t,o){super(e,r,t,o);}createAuthorizationUrlStrategy(){return new m}createTokenExchangeStrategy(){return new g}};var d=class{constructor(e){this.profileEndpoint=e;}async fetchUserInfo(e){let r=await fetch(this.profileEndpoint,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json",...this.getAdditionalHeaders()}});if(!r.ok)throw new Error(`Failed to fetch profile from ${this.profileEndpoint}: ${r.statusText}`);let t=await r.json();return this.mapToUserProfile(t)}getAdditionalHeaders(){return {}}getEndpoint(){return this.profileEndpoint}};var T=class extends d{constructor(){super("https://www.googleapis.com/oauth2/v2/userinfo");}mapToUserProfile(e){return {email:e.email,name:e.name,id:e.id,avatar:e.picture,username:e.email,raw:e}}};var P=class extends d{constructor(){super("https://api.github.com/user");}mapToUserProfile(e){var r;return {email:e.email,name:e.name||e.login,id:(r=e.id)==null?void 0:r.toString(),avatar:e.avatar_url,username:e.login,raw:e}}getAdditionalHeaders(){return {"User-Agent":"OAuth2-Token-Manager"}}};var v=class extends d{constructor(){super("https://graph.microsoft.com/v1.0/me");}mapToUserProfile(e){return {email:e.mail||e.userPrincipalName,name:e.displayName,id:e.id,avatar:void 0,username:e.userPrincipalName,raw:e}}};var h=class extends d{constructor(r,t,o){super(r);this.mapping=t;this.additionalHeaders=o;}mapToUserProfile(r){return this.mapping?{email:this.getNestedProperty(r,this.mapping.email),name:this.mapping.name?this.getNestedProperty(r,this.mapping.name):void 0,id:this.mapping.id?this.getNestedProperty(r,this.mapping.id):void 0,avatar:this.mapping.avatar?this.getNestedProperty(r,this.mapping.avatar):void 0,username:this.mapping.username?this.getNestedProperty(r,this.mapping.username):void 0,raw:r}:{email:r.email||r.mail||r.emailAddress,name:r.name||r.displayName||r.full_name,id:r.id||r.sub||r.user_id,avatar:r.avatar||r.picture||r.avatar_url,username:r.username||r.login||r.preferred_username,raw:r}}getAdditionalHeaders(){return this.additionalHeaders||{}}getNestedProperty(r,t){return t.split(".").reduce((o,i)=>o==null?void 0:o[i],r)}};var A=class{static createProfileFetcher(e,r,t){if(t!=null&&t.profileUrl)return new h(t.profileUrl,t.profileMapping,t.profileHeaders);switch(e){case "google":return new T;case "github":return new P;case "microsoft":case "outlook":return new v;case "facebook":return new h("https://graph.facebook.com/me?fields=id,name,email,picture");case "generic":default:let o=r.profileUrl||r.userInfoUrl;if(!o)throw new Error(`Profile URL must be provided for ${e} provider`);return new h(o)}}static registerCustomProfileFetcher(e,r){this.customFetchers.set(e,r);}static customFetchers=new Map;static getCustomProfileFetcher(e){return this.customFetchers.get(e)}};var y=class s{static presetConfigs={google:{authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",profileUrl:"https://www.googleapis.com/oauth2/v2/userinfo",usePKCE:true,extraAuthParams:{access_type:"offline",prompt:"consent"}},github:{authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",profileUrl:"https://api.github.com/user"},microsoft:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true},outlook:{authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",profileUrl:"https://graph.microsoft.com/v1.0/me",usePKCE:true,extraAuthParams:{prompt:"select_account"}},facebook:{authorizationUrl:"https://www.facebook.com/v12.0/dialog/oauth",tokenUrl:"https://graph.facebook.com/v12.0/oauth/access_token",profileUrl:"https://graph.facebook.com/me?fields=id,name,email,picture"}};createProvider(e,r){let t=e!=="generic"?s.presetConfigs[e]||{}:{},o={...t,...r,authorizationUrl:r.authorizationUrl||t.authorizationUrl||"",tokenUrl:r.tokenUrl||t.tokenUrl||"",profileUrl:r.profileUrl||t.profileUrl,extraAuthParams:{...t.extraAuthParams||{},...r.extraAuthParams||{}}},i=A.createProfileFetcher(e,o);return new k(o,void 0,void 0,i)}static registerPreset(e,r){s.presetConfigs[e]=r;}static getPresetConfig(e){return s.presetConfigs[e]}};var l=class{tokens=new Map;states=new Map;profileFetchers=new Map;generateId(){return Math.random().toString(36).substring(2)+Date.now().toString(36)}async saveToken(e){let r=await this.getToken(e.provider,e.email);if(r){let o={...r,...e,id:r.id,createdAt:r.createdAt,updatedAt:new Date};return this.tokens.set(r.id,o),o}let t={...e,id:this.generateId(),createdAt:new Date,updatedAt:new Date};return this.tokens.set(t.id,t),t}async queryTokens(e){let r=Array.from(this.tokens.values());if(e.id&&(r=r.filter(t=>t.id===e.id)),e.provider&&(r=r.filter(t=>t.provider===e.provider)),e.userId&&(r=r.filter(t=>t.userId===e.userId)),e.email&&(r=r.filter(t=>t.email===e.email)),!e.includeExpired){let t=new Date().getTime();r=r.filter(o=>new Date(o.token.expiresAt).getTime()>=t);}return e.offset!==void 0&&(r=r.slice(e.offset)),e.limit!==void 0&&(r=r.slice(0,e.limit)),r}async getToken(e,r){return (await this.queryTokens({provider:e,email:r,includeExpired:true}))[0]||null}async getTokenById(e){return (await this.queryTokens({id:e,includeExpired:true}))[0]||null}async getTokensByUserId(e){return this.queryTokens({userId:e})}async getTokensByEmail(e){return this.queryTokens({email:e})}async getTokensByProvider(e){return this.queryTokens({provider:e})}async getAccounts(e,r){return this.queryTokens({userId:e,provider:r})}async getTokensForEmail(e,r,t){return (await this.queryTokens({userId:e,provider:r,email:t}))[0]||null}async getTokens(e,r){return this.queryTokens({userId:e,provider:r})}async updateToken(e,r){let t=this.tokens.get(e);if(!t)return null;let o={...t,...r.token&&{token:r.token},...r.metadata&&{metadata:{...t.metadata,...r.metadata}},updatedAt:new Date};return this.tokens.set(e,o),o}async deleteToken(e){return this.tokens.delete(e)}async deleteTokenByProviderEmail(e,r){let t=await this.getToken(e,r);return t?this.tokens.delete(t.id):false}async deleteExpiredTokens(){let e=new Date().getTime(),r=Array.from(this.tokens.entries()).filter(([,t])=>new Date(t.token.expiresAt).getTime()<e).map(([t])=>t);return r.forEach(t=>this.tokens.delete(t)),r.length}async saveAuthorizationState(e){let r={...e,createdAt:new Date(Date.now())};return this.states.set(e.state,r),r}async getAuthorizationState(e){return this.states.get(e)||null}async deleteAuthorizationState(e){return this.states.delete(e)}async cleanupExpiredStates(){let e=new Date().getTime(),r=10*60*1e3,t=Array.from(this.states.entries()).filter(([,o])=>e-o.createdAt.getTime()>r).map(([o])=>o);return t.forEach(o=>this.states.delete(o)),t.length}registerProfileFetcher(e,r){this.profileFetchers.set(e,r);}getProfileFetcher(e){return this.profileFetchers.get(e)}getProfileFetchers(){return new Map(this.profileFetchers)}};var b=()=>randomBytes(32).toString("base64").replace(/[^a-zA-Z0-9]/g,"").substring(0,128),F=s=>createHash("sha256").update(s).digest("base64url"),C=()=>randomBytes(16).toString("base64url");var w=class{storage;providerFactory;providers=new Map;providerConfigs=new Map;now;autoRefreshOptions;constructor(e={}){var r,t,o;this.storage=e.storage||new l,this.providerFactory=new y,this.now=Date.now,this.autoRefreshOptions={enabled:((r=e.autoRefresh)==null?void 0:r.enabled)??true,refreshBuffer:((t=e.autoRefresh)==null?void 0:t.refreshBuffer)??10,onRefreshError:(o=e.autoRefresh)==null?void 0:o.onRefreshError},e.providers&&Object.entries(e.providers).forEach(([i,n])=>{this.registerProvider(i,n);});}registerProvider(e,r){this.providerConfigs.set(e,r);let t=this.detectProviderType(e,r),o=this.providerFactory.createProvider(t,r),i=this.storage.getProfileFetcher(e);i&&o.setProfileFetcher(i),this.providers.set(e,o);}async authorize(e){var a;let r=this.providers.get(e.provider);if(!r)throw new Error(`Provider ${e.provider} not found`);let t=C(),o,i;if(((a=this.providerConfigs.get(e.provider))==null?void 0:a.usePKCE)||e.usePKCE){let p=b(),c=F(p);o=r.generateAuthorizationUrl(t,c),i={state:t,codeVerifier:p,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};}else o=r.generateAuthorizationUrl(t),i={state:t,config:this.providerConfigs.get(e.provider),metadata:{...e.metadata,userId:e.userId,email:e.email,provider:e.provider}};return await this.storage.saveAuthorizationState(i),{url:o,state:t}}async handleCallback(e,r){var S,U,O;let t=await this.storage.getAuthorizationState(r);if(!t)throw new Error("Invalid or expired state");let o=(S=t.metadata)==null?void 0:S.provider;if(!o)throw new Error("Provider not found in authorization state");let i=this.providers.get(o);if(!i)throw new Error(`Provider ${o} not found`);let n=await i.exchangeCodeForToken(e,t.codeVerifier),a=(U=t.metadata)==null?void 0:U.userId,p=(O=t.metadata)==null?void 0:O.email;if(!a||!p)throw new Error("User ID and email are required in authorization state");let c;if(i.hasProfileFetcher())try{c=await i.fetchProfile(n.accessToken);}catch(R){console.warn("Failed to fetch user profile:",R);}let x=await this.storage.saveToken({provider:o,userId:a,email:(c==null?void 0:c.email)||p,token:n,metadata:{...t.metadata,profileFetched:!!c}});await this.storage.deleteAuthorizationState(r);let f=this.providerConfigs.get(o);return f!=null&&f.onSuccess&&await f.onSuccess(a,n),{token:x,profile:c}}async getAccessToken(e,r,t={}){return (await this.getValidToken(e,r,t)).accessToken}async getValidToken(e,r,t={}){let o=await this.storage.getToken(e,r);if(!o)throw new Error(`No token found for provider ${e} and email ${r}`);if(!(t.autoRefresh!==false&&this.isTokenExpired(o.token,t)))return o.token;if(!o.token.refreshToken)throw new Error("Token expired and no refresh token available");let n=this.providers.get(e);if(!n)throw new Error(`Provider ${e} not found`);let a=await n.refreshToken(o.token.refreshToken);return await this.storage.updateToken(o.id,{token:a}),a}async queryTokens(e){let r=this.autoRefreshOptions.enabled&&!e.includeExpired?{...e,includeExpired:true}:e,t=await this.storage.queryTokens(r);return this.autoRefreshOptions.enabled&&!e.includeExpired?(await this.refreshTokensIfNeeded(t)).filter(i=>new Date(i.token.expiresAt).getTime()>this.now()):t}async getTokensByUserId(e){return this.queryTokens({userId:e})}async getTokensByEmail(e){return this.queryTokens({email:e})}async deleteToken(e,r){return this.storage.deleteTokenByProviderEmail(e,r)}async cleanupExpiredTokens(){return this.storage.deleteExpiredTokens()}async cleanupExpiredStates(){return this.storage.cleanupExpiredStates()}isTokenExpired(e,r={}){let{expirationBuffer:t=300}=r;if(e.createdAt&&e.expiresIn!==void 0){let n=e.createdAt+e.expiresIn*1e3;return this.now()+t*1e3>=n}let o=new Date(e.expiresAt).getTime();return this.now()+t*1e3>=o}detectProviderType(e,r){var o;let t=r.authorizationUrl.toLowerCase();return t.includes("accounts.google.com")?"google":t.includes("github.com")?"github":t.includes("facebook.com")?"facebook":t.includes("microsoft.com")||t.includes("microsoftonline.com")?e.toLowerCase().includes("outlook")||(o=r.scopes)!=null&&o.some(i=>i.includes("outlook"))?"outlook":"microsoft":"generic"}async refreshTokensIfNeeded(e){let r=e.map(async t=>{if(this.shouldRefreshToken(t))try{let o=this.providers.get(t.provider);if(!o)return console.warn(`Provider ${t.provider} not found for token refresh`),t;if(!t.token.refreshToken)return console.warn(`No refresh token available for ${t.provider}:${t.email}`),t;let i=await o.refreshToken(t.token.refreshToken);return await this.storage.updateToken(t.id,{token:i})||t}catch(o){return this.autoRefreshOptions.onRefreshError&&this.autoRefreshOptions.onRefreshError(o,t),console.error(`Failed to refresh token for ${t.provider}:${t.email}:`,o),t}return t});return Promise.all(r)}shouldRefreshToken(e){if(!e.token.refreshToken)return false;let r=new Date(e.token.expiresAt).getTime(),t=this.now();if(t>=r)return true;let o=this.autoRefreshOptions.refreshBuffer*60*1e3,i=r-o;return t>=i}updateAutoRefreshOptions(e){this.autoRefreshOptions={...this.autoRefreshOptions,...e};}};var ge=(s,e)=>sealData(s,{password:e}),ke=(s,e)=>unsealData(s,{password:e});
2
+ export{d as BaseProfileFetcher,k as GenericOAuth2Provider,h as GenericProfileFetcher,P as GitHubProfileFetcher,T as GoogleProfileFetcher,l as InMemoryStorageAdapter,v as MicrosoftProfileFetcher,w as OAuth2Client,u as OAuth2Provider,A as ProfileFetcherFactory,m as StandardAuthorizationUrlStrategy,g as StandardTokenExchangeStrategy,F as createCodeChallenge,b as createCodeVerifier,C as generateState,ge as seal,ke as unseal};//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","query","tokens","t","provider","email","id","userId","update","token","expiredTokens","newState","maxAge","expiredStates","fetcher","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","customFetcher","authUrl","authState","_b","_c","providerInstance","profile","error","savedToken","storedToken","expirationBuffer","expiresAt","s","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.js","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport {\n StorageAdapter,\n StoredToken,\n SaveTokenInput,\n UpdateTokenInput,\n TokenQuery,\n} from './interfaces';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n private profileFetchers: Map<string, BaseProfileFetcher> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async queryTokens(query: TokenQuery): Promise<StoredToken[]> {\n let tokens = Array.from(this.tokens.values());\n\n // Apply filters\n if (query.id) {\n tokens = tokens.filter((t) => t.id === query.id);\n }\n if (query.provider) {\n tokens = tokens.filter((t) => t.provider === query.provider);\n }\n if (query.userId) {\n tokens = tokens.filter((t) => t.userId === query.userId);\n }\n if (query.email) {\n tokens = tokens.filter((t) => t.email === query.email);\n }\n\n // Filter out expired tokens unless explicitly requested\n if (!query.includeExpired) {\n const now = new Date().getTime();\n tokens = tokens.filter((t) => {\n const expiresAt = new Date(t.token.expiresAt).getTime();\n return expiresAt >= now;\n });\n }\n\n // Apply pagination\n if (query.offset !== undefined) {\n tokens = tokens.slice(query.offset);\n }\n if (query.limit !== undefined) {\n tokens = tokens.slice(0, query.limit);\n }\n\n return tokens;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ provider, email, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ id, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId });\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.queryTokens({ email });\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ provider });\n }\n\n async getAccounts(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async getTokensForEmail(\n userId: string,\n provider: string,\n email: string,\n ): Promise<StoredToken | null> {\n const results = await this.queryTokens({ userId, provider, email });\n return results[0] || null;\n }\n\n async getTokens(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n\n // Profile fetcher operations\n registerProfileFetcher(providerName: string, fetcher: BaseProfileFetcher): void {\n this.profileFetchers.set(providerName, fetcher);\n }\n\n getProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.profileFetchers.get(providerName);\n }\n\n getProfileFetchers(): Map<string, BaseProfileFetcher> {\n return new Map(this.profileFetchers);\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n\n // Check if storage has a custom profile fetcher for this provider\n const customFetcher = this.storage.getProfileFetcher(name);\n if (customFetcher) {\n provider.setProfileFetcher(customFetcher);\n }\n\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email: profile?.email || email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.storage.getTokensByUserId(userId);\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.storage.getTokensByEmail(email);\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
1
+ {"version":3,"sources":["../src/strategies/standard-authorization-url.strategy.ts","../src/strategies/standard-token-exchange.strategy.ts","../src/providers/base.provider.ts","../src/providers/generic.provider.ts","../src/profile/base-profile-fetcher.ts","../src/profile/google-profile-fetcher.ts","../src/profile/github-profile-fetcher.ts","../src/profile/microsoft-profile-fetcher.ts","../src/profile/generic-profile-fetcher.ts","../src/profile/profile-fetcher-factory.ts","../src/providers/provider.factory.ts","../src/storage/memory.adapter.ts","../src/utils/crypto.ts","../src/facade/oauth2.facade.ts","../src/utils/seal.ts"],"names":["StandardAuthorizationUrlStrategy","params","value","key","config","state","codeChallenge","extraParams","StandardTokenExchangeStrategy","code","codeVerifier","response","errorText","data","tokenData","now","expiresIn","refreshToken","OAuth2Provider","authUrlStrategy","tokenStrategy","profileFetcher","accessToken","GenericOAuth2Provider","BaseProfileFetcher","profileEndpoint","rawData","GoogleProfileFetcher","GitHubProfileFetcher","_a","MicrosoftProfileFetcher","GenericProfileFetcher","mapping","additionalHeaders","obj","path","current","ProfileFetcherFactory","providerType","options","profileUrl","providerName","OAuth2ProviderFactory","_OAuth2ProviderFactory","type","presetConfig","mergedConfig","name","InMemoryStorageAdapter","input","existingToken","updatedToken","newToken","query","tokens","t","provider","email","id","userId","update","token","expiredTokens","newState","maxAge","expiredStates","fetcher","createCodeVerifier","randomBytes","createCodeChallenge","verifier","createHash","generateState","OAuth2Client","_b","_c","customFetcher","authUrl","authState","providerInstance","profile","error","savedToken","storedToken","queryWithExpired","expirationBuffer","expiresAt","s","refreshPromises","bufferMs","shouldRefreshAt","seal","d","sealData","unseal","unsealData"],"mappings":"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","file":"index.js","sourcesContent":["import { OAuth2Config } from '../types';\nimport { AuthorizationUrlStrategy } from './authorization-url.strategy';\n\nexport class StandardAuthorizationUrlStrategy implements AuthorizationUrlStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n generateAuthorizationUrl(config: OAuth2Config, state: string, codeChallenge?: string): string {\n const params: Record<string, string | undefined> = {\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: 'code',\n scope: config.scopes.join(' '),\n state,\n };\n\n // Add PKCE parameters\n if ((config.usePKCE || config.pkce) && codeChallenge) {\n params.code_challenge = codeChallenge;\n params.code_challenge_method = 'S256';\n }\n\n // Merge additional parameters (for both additionalParams and extraAuthParams)\n const extraParams = {\n ...config.additionalParams,\n ...config.extraAuthParams,\n };\n\n Object.assign(params, extraParams);\n\n return `${config.authorizationUrl}?${this.buildUrlParams(params)}`;\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\nimport { TokenExchangeStrategy } from './token-exchange.strategy';\n\nexport class StandardTokenExchangeStrategy implements TokenExchangeStrategy {\n protected buildUrlParams(params: Record<string, string | undefined>): string {\n const filtered = Object.entries(params)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${encodeURIComponent(value as string)}`);\n\n return filtered.join('&');\n }\n\n async exchangeCodeForToken(\n code: string,\n config: OAuth2Config,\n codeVerifier?: string,\n ): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'authorization_code',\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n };\n\n // Handle PKCE\n if ((config.usePKCE || config.pkce) && codeVerifier) {\n params.code_verifier = codeVerifier;\n } else if (config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n\n // Handle nested response (e.g., Outlook might nest tokens)\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n\n async refreshToken(refreshToken: string, config: OAuth2Config): Promise<OAuth2Token> {\n const params: Record<string, string | undefined> = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.clientId,\n };\n\n // Only add client_secret if not using PKCE\n if (!(config.usePKCE || config.pkce) && config.clientSecret) {\n params.client_secret = config.clientSecret;\n }\n\n const response = await fetch(config.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: this.buildUrlParams(params),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed: ${response.statusText} - ${errorText}`);\n }\n\n const data = await response.json();\n const tokenData = config.responseRootKey ? data[config.responseRootKey] : data;\n\n const now = Date.now();\n const expiresIn = tokenData.expires_in || 3600;\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token || refreshToken,\n expiresAt: new Date(now + expiresIn * 1000),\n expiresIn: expiresIn,\n tokenType: tokenData.token_type || 'Bearer',\n scope: tokenData.scope,\n createdAt: now,\n raw: data,\n };\n }\n}\n","import { OAuth2Config, OAuth2Token } from '../types';\n\nimport { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { UserProfile } from './interfaces/profile-fetcher.interface';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport abstract class OAuth2Provider {\n protected authUrlStrategy: AuthorizationUrlStrategy;\n protected tokenStrategy: TokenExchangeStrategy;\n protected profileFetcher?: BaseProfileFetcher;\n\n constructor(\n protected config: OAuth2Config,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n this.authUrlStrategy = authUrlStrategy || this.createAuthorizationUrlStrategy();\n this.tokenStrategy = tokenStrategy || this.createTokenExchangeStrategy();\n this.profileFetcher = profileFetcher;\n }\n\n // Factory methods\n protected abstract createAuthorizationUrlStrategy(): AuthorizationUrlStrategy;\n protected abstract createTokenExchangeStrategy(): TokenExchangeStrategy;\n\n // Profile fetching methods\n async fetchProfile(accessToken: string): Promise<UserProfile> {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.fetchUserInfo(accessToken);\n }\n\n getProfileEndpoint(): string {\n if (!this.profileFetcher) {\n throw new Error('Profile fetcher not configured for this provider');\n }\n return this.profileFetcher.getEndpoint();\n }\n\n setProfileFetcher(profileFetcher: BaseProfileFetcher): void {\n this.profileFetcher = profileFetcher;\n }\n\n hasProfileFetcher(): boolean {\n return !!this.profileFetcher;\n }\n\n generateAuthorizationUrl(state: string, codeChallenge?: string): string {\n return this.authUrlStrategy.generateAuthorizationUrl(this.config, state, codeChallenge);\n }\n\n async exchangeCodeForToken(code: string, codeVerifier?: string): Promise<OAuth2Token> {\n return this.tokenStrategy.exchangeCodeForToken(code, this.config, codeVerifier);\n }\n\n async refreshToken(refreshToken: string): Promise<OAuth2Token> {\n return this.tokenStrategy.refreshToken(refreshToken, this.config);\n }\n}\n","import { AuthorizationUrlStrategy } from '../strategies/authorization-url.strategy';\nimport { StandardAuthorizationUrlStrategy } from '../strategies/standard-authorization-url.strategy';\nimport { StandardTokenExchangeStrategy } from '../strategies/standard-token-exchange.strategy';\nimport { TokenExchangeStrategy } from '../strategies/token-exchange.strategy';\nimport { OAuth2Provider } from './base.provider';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class GenericOAuth2Provider extends OAuth2Provider {\n constructor(\n config: any,\n authUrlStrategy?: AuthorizationUrlStrategy,\n tokenStrategy?: TokenExchangeStrategy,\n profileFetcher?: BaseProfileFetcher,\n ) {\n super(config, authUrlStrategy, tokenStrategy, profileFetcher);\n }\n\n protected createAuthorizationUrlStrategy(): AuthorizationUrlStrategy {\n return new StandardAuthorizationUrlStrategy();\n }\n\n protected createTokenExchangeStrategy(): TokenExchangeStrategy {\n return new StandardTokenExchangeStrategy();\n }\n}\n","import { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport abstract class BaseProfileFetcher {\n constructor(protected profileEndpoint: string) {}\n\n /**\n * Fetch user profile information from the OAuth provider\n * @param accessToken The OAuth access token\n * @returns Promise resolving to standardized user profile\n */\n async fetchUserInfo(accessToken: string): Promise<UserProfile> {\n const response = await fetch(this.profileEndpoint, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n Accept: 'application/json',\n ...this.getAdditionalHeaders(),\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch profile from ${this.profileEndpoint}: ${response.statusText}`,\n );\n }\n\n const rawData = await response.json();\n return this.mapToUserProfile(rawData);\n }\n\n /**\n * Map the raw API response to our standardized UserProfile structure\n * Override this method to customize mapping for different providers\n */\n protected abstract mapToUserProfile(rawData: any): UserProfile;\n\n /**\n * Get additional headers if needed for the profile request\n * Override this method to add provider-specific headers\n */\n protected getAdditionalHeaders(): Record<string, string> {\n return {};\n }\n\n /**\n * Get the profile endpoint URL\n */\n getEndpoint(): string {\n return this.profileEndpoint;\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GoogleProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://www.googleapis.com/oauth2/v2/userinfo');\n }\n\n mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name,\n id: rawData.id,\n avatar: rawData.picture,\n username: rawData.email,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class GitHubProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://api.github.com/user');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.email,\n name: rawData.name || rawData.login,\n id: rawData.id?.toString(),\n avatar: rawData.avatar_url,\n username: rawData.login,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return {\n 'User-Agent': 'OAuth2-Token-Manager', // GitHub requires User-Agent\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport class MicrosoftProfileFetcher extends BaseProfileFetcher {\n constructor() {\n super('https://graph.microsoft.com/v1.0/me');\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n return {\n email: rawData.mail || rawData.userPrincipalName,\n name: rawData.displayName,\n id: rawData.id,\n avatar: undefined, // Microsoft Graph doesn't include avatar in basic profile\n username: rawData.userPrincipalName,\n raw: rawData,\n };\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface ProfileMapping {\n email: string;\n name?: string;\n id?: string;\n avatar?: string;\n username?: string;\n}\n\nexport class GenericProfileFetcher extends BaseProfileFetcher {\n constructor(\n profileEndpoint: string,\n private mapping?: ProfileMapping,\n private additionalHeaders?: Record<string, string>,\n ) {\n super(profileEndpoint);\n }\n\n protected mapToUserProfile(rawData: any): UserProfile {\n if (this.mapping) {\n return {\n email: this.getNestedProperty(rawData, this.mapping.email),\n name: this.mapping.name ? this.getNestedProperty(rawData, this.mapping.name) : undefined,\n id: this.mapping.id ? this.getNestedProperty(rawData, this.mapping.id) : undefined,\n avatar: this.mapping.avatar\n ? this.getNestedProperty(rawData, this.mapping.avatar)\n : undefined,\n username: this.mapping.username\n ? this.getNestedProperty(rawData, this.mapping.username)\n : undefined,\n raw: rawData,\n };\n }\n\n // Default generic mapping\n return {\n email: rawData.email || rawData.mail || rawData.emailAddress,\n name: rawData.name || rawData.displayName || rawData.full_name,\n id: rawData.id || rawData.sub || rawData.user_id,\n avatar: rawData.avatar || rawData.picture || rawData.avatar_url,\n username: rawData.username || rawData.login || rawData.preferred_username,\n raw: rawData,\n };\n }\n\n protected getAdditionalHeaders(): Record<string, string> {\n return this.additionalHeaders || {};\n }\n\n private getNestedProperty(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n }\n}\n","import { BaseProfileFetcher } from './base-profile-fetcher';\nimport { GoogleProfileFetcher } from './google-profile-fetcher';\nimport { GitHubProfileFetcher } from './github-profile-fetcher';\nimport { MicrosoftProfileFetcher } from './microsoft-profile-fetcher';\nimport { GenericProfileFetcher, ProfileMapping } from './generic-profile-fetcher';\nimport { ProviderType } from '../providers/provider.factory';\nimport { OAuth2Config } from '../types';\n\nexport interface ProfileFetcherOptions {\n profileUrl?: string;\n profileMapping?: ProfileMapping;\n profileHeaders?: Record<string, string>;\n}\n\nexport class ProfileFetcherFactory {\n static createProfileFetcher(\n providerType: ProviderType,\n config: OAuth2Config,\n options?: ProfileFetcherOptions,\n ): BaseProfileFetcher {\n // If custom options are provided, use GenericProfileFetcher\n if (options?.profileUrl) {\n return new GenericProfileFetcher(\n options.profileUrl,\n options.profileMapping,\n options.profileHeaders,\n );\n }\n\n // Use provider-specific fetchers for known providers\n switch (providerType) {\n case 'google':\n return new GoogleProfileFetcher();\n case 'github':\n return new GitHubProfileFetcher();\n case 'microsoft':\n case 'outlook':\n return new MicrosoftProfileFetcher();\n case 'facebook':\n return new GenericProfileFetcher(\n 'https://graph.facebook.com/me?fields=id,name,email,picture',\n );\n case 'generic':\n default:\n // For generic providers, use the profileUrl from config\n const profileUrl = config.profileUrl || config.userInfoUrl;\n if (!profileUrl) {\n throw new Error(`Profile URL must be provided for ${providerType} provider`);\n }\n return new GenericProfileFetcher(profileUrl);\n }\n }\n\n static registerCustomProfileFetcher(\n providerName: string,\n profileFetcher: BaseProfileFetcher,\n ): void {\n // Store custom profile fetchers for later use\n this.customFetchers.set(providerName, profileFetcher);\n }\n\n private static customFetchers = new Map<string, BaseProfileFetcher>();\n\n static getCustomProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.customFetchers.get(providerName);\n }\n}\n","import { OAuth2Config } from '../types';\nimport { OAuth2Provider } from './base.provider';\nimport { GenericOAuth2Provider } from './generic.provider';\nimport { ProfileFetcherFactory } from '../profile/profile-fetcher-factory';\n\nexport type ProviderType = 'google' | 'github' | 'microsoft' | 'outlook' | 'facebook' | 'generic';\n\nexport interface ProviderFactory {\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider;\n}\n\nexport class OAuth2ProviderFactory implements ProviderFactory {\n private static presetConfigs: Record<string, Partial<OAuth2Config>> = {\n google: {\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n profileUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n usePKCE: true,\n extraAuthParams: {\n access_type: 'offline',\n prompt: 'consent',\n },\n },\n github: {\n authorizationUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n profileUrl: 'https://api.github.com/user',\n },\n microsoft: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n },\n outlook: {\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n profileUrl: 'https://graph.microsoft.com/v1.0/me',\n usePKCE: true,\n extraAuthParams: {\n prompt: 'select_account',\n },\n },\n facebook: {\n authorizationUrl: 'https://www.facebook.com/v12.0/dialog/oauth',\n tokenUrl: 'https://graph.facebook.com/v12.0/oauth/access_token',\n profileUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',\n },\n };\n\n createProvider(type: ProviderType, config: OAuth2Config): OAuth2Provider {\n const presetConfig = type !== 'generic' ? OAuth2ProviderFactory.presetConfigs[type] || {} : {};\n\n // Only override preset values if the user explicitly provides them (not empty strings)\n const mergedConfig: OAuth2Config = {\n ...presetConfig,\n ...config,\n // Don't override preset URLs with empty strings\n authorizationUrl: config.authorizationUrl || presetConfig.authorizationUrl || '',\n tokenUrl: config.tokenUrl || presetConfig.tokenUrl || '',\n profileUrl: config.profileUrl || presetConfig.profileUrl,\n extraAuthParams: {\n ...(presetConfig.extraAuthParams || {}),\n ...(config.extraAuthParams || {}),\n },\n };\n\n const profileFetcher = ProfileFetcherFactory.createProfileFetcher(type, mergedConfig);\n\n return new GenericOAuth2Provider(mergedConfig, undefined, undefined, profileFetcher);\n }\n\n static registerPreset(name: string, config: Partial<OAuth2Config>): void {\n OAuth2ProviderFactory.presetConfigs[name] = config;\n }\n\n static getPresetConfig(name: string): Partial<OAuth2Config> | undefined {\n return OAuth2ProviderFactory.presetConfigs[name];\n }\n}\n","import { AuthorizationState } from '../types';\nimport {\n StorageAdapter,\n StoredToken,\n SaveTokenInput,\n UpdateTokenInput,\n TokenQuery,\n} from './interfaces';\nimport { BaseProfileFetcher } from '../profile/base-profile-fetcher';\n\nexport class InMemoryStorageAdapter implements StorageAdapter {\n private tokens: Map<string, StoredToken> = new Map();\n private states: Map<string, AuthorizationState> = new Map();\n private profileFetchers: Map<string, BaseProfileFetcher> = new Map();\n\n private generateId(): string {\n return Math.random().toString(36).substring(2) + Date.now().toString(36);\n }\n\n // Token operations\n async saveToken(input: SaveTokenInput): Promise<StoredToken> {\n // Check if token with same provider + email exists\n const existingToken = await this.getToken(input.provider, input.email);\n\n if (existingToken) {\n // Replace existing token\n const updatedToken: StoredToken = {\n ...existingToken,\n ...input,\n id: existingToken.id,\n createdAt: existingToken.createdAt,\n updatedAt: new Date(),\n };\n this.tokens.set(existingToken.id, updatedToken);\n return updatedToken;\n }\n\n // Create new token\n const newToken: StoredToken = {\n ...input,\n id: this.generateId(),\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n this.tokens.set(newToken.id, newToken);\n return newToken;\n }\n\n async queryTokens(query: TokenQuery): Promise<StoredToken[]> {\n let tokens = Array.from(this.tokens.values());\n\n // Apply filters\n if (query.id) {\n tokens = tokens.filter((t) => t.id === query.id);\n }\n if (query.provider) {\n tokens = tokens.filter((t) => t.provider === query.provider);\n }\n if (query.userId) {\n tokens = tokens.filter((t) => t.userId === query.userId);\n }\n if (query.email) {\n tokens = tokens.filter((t) => t.email === query.email);\n }\n\n // Filter out expired tokens unless explicitly requested\n if (!query.includeExpired) {\n const now = new Date().getTime();\n tokens = tokens.filter((t) => {\n const expiresAt = new Date(t.token.expiresAt).getTime();\n return expiresAt >= now;\n });\n }\n\n // Apply pagination\n if (query.offset !== undefined) {\n tokens = tokens.slice(query.offset);\n }\n if (query.limit !== undefined) {\n tokens = tokens.slice(0, query.limit);\n }\n\n return tokens;\n }\n\n async getToken(provider: string, email: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ provider, email, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokenById(id: string): Promise<StoredToken | null> {\n const results = await this.queryTokens({ id, includeExpired: true });\n return results[0] || null;\n }\n\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId });\n }\n\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.queryTokens({ email });\n }\n\n async getTokensByProvider(provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ provider });\n }\n\n async getAccounts(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async getTokensForEmail(\n userId: string,\n provider: string,\n email: string,\n ): Promise<StoredToken | null> {\n const results = await this.queryTokens({ userId, provider, email });\n return results[0] || null;\n }\n\n async getTokens(userId: string, provider: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId, provider });\n }\n\n async updateToken(id: string, update: UpdateTokenInput): Promise<StoredToken | null> {\n const token = this.tokens.get(id);\n if (!token) return null;\n\n const updatedToken: StoredToken = {\n ...token,\n ...(update.token && { token: update.token }),\n ...(update.metadata && { metadata: { ...token.metadata, ...update.metadata } }),\n updatedAt: new Date(),\n };\n this.tokens.set(id, updatedToken);\n return updatedToken;\n }\n\n async deleteToken(id: string): Promise<boolean> {\n return this.tokens.delete(id);\n }\n\n async deleteTokenByProviderEmail(provider: string, email: string): Promise<boolean> {\n const token = await this.getToken(provider, email);\n if (!token) return false;\n return this.tokens.delete(token.id);\n }\n\n async deleteExpiredTokens(): Promise<number> {\n const now = new Date().getTime();\n const expiredTokens = Array.from(this.tokens.entries())\n .filter(([, token]) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt < now;\n })\n .map(([id]) => id);\n\n expiredTokens.forEach((id) => this.tokens.delete(id));\n return expiredTokens.length;\n }\n\n // Authorization state operations\n async saveAuthorizationState(\n state: Omit<AuthorizationState, 'createdAt'>,\n ): Promise<AuthorizationState> {\n const newState: AuthorizationState = {\n ...state,\n createdAt: new Date(Date.now()),\n };\n this.states.set(state.state, newState);\n return newState;\n }\n\n async getAuthorizationState(state: string): Promise<AuthorizationState | null> {\n return this.states.get(state) || null;\n }\n\n async deleteAuthorizationState(state: string): Promise<boolean> {\n return this.states.delete(state);\n }\n\n async cleanupExpiredStates(): Promise<number> {\n const now = new Date().getTime();\n const maxAge = 10 * 60 * 1000; // 10 minutes\n\n const expiredStates = Array.from(this.states.entries())\n .filter(([, state]) => {\n const stateAge = now - state.createdAt.getTime();\n return stateAge > maxAge;\n })\n .map(([key]) => key);\n\n expiredStates.forEach((key) => this.states.delete(key));\n return expiredStates.length;\n }\n\n // Profile fetcher operations\n registerProfileFetcher(providerName: string, fetcher: BaseProfileFetcher): void {\n this.profileFetchers.set(providerName, fetcher);\n }\n\n getProfileFetcher(providerName: string): BaseProfileFetcher | undefined {\n return this.profileFetchers.get(providerName);\n }\n\n getProfileFetchers(): Map<string, BaseProfileFetcher> {\n return new Map(this.profileFetchers);\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\nexport const createCodeVerifier = () =>\n randomBytes(32)\n .toString('base64')\n .replace(/[^a-zA-Z0-9]/g, '')\n .substring(0, 128);\n\nexport const createCodeChallenge = (verifier: string): string => {\n return createHash('sha256').update(verifier).digest('base64url');\n};\n\nexport const generateState = (): string => {\n return randomBytes(16).toString('base64url');\n};\n","import { OAuth2Config, OAuth2Token, AuthorizationState } from '../types';\nimport { OAuth2ProviderFactory, ProviderType } from '../providers/provider.factory';\nimport { StorageAdapter, StoredToken, TokenQuery } from '../storage/interfaces';\nimport { InMemoryStorageAdapter } from '../storage/memory.adapter';\nimport { ProviderFactory } from '../providers/provider.factory';\nimport { createCodeVerifier, createCodeChallenge, generateState } from '../utils/crypto';\nimport { OAuth2Provider } from '../providers/base.provider';\nimport { UserProfile } from '../providers/interfaces/profile-fetcher.interface';\n\nexport interface OAuth2Options {\n storage?: StorageAdapter;\n providers?: Record<string, OAuth2Config>;\n autoRefresh?: AutoRefreshOptions;\n}\n\nexport interface AutoRefreshOptions {\n enabled?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n onRefreshError?: (error: Error, token: StoredToken) => void;\n}\n\nexport interface AuthorizationOptions {\n provider: string;\n userId: string;\n email: string;\n scopes?: string[];\n metadata?: Record<string, any>;\n usePKCE?: boolean;\n}\n\nexport interface TokenOptions {\n autoRefresh?: boolean;\n refreshBuffer?: number; // minutes before expiry to refresh\n expirationBuffer?: number; // seconds before expiry to consider expired\n defaultExpiresIn?: number; // default expiration in seconds\n}\n\nexport interface CallbackResult {\n token: StoredToken;\n profile?: UserProfile;\n}\n\nexport class OAuth2Client {\n private storage: StorageAdapter;\n private providerFactory: ProviderFactory;\n private providers: Map<string, OAuth2Provider> = new Map();\n private providerConfigs: Map<string, OAuth2Config> = new Map();\n private now: () => number;\n private autoRefreshOptions: AutoRefreshOptions;\n\n constructor(options: OAuth2Options = {}) {\n this.storage = options.storage || new InMemoryStorageAdapter();\n this.providerFactory = new OAuth2ProviderFactory();\n this.now = Date.now;\n\n // Set default auto-refresh options - enabled by default\n this.autoRefreshOptions = {\n enabled: options.autoRefresh?.enabled ?? true, // Enabled by default\n refreshBuffer: options.autoRefresh?.refreshBuffer ?? 10, // 10 minutes before expiry (safe for Google's 1-hour tokens)\n onRefreshError: options.autoRefresh?.onRefreshError,\n };\n\n // Register predefined providers\n if (options.providers) {\n Object.entries(options.providers).forEach(([name, config]) => {\n this.registerProvider(name, config);\n });\n }\n }\n\n /**\n * Register a provider configuration\n */\n registerProvider(name: string, config: OAuth2Config): void {\n this.providerConfigs.set(name, config);\n\n // Determine provider type based on configuration\n const providerType = this.detectProviderType(name, config);\n const provider = this.providerFactory.createProvider(providerType, config);\n\n // Check if storage has a custom profile fetcher for this provider\n const customFetcher = this.storage.getProfileFetcher(name);\n if (customFetcher) {\n provider.setProfileFetcher(customFetcher);\n }\n\n this.providers.set(name, provider);\n }\n\n /**\n * Start OAuth2 authorization flow\n */\n async authorize(options: AuthorizationOptions): Promise<{ url: string; state: string }> {\n const provider = this.providers.get(options.provider);\n if (!provider) throw new Error(`Provider ${options.provider} not found`);\n\n const state = generateState();\n let authUrl: string;\n let authState: Omit<AuthorizationState, 'createdAt'>;\n\n const requiresPKCE = this.providerConfigs.get(options.provider)?.usePKCE || options.usePKCE;\n\n if (requiresPKCE) {\n const codeVerifier = createCodeVerifier();\n const codeChallenge = createCodeChallenge(codeVerifier);\n authUrl = provider.generateAuthorizationUrl(state, codeChallenge);\n authState = {\n state,\n codeVerifier,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n } else {\n authUrl = provider.generateAuthorizationUrl(state);\n authState = {\n state,\n config: this.providerConfigs.get(options.provider)!,\n metadata: {\n ...options.metadata,\n userId: options.userId,\n email: options.email,\n provider: options.provider,\n },\n };\n }\n\n await this.storage.saveAuthorizationState(authState);\n return { url: authUrl, state };\n }\n\n /**\n * Handle OAuth2 callback\n */\n async handleCallback(code: string, state: string): Promise<CallbackResult> {\n const authState = await this.storage.getAuthorizationState(state);\n if (!authState) throw new Error('Invalid or expired state');\n\n const provider = authState.metadata?.provider;\n if (!provider) throw new Error('Provider not found in authorization state');\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n // Exchange code for tokens\n const tokens = await providerInstance.exchangeCodeForToken(code, authState.codeVerifier);\n\n // Extract user data from metadata\n const userId = authState.metadata?.userId;\n const email = authState.metadata?.email;\n\n if (!userId || !email) {\n throw new Error('User ID and email are required in authorization state');\n }\n\n // Fetch profile if available\n let profile: UserProfile | undefined;\n if (providerInstance.hasProfileFetcher()) {\n try {\n profile = await providerInstance.fetchProfile(tokens.accessToken);\n } catch (error) {\n console.warn('Failed to fetch user profile:', error);\n }\n }\n\n // Save token\n const savedToken = await this.storage.saveToken({\n provider,\n userId,\n email: profile?.email || email,\n token: tokens,\n metadata: {\n ...authState.metadata,\n profileFetched: !!profile,\n },\n });\n\n // Clean up authorization state\n await this.storage.deleteAuthorizationState(state);\n\n // Call onSuccess callback if defined\n const config = this.providerConfigs.get(provider);\n if (config?.onSuccess) {\n await config.onSuccess(userId, tokens);\n }\n\n return {\n token: savedToken,\n profile,\n };\n }\n\n /**\n * Get a valid access token (auto-refresh if needed)\n */\n async getAccessToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<string> {\n const token = await this.getValidToken(provider, email, options);\n return token.accessToken;\n }\n\n /**\n * Get a valid token (auto-refresh if needed)\n */\n async getValidToken(\n provider: string,\n email: string,\n options: TokenOptions = {},\n ): Promise<OAuth2Token> {\n const storedToken = await this.storage.getToken(provider, email);\n if (!storedToken) {\n throw new Error(`No token found for provider ${provider} and email ${email}`);\n }\n\n const needsRefresh =\n options.autoRefresh !== false && this.isTokenExpired(storedToken.token, options);\n\n if (!needsRefresh) {\n return storedToken.token;\n }\n\n // Refresh the token\n if (!storedToken.token.refreshToken) {\n throw new Error('Token expired and no refresh token available');\n }\n\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) throw new Error(`Provider ${provider} not found`);\n\n const newToken = await providerInstance.refreshToken(storedToken.token.refreshToken);\n await this.storage.updateToken(storedToken.id, { token: newToken });\n\n return newToken;\n }\n\n /**\n * Query tokens with automatic refresh\n */\n async queryTokens(query: TokenQuery): Promise<StoredToken[]> {\n // When auto-refresh is enabled, we need to include expired tokens\n // so we can attempt to refresh them\n const queryWithExpired =\n this.autoRefreshOptions.enabled && !query.includeExpired\n ? { ...query, includeExpired: true }\n : query;\n\n const tokens = await this.storage.queryTokens(queryWithExpired);\n\n if (this.autoRefreshOptions.enabled && !query.includeExpired) {\n const refreshedTokens = await this.refreshTokensIfNeeded(tokens);\n // Filter out tokens that are still expired after refresh attempt\n return refreshedTokens.filter((token) => {\n const expiresAt = new Date(token.token.expiresAt).getTime();\n return expiresAt > this.now();\n });\n }\n\n return tokens;\n }\n\n /**\n * Get all tokens for a user\n */\n async getTokensByUserId(userId: string): Promise<StoredToken[]> {\n return this.queryTokens({ userId });\n }\n\n /**\n * Get all tokens for an email\n */\n async getTokensByEmail(email: string): Promise<StoredToken[]> {\n return this.queryTokens({ email });\n }\n\n /**\n * Delete a token\n */\n async deleteToken(provider: string, email: string): Promise<boolean> {\n return this.storage.deleteTokenByProviderEmail(provider, email);\n }\n\n /**\n * Delete all expired tokens\n */\n async cleanupExpiredTokens(): Promise<number> {\n return this.storage.deleteExpiredTokens();\n }\n\n /**\n * Clean up expired authorization states\n */\n async cleanupExpiredStates(): Promise<number> {\n return this.storage.cleanupExpiredStates();\n }\n\n // Helper methods\n private isTokenExpired(token: OAuth2Token, options: TokenOptions = {}): boolean {\n const { expirationBuffer = 300 } = options;\n\n if (token.createdAt && token.expiresIn !== undefined) {\n const expiresAt = token.createdAt + token.expiresIn * 1000;\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n const expiresAt = new Date(token.expiresAt).getTime();\n const effectiveNow = this.now() + expirationBuffer * 1000;\n return effectiveNow >= expiresAt;\n }\n\n private detectProviderType(name: string, config: OAuth2Config): ProviderType {\n // Try to detect based on the authorization URL\n const authUrl = config.authorizationUrl.toLowerCase();\n\n // Check for known providers that have specific implementations\n if (authUrl.includes('accounts.google.com')) return 'google';\n if (authUrl.includes('github.com')) return 'github';\n if (authUrl.includes('facebook.com')) return 'facebook';\n if (authUrl.includes('microsoft.com') || authUrl.includes('microsoftonline.com')) {\n // Check if it's specifically for Outlook\n if (\n name.toLowerCase().includes('outlook') ||\n config.scopes?.some((s) => s.includes('outlook'))\n ) {\n return 'outlook';\n }\n return 'microsoft';\n }\n\n // Default to generic provider for all others\n return 'generic';\n }\n\n /**\n * Refresh tokens if they are near expiration\n */\n private async refreshTokensIfNeeded(tokens: StoredToken[]): Promise<StoredToken[]> {\n const refreshPromises = tokens.map(async (token) => {\n if (this.shouldRefreshToken(token)) {\n try {\n const provider = this.providers.get(token.provider);\n if (!provider) {\n console.warn(`Provider ${token.provider} not found for token refresh`);\n return token;\n }\n\n if (!token.token.refreshToken) {\n console.warn(`No refresh token available for ${token.provider}:${token.email}`);\n return token;\n }\n\n const newToken = await provider.refreshToken(token.token.refreshToken);\n const updated = await this.storage.updateToken(token.id, { token: newToken });\n return updated || token;\n } catch (error) {\n if (this.autoRefreshOptions.onRefreshError) {\n this.autoRefreshOptions.onRefreshError(error as Error, token);\n }\n console.error(`Failed to refresh token for ${token.provider}:${token.email}:`, error);\n return token;\n }\n }\n return token;\n });\n\n return Promise.all(refreshPromises);\n }\n\n /**\n * Check if a token should be refreshed\n */\n private shouldRefreshToken(storedToken: StoredToken): boolean {\n // Skip if no refresh token\n if (!storedToken.token.refreshToken) {\n return false;\n }\n\n // Check if token is expired or near expiration\n const expiresAt = new Date(storedToken.token.expiresAt).getTime();\n const now = this.now();\n\n // If already expired, definitely try to refresh\n if (now >= expiresAt) {\n return true;\n }\n\n // Otherwise, check if within refresh buffer\n const bufferMs = this.autoRefreshOptions.refreshBuffer! * 60 * 1000;\n const shouldRefreshAt = expiresAt - bufferMs;\n\n return now >= shouldRefreshAt;\n }\n\n /**\n * Update auto-refresh options\n */\n updateAutoRefreshOptions(options: Partial<AutoRefreshOptions>): void {\n this.autoRefreshOptions = { ...this.autoRefreshOptions, ...options };\n }\n}\n","import { sealData, unsealData } from 'iron-session';\n\nexport const seal = <T>(d: T, key: string) => sealData(d, { password: key });\nexport const unseal = <T>(s: string, key: string) => unsealData<T>(s, { password: key });\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dainprotocol/oauth2-token-manager",
3
- "version": "0.1.8-alpha.2",
3
+ "version": "0.2.0",
4
4
  "description": "A scalable OAuth2 token management library with multi-system support",
5
5
  "keywords": [
6
6
  "oauth2",
@@ -34,14 +34,36 @@
34
34
  "README.md",
35
35
  "LICENSE"
36
36
  ],
37
+ "scripts": {
38
+ "dev": "tsx watch src/index.ts",
39
+ "dev:example": "tsx src/examples/basic.ts",
40
+ "build": "tsup",
41
+ "build:watch": "tsup --watch",
42
+ "test": "vitest",
43
+ "test:ui": "vitest --ui",
44
+ "test:coverage": "vitest run --coverage",
45
+ "test:watch": "vitest watch",
46
+ "lint": "eslint .",
47
+ "lint:fix": "eslint --fix .",
48
+ "lint:config": "eslint --print-config src/index.ts",
49
+ "format": "prettier --write",
50
+ "format:check": "prettier",
51
+ "typecheck": "tsc --noEmit",
52
+ "docs": "typedoc",
53
+ "docs:watch": "typedoc --watch",
54
+ "ci": "npm run lint && npm run typecheck && npm run test:coverage && npm run build",
55
+ "prepublishOnly": "npm run ci",
56
+ "prepare": "husky install",
57
+ "release": "npm run ci:all && changeset publish",
58
+ "_postinstall": "husky",
59
+ "prepack": "pinst --disable",
60
+ "postpack": "pinst --enable"
61
+ },
37
62
  "dependencies": {
38
63
  "@changesets/cli": "^2.29.4",
39
64
  "@types/node": "^22.15.29",
40
65
  "crypto": "^1.0.1",
41
66
  "iron-session": "^8.0.4",
42
- "la": "link:../../../Library/pnpm/global/5/node_modules/la",
43
- "ls": "link:../../../Library/pnpm/global/5/node_modules/ls",
44
- "oauth2-token-manager": "link:../../../Library/pnpm/global/5/node_modules/@dainprotocol/oauth2-token-manager",
45
67
  "pinst": "^3.0.0",
46
68
  "tsup": "^8.5.0",
47
69
  "tsx": "^4.19.4",
@@ -70,26 +92,5 @@
70
92
  },
71
93
  "publishConfig": {
72
94
  "access": "public"
73
- },
74
- "scripts": {
75
- "dev": "tsx watch src/index.ts",
76
- "dev:example": "tsx src/examples/basic.ts",
77
- "build": "tsup",
78
- "build:watch": "tsup --watch",
79
- "test": "vitest",
80
- "test:ui": "vitest --ui",
81
- "test:coverage": "vitest run --coverage",
82
- "test:watch": "vitest watch",
83
- "lint": "eslint .",
84
- "lint:fix": "eslint --fix .",
85
- "lint:config": "eslint --print-config src/index.ts",
86
- "format": "prettier --write",
87
- "format:check": "prettier",
88
- "typecheck": "tsc --noEmit",
89
- "docs": "typedoc",
90
- "docs:watch": "typedoc --watch",
91
- "ci": "npm run lint && npm run typecheck && npm run test:coverage && npm run build",
92
- "release": "npm run ci:all && changeset publish",
93
- "_postinstall": "husky"
94
95
  }
95
- }
96
+ }