@alter-ai/connect 0.10.0 → 0.11.1

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.
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).AlterConnect=t()}(this,function(){"use strict";const e="https://backend.alterauth.com";function t(e,...t){e.debug&&console.log("[Alter Connect]",...t)}class s{constructor(){this.events=new Map}on(e,t){return this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t),()=>this.off(e,t)}off(e,t){const s=this.events.get(e);s&&s.delete(t)}emit(e,...t){const s=this.events.get(e);s&&s.forEach(s=>{try{s(...t)}catch(t){console.error(`[Alter Connect] Error in event handler for '${e}':`,t)}})}removeAllListeners(e){e?this.events.delete(e):this.events.clear()}}class n{constructor(){this.state={isOpen:!1,sessionToken:null,error:null},this.listeners=new Set}getState(){return{...this.state}}get(e){return this.state[e]}setState(e){this.state={...this.state,...e},this.notifyListeners()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}clearListeners(){this.listeners.clear()}notifyListeners(){const e=this.getState();this.listeners.forEach(t=>{try{t(e)}catch(e){console.error("[Alter Connect] Error in state listener:",e)}})}}function i(){const e=navigator.userAgent||navigator.vendor||window.opera||"",t=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e),s="ontouchstart"in window||navigator.maxTouchPoints>0||(navigator.msMaxTouchPoints??0)>0,n=window.innerWidth<=768;return t||s&&n}function r(){return i()&&window.innerWidth<=480?"phone":i()&&window.innerWidth>480&&window.innerWidth<=1024?"tablet":"desktop"}function o(e){return"reauth"===e?"reauth":"creation"}function a(e){return"pending"===e?"pending":"error"===e?"error":"active"}function h(e){sessionStorage.removeItem("alter_oauth_state");try{const t=new URL(e);window.history.replaceState({},document.title,t.pathname+t.search+t.hash)}catch{window.history.replaceState({},document.title,window.location.pathname)}}class c{constructor(t){this.popup=null,this.pollInterval=null,this.messageListener=null,this.settled=!1,this.options={baseURL:t.baseURL,onSuccess:t.onSuccess,onError:t.onError,onCancel:t.onCancel,popupWidth:t.popupWidth||500,popupHeight:t.popupHeight||700,debug:t.debug||!1,expectedOrigin:t.expectedOrigin||""};try{this.expectedOrigin=new URL(t.baseURL).origin}catch{throw new Error(`Invalid baseURL: "${t.baseURL}". Must be a full URL with protocol (e.g., "${e}").`)}}startOAuth(e){if(!this.options.expectedOrigin)try{const t=new URL(e);this.options.expectedOrigin=t.origin,this.log("Derived expected origin:",this.options.expectedOrigin)}catch{return this.log("Failed to parse OAuth URL for origin validation:",e),void this.options.onError({code:"invalid_oauth_url",message:"Failed to determine origin from OAuth URL. Cannot proceed securely."})}!function(){const e=r();return"phone"===e||"tablet"===e&&window.innerHeight>window.innerWidth}()?(this.log("Using popup flow for desktop"),this.openPopup(e)):(this.log("Using redirect flow for mobile device"),this.startRedirectFlow(e))}startRedirectFlow(e){this.log("Starting redirect flow:",e);const t={timestamp:Date.now(),returnUrl:window.location.href};try{sessionStorage.setItem("alter_oauth_state",JSON.stringify(t))}catch(e){return this.log("Failed to save state:",e),void this.options.onError({code:"redirect_error",message:"Failed to start OAuth flow: could not save session state",details:{error:e}})}window.location.href=e}static checkOAuthReturn(e,t){const s=sessionStorage.getItem("alter_oauth_state");if(!s)return!1;try{const n=JSON.parse(s);if(Date.now()-n.timestamp>3e5)return sessionStorage.removeItem("alter_oauth_state"),!1;const i=new URLSearchParams(window.location.search),r=i.get("alter_connect_success"),c=i.get("alter_connect_error");if("true"===r){const s=i.get("grant_id"),r=i.get("provider"),c=i.get("account_identifier");if(!s||!r||!c)return h(n.returnUrl),t({code:"invalid_response",message:"OAuth redirect returned incomplete grant data"}),!0;const l={grant_id:s,provider:r,provider_name:i.get("provider_name")||r,account_identifier:c,timestamp:i.get("timestamp")||(new Date).toISOString(),operation:o(i.get("operation")),scopes:i.get("scopes")?.split(",")||[],status:a(i.get("status"))};return h(n.returnUrl),e([l]),!0}if(c){const e={code:i.get("error_code")||"oauth_error",message:i.get("error_description")||"OAuth authorization failed"};return h(n.returnUrl),t(e),!0}return!1}catch(e){return console.error("[OAuth Handler] Failed to check OAuth return:",e),sessionStorage.removeItem("alter_oauth_state"),!1}}openPopup(e){const t=window.screenX+(window.outerWidth-this.options.popupWidth)/2,s=window.screenY+(window.outerHeight-this.options.popupHeight)/2,n=[`width=${this.options.popupWidth}`,`height=${this.options.popupHeight}`,`left=${t}`,`top=${s}`,"resizable=yes","scrollbars=yes","status=yes"].join(",");this.log("Opening OAuth popup:",e),this.popup=window.open(e,"alter_oauth_popup",n),this.popup?(this.startPolling(),this.setupMessageListener()):this.options.onError({code:"popup_blocked",message:"Popup was blocked by browser. Please allow popups for this site."})}close(){this.log("Closing OAuth handler"),this.popup&&!this.popup.closed&&this.popup.close(),this.popup=null,null!==this.pollInterval&&(clearInterval(this.pollInterval),this.pollInterval=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null)}startPolling(){this.pollInterval=window.setInterval(()=>{this.settled||this.popup&&!this.popup.closed||(this.log("Popup closed by user"),this.settled=!0,this.close(),this.options.onCancel())},500)}setupMessageListener(){this.messageListener=e=>{if(this.settled)return;if(e.origin!==this.expectedOrigin)return void this.log("Rejected message from unexpected origin:",e.origin,"(expected:",this.expectedOrigin+")");this.log("Received message from",e.origin);const t=e.data;if(t&&"object"==typeof t)if("alter_connect_success"===t.type){this.log("OAuth success");const e=Array.isArray(t.grants)?t.grants:null;if(e){this.log("Multi-provider success:",e.length,"grants");const t=[];for(const s of e){const e=s.grant_id;e&&s.provider?t.push({grant_id:e,provider:s.provider,provider_name:s.provider_name||s.provider,account_identifier:s.account_identifier||"",timestamp:s.timestamp||(new Date).toISOString(),operation:o(s.operation),scopes:Array.isArray(s.scopes)?s.scopes:[],status:a(s.status),metadata:s.metadata}):this.log("Skipping invalid grant item:",s)}return 0===t.length?(this.settled=!0,this.close(),void this.options.onError({code:"invalid_response",message:"Server returned empty grants array"})):(this.settled=!0,this.close(),void this.options.onSuccess(t))}this.settled=!0,this.close(),this.options.onError({code:"invalid_response",message:"Server returned success without grants array"})}else if("alter_connect_error"===t.type){this.log("OAuth error");const e={code:t.error||"oauth_error",message:t.error_description||"OAuth authorization failed",details:t};this.settled=!0,this.close(),this.options.onError(e)}},window.addEventListener("message",this.messageListener)}log(...e){this.options.debug&&console.log("[OAuth Handler]",...e)}}const l="0.2.0";let d=!1;class u{constructor(i={}){if(this._oauthHandler=null,this._perOpenCleanups=[],function(e){if(void 0!==e.baseURL)throw e.baseURL,new Error("AlterConnectConfig.baseURL is reserved and not yet supported. Omit the field to use the production Alter host.")}(i),this.config=function(e){return{debug:e.debug??!1}}(i),this._baseURL=(i.baseURL??e).replace(/\/+$/,""),this._baseURL!==e&&!d){d=!0;const e=new URL(this._baseURL).origin;console.warn(`[alter-connect] Using non-default Alter host: ${e}. Unset baseURL in AlterConnect.create() for production.`)}this.eventEmitter=new s,this.stateManager=new n,this._isInitialized=!0,t(this.config,"Alter Connect SDK initialized",{version:l,baseURL:this._baseURL}),this.checkRedirectReturn()}checkRedirectReturn(){c.checkOAuthReturn(e=>{t(this.config,"OAuth redirect return - success:",e),this.eventEmitter.emit("success",e)},e=>{t(this.config,"OAuth redirect return - error:",e),this.eventEmitter.emit("error",e)})&&t(this.config,"OAuth redirect return detected and handled")}static create(e){return new u(e)}async open(e){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call open() - SDK instance has been destroyed");if(t(this.config,"Opening Connect UI"),!e.token||"string"!=typeof e.token)throw this.createError("invalid_options","Session token is required. Create one from your backend using POST /sdk/oauth/connect/session");if(!e.onSuccess||"function"!=typeof e.onSuccess)throw this.createError("invalid_options","onSuccess callback is required");if(this.isOpen())return void t(this.config,"Connect UI is already open");this._oauthHandler=new c({baseURL:this._baseURL,onSuccess:e=>{t(this.config,"OAuth success:",e),this.handleOAuthSuccess(e)},onError:e=>{t(this.config,"OAuth error:",e),this.handleOAuthError(e)},onCancel:()=>{t(this.config,"OAuth cancelled (popup closed)"),this.handleOAuthCancel()},popupWidth:500,popupHeight:700,debug:this.config.debug}),this.stateManager.setState({isOpen:!0,error:null,sessionToken:e.token}),this.registerEventHandlers(e);const s=`${this._baseURL}/sdk/oauth/connect#session=${encodeURIComponent(e.token)}`;t(this.config,"Connect URL:",s),this._oauthHandler.startOAuth(s),e.onEvent&&e.onEvent("connect_opened",{timestamp:(new Date).toISOString()}),t(this.config,"Connect UI opened successfully")}close(){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call close() - SDK instance has been destroyed");t(this.config,"Closing Connect UI"),this._oauthHandler&&(this._oauthHandler.close(),this._oauthHandler=null),this._perOpenCleanups.forEach(e=>e()),this._perOpenCleanups=[],this.stateManager.setState({isOpen:!1}),this.eventEmitter.emit("close")}destroy(){this._isInitialized&&(t(this.config,"Destroying SDK instance"),this._oauthHandler&&(this._oauthHandler.close(),this._oauthHandler=null),this.stateManager.get("isOpen")&&this.stateManager.setState({isOpen:!1}),this.eventEmitter.removeAllListeners(),this.stateManager.clearListeners(),this._isInitialized=!1)}on(e,t){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call on() - SDK instance has been destroyed");return this.eventEmitter.on(e,t)}off(e,t){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call off() - SDK instance has been destroyed");this.eventEmitter.off(e,t)}isOpen(){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call isOpen() - SDK instance has been destroyed");return this.stateManager.get("isOpen")}getVersion(){return l}cleanupHandler(){this._oauthHandler=null}handleOAuthSuccess(e){this.cleanupHandler(),this.eventEmitter.emit("success",e)}handleOAuthError(e){this.cleanupHandler(),this.stateManager.setState({error:e}),this.eventEmitter.emit("error",e)}handleOAuthCancel(){this.cleanupHandler(),this.eventEmitter.emit("exit")}registerEventHandlers(e){e.onSuccess&&this._perOpenCleanups.push(this.eventEmitter.on("success",t=>{e.onSuccess(t),this.close()})),e.onExit&&this._perOpenCleanups.push(this.eventEmitter.on("exit",()=>{e.onExit(),this.close()})),this._perOpenCleanups.push(this.eventEmitter.on("error",t=>{e.onError&&e.onError(t),this.close()})),e.onEvent&&this._perOpenCleanups.push(this.eventEmitter.on("event",(t,s)=>{e.onEvent(t,s)}))}createError(e,t,s){const n=new Error(t);return n.code=e,n.details=s,n}}return u});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).AlterConnect=t()}(this,function(){"use strict";const e="https://backend.alterauth.com";function t(e,...t){e.debug&&console.log("[Alter Connect]",...t)}class n{constructor(){this.events=new Map}on(e,t){return this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t),()=>this.off(e,t)}off(e,t){const n=this.events.get(e);n&&n.delete(t)}emit(e,...t){const n=this.events.get(e);n&&n.forEach(n=>{try{n(...t)}catch(t){console.error(`[Alter Connect] Error in event handler for '${e}':`,t)}})}removeAllListeners(e){e?this.events.delete(e):this.events.clear()}}class s{constructor(){this.state={isOpen:!1,sessionToken:null,error:null},this.listeners=new Set}getState(){return{...this.state}}get(e){return this.state[e]}setState(e){this.state={...this.state,...e},this.notifyListeners()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}clearListeners(){this.listeners.clear()}notifyListeners(){const e=this.getState();this.listeners.forEach(t=>{try{t(e)}catch(e){console.error("[Alter Connect] Error in state listener:",e)}})}}var r;function o(e,t,n){function s(n,s){if(n._zod||Object.defineProperty(n,"_zod",{value:{def:s,constr:i,traits:new Set},enumerable:!1}),n._zod.traits.has(e))return;n._zod.traits.add(e),t(n,s);const r=i.prototype,o=Object.keys(r);for(let e=0;e<o.length;e++){const t=o[e];t in n||(n[t]=r[t].bind(n))}}const r=n?.Parent??Object;class o extends r{}function i(e){var t;const r=n?.Parent?new o:this;s(r,e),(t=r._zod).deferred??(t.deferred=[]);for(const e of r._zod.deferred)e();return r}return Object.defineProperty(o,"name",{value:e}),Object.defineProperty(i,"init",{value:s}),Object.defineProperty(i,Symbol.hasInstance,{value:t=>!!(n?.Parent&&t instanceof n.Parent)||t?._zod?.traits?.has(e)}),Object.defineProperty(i,"name",{value:e}),i}class i extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class a extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`),this.name="ZodEncodeError"}}(r=globalThis).__zod_globalConfig??(r.__zod_globalConfig={});const c=globalThis.__zod_globalConfig;function u(e){return c}function l(e,t){return"bigint"==typeof t?t.toString():t}const d=Symbol("evaluating");function p(e,t,n){let s;Object.defineProperty(e,t,{get(){if(s!==d)return void 0===s&&(s=d,s=n()),s},set(n){Object.defineProperty(e,t,{value:n})},configurable:!0})}const h="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function f(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function g(e){return function(e){if(!1===f(e))return!1;const t=e.constructor;if(void 0===t)return!0;if("function"!=typeof t)return!0;const n=t.prototype;return!1!==f(n)&&!1!==Object.prototype.hasOwnProperty.call(n,"isPrototypeOf")}(e)?{...e}:Array.isArray(e)?[...e]:e instanceof Map?new Map(e):e instanceof Set?new Set(e):e}const _=new Set(["string","number","symbol"]);function v(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function m(e,t=0){if(!0===e.aborted)return!0;for(let n=t;n<e.issues.length;n++)if(!0!==e.issues[n]?.continue)return!0;return!1}function y(e,t=0){if(!0===e.aborted)return!0;for(let n=t;n<e.issues.length;n++)if(!1===e.issues[n]?.continue)return!0;return!1}function w(e,t){return t.map(t=>{var n;return(n=t).path??(n.path=[]),t.path.unshift(e),t})}function z(e){return"string"==typeof e?e:e?.message}function b(e,t,n){const s=e.message?e.message:z(e.inst?._zod.def?.error?.(e))??z(t?.error?.(e))??z(n.customError?.(e))??z(n.localeError?.(e))??"Invalid input",{inst:r,continue:o,input:i,...a}=e;return a.path??(a.path=[]),a.message=s,t?.reportInput&&(a.input=i),a}const O=(e,t)=>{e.name="$ZodError",Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:t,enumerable:!1}),e.message=JSON.stringify(t,l,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},E=o("$ZodError",O),S=o("$ZodError",O,{Parent:Error}),k=(e=>(t,n,s,r)=>{const o=s?{...s,async:!1}:{async:!1},a=t._zod.run({value:n,issues:[]},o);if(a instanceof Promise)throw new i;if(a.issues.length){const t=new(r?.Err??e)(a.issues.map(e=>b(e,o,u())));throw h(t,r?.callee),t}return a.value})(S),P=(e=>async(t,n,s,r)=>{const o=s?{...s,async:!0}:{async:!0};let i=t._zod.run({value:n,issues:[]},o);if(i instanceof Promise&&(i=await i),i.issues.length){const t=new(r?.Err??e)(i.issues.map(e=>b(e,o,u())));throw h(t,r?.callee),t}return i.value})(S),A=(e=>(t,n,s)=>{const r=s?{...s,async:!1}:{async:!1},o=t._zod.run({value:n,issues:[]},r);if(o instanceof Promise)throw new i;return o.issues.length?{success:!1,error:new(e??E)(o.issues.map(e=>b(e,r,u())))}:{success:!0,data:o.value}})(S),C=(e=>async(t,n,s)=>{const r=s?{...s,async:!0}:{async:!0};let o=t._zod.run({value:n,issues:[]},r);return o instanceof Promise&&(o=await o),o.issues.length?{success:!1,error:new e(o.issues.map(e=>b(e,r,u())))}:{success:!0,data:o.value}})(S),L=o("$ZodCheck",(e,t)=>{var n;e._zod??(e._zod={}),e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),$=o("$ZodCheckMinLength",(e,t)=>{var n;L.init(e,t),(n=e._zod.def).when??(n.when=e=>{const t=e.value;return!(n=t,null==n||void 0===t.length);var n}),e._zod.onattach.push(e=>{const n=e._zod.bag.minimum??Number.NEGATIVE_INFINITY;t.minimum>n&&(e._zod.bag.minimum=t.minimum)}),e._zod.check=n=>{const s=n.value;if(s.length>=t.minimum)return;const r=function(e){return Array.isArray(e)?"array":"string"==typeof e?"string":"unknown"}(s);n.issues.push({origin:r,code:"too_small",minimum:t.minimum,inclusive:!0,input:s,inst:e,continue:!t.abort})}}),R={major:4,minor:4,patch:3},U=o("$ZodType",(e,t)=>{var n;e??(e={}),e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=R;const s=[...e._zod.def.checks??[]];e._zod.traits.has("$ZodCheck")&&s.unshift(e);for(const t of s)for(const n of t._zod.onattach)n(e);if(0===s.length)(n=e._zod).deferred??(n.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{const t=(e,t,n)=>{let s,r=m(e);for(const o of t){if(o._zod.def.when){if(y(e))continue;if(!o._zod.def.when(e))continue}else if(r)continue;const t=e.issues.length,a=o._zod.check(e);if(a instanceof Promise&&!1===n?.async)throw new i;if(s||a instanceof Promise)s=(s??Promise.resolve()).then(async()=>{await a;e.issues.length!==t&&(r||(r=m(e,t)))});else{if(e.issues.length===t)continue;r||(r=m(e,t))}}return s?s.then(()=>e):e},n=(n,r,o)=>{if(m(n))return n.aborted=!0,n;const a=t(r,s,o);if(a instanceof Promise){if(!1===o.async)throw new i;return a.then(t=>e._zod.parse(t,o))}return e._zod.parse(a,o)};e._zod.run=(r,o)=>{if(o.skipChecks)return e._zod.parse(r,o);if("backward"===o.direction){const t=e._zod.parse({value:r.value,issues:[]},{...o,skipChecks:!0});return t instanceof Promise?t.then(e=>n(e,r,o)):n(t,r,o)}const a=e._zod.parse(r,o);if(a instanceof Promise){if(!1===o.async)throw new i;return a.then(e=>t(e,s,o))}return t(a,s,o)}}p(e,"~standard",()=>({validate:t=>{try{const n=A(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch(n){return C(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:"zod",version:1}))}),I=o("$ZodString",(e,t)=>{var n;U.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??(n=e._zod.bag,new RegExp(`^${n?`[\\s\\S]{${n?.minimum??0},${n?.maximum??""}}`:"[\\s\\S]*"}$`)),e._zod.parse=(n,s)=>{if(t.coerce)try{n.value=String(n.value)}catch(s){}return"string"==typeof n.value||n.issues.push({expected:"string",code:"invalid_type",input:n.value,inst:e}),n}}),j=o("$ZodUnknown",(e,t)=>{U.init(e,t),e._zod.parse=e=>e});function T(e,t,n){e.issues.length&&t.issues.push(...w(n,e.issues)),t.value[n]=e.value}const M=o("$ZodArray",(e,t)=>{U.init(e,t),e._zod.parse=(n,s)=>{const r=n.value;if(!Array.isArray(r))return n.issues.push({expected:"array",code:"invalid_type",input:r,inst:e}),n;n.value=Array(r.length);const o=[];for(let e=0;e<r.length;e++){const i=r[e],a=t.element._zod.run({value:i,issues:[]},s);a instanceof Promise?o.push(a.then(t=>T(t,n,e))):T(a,n,e)}return o.length?Promise.all(o).then(()=>n):n}});function Z(e,t,n,s,r,o){const i=n in s;if(e.issues.length){if(r&&o&&!i)return;t.issues.push(...w(n,e.issues))}i||r?void 0===e.value?i&&(t.value[n]=void 0):t.value[n]=e.value:e.issues.length||t.issues.push({code:"invalid_type",expected:"nonoptional",input:void 0,path:[n]})}function x(e){const t=Object.keys(e.shape);for(const n of t)if(!e.shape?.[n]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${n}": expected a Zod schema`);const n=(s=e.shape,Object.keys(s).filter(e=>"optional"===s[e]._zod.optin&&"optional"===s[e]._zod.optout));var s;return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(n)}}const H=o("$ZodObject",(e,t)=>{U.init(e,t);const n=Object.getOwnPropertyDescriptor(t,"shape");if(!n?.get){const e=t.shape;Object.defineProperty(t,"shape",{get:()=>{const n={...e};return Object.defineProperty(t,"shape",{value:n}),n}})}const s=(r=()=>x(t),{get value(){{const e=r();return Object.defineProperty(this,"value",{value:e}),e}}});var r;p(e._zod,"propValues",()=>{const e=t.shape,n={};for(const t in e){const s=e[t]._zod;if(s.values){n[t]??(n[t]=new Set);for(const e of s.values)n[t].add(e)}}return n});const o=f,i=t.catchall;let a;e._zod.parse=(t,n)=>{a??(a=s.value);const r=t.value;if(!o(r))return t.issues.push({expected:"object",code:"invalid_type",input:r,inst:e}),t;t.value={};const c=[],u=a.shape;for(const e of a.keys){const s=u[e],o="optional"===s._zod.optin,i="optional"===s._zod.optout,a=s._zod.run({value:r[e],issues:[]},n);a instanceof Promise?c.push(a.then(n=>Z(n,t,e,r,o,i))):Z(a,t,e,r,o,i)}return i?function(e,t,n,s,r,o){const i=[],a=r.keySet,c=r.catchall._zod,u=c.def.type,l="optional"===c.optin,d="optional"===c.optout;for(const r in t){if("__proto__"===r)continue;if(a.has(r))continue;if("never"===u){i.push(r);continue}const o=c.run({value:t[r],issues:[]},s);o instanceof Promise?e.push(o.then(e=>Z(e,n,r,t,l,d))):Z(o,n,r,t,l,d)}return i.length&&n.issues.push({code:"unrecognized_keys",keys:i,input:t,inst:o}),e.length?Promise.all(e).then(()=>n):n}(c,r,t,n,s.value,e):c.length?Promise.all(c).then(()=>t):t}}),D=o("$ZodEnum",(e,t)=>{U.init(e,t);const n=function(e){const t=Object.values(e).filter(e=>"number"==typeof e);return Object.entries(e).filter(([e,n])=>-1===t.indexOf(+e)).map(([e,t])=>t)}(t.entries),s=new Set(n);e._zod.values=s,e._zod.pattern=new RegExp(`^(${n.filter(e=>_.has(typeof e)).map(e=>"string"==typeof e?v(e):e.toString()).join("|")})$`),e._zod.parse=(t,r)=>{const o=t.value;return s.has(o)||t.issues.push({code:"invalid_value",values:n,input:o,inst:e}),t}}),W=o("$ZodLiteral",(e,t)=>{if(U.init(e,t),0===t.values.length)throw new Error("Cannot create literal schema with no valid values");const n=new Set(t.values);e._zod.values=n,e._zod.pattern=new RegExp(`^(${t.values.map(e=>"string"==typeof e?v(e):e?v(e.toString()):String(e)).join("|")})$`),e._zod.parse=(s,r)=>{const o=s.value;return n.has(o)||s.issues.push({code:"invalid_value",values:t.values,input:o,inst:e}),s}}),V=o("$ZodTransform",(e,t)=>{U.init(e,t),e._zod.optin="optional",e._zod.parse=(n,s)=>{if("backward"===s.direction)throw new a(e.constructor.name);const r=t.transform(n.value,n);if(s.async){return(r instanceof Promise?r:Promise.resolve(r)).then(e=>(n.value=e,n.fallback=!0,n))}if(r instanceof Promise)throw new i;return n.value=r,n.fallback=!0,n}});function K(e,t){return void 0===t&&(e.issues.length||e.fallback)?{issues:[],value:void 0}:e}const F=o("$ZodOptional",(e,t)=>{U.init(e,t),e._zod.optin="optional",e._zod.optout="optional",p(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),p(e._zod,"pattern",()=>{const e=t.innerType._zod.pattern;return e?new RegExp(`^(${function(e){const t=e.startsWith("^")?1:0,n=e.endsWith("$")?e.length-1:e.length;return e.slice(t,n)}(e.source)})?$`):void 0}),e._zod.parse=(e,n)=>{if("optional"===t.innerType._zod.optin){const s=e.value,r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(e=>K(e,s)):K(r,s)}return void 0===e.value?e:t.innerType._zod.run(e,n)}}),N=o("$ZodDefault",(e,t)=>{U.init(e,t),e._zod.optin="optional",p(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(e,n)=>{if("backward"===n.direction)return t.innerType._zod.run(e,n);if(void 0===e.value)return e.value=t.defaultValue,e;const s=t.innerType._zod.run(e,n);return s instanceof Promise?s.then(e=>G(e,t)):G(s,t)}});function G(e,t){return void 0===e.value&&(e.value=t.defaultValue),e}const J=o("$ZodCatch",(e,t)=>{U.init(e,t),e._zod.optin="optional",p(e._zod,"optout",()=>t.innerType._zod.optout),p(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(e,n)=>{if("backward"===n.direction)return t.innerType._zod.run(e,n);const s=t.innerType._zod.run(e,n);return s instanceof Promise?s.then(s=>(e.value=s.value,s.issues.length&&(e.value=t.catchValue({...e,error:{issues:s.issues.map(e=>b(e,n,u()))},input:e.value}),e.issues=[],e.fallback=!0),e)):(e.value=s.value,s.issues.length&&(e.value=t.catchValue({...e,error:{issues:s.issues.map(e=>b(e,n,u()))},input:e.value}),e.issues=[],e.fallback=!0),e)}}),q=o("$ZodPipe",(e,t)=>{U.init(e,t),p(e._zod,"values",()=>t.in._zod.values),p(e._zod,"optin",()=>t.in._zod.optin),p(e._zod,"optout",()=>t.out._zod.optout),p(e._zod,"propValues",()=>t.in._zod.propValues),e._zod.parse=(e,n)=>{if("backward"===n.direction){const s=t.out._zod.run(e,n);return s instanceof Promise?s.then(e=>B(e,t.in,n)):B(s,t.in,n)}const s=t.in._zod.run(e,n);return s instanceof Promise?s.then(e=>B(e,t.out,n)):B(s,t.out,n)}});function B(e,t,n){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues,fallback:e.fallback},n)}var Y;class X{constructor(){this._map=new WeakMap,this._idmap=new Map}add(e,...t){const n=t[0];return this._map.set(e,n),n&&"object"==typeof n&&"id"in n&&this._idmap.set(n.id,e),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(e){const t=this._map.get(e);return t&&"object"==typeof t&&"id"in t&&this._idmap.delete(t.id),this._map.delete(e),this}get(e){const t=e._zod.parent;if(t){const n={...this.get(t)??{}};delete n.id;const s={...n,...this._map.get(e)};return Object.keys(s).length?s:void 0}return this._map.get(e)}has(e){return this._map.has(e)}}(Y=globalThis).__zod_globalRegistry??(Y.__zod_globalRegistry=new X);const Q=o("ZodMiniType",(e,t)=>{if(!e._zod)throw new Error("Uninitialized schema in ZodMiniType.");U.init(e,t),e.def=t,e.type=t.type,e.parse=(t,n)=>k(e,t,n,{callee:e.parse}),e.safeParse=(t,n)=>A(e,t,n),e.parseAsync=async(t,n)=>P(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>C(e,t,n),e.check=(...n)=>e.clone({...t,checks:[...t.checks??[],...n.map(e=>"function"==typeof e?{_zod:{check:e,def:{check:"custom"},onattach:[]}}:e)]},{parent:!0}),e.with=e.check,e.clone=(t,n)=>function(e,t,n){const s=new e._zod.constr(t??e._zod.def);return t&&!n?.parent||(s._zod.parent=e),s}(e,t,n),e.brand=()=>e,e.register=(t,n)=>(t.add(e,n),e),e.apply=t=>t(e)}),ee=o("ZodMiniString",(e,t)=>{I.init(e,t),Q.init(e,t)});function te(e){return new ee({type:"string"})}const ne=o("ZodMiniUnknown",(e,t)=>{j.init(e,t),Q.init(e,t)});function se(){return new ne({type:"unknown"})}const re=o("ZodMiniArray",(e,t)=>{M.init(e,t),Q.init(e,t)});function oe(e,t){return new re({type:"array",element:e})}const ie=o("ZodMiniObject",(e,t)=>{H.init(e,t),Q.init(e,t),p(e,"shape",()=>t.shape)});function ae(e,t){return new ie({type:"object",shape:e??{}})}const ce=o("ZodMiniEnum",(e,t)=>{D.init(e,t),Q.init(e,t),e.options=Object.values(t.entries)});function ue(e,t){const n=Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e;return new ce({type:"enum",entries:n})}const le=o("ZodMiniLiteral",(e,t)=>{W.init(e,t),Q.init(e,t)});function de(e,t){return new le({type:"literal",values:Array.isArray(e)?e:[e]})}const pe=o("ZodMiniTransform",(e,t)=>{V.init(e,t),Q.init(e,t)});function he(e){return new pe({type:"transform",transform:e})}const fe=o("ZodMiniOptional",(e,t)=>{F.init(e,t),Q.init(e,t)});function ge(e){return new fe({type:"optional",innerType:e})}const _e=o("ZodMiniDefault",(e,t)=>{N.init(e,t),Q.init(e,t)});function ve(e,t){return new _e({type:"default",innerType:e,get defaultValue(){return"function"==typeof t?t():g(t)}})}const me=o("ZodMiniCatch",(e,t)=>{J.init(e,t),Q.init(e,t)});function ye(e,t){return new me({type:"catch",innerType:e,catchValue:"function"==typeof t?t:()=>t})}const we=o("ZodMiniPipe",(e,t)=>{q.init(e,t),Q.init(e,t)});function ze(e,t){return new we({type:"pipe",in:e,out:t})}function be(){const e=navigator.userAgent||navigator.vendor||window.opera||"",t=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e),n="ontouchstart"in window||navigator.maxTouchPoints>0||(navigator.msMaxTouchPoints??0)>0,s=window.innerWidth<=768;return t||n&&s}function Oe(){return be()&&window.innerWidth<=480?"phone":be()&&window.innerWidth>480&&window.innerWidth<=1024?"tablet":"desktop"}function Ee(e){return"pending"===e?"pending":"error"===e?"error":"active"}const Se=te().check(new $({check:"min_length",minimum:1}));const ke=function(e,t){return e.clone({...e._zod.def,catchall:t})}(ae({account_display_name:ge(te()),account_email:ge(te())}),se()),Pe=ze(ae({grant_id:Se,provider:Se,provider_name:ge(te()),account_identifier:ge(te()),timestamp:ge(te()),operation:ve(ge(ue(["creation","reauth"])),"creation"),scopes:ve(ge(oe(te())),[]),status:ve(ge(ue(["active","pending","error"])),"active"),metadata:ge(ke)}),he(e=>{const t={grant_id:e.grant_id,provider:e.provider,provider_name:e.provider_name??e.provider,account_identifier:e.account_identifier??"",timestamp:e.timestamp??(new Date).toISOString(),operation:e.operation,scopes:e.scopes,status:e.status};return void 0!==e.metadata&&(t.metadata=e.metadata),t})),Ae=ze(ae({provider_id:Se,reason:Se,message:Se}),he(e=>({providerId:e.provider_id,reason:e.reason,message:e.message}))),Ce=ae({type:ue(["alter_connect_success","alter_connect_error"])}),Le=ae({type:de("alter_connect_success"),grants:oe(Pe),failed_grants:ve(ge(oe(Ae)),[])}),$e=(Re={type:de("alter_connect_error"),error:ye(te(),"oauth_error"),error_description:ye(te(),"OAuth authorization failed")},new ie({type:"object",shape:Re,catchall:se()}));var Re;function Ue(e){const t=e.issues[0]?.path[0];return"failed_grants"===t?"Server returned malformed failed_grants data":"grants"===t&&1===e.issues[0]?.path.length?"Server returned success without grants array":"Server returned malformed grant data"}function Ie(e){sessionStorage.removeItem("alter_oauth_state");try{const t=new URL(e);window.history.replaceState({},document.title,t.pathname+t.search+t.hash)}catch{window.history.replaceState({},document.title,window.location.pathname)}}class je{constructor(t){this.popup=null,this.pollInterval=null,this.messageListener=null,this.settled=!1,this.options={baseURL:t.baseURL,onSuccess:t.onSuccess,onError:t.onError,onCancel:t.onCancel,popupWidth:t.popupWidth||500,popupHeight:t.popupHeight||700,debug:t.debug||!1,expectedOrigin:t.expectedOrigin||""};try{this.expectedOrigin=new URL(t.baseURL).origin}catch{throw new Error(`Invalid baseURL: "${t.baseURL}". Must be a full URL with protocol (e.g., "${e}").`)}}startOAuth(e){if(!this.options.expectedOrigin)try{const t=new URL(e);this.options.expectedOrigin=t.origin,this.log("Derived expected origin:",this.options.expectedOrigin)}catch{return this.log("Failed to parse OAuth URL for origin validation:",e),void this.options.onError({code:"invalid_oauth_url",message:"Failed to determine origin from OAuth URL. Cannot proceed securely."})}!function(){const e=Oe();return"phone"===e||"tablet"===e&&window.innerHeight>window.innerWidth}()?(this.log("Using popup flow for desktop"),this.openPopup(e)):(this.log("Using redirect flow for mobile device"),this.startRedirectFlow(e))}startRedirectFlow(e){this.log("Starting redirect flow:",e);const t={timestamp:Date.now(),returnUrl:window.location.href};try{sessionStorage.setItem("alter_oauth_state",JSON.stringify(t))}catch(e){return this.log("Failed to save state:",e),void this.options.onError({code:"redirect_error",message:"Failed to start OAuth flow: could not save session state",details:{error:e}})}window.location.href=e}static checkOAuthReturn(e,t){const n=sessionStorage.getItem("alter_oauth_state");if(!n)return!1;try{const r=JSON.parse(n);if(Date.now()-r.timestamp>3e5)return sessionStorage.removeItem("alter_oauth_state"),!1;const o=new URLSearchParams(window.location.search),i=o.get("alter_connect_success"),a=o.get("alter_connect_error");if("true"===i){const n=o.get("grant_id"),i=o.get("provider"),a=o.get("account_identifier");if(!n||!i||!a)return Ie(r.returnUrl),t({code:"invalid_response",message:"OAuth redirect returned incomplete grant data"}),!0;const c={grant_id:n,provider:i,provider_name:o.get("provider_name")||i,account_identifier:a,timestamp:o.get("timestamp")||(new Date).toISOString(),operation:(s=o.get("operation"),"reauth"===s?"reauth":"creation"),scopes:o.get("scopes")?.split(",")||[],status:Ee(o.get("status"))};Ie(r.returnUrl);const u=[c];return e(u,{grants:u,failedGrants:[]}),!0}if(a){const e={code:o.get("error_code")||"oauth_error",message:o.get("error_description")||"OAuth authorization failed"};return Ie(r.returnUrl),t(e),!0}return!1}catch(e){return console.error("[OAuth Handler] Failed to check OAuth return:",e),sessionStorage.removeItem("alter_oauth_state"),!1}var s}openPopup(e){const t=window.screenX+(window.outerWidth-this.options.popupWidth)/2,n=window.screenY+(window.outerHeight-this.options.popupHeight)/2,s=[`width=${this.options.popupWidth}`,`height=${this.options.popupHeight}`,`left=${t}`,`top=${n}`,"resizable=yes","scrollbars=yes","status=yes"].join(",");this.log("Opening OAuth popup:",e),this.popup=window.open(e,"alter_oauth_popup",s),this.popup?(this.startPolling(),this.setupMessageListener()):this.options.onError({code:"popup_blocked",message:"Popup was blocked by browser. Please allow popups for this site."})}close(){this.log("Closing OAuth handler"),this.popup&&!this.popup.closed&&this.popup.close(),this.popup=null,null!==this.pollInterval&&(clearInterval(this.pollInterval),this.pollInterval=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null)}startPolling(){this.pollInterval=window.setInterval(()=>{this.settled||this.popup&&!this.popup.closed||(this.log("Popup closed by user"),this.settled=!0,this.close(),this.options.onCancel())},500)}setupMessageListener(){this.messageListener=e=>{if(this.settled)return;if(e.origin!==this.expectedOrigin)return void this.log("Rejected message from unexpected origin:",e.origin,"(expected:",this.expectedOrigin+")");this.log("Received message from",e.origin);const t=Ce.safeParse(e.data);if(!t.success)return;if("alter_connect_success"===t.data.type){this.log("OAuth success");const t=Le.safeParse(e.data);if(!t.success)return this.settled=!0,this.close(),void this.options.onError({code:"invalid_response",message:Ue(t.error)});const{grants:n,failed_grants:s}=t.data;if(this.log("Connect completion:",n.length,"grants"),0===n.length)return this.settled=!0,this.close(),void(s.length>0?this.options.onError({code:"grant_policy_application_failed",message:"The connection was not completed because the selected usage limits could not be applied.",failedGrants:s}):this.options.onError({code:"invalid_response",message:"Server returned empty grants array"}));const r={grants:n,failedGrants:s};return this.settled=!0,this.close(),void this.options.onSuccess(n,r)}const n=$e.safeParse(e.data);if(n.success){this.log("OAuth error");const e={code:n.data.error,message:n.data.error_description,details:n.data};this.settled=!0,this.close(),this.options.onError(e)}},window.addEventListener("message",this.messageListener)}log(...e){this.options.debug&&console.log("[OAuth Handler]",...e)}}const Te="0.2.0";let Me=!1;class Ze{constructor(r={}){if(this._oauthHandler=null,this._perOpenCleanups=[],function(e){if(void 0!==e.baseURL)throw e.baseURL,new Error("AlterConnectConfig.baseURL is reserved and not yet supported. Omit the field to use the production Alter host.")}(r),this.config=function(e){return{debug:e.debug??!1}}(r),this._baseURL=(r.baseURL??e).replace(/\/+$/,""),this._baseURL!==e&&!Me){Me=!0;const e=new URL(this._baseURL).origin;console.warn(`[alter-connect] Using non-default Alter host: ${e}. Unset baseURL in AlterConnect.create() for production.`)}this.eventEmitter=new n,this.stateManager=new s,this._isInitialized=!0,t(this.config,"Alter Connect SDK initialized",{version:Te,baseURL:this._baseURL}),this.checkRedirectReturn()}checkRedirectReturn(){je.checkOAuthReturn((e,n)=>{t(this.config,"OAuth redirect return - success:",e),this.eventEmitter.emit("success",e,n)},e=>{t(this.config,"OAuth redirect return - error:",e),this.eventEmitter.emit("error",e)})&&t(this.config,"OAuth redirect return detected and handled")}static create(e){return new Ze(e)}async open(e){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call open() - SDK instance has been destroyed");if(t(this.config,"Opening Connect UI"),!e.token||"string"!=typeof e.token)throw this.createError("invalid_options","Session token is required. Create one from the application backend with an Alter SDK.");if(!e.onSuccess||"function"!=typeof e.onSuccess)throw this.createError("invalid_options","onSuccess callback is required");if(this.isOpen())return void t(this.config,"Connect UI is already open");this._oauthHandler=new je({baseURL:this._baseURL,onSuccess:(e,n)=>{t(this.config,"OAuth success:",e),this.handleOAuthSuccess(e,n)},onError:e=>{t(this.config,"OAuth error:",e),this.handleOAuthError(e)},onCancel:()=>{t(this.config,"OAuth cancelled (popup closed)"),this.handleOAuthCancel()},popupWidth:500,popupHeight:700,debug:this.config.debug}),this.stateManager.setState({isOpen:!0,error:null,sessionToken:e.token}),this.registerEventHandlers(e);const n=`${this._baseURL}/sdk/oauth/connect#session=${encodeURIComponent(e.token)}`;t(this.config,"Connect URL:",n),this._oauthHandler.startOAuth(n),e.onEvent&&e.onEvent("connect_opened",{timestamp:(new Date).toISOString()}),t(this.config,"Connect UI opened successfully")}close(){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call close() - SDK instance has been destroyed");t(this.config,"Closing Connect UI"),this._oauthHandler&&(this._oauthHandler.close(),this._oauthHandler=null),this._perOpenCleanups.forEach(e=>e()),this._perOpenCleanups=[],this.stateManager.setState({isOpen:!1}),this.eventEmitter.emit("close")}destroy(){this._isInitialized&&(t(this.config,"Destroying SDK instance"),this._oauthHandler&&(this._oauthHandler.close(),this._oauthHandler=null),this.stateManager.get("isOpen")&&this.stateManager.setState({isOpen:!1}),this.eventEmitter.removeAllListeners(),this.stateManager.clearListeners(),this._isInitialized=!1)}on(e,t){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call on() - SDK instance has been destroyed");return this.eventEmitter.on(e,t)}off(e,t){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call off() - SDK instance has been destroyed");this.eventEmitter.off(e,t)}isOpen(){if(!this._isInitialized)throw this.createError("sdk_destroyed","Cannot call isOpen() - SDK instance has been destroyed");return this.stateManager.get("isOpen")}getVersion(){return Te}cleanupHandler(){this._oauthHandler=null}handleOAuthSuccess(e,t){this.cleanupHandler(),this.eventEmitter.emit("success",e,t)}handleOAuthError(e){this.cleanupHandler(),this.stateManager.setState({error:e}),this.eventEmitter.emit("error",e)}handleOAuthCancel(){this.cleanupHandler(),this.eventEmitter.emit("exit")}registerEventHandlers(e){e.onSuccess&&this._perOpenCleanups.push(this.eventEmitter.on("success",(t,n)=>{e.onSuccess(t,n),this.close()})),e.onExit&&this._perOpenCleanups.push(this.eventEmitter.on("exit",()=>{e.onExit(),this.close()})),this._perOpenCleanups.push(this.eventEmitter.on("error",t=>{e.onError&&e.onError(t),this.close()})),e.onEvent&&this._perOpenCleanups.push(this.eventEmitter.on("event",(t,n)=>{e.onEvent(t,n)}))}createError(e,t,n){const s=new Error(t);return s.code=e,s.details=n,s}}return Ze});
2
2
  //# sourceMappingURL=alter-connect.umd.js.map