@alter-ai/connect 0.12.0 → 0.12.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.
package/README.md CHANGED
@@ -151,17 +151,20 @@ await alterConnect.open({
151
151
  |-----------|------|----------|-------------|
152
152
  | `token` | `string` | Yes | Short-lived session token created by the application backend with an Alter SDK |
153
153
  | `onSuccess` | `(grants, completion) => void` | Yes | Called with the legacy grants array and a typed completion object. `completion.failedGrants` identifies partial failures. |
154
- | `onError` | `(error) => void` | No | Called for failures delivered to the browser SDK, such as a blocked popup, a malformed result, or a total usage-limit application failure. Hosted-page-only failures require backend polling. |
154
+ | `onError` | `(error) => void` | No | Called for failures delivered to the browser SDK, including a terminal provider denial (`code: "connect_denied"`). |
155
155
  | `onExit` | `function` | No | Called when the user closes the desktop popup; this does not mark the backend session denied |
156
- | `onEvent` | `(eventName, metadata) => void` | No | Called once with `connect_opened` after each launch attempt, including a blocked popup |
156
+ | `onEvent` | `(eventName, metadata) => void` | No | Called with `connect_opened` after each launch attempt (including a blocked popup), with `provider_declined` when the user refuses a provider in a session that can still continue, and with `provider_error` when the provider itself fails in such a session |
157
157
 
158
158
  The promise resolves after the launch attempt, not after user authorization. Missing or invalid `token` or `onSuccess` values reject the returned promise with `code: "invalid_options"`. `baseURL` is not an `OpenOptions` field: TypeScript rejects it, while plain JavaScript ignores it.
159
159
 
160
160
  `onSuccess`, `onError`, and `onExit` run through the event emitter's exception
161
- guard. If one throws, the SDK logs the exception and does not perform that
162
- callback's final state/listener cleanup; callback code should not throw.
163
- `onEvent` is invoked directly, so an exception from it rejects `open()` after
164
- the launch attempt.
161
+ guard. If one throws, the SDK logs the exception and still performs that
162
+ callback's final state/listener cleanup. `onEvent` splits: `connect_opened` is
163
+ invoked directly, so an exception from it rejects `open()` after the launch
164
+ attempt, while the hosted-flow events run through that same guard. The terminal
165
+ handlers are always registered and always release the flow, so a manual popup
166
+ close resets `isOpen()` whether or not `onExit` was supplied and whether or not
167
+ it threw.
165
168
 
166
169
  **Completion data (`onSuccess`):**
167
170
 
@@ -202,6 +205,21 @@ A completion with no successful grants and one or more failed grants invokes
202
205
  `onError` with `code: "grant_policy_application_failed"` instead of reporting
203
206
  bare success.
204
207
 
208
+ A provider denial is terminal only when the session has nothing left to try.
209
+ Desktop delivers `code: "connect_denied"` to `onError` and the `error` event; a
210
+ mobile flow with `returnUrl` delivers the same code to the returning page's
211
+ `error` listener. If the session allows another provider, already authorized a
212
+ grant, or still has an account the user has connected and can approve, Connect
213
+ returns to the picker and leaves backend polling pending so the user can
214
+ continue — and reports the refusal as a non-terminal `provider_declined` event
215
+ (`onEvent` and the `event` bus) rather than an error, because `onError` closes
216
+ the Connect UI and would strand a user who declined only one of several
217
+ providers. A provider failure that was not a refusal reports as `provider_error`
218
+ on that same channel, so an application must branch on the event name rather
219
+ than treat every notice as a user decision. Both are popup-flow only: the mobile
220
+ `returnUrl` flow has no opening window to notify. Closing the popup through
221
+ browser chrome remains `onExit`; it is not a provider denial.
222
+
205
223
  ---
206
224
 
207
225
  ### `alterConnect.close()`
@@ -238,7 +256,7 @@ const unsubscribe = alterConnect.on('success', (grants, completion) => {
238
256
  // Later: unsubscribe();
239
257
  ```
240
258
 
241
- **Emitted bus events:** `success`, `error`, `exit`, `close`. The `success` handler receives `(grants, completion)`. Analytics does not emit an `event` bus event; use the per-open `onEvent` callback.
259
+ **Emitted bus events:** `success`, `error`, `exit`, `close`, `event`. The `success` handler receives `(grants, completion)`; the `event` handler receives `(eventName, metadata)` and carries the non-terminal transitions `provider_declined` and `provider_error`. `connect_opened` is raised directly by `open()` and reaches the per-open `onEvent` callback only.
242
260
 
243
261
  ---
244
262
 
@@ -259,8 +277,8 @@ alterConnect.off('error', handleError);
259
277
 
260
278
  Returns the SDK's open-state flag. It becomes `true` when a launch starts and
261
279
  returns to `false` when `close()` runs. A manually closed popup resets it
262
- automatically only when the supplied `onExit` callback returns normally; if
263
- `onExit` is omitted or throws, call `close()` explicitly before opening again.
280
+ automatically, whether or not `onExit` was supplied and whether or not that
281
+ callback threw.
264
282
 
265
283
  ```javascript
266
284
  if (alterConnect.isOpen()) {
@@ -297,6 +315,12 @@ Closing the desktop popup invokes `onExit` locally but sends no denial
297
315
  transition to the backend. A server-side poll remains pending until its timeout
298
316
  or the session expires.
299
317
 
318
+ A provider can likewise render an authorization error on its own origin without
319
+ redirecting to Alter. The browser SDK cannot observe that page or manufacture a
320
+ provider error. Server SDK polling reports the no-callback outcome as
321
+ `ConnectTimeoutError`; `details.reason` distinguishes a local polling deadline
322
+ from a session that was first observed pending and later expired.
323
+
300
324
  ## Security
301
325
 
302
326
  - **API keys stay on the backend.** The frontend only receives a short-lived session token minted by the application backend.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});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)}hasListeners(e){const t=this.events.get(e);return void 0!==t&&t.size>0}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 h(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 p="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 m=new Set(["string","number","symbol"]);function _(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function v(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 b(e){return"string"==typeof e?e:e?.message}function z(e,t,n){const s=e.message?e.message:b(e.inst?._zod.def?.error?.(e))??b(t?.error?.(e))??b(n.customError?.(e))??b(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=>z(e,o,u())));throw p(t,r?.callee),t}return a.value})(S),A=(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=>z(e,o,u())));throw p(t,r?.callee),t}return i.value})(S),P=(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=>z(e,r,u())))}:{success:!0,data:o.value}})(S),R=(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=>z(e,r,u())))}:{success:!0,data:o.value}})(S),U=o("$ZodCheck",(e,t)=>{var n;e._zod??(e._zod={}),e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),L=o("$ZodCheckMinLength",(e,t)=>{var n;U.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})}}),C={major:4,minor:4,patch:3},$=o("$ZodType",(e,t)=>{var n;e??(e={}),e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=C;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=v(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=v(e,t)))});else{if(e.issues.length===t)continue;r||(r=v(e,t))}}return s?s.then(()=>e):e},n=(n,r,o)=>{if(v(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)}}h(e,"~standard",()=>({validate:t=>{try{const n=P(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch(n){return R(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:"zod",version:1}))}),I=o("$ZodString",(e,t)=>{var n;$.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)=>{$.init(e,t),e._zod.parse=e=>e});function M(e,t,n){e.issues.length&&t.issues.push(...w(n,e.issues)),t.value[n]=e.value}const T=o("$ZodArray",(e,t)=>{$.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=>M(t,n,e))):M(a,n,e)}return o.length?Promise.all(o).then(()=>n):n}});function x(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 Z(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)=>{$.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=()=>Z(t),{get value(){{const e=r();return Object.defineProperty(this,"value",{value:e}),e}}});var r;h(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=>x(n,t,e,r,o,i))):x(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=>x(e,n,r,t,l,d))):x(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)=>{$.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=>m.has(typeof e)).map(e=>"string"==typeof e?_(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($.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?_(e):e?_(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)=>{$.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 F(e,t){return void 0===t&&(e.issues.length||e.fallback)?{issues:[],value:void 0}:e}const K=o("$ZodOptional",(e,t)=>{$.init(e,t),e._zod.optin="optional",e._zod.optout="optional",h(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),h(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=>F(e,s)):F(r,s)}return void 0===e.value?e:t.innerType._zod.run(e,n)}}),N=o("$ZodDefault",(e,t)=>{$.init(e,t),e._zod.optin="optional",h(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)=>{$.init(e,t),e._zod.optin="optional",h(e._zod,"optout",()=>t.innerType._zod.optout),h(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=>z(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=>z(e,n,u()))},input:e.value}),e.issues=[],e.fallback=!0),e)}}),q=o("$ZodPipe",(e,t)=>{$.init(e,t),h(e._zod,"values",()=>t.in._zod.values),h(e._zod,"optin",()=>t.in._zod.optin),h(e._zod,"optout",()=>t.out._zod.optout),h(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.");$.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)=>P(e,t,n),e.parseAsync=async(t,n)=>A(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>R(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)=>{T.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),h(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 he=o("ZodMiniTransform",(e,t)=>{V.init(e,t),Q.init(e,t)});function pe(e){return new he({type:"transform",transform:e})}const fe=o("ZodMiniOptional",(e,t)=>{K.init(e,t),Q.init(e,t)});function ge(e){return new fe({type:"optional",innerType:e})}const me=o("ZodMiniDefault",(e,t)=>{N.init(e,t),Q.init(e,t)});function _e(e,t){return new me({type:"default",innerType:e,get defaultValue(){return"function"==typeof t?t():g(t)}})}const ve=o("ZodMiniCatch",(e,t)=>{J.init(e,t),Q.init(e,t)});function ye(e,t){return new ve({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 be(e,t){return new we({type:"pipe",in:e,out:t})}function ze(){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 ze()&&window.innerWidth<=480?"phone":ze()&&window.innerWidth>480&&window.innerWidth<=1024?"tablet":"desktop"}function Ee(e){return"pending"===e?"pending":"error"===e?"error":"active"}const Se=te().check(new L({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()),Ae=be(ae({grant_id:Se,provider:Se,provider_name:ge(te()),account_identifier:ge(te()),timestamp:ge(te()),operation:_e(ge(ue(["creation","reauth"])),"creation"),scopes:_e(ge(oe(te())),[]),status:_e(ge(ue(["active","pending","error"])),"active"),metadata:ge(ke)}),pe(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})),Pe=be(ae({provider_id:Se,reason:Se,message:Se}),pe(e=>({providerId:e.provider_id,reason:e.reason,message:e.message}))),Re=ae({type:ue(["alter_connect_success","alter_connect_error"])}),Ue=ae({type:de("alter_connect_success"),grants:oe(Ae),failed_grants:_e(ge(oe(Pe)),[])}),Le=(Ce={type:de("alter_connect_error"),error:ye(te(),"oauth_error"),error_description:ye(te(),"OAuth authorization failed")},new ie({type:"object",shape:Ce,catchall:se()}));var Ce;function $e(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"}const Ie="alter_oauth_state",je="alter_connect_nonce",Me=["alter_connect_success","alter_connect_error",je,"grant_id","provider","provider_name","account_identifier","timestamp","operation","scopes","status","error_code","error_message"];function Te(){const e=new URLSearchParams(window.location.search);return null!==e.get("alter_connect_success")||null!==e.get("alter_connect_error")}function xe(e){sessionStorage.removeItem(Ie);try{const t=new URL(e);if(t.pathname===window.location.pathname)return void window.history.replaceState({},document.title,t.pathname+t.search+t.hash)}catch{}Ze()}function Ze(){const e=new URL(window.location.href);for(const t of Me)e.searchParams.delete(t);window.history.replaceState({},document.title,e.pathname+e.search+e.hash)}class He{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=function(){const e=globalThis.crypto;if(!e)return null;if("function"==typeof e.randomUUID)return e.randomUUID();if("function"==typeof e.getRandomValues){const t=e.getRandomValues(new Uint8Array(16));return Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}return null}();if(null===t)return this.log("No cryptographic randomness available; refusing redirect flow"),void this.options.onError({code:"redirect_error",message:"Failed to start OAuth flow: this browser provides no secure random source, so the OAuth callback could not be bound to this flow"});let n;try{const s=new URL(e);s.searchParams.set(je,t),n=s.toString()}catch{return this.log("Failed to parse OAuth URL for redirect flow:",e),void this.options.onError({code:"invalid_oauth_url",message:"Failed to start OAuth flow: the OAuth URL is not a valid absolute URL"})}const s={timestamp:Date.now(),returnUrl:window.location.href,nonce:t};try{sessionStorage.setItem(Ie,JSON.stringify(s))}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=n}static checkOAuthReturn(e,t){const n=sessionStorage.getItem(Ie);if(!n)return!!Te()&&(Ze(),t({code:"redirect_state_missing",message:"Received an Alter Connect redirect callback, but no matching flow state exists on this origin. The return URL must be on the SAME origin (scheme, host and port) as the page that called open() — browsers scope the flow's session storage to one origin, so a callback delivered elsewhere cannot be completed.",details:{origin:window.location.origin}}),!0);try{const r=function(e){let t;try{t=JSON.parse(e)}catch{return null}if("object"!=typeof t||null===t)return null;const{timestamp:n,returnUrl:s,nonce:r}=t;return"number"==typeof n&&Number.isFinite(n)?"string"!=typeof s||0===s.length||"string"!=typeof r||0===r.length?null:{timestamp:n,returnUrl:s,nonce:r}:null}(n);if(null===r)return sessionStorage.removeItem(Ie),Te()&&Ze(),!1;const o=Date.now()-r.timestamp;if(o<0||o>3e5)return sessionStorage.removeItem(Ie),Te()&&Ze(),!1;const i=new URLSearchParams(window.location.search),a=i.get("alter_connect_success"),c=i.get("alter_connect_error");if(null===a&&null===c)return!1;if(i.get(je)!==r.nonce)return console.warn("[OAuth Handler] Ignoring OAuth callback parameters that do not carry this flow's nonce"),Ze(),!1;if("true"===a){const n=i.get("grant_id"),o=i.get("provider"),a=i.get("account_identifier");if(!n||!o||!a)return xe(r.returnUrl),t({code:"invalid_response",message:"OAuth redirect returned incomplete grant data"}),!0;const c={grant_id:n,provider:o,provider_name:i.get("provider_name")||o,account_identifier:a,timestamp:i.get("timestamp")||(new Date).toISOString(),operation:(s=i.get("operation"),"reauth"===s?"reauth":"creation"),scopes:i.get("scopes")?.split(",")||[],status:Ee(i.get("status"))};xe(r.returnUrl);const u=[c];return e(u,{grants:u,failedGrants:[]}),!0}if(c){const e={code:i.get("error_code")||"oauth_error",message:i.get("error_description")||"OAuth authorization failed"};return xe(r.returnUrl),t(e),!0}return xe(r.returnUrl),!1}catch(e){return console.error("[OAuth Handler] Failed to check OAuth return:",e),sessionStorage.removeItem(Ie),Te()&&Ze(),!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=Re.safeParse(e.data);if(!t.success)return;if("alter_connect_success"===t.data.type){this.log("OAuth success");const t=Ue.safeParse(e.data);if(!t.success)return this.settled=!0,this.close(),void this.options.onError({code:"invalid_response",message:$e(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=Le.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 De="0.2.0";let We=!1;class Ve{constructor(r={}){if(this._oauthHandler=null,this._perOpenCleanups=[],this.pendingRedirectOutcome=null,function(e){if(void 0!==e.baseURL)throw 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&&!We){We=!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:De,baseURL:this._baseURL}),this.checkRedirectReturn()}checkRedirectReturn(){He.checkOAuthReturn((e,n)=>{t(this.config,"OAuth redirect return - success:",e),this.deliverRedirectOutcome("success",[e,n])},e=>{t(this.config,"OAuth redirect return - error:",e),this.deliverRedirectOutcome("error",[e])})&&t(this.config,"OAuth redirect return detected and handled")}deliverRedirectOutcome(e,t){this.eventEmitter.hasListeners(e)?this.eventEmitter.emit(e,...t):this.pendingRedirectOutcome={event:e,args:t}}flushRedirectOutcome(e){const t=this.pendingRedirectOutcome;null!==t&&t.event===e&&(this.pendingRedirectOutcome=null,this.eventEmitter.emit(t.event,...t.args))}static create(e){return new Ve(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 He({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.pendingRedirectOutcome=null,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");const n=this.eventEmitter.on(e,t);return this.flushRedirectOutcome(e),n}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 De}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}}exports.default=Ve;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});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)}hasListeners(e){const t=this.events.get(e);return void 0!==t&&t.size>0}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 h(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 p="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function f(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function g(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")}const m=new Set(["string","number","symbol"]);function v(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function _(e){const t=e;if(!t)return{};if("string"==typeof t)return{error:()=>t};if(void 0!==t?.message){if(void 0!==t?.error)throw new Error("Cannot specify both `message` and `error` params");t.error=t.message}return delete t.message,"string"==typeof t.error?{...t,error:()=>t.error}:t}function y(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 w(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 b(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 O(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 k=(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",k),S=o("$ZodError",k,{Parent:Error}),A=(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=>O(e,o,u())));throw p(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=>O(e,o,u())));throw p(t,r?.callee),t}return i.value},R=P(S),U=(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=>O(e,r,u())))}:{success:!0,data:o.value}})(S),L=(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=>O(e,r,u())))}:{success:!0,data:o.value}})(S),C=/^-?\d+(?:\.\d+)?$/,T=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;T.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})}}),I={major:4,minor:4,patch:3},j=o("$ZodType",(e,t)=>{var n;e??(e={}),e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=I;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=y(e);for(const o of t){if(o._zod.def.when){if(w(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=y(e,t)))});else{if(e.issues.length===t)continue;r||(r=y(e,t))}}return s?s.then(()=>e):e},n=(n,r,o)=>{if(y(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)}}h(e,"~standard",()=>({validate:t=>{try{const n=U(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch(n){return L(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:"zod",version:1}))}),M=o("$ZodString",(e,t)=>{var n;j.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}}),Z=o("$ZodUnknown",(e,t)=>{j.init(e,t),e._zod.parse=e=>e});function x(e,t,n){e.issues.length&&t.issues.push(...b(n,e.issues)),t.value[n]=e.value}const H=o("$ZodArray",(e,t)=>{j.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=>x(t,n,e))):x(a,n,e)}return o.length?Promise.all(o).then(()=>n):n}});function D(e,t,n,s,r,o){const i=n in s;if(e.issues.length){if(r&&o&&!i)return;t.issues.push(...b(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 W(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 N=o("$ZodObject",(e,t)=>{j.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=()=>W(t),{get value(){{const e=r();return Object.defineProperty(this,"value",{value:e}),e}}});var r;h(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=>D(n,t,e,r,o,i))):D(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=>D(e,n,r,t,l,d))):D(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}}),V=o("$ZodRecord",(e,t)=>{j.init(e,t),e._zod.parse=(n,s)=>{const r=n.value;if(!g(r))return n.issues.push({expected:"record",code:"invalid_type",input:r,inst:e}),n;const o=[],i=t.keyType._zod.values;if(i){n.value={};const a=new Set;for(const c of i)if("string"==typeof c||"number"==typeof c||"symbol"==typeof c){a.add("number"==typeof c?c.toString():c);const i=t.keyType._zod.run({value:c,issues:[]},s);if(i instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if(i.issues.length){n.issues.push({code:"invalid_key",origin:"record",issues:i.issues.map(e=>O(e,s,u())),input:c,path:[c],inst:e});continue}const l=i.value,d=t.valueType._zod.run({value:r[c],issues:[]},s);d instanceof Promise?o.push(d.then(e=>{e.issues.length&&n.issues.push(...b(c,e.issues)),n.value[l]=e.value})):(d.issues.length&&n.issues.push(...b(c,d.issues)),n.value[l]=d.value)}let c;for(const e in r)a.has(e)||(c=c??[],c.push(e));c&&c.length>0&&n.issues.push({code:"unrecognized_keys",input:r,inst:e,keys:c})}else{n.value={};for(const i of Reflect.ownKeys(r)){if("__proto__"===i)continue;if(!Object.prototype.propertyIsEnumerable.call(r,i))continue;let a=t.keyType._zod.run({value:i,issues:[]},s);if(a instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if("string"==typeof i&&C.test(i)&&a.issues.length){const e=t.keyType._zod.run({value:Number(i),issues:[]},s);if(e instanceof Promise)throw new Error("Async schemas not supported in object keys currently");0===e.issues.length&&(a=e)}if(a.issues.length){"loose"===t.mode?n.value[i]=r[i]:n.issues.push({code:"invalid_key",origin:"record",issues:a.issues.map(e=>O(e,s,u())),input:i,path:[i],inst:e});continue}const c=t.valueType._zod.run({value:r[i],issues:[]},s);c instanceof Promise?o.push(c.then(e=>{e.issues.length&&n.issues.push(...b(i,e.issues)),n.value[a.value]=e.value})):(c.issues.length&&n.issues.push(...b(i,c.issues)),n.value[a.value]=c.value)}}return o.length?Promise.all(o).then(()=>n):n}}),F=o("$ZodEnum",(e,t)=>{j.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=>m.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}}),K=o("$ZodLiteral",(e,t)=>{if(j.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}}),G=o("$ZodTransform",(e,t)=>{j.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 J(e,t){return void 0===t&&(e.issues.length||e.fallback)?{issues:[],value:void 0}:e}const q=o("$ZodOptional",(e,t)=>{j.init(e,t),e._zod.optin="optional",e._zod.optout="optional",h(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),h(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=>J(e,s)):J(r,s)}return void 0===e.value?e:t.innerType._zod.run(e,n)}}),B=o("$ZodDefault",(e,t)=>{j.init(e,t),e._zod.optin="optional",h(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=>Y(e,t)):Y(s,t)}});function Y(e,t){return void 0===e.value&&(e.value=t.defaultValue),e}const X=o("$ZodCatch",(e,t)=>{j.init(e,t),e._zod.optin="optional",h(e._zod,"optout",()=>t.innerType._zod.optout),h(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=>O(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=>O(e,n,u()))},input:e.value}),e.issues=[],e.fallback=!0),e)}}),Q=o("$ZodPipe",(e,t)=>{j.init(e,t),h(e._zod,"values",()=>t.in._zod.values),h(e._zod,"optin",()=>t.in._zod.optin),h(e._zod,"optout",()=>t.out._zod.optout),h(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=>ee(e,t.in,n)):ee(s,t.in,n)}const s=t.in._zod.run(e,n);return s instanceof Promise?s.then(e=>ee(e,t.out,n)):ee(s,t.out,n)}});function ee(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 te;class ne{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)}}(te=globalThis).__zod_globalRegistry??(te.__zod_globalRegistry=new ne);const se=o("ZodMiniType",(e,t)=>{if(!e._zod)throw new Error("Uninitialized schema in ZodMiniType.");j.init(e,t),e.def=t,e.type=t.type,e.parse=(t,n)=>A(e,t,n,{callee:e.parse}),e.safeParse=(t,n)=>U(e,t,n),e.parseAsync=async(t,n)=>R(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>L(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)}),re=o("ZodMiniString",(e,t)=>{M.init(e,t),se.init(e,t)});function oe(e){return function(e,t){return new e({type:"string",..._(t)})}(re,e)}const ie=o("ZodMiniUnknown",(e,t)=>{Z.init(e,t),se.init(e,t)});function ae(){return new ie({type:"unknown"})}const ce=o("ZodMiniArray",(e,t)=>{H.init(e,t),se.init(e,t)});function ue(e,t){return new ce({type:"array",element:e,..._(t)})}const le=o("ZodMiniObject",(e,t)=>{N.init(e,t),se.init(e,t),h(e,"shape",()=>t.shape)});function de(e,t){const n={type:"object",shape:e??{},..._(t)};return new le(n)}function he(e,t){return new le({type:"object",shape:e,catchall:ae(),..._(t)})}const pe=o("ZodMiniRecord",(e,t)=>{V.init(e,t),se.init(e,t)});const fe=o("ZodMiniEnum",(e,t)=>{F.init(e,t),se.init(e,t),e.options=Object.values(t.entries)});function ge(e,t){const n=Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e;return new fe({type:"enum",entries:n,..._(t)})}const me=o("ZodMiniLiteral",(e,t)=>{K.init(e,t),se.init(e,t)});function ve(e,t){return new me({type:"literal",values:Array.isArray(e)?e:[e],..._(t)})}const _e=o("ZodMiniTransform",(e,t)=>{G.init(e,t),se.init(e,t)});function ye(e){return new _e({type:"transform",transform:e})}const we=o("ZodMiniOptional",(e,t)=>{q.init(e,t),se.init(e,t)});function be(e){return new we({type:"optional",innerType:e})}const ze=o("ZodMiniDefault",(e,t)=>{B.init(e,t),se.init(e,t)});function Oe(e,t){return new ze({type:"default",innerType:e,get defaultValue(){return"function"==typeof t?t():g(e=t)?{...e}:Array.isArray(e)?[...e]:e instanceof Map?new Map(e):e instanceof Set?new Set(e):e;var e}})}const ke=o("ZodMiniCatch",(e,t)=>{X.init(e,t),se.init(e,t)});function Ee(e,t){return new ke({type:"catch",innerType:e,catchValue:"function"==typeof t?t:()=>t})}const Se=o("ZodMiniPipe",(e,t)=>{Q.init(e,t),se.init(e,t)});function Ae(e,t){return new Se({type:"pipe",in:e,out:t})}function Pe(){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 Re(){return Pe()&&window.innerWidth<=480?"phone":Pe()&&window.innerWidth>480&&window.innerWidth<=1024?"tablet":"desktop"}function Ue(e){return"pending"===e?"pending":"error"===e?"error":"active"}const Le=oe().check((Ce=1,new $({check:"min_length",..._(Te),minimum:Ce})));var Ce,Te;const $e=function(e,t){return e.clone({...e._zod.def,catchall:t})}(de({account_display_name:be(oe()),account_email:be(oe())}),ae()),Ie=Ae(de({grant_id:Le,provider:Le,provider_name:be(oe()),account_identifier:be(oe()),timestamp:be(oe()),operation:Oe(be(ge(["creation","reauth"])),"creation"),scopes:Oe(be(ue(oe())),[]),status:Oe(be(ge(["active","pending","error"])),"active"),metadata:be($e)}),ye(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})),je=Ae(de({provider_id:Le,reason:Le,message:Le}),ye(e=>({providerId:e.provider_id,reason:e.reason,message:e.message}))),Me=de({type:ge(["alter_connect_success","alter_connect_error","alter_connect_event"])}),Ze=de({type:ve("alter_connect_success"),grants:ue(Ie),failed_grants:Oe(be(ue(je)),[])}),xe=he({type:ve("alter_connect_error"),error:Ee(oe(),"oauth_error"),error_description:Ee(oe(),"OAuth authorization failed")}),He=he({type:ve("alter_connect_event"),event:Ee(oe(),"connect_notice"),metadata:Ee(function(e,t,n){return t&&t._zod?new pe({type:"record",keyType:e,valueType:t,..._(n)}):new pe({type:"record",keyType:oe(),valueType:e,..._(t)})}(oe(),ae()),{})});function De(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"}const We="alter_oauth_state",Ne="alter_connect_nonce",Ve=["alter_connect_success","alter_connect_error",Ne,"grant_id","provider","provider_name","account_identifier","timestamp","operation","scopes","status","error_code","error_message"];function Fe(){const e=new URLSearchParams(window.location.search);return null!==e.get("alter_connect_success")||null!==e.get("alter_connect_error")}function Ke(e){sessionStorage.removeItem(We);try{const t=new URL(e);if(t.pathname===window.location.pathname)return void window.history.replaceState({},document.title,t.pathname+t.search+t.hash)}catch{}Ge()}function Ge(){const e=new URL(window.location.href);for(const t of Ve)e.searchParams.delete(t);window.history.replaceState({},document.title,e.pathname+e.search+e.hash)}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,onNotice:t.onNotice||(()=>{}),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=Re();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=function(){const e=globalThis.crypto;if(!e)return null;if("function"==typeof e.randomUUID)return e.randomUUID();if("function"==typeof e.getRandomValues){const t=e.getRandomValues(new Uint8Array(16));return Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}return null}();if(null===t)return this.log("No cryptographic randomness available; refusing redirect flow"),void this.options.onError({code:"redirect_error",message:"Failed to start OAuth flow: this browser provides no secure random source, so the OAuth callback could not be bound to this flow"});let n;try{const s=new URL(e);s.searchParams.set(Ne,t),n=s.toString()}catch{return this.log("Failed to parse OAuth URL for redirect flow:",e),void this.options.onError({code:"invalid_oauth_url",message:"Failed to start OAuth flow: the OAuth URL is not a valid absolute URL"})}const s={timestamp:Date.now(),returnUrl:window.location.href,nonce:t};try{sessionStorage.setItem(We,JSON.stringify(s))}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=n}static checkOAuthReturn(e,t){const n=sessionStorage.getItem(We);if(!n)return!!Fe()&&(Ge(),t({code:"redirect_state_missing",message:"Received an Alter Connect redirect callback, but no matching flow state exists on this origin. The return URL must be on the SAME origin (scheme, host and port) as the page that called open() — browsers scope the flow's session storage to one origin, so a callback delivered elsewhere cannot be completed.",details:{origin:window.location.origin}}),!0);try{const r=function(e){let t;try{t=JSON.parse(e)}catch{return null}if("object"!=typeof t||null===t)return null;const{timestamp:n,returnUrl:s,nonce:r}=t;return"number"==typeof n&&Number.isFinite(n)?"string"!=typeof s||0===s.length||"string"!=typeof r||0===r.length?null:{timestamp:n,returnUrl:s,nonce:r}:null}(n);if(null===r)return sessionStorage.removeItem(We),Fe()&&Ge(),!1;const o=Date.now()-r.timestamp;if(o<0||o>3e5)return sessionStorage.removeItem(We),Fe()&&Ge(),!1;const i=new URLSearchParams(window.location.search),a=i.get("alter_connect_success"),c=i.get("alter_connect_error");if(null===a&&null===c)return!1;if(i.get(Ne)!==r.nonce)return console.warn("[OAuth Handler] Ignoring OAuth callback parameters that do not carry this flow's nonce"),Ge(),!1;if("true"===a){const n=i.get("grant_id"),o=i.get("provider"),a=i.get("account_identifier");if(!n||!o||!a)return Ke(r.returnUrl),t({code:"invalid_response",message:"OAuth redirect returned incomplete grant data"}),!0;const c={grant_id:n,provider:o,provider_name:i.get("provider_name")||o,account_identifier:a,timestamp:i.get("timestamp")||(new Date).toISOString(),operation:(s=i.get("operation"),"reauth"===s?"reauth":"creation"),scopes:i.get("scopes")?.split(",")||[],status:Ue(i.get("status"))};Ke(r.returnUrl);const u=[c];return e(u,{grants:u,failedGrants:[]}),!0}if(c){const e={code:i.get("error_code")||"oauth_error",message:i.get("error_description")||"OAuth authorization failed"};return Ke(r.returnUrl),t(e),!0}return Ke(r.returnUrl),!1}catch(e){return console.error("[OAuth Handler] Failed to check OAuth return:",e),sessionStorage.removeItem(We),Fe()&&Ge(),!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=Me.safeParse(e.data);if(!t.success)return;if("alter_connect_event"===t.data.type){const t=He.safeParse(e.data);return void(t.success&&(this.log("Connect notice:",t.data.event),this.options.onNotice(t.data.event,t.data.metadata)))}if("alter_connect_success"===t.data.type){this.log("OAuth success");const t=Ze.safeParse(e.data);if(!t.success)return this.settled=!0,this.close(),void this.options.onError({code:"invalid_response",message:De(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=xe.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 qe="0.2.0";let Be=!1;class Ye{constructor(r={}){if(this._oauthHandler=null,this._perOpenCleanups=[],this.pendingRedirectOutcome=null,function(e){if(void 0!==e.baseURL)throw 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&&!Be){Be=!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:qe,baseURL:this._baseURL}),this.checkRedirectReturn()}checkRedirectReturn(){Je.checkOAuthReturn((e,n)=>{t(this.config,"OAuth redirect return - success:",e),this.deliverRedirectOutcome("success",[e,n])},e=>{t(this.config,"OAuth redirect return - error:",e),this.deliverRedirectOutcome("error",[e])})&&t(this.config,"OAuth redirect return detected and handled")}deliverRedirectOutcome(e,t){this.eventEmitter.hasListeners(e)?this.eventEmitter.emit(e,...t):this.pendingRedirectOutcome={event:e,args:t}}flushRedirectOutcome(e){const t=this.pendingRedirectOutcome;null!==t&&t.event===e&&(this.pendingRedirectOutcome=null,this.eventEmitter.emit(t.event,...t.args))}static create(e){return new Ye(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()},onNotice:(e,n)=>{t(this.config,"OAuth notice:",e),this.eventEmitter.emit("event",e,n)},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.pendingRedirectOutcome=null,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");const n=this.eventEmitter.on(e,t);return this.flushRedirectOutcome(e),n}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 qe}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")}releaseAfterTerminal(e){try{e()}finally{this._isInitialized&&this.close()}}registerEventHandlers(e){this._perOpenCleanups.push(this.eventEmitter.on("success",(t,n)=>{this.releaseAfterTerminal(()=>e.onSuccess?.(t,n))})),this._perOpenCleanups.push(this.eventEmitter.on("exit",()=>{this.releaseAfterTerminal(()=>e.onExit?.())})),this._perOpenCleanups.push(this.eventEmitter.on("error",t=>{this.releaseAfterTerminal(()=>e.onError?.(t))})),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}}exports.default=Ye;
2
2
  //# sourceMappingURL=alter-connect.cjs.js.map