@aippy/runtime 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,6 +39,6 @@
39
39
  export { aippyAIProvider, type AippyProvider } from './openai';
40
40
  export type { AippyOpenAIConfig } from './openai';
41
41
  export { aippyChatConfig, type AippyUseChatOptions, type AippyUIConfig, type AippyChatConfig, UI_CHAT_ENDPOINT, } from './ui';
42
- export { DEFAULT_BASE_URL, DEFAULT_UI_BASE_URL, DEFAULT_CHAT_MODEL, DEFAULT_CHAT_SYSTEM, } from './shared';
42
+ export { DEFAULT_BASE_URL, DEFAULT_UI_BASE_URL, DEFAULT_CHAT_MODEL, DEFAULT_CHAT_SYSTEM, resolveOpenAIConfig, resolveUIConfig, } from './shared';
43
43
  export { normalizeError } from './errors';
44
44
  export { type AIConfig, type AIConfigValue, type AIConfigItem, type NumberAIConfigItem, type BooleanAIConfigItem, type TextAIConfigItem, type EnumAIConfigItem, type AIConfigError, type AIConfigValues, validateAIConfig, parseAIConfig, loadAIConfig, getAIConfigValue, sendAIConfigToContainer, createAIConfig, } from './config';
package/dist/ai/index.js CHANGED
@@ -1,19 +1,21 @@
1
- import { D as i, d as r, e, c as n, U as C, a as _, b as E, f as I, g as T, l as f, n as g, p, s as U, v as t } from "../helper-DHOIfdTx.js";
1
+ import { D as i, d as A, e as r, c as n, U as C, a as I, b as f, h as g, g as _, l as p, n as E, p as T, r as U, f as t, s as l, v as D } from "../helper-KmxP93y0.js";
2
2
  import "react";
3
- import "../bridge-CqV1iP30.js";
3
+ import "../bridge-CtB9L5kL.js";
4
4
  export {
5
5
  i as DEFAULT_BASE_URL,
6
- r as DEFAULT_CHAT_MODEL,
7
- e as DEFAULT_CHAT_SYSTEM,
6
+ A as DEFAULT_CHAT_MODEL,
7
+ r as DEFAULT_CHAT_SYSTEM,
8
8
  n as DEFAULT_UI_BASE_URL,
9
9
  C as UI_CHAT_ENDPOINT,
10
- _ as aippyAIProvider,
11
- E as aippyChatConfig,
12
- I as createAIConfig,
13
- T as getAIConfigValue,
14
- f as loadAIConfig,
15
- g as normalizeError,
16
- p as parseAIConfig,
17
- U as sendAIConfigToContainer,
18
- t as validateAIConfig
10
+ I as aippyAIProvider,
11
+ f as aippyChatConfig,
12
+ g as createAIConfig,
13
+ _ as getAIConfigValue,
14
+ p as loadAIConfig,
15
+ E as normalizeError,
16
+ T as parseAIConfig,
17
+ U as resolveOpenAIConfig,
18
+ t as resolveUIConfig,
19
+ l as sendAIConfigToContainer,
20
+ D as validateAIConfig
19
21
  };
@@ -46,9 +46,17 @@ export declare const DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
46
46
  export declare const DEFAULT_CHAT_SYSTEM = "";
47
47
  /**
48
48
  * Resolves OpenAI-compatible configuration with defaults.
49
+ *
50
+ * Calls `resolveApiBaseUrl()` at invocation time instead of reading
51
+ * the module-level `DEFAULT_BASE_URL` constant. In browsers this
52
+ * returns the same cached value; the real benefit is testability —
53
+ * tests can `_resetCachedApiBaseUrl()` between cases and verify
54
+ * hostname-dependent resolution without re-importing the module.
49
55
  */
50
56
  export declare function resolveOpenAIConfig(config?: AippyOpenAIConfig): Required<AippyOpenAIConfig>;
51
57
  /**
52
58
  * Resolves UI (Data Stream Protocol) configuration with defaults.
59
+ *
60
+ * @see resolveOpenAIConfig — same call-time resolution rationale.
53
61
  */
54
62
  export declare function resolveUIConfig(config?: AippyUIConfig): Required<AippyUIConfig>;
@@ -45,8 +45,5 @@ export declare class AudioSilenceDetector {
45
45
  * Pause media element to stop audio output
46
46
  */
47
47
  private pauseMedia;
48
- /**
49
- * Resume media element playback
50
- */
51
48
  private resumeMedia;
52
49
  }
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Audio module for iOS-compatible Web Audio API
3
3
  *
4
- * This module provides utilities to bypass iOS silent mode restrictions
5
- * on Web Audio API playback.
4
+ * Provides utilities to bypass iOS silent mode restrictions, manage
5
+ * AudioContext lifecycle across page transitions, and play sound effects
6
+ * through the Web Audio pipeline (not HTMLAudioElement).
6
7
  *
7
8
  * @module @aippy/runtime/audio
8
9
  */
@@ -11,4 +12,6 @@ export type { AudioContextPatchOptions, AutoPauseOptions, MediaElementType, Patc
11
12
  export { createHiddenMediaElement, isMediaStreamAudioSupported, } from './utils';
12
13
  export { useAudioContext } from './useAudioContext';
13
14
  export type { UseAudioContextOptions, UseAudioContextReturn } from './useAudioContext';
15
+ export { useSound } from './useSound';
16
+ export type { UseSoundOptions, UseSoundReturn, PlayOptions } from './useSound';
14
17
  export { isIOSDevice } from './utils';
@@ -1,8 +1,9 @@
1
- import { c as i, a as t, i as d, p as o, u as s } from "../useAudioContext-D9F3x80Y.js";
1
+ import { c as i, b as s, i as t, p as d, u as o, a as u } from "../useSound-jHl7rkaq.js";
2
2
  export {
3
3
  i as createHiddenMediaElement,
4
- t as isIOSDevice,
5
- d as isMediaStreamAudioSupported,
6
- o as patchAudioContext,
7
- s as useAudioContext
4
+ s as isIOSDevice,
5
+ t as isMediaStreamAudioSupported,
6
+ d as patchAudioContext,
7
+ o as useAudioContext,
8
+ u as useSound
8
9
  };
@@ -1,37 +1,15 @@
1
1
  import { AudioContextPatchOptions, PatchedAudioContext } from './types';
2
2
  /**
3
- * Patches an AudioContext to bypass iOS silent mode restrictions
3
+ * Patches an AudioContext to bypass iOS silent mode restrictions.
4
4
  *
5
- * On iOS devices, Web Audio API is affected by the hardware silent switch.
6
- * This function routes audio through a MediaStreamAudioDestinationNode
7
- * connected to a hidden video element, which bypasses the restriction.
5
+ * On iOS, routes Web Audio output through a MediaStreamAudioDestinationNode
6
+ * connected to a hidden video element. On non-iOS devices, returns the
7
+ * original context with zero overhead.
8
8
  *
9
- * Features:
10
- * - Auto-pause: Automatically pauses MediaElement when audio becomes silent
11
- * to prevent iOS Safari audio buffer looping bug (~50ms latency)
12
- * - Auto-resume: Automatically resumes playback when new audio is detected
13
- * - Zero user code changes: Use standard Web Audio API after unlock
9
+ * Handles page lifecycle (bfcache, interrupted state) so audio recovers
10
+ * automatically after iOS force-quit / Android WebView navigation.
14
11
  *
15
- * On non-iOS devices, this function returns the original context with
16
- * minimal modifications (zero overhead).
17
- *
18
- * @param audioContext - The AudioContext to patch
19
- * @param options - Configuration options
20
- * @returns Enhanced AudioContext with iOS compatibility
21
- *
22
- * @example
23
- * ```typescript
24
- * const ctx = new AudioContext();
25
- * const patchedCtx = patchAudioContext(ctx);
26
- *
27
- * // Unlock on user interaction (iOS only)
28
- * button.onclick = () => patchedCtx.unlock();
29
- *
30
- * // Use native Web Audio API normally
31
- * const osc = patchedCtx.createOscillator();
32
- * osc.connect(patchedCtx.destination); // Auto-routed on iOS
33
- * osc.start();
34
- * osc.stop(); // Audio will auto-stop ~50ms after silence detected
35
- * ```
12
+ * Idempotent: calling on an already-patched context returns the same object.
13
+ * After cleanup(), the context can be re-patched.
36
14
  */
37
15
  export declare function patchAudioContext(audioContext: AudioContext, options?: AudioContextPatchOptions): PatchedAudioContext;
@@ -63,21 +63,10 @@ export interface AudioContextPatchOptions {
63
63
  * Extended AudioContext with iOS compatibility features
64
64
  */
65
65
  export interface PatchedAudioContext extends AudioContext {
66
- /**
67
- * Unlock audio playback on iOS (must be called in user interaction)
68
- * @returns Promise that resolves when unlocked
69
- */
70
66
  unlock(): Promise<void>;
71
- /**
72
- * Manually cleanup patched resources
73
- */
74
67
  cleanup(): void;
75
- /**
76
- * Indicates whether the context has been patched
77
- */
78
68
  readonly isPatched: boolean;
79
- /**
80
- * Reference to the original AudioDestinationNode
81
- */
82
69
  readonly originalDestination: AudioDestinationNode;
70
+ /** @internal Current unlock state — read by useAudioContext to sync React state. */
71
+ readonly _isUnlocked: boolean;
83
72
  }
@@ -13,56 +13,26 @@ export interface UseAudioContextOptions extends AudioContextPatchOptions {
13
13
  * Return type for useAudioContext hook
14
14
  */
15
15
  export interface UseAudioContextReturn {
16
- /**
17
- * Patched AudioContext instance
18
- */
16
+ /** Reactive value for render-time checks (`if (!audioContext) return ...`). */
19
17
  audioContext: PatchedAudioContext | null;
20
- /**
21
- * Whether audio has been unlocked (ready for playback)
22
- */
23
18
  isUnlocked: boolean;
24
- /**
25
- * Manually unlock audio (call during user interaction)
26
- */
19
+ /** Stable reference. Safe in any closure. */
27
20
  unlock: () => Promise<void>;
21
+ /** Stable getter. Always returns the latest AudioContext (or null). Use in callbacks / closures instead of the reactive `audioContext` value. */
22
+ getAudioContext: () => PatchedAudioContext | null;
28
23
  }
29
24
  /**
30
- * React hook for managing AudioContext lifecycle with iOS silent mode bypass
25
+ * React hook for managing AudioContext lifecycle with iOS silent mode bypass.
31
26
  *
32
27
  * Automatically handles:
33
28
  * - AudioContext creation and patching
34
- * - Auto-pause/resume to prevent iOS audio buffer looping (~50ms latency)
29
+ * - Auto-pause/resume to prevent iOS audio buffer looping
30
+ * - Page lifecycle recovery (bfcache, interrupted state)
31
+ * - Re-unlock after iOS force-quit or Android WebView navigation
35
32
  * - Cleanup on unmount
36
- * - Optional auto-unlock on first user interaction
37
- *
38
- * Note: Built for React 19 - no useCallback needed for optimal performance
39
- *
40
- * @param options - Configuration options
41
- * @returns AudioContext instance, unlock status, and unlock function
42
- *
43
- * @example
44
- * ```tsx
45
- * function AudioComponent() {
46
- * const { audioContext, isUnlocked, unlock } = useAudioContext();
47
- *
48
- * const playSound = async () => {
49
- * if (!audioContext) return;
50
- *
51
- * // Unlock if needed (handles iOS restrictions)
52
- * if (!isUnlocked) {
53
- * await unlock();
54
- * }
55
- *
56
- * // Play sound using Web Audio API - just use standard API!
57
- * const osc = audioContext.createOscillator();
58
- * osc.connect(audioContext.destination);
59
- * osc.start();
60
- * osc.stop(audioContext.currentTime + 0.3);
61
- * // Audio will auto-stop ~50ms after silence detected
62
- * };
63
33
  *
64
- * return <button onClick={playSound}>Play Sound</button>;
65
- * }
66
- * ```
34
+ * **Options are read once on mount.** Pass per-call parameters (e.g. volume)
35
+ * through the returned `audioContext` or per-play options instead of changing
36
+ * hook options after mount.
67
37
  */
68
38
  export declare function useAudioContext(options?: UseAudioContextOptions): UseAudioContextReturn;
@@ -0,0 +1,69 @@
1
+ import { useAudioContext, UseAudioContextOptions } from './useAudioContext';
2
+ export interface UseSoundOptions extends UseAudioContextOptions {
3
+ /**
4
+ * Preload all sound buffers on mount (after first unlock).
5
+ * @default false
6
+ */
7
+ preload?: boolean;
8
+ /**
9
+ * Master volume for all sounds (0-1).
10
+ * @default 1
11
+ */
12
+ volume?: number;
13
+ }
14
+ export interface PlayOptions {
15
+ loop?: boolean;
16
+ volume?: number;
17
+ }
18
+ export interface UseSoundReturn {
19
+ /**
20
+ * Play a sound by name. Stable reference — safe to pass to PixiJS, rAF, or
21
+ * any closure that outlives a single render. Auto-unlocks on first call.
22
+ * Returns a stop handle, or null if context isn't ready or name is unknown.
23
+ */
24
+ play: (name: string, options?: PlayOptions) => Promise<(() => void) | null>;
25
+ /** Stop a specific named sound. Stable reference. */
26
+ stop: (name: string) => void;
27
+ /** Stop all currently playing sounds. Stable reference. */
28
+ stopAll: () => void;
29
+ /** Whether the AudioContext is created and unlocked. */
30
+ isReady: boolean;
31
+ /** Reactive AudioContext value for render-time checks. */
32
+ audioContext: ReturnType<typeof useAudioContext>['audioContext'];
33
+ /** Stable unlock function. */
34
+ unlock: ReturnType<typeof useAudioContext>['unlock'];
35
+ /** Stable getter for the underlying AudioContext. Use in callbacks / closures. */
36
+ getAudioContext: ReturnType<typeof useAudioContext>['getAudioContext'];
37
+ }
38
+ /**
39
+ * Hook for playing sound effects from URLs via Web Audio API.
40
+ *
41
+ * ALL audio goes through AudioContext (not HTMLAudioElement), which means:
42
+ * - iOS silent mode bypass works automatically
43
+ * - Page lifecycle management (pagehide/bfcache) stops audio correctly
44
+ * - Android WebView navigation stops audio correctly
45
+ * - No HTMLAudioElement concurrency issues on low-end devices
46
+ *
47
+ * **Options are read once on mount** — pass volume per-play() to change it
48
+ * dynamically.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * const SOUNDS = {
53
+ * jump: 'https://cdn.aippy.ai/audio/jump.mp3',
54
+ * coin: 'https://cdn.aippy.ai/audio/coin.wav',
55
+ * bgm: 'https://cdn.aippy.ai/audio/bgm.mp3',
56
+ * };
57
+ *
58
+ * function Game() {
59
+ * const { play, stop, stopAll } = useSound(SOUNDS);
60
+ *
61
+ * const onJump = async () => { await play('jump'); };
62
+ * const startBGM = async () => { await play('bgm', { loop: true, volume: 0.5 }); };
63
+ * const stopBGM = () => { stop('bgm'); };
64
+ *
65
+ * return <canvas onClick={onJump} />;
66
+ * }
67
+ * ```
68
+ */
69
+ export declare function useSound(urls: Record<string, string>, options?: UseSoundOptions): UseSoundReturn;
@@ -1,23 +1,38 @@
1
- import { a as U } from "./runtime-CmoG3v2m.js";
2
- import { r as v, s as L, i as p } from "./app-version-checker-Bz7FrEZz.js";
3
- import { c as B, a as I } from "./errors-B3bDbQbD.js";
4
- const f = {
5
- apiBaseUrl: "https://api.aippy.dev/api",
1
+ import { a as v } from "./runtime-CmoG3v2m.js";
2
+ import "react";
3
+ import { r as k, s as C, i as f } from "./app-version-checker-Bz7FrEZz.js";
4
+ import { c as h, a as U } from "./errors-B3bDbQbD.js";
5
+ const S = ".aippynow.com", R = "https://api.aippy.dev", _ = "https://api.aippy.ai";
6
+ let p;
7
+ function q() {
8
+ if (p) return p;
9
+ let n = _;
10
+ if (typeof window < "u" && window.location) {
11
+ const e = window.location.hostname;
12
+ (e.endsWith(S) || e === "localhost" || e === "127.0.0.1") && (n = R);
13
+ }
14
+ return p = n, n;
15
+ }
16
+ function K() {
17
+ p = void 0;
18
+ }
19
+ const B = {
20
+ apiBaseUrl: `${q()}/api`,
6
21
  authToken: "",
7
22
  currentUserId: null
8
23
  };
9
- function E(n) {
10
- Object.assign(f, n);
24
+ function P(n) {
25
+ Object.assign(B, n);
11
26
  }
12
- function R(n) {
13
- f.authToken = n;
27
+ function D(n) {
28
+ B.authToken = n;
14
29
  }
15
- function q(n) {
16
- f.currentUserId = n;
30
+ function O(n) {
31
+ B.currentUserId = n;
17
32
  }
18
- const k = 3e3, T = 50, g = 500, c = { uid: "", token: "" };
33
+ const b = 3e3, T = 50, g = 500, c = { uid: "", token: "" };
19
34
  let l = null, u = !1, a = null, t = null;
20
- function w(n) {
35
+ function I(n) {
21
36
  if (!n || typeof n != "object") return null;
22
37
  let e = n;
23
38
  if (e.credentials && typeof e.credentials == "object" && (e = e.credentials), e.user && typeof e.user == "object" && e.token) {
@@ -27,9 +42,9 @@ function w(n) {
27
42
  const r = e.uid || e.userId || e.id || "", o = e.token || e.authToken || "", s = e.apiBaseUrl;
28
43
  if (!r || !o) return null;
29
44
  const i = { uid: String(r), token: o, apiBaseUrl: s };
30
- return q(i.uid), R(o), s && E({ apiBaseUrl: s }), i;
45
+ return O(i.uid), D(o), s && P({ apiBaseUrl: s }), i;
31
46
  }
32
- function m(n) {
47
+ function y(n) {
33
48
  if (console.log("🔄 [Bridge] processUserInfoData called with:", n), !n || typeof n != "object")
34
49
  return console.warn("⚠️ [Bridge] Invalid data (null or not object):", n), null;
35
50
  let e = n;
@@ -40,7 +55,7 @@ function m(n) {
40
55
  const o = { uid: String(r), ...e };
41
56
  return console.log("✅ [Bridge] Created userInfo:", o), l = o, u = !0, console.log("✅ [Bridge] Cached userInfo, userInfoReceived = true"), o;
42
57
  }
43
- function A(n = g) {
58
+ function j(n = g) {
44
59
  return console.log("📱 [Bridge] requestCredentialsFromiOS called, timeout:", n), a ? (console.log("⏳ [Bridge] Pending credentials request exists, waiting..."), new Promise((e) => {
45
60
  const r = a.resolve;
46
61
  a.resolve = (o) => {
@@ -53,7 +68,7 @@ function A(n = g) {
53
68
  hasWebkit: !!window.webkit,
54
69
  hasMessageHandlers: !!window.webkit?.messageHandlers,
55
70
  hasAippyListener: !!r
56
- }), r || (console.log("⏳ [Bridge] aippyListener not found, waiting for injection..."), r = await b(1500)), !r) {
71
+ }), r || (console.log("⏳ [Bridge] aippyListener not found, waiting for injection..."), r = await E(1500)), !r) {
57
72
  console.warn("⚠️ [Bridge] No aippyListener found after waiting, returning empty credentials"), e(c);
58
73
  return;
59
74
  }
@@ -64,9 +79,9 @@ function A(n = g) {
64
79
  resolve: (s) => {
65
80
  console.log("✅ [Bridge] pendingCredentialsRequest.resolve called with:", s), clearTimeout(o), a = null, e(s);
66
81
  }
67
- }, console.log("📱 [Bridge] pendingCredentialsRequest set"), U.receiveChannel.once("user.credentials", (s) => {
82
+ }, console.log("📱 [Bridge] pendingCredentialsRequest set"), v.receiveChannel.once("user.credentials", (s) => {
68
83
  console.log("📩 [Bridge] Received user.credentials via receiveChannel:", s), clearTimeout(o);
69
- const i = w(s) || c;
84
+ const i = I(s) || c;
70
85
  a && a.resolve(i);
71
86
  });
72
87
  try {
@@ -81,16 +96,16 @@ function A(n = g) {
81
96
  })();
82
97
  });
83
98
  }
84
- function S(n = g) {
99
+ function M(n = g) {
85
100
  return new Promise((e) => {
86
- if (!p()) {
101
+ if (!f()) {
87
102
  e(c);
88
103
  return;
89
104
  }
90
105
  const r = setTimeout(() => {
91
106
  window.removeEventListener("message", o), e(c);
92
107
  }, n), o = (s) => {
93
- s.data?.type === "user-credentials-response" && (clearTimeout(r), window.removeEventListener("message", o), e(w(s.data) || c));
108
+ s.data?.type === "user-credentials-response" && (clearTimeout(r), window.removeEventListener("message", o), e(I(s.data) || c));
94
109
  };
95
110
  window.addEventListener("message", o);
96
111
  try {
@@ -100,9 +115,9 @@ function S(n = g) {
100
115
  }
101
116
  });
102
117
  }
103
- const D = () => /Aippy\/[\d.]+\/\d+\/Android/i.test(navigator.userAgent);
104
- async function b(n = 1500) {
105
- if (!D())
118
+ const F = () => /Aippy\/[\d.]+\/\d+\/Android/i.test(navigator.userAgent);
119
+ async function E(n = 1500) {
120
+ if (!F())
106
121
  return console.log("📱 [Bridge] Not Android, skipping waitForAippyListener"), window.webkit?.messageHandlers?.aippyListener || null;
107
122
  const e = Date.now(), r = 50;
108
123
  for (console.log("🤖 [Bridge] Android: Waiting for aippyListener (max", n, "ms)..."); Date.now() - e < n; ) {
@@ -113,7 +128,7 @@ async function b(n = 1500) {
113
128
  }
114
129
  return console.warn("⏰ [Bridge] aippyListener not available after", n, "ms"), null;
115
130
  }
116
- function O(n = !1, e = g) {
131
+ function N(n = !1, e = g) {
117
132
  return console.log("📱 [Bridge] requestUserInfoFromiOS called:", { forceRefresh: n, timeoutMs: e }), console.log("📱 [Bridge] Cache state:", { userInfoReceived: u, cachedUserInfo: l ? "(cached)" : null }), u && l && !n ? (console.log("✅ [Bridge] Returning cached userInfo from requestUserInfoFromiOS"), Promise.resolve(l)) : t ? (console.log("⏳ [Bridge] Pending userInfo request exists, waiting..."), new Promise((r) => {
118
133
  const o = t.resolve;
119
134
  t.resolve = (s) => {
@@ -126,7 +141,7 @@ function O(n = !1, e = g) {
126
141
  hasWebkit: !!window.webkit,
127
142
  hasMessageHandlers: !!window.webkit?.messageHandlers,
128
143
  hasAippyListener: !!o
129
- }), o || (console.log("⏳ [Bridge] aippyListener not found, waiting for injection..."), o = await b(1500)), !o) {
144
+ }), o || (console.log("⏳ [Bridge] aippyListener not found, waiting for injection..."), o = await E(1500)), !o) {
130
145
  console.warn("⚠️ [Bridge] No aippyListener found after waiting, returning null"), r(null);
131
146
  return;
132
147
  }
@@ -136,9 +151,9 @@ function O(n = !1, e = g) {
136
151
  }, e);
137
152
  t = { resolve: (i) => {
138
153
  console.log("✅ [Bridge] pendingUserInfoRequest.resolve called with:", i), clearTimeout(s), t = null, r(i);
139
- } }, console.log("📱 [Bridge] pendingUserInfoRequest set"), U.receiveChannel.once("user.info", (i) => {
154
+ } }, console.log("📱 [Bridge] pendingUserInfoRequest set"), v.receiveChannel.once("user.info", (i) => {
140
155
  console.log("📩 [Bridge] Received user.info via receiveChannel:", i), clearTimeout(s);
141
- const d = m(i);
156
+ const d = y(i);
142
157
  console.log("📩 [Bridge] Processed userInfo:", d), t ? t.resolve(d) : console.warn("⚠️ [Bridge] No pendingUserInfoRequest when receiveChannel fired");
143
158
  }), console.log("📱 [Bridge] receiveChannel.once registered for user.info");
144
159
  try {
@@ -153,16 +168,16 @@ function O(n = !1, e = g) {
153
168
  })();
154
169
  });
155
170
  }
156
- function C(n = g) {
171
+ function A(n = g) {
157
172
  return new Promise((e) => {
158
- if (!p()) {
173
+ if (!f()) {
159
174
  e(null);
160
175
  return;
161
176
  }
162
177
  const r = setTimeout(() => {
163
178
  window.removeEventListener("message", o), e(null);
164
179
  }, n), o = (s) => {
165
- s.data?.type === "user-info-response" && (clearTimeout(r), window.removeEventListener("message", o), e(m(s.data)));
180
+ s.data?.type === "user-info-response" && (clearTimeout(r), window.removeEventListener("message", o), e(y(s.data)));
166
181
  };
167
182
  window.addEventListener("message", o);
168
183
  try {
@@ -172,66 +187,73 @@ function C(n = g) {
172
187
  }
173
188
  });
174
189
  }
175
- async function P() {
176
- const { envCheck: n } = v("userCredentials");
190
+ async function L() {
191
+ const { envCheck: n } = k("userCredentials");
177
192
  switch (n.type) {
178
193
  case "new_app": {
179
- const e = await A(k);
180
- if (!e?.token) throw B("Token unavailable in app", I.PERMISSION_DENIED);
194
+ const e = await j(b);
195
+ if (!e?.token) throw h("Token unavailable in app", U.PERMISSION_DENIED);
181
196
  return e.token;
182
197
  }
183
198
  case "iframe": {
184
- const e = await S(T);
199
+ const e = await M(T);
185
200
  if (e?.token) return e.token;
186
- throw L("Sign in to continue.Open this project in the app.", "signin"), B("Token unavailable: User needs to login", I.PERMISSION_DENIED);
201
+ throw C("Sign in to continue.Open this project in the app.", "signin"), h("Token unavailable: User needs to login", U.PERMISSION_DENIED);
187
202
  }
188
203
  default:
189
204
  return "";
190
205
  }
191
206
  }
192
- async function _(n = !1) {
207
+ async function H(n = !1) {
193
208
  if (console.log("🔍 [Bridge] getUserInfoAsync called, forceRefresh:", n), console.log("🔍 [Bridge] Current cache state:", { userInfoReceived: u, cachedUserInfo: l }), u && l && !n)
194
209
  return console.log("✅ [Bridge] Returning cached userInfo"), l;
195
- const { envCheck: e } = v("userInfo");
210
+ const { envCheck: e } = k("userInfo");
196
211
  switch (console.log("🔍 [Bridge] Environment check result:", e), e.type) {
197
212
  case "new_app":
198
- return console.log("📱 [Bridge] Detected new_app environment"), await O(n, k);
213
+ return console.log("📱 [Bridge] Detected new_app environment"), await N(n, b);
199
214
  case "iframe":
200
- return console.log("🖼️ [Bridge] Detected iframe environment"), await C(T);
215
+ return console.log("🖼️ [Bridge] Detected iframe environment"), await A(T);
201
216
  default:
202
217
  return console.log("🌐 [Bridge] Detected web environment, returning cached:", l), l;
203
218
  }
204
219
  }
205
- async function H(n = g) {
206
- return p() ? await C(n) : null;
220
+ async function x(n = g) {
221
+ return f() ? await A(n) : null;
207
222
  }
208
- function y(n) {
209
- const e = w(n);
223
+ function w(n) {
224
+ const e = I(n);
210
225
  e && a && (a.resolve(e), a = null);
211
226
  }
212
- function h(n) {
227
+ function m(n) {
213
228
  console.log("📩 [Bridge] window.processUserInfo called with:", n), console.log("📩 [Bridge] pendingUserInfoRequest exists:", !!t);
214
- const e = m(n);
229
+ const e = y(n);
215
230
  t ? (console.log("✅ [Bridge] Resolving pendingUserInfoRequest with:", e), t.resolve(e), t = null) : (console.warn("⚠️ [Bridge] No pendingUserInfoRequest when processUserInfo called!"), console.warn("⚠️ [Bridge] UserInfo was processed but no one is waiting for it"));
216
231
  }
217
- function j() {
232
+ function z() {
218
233
  if (typeof window > "u") {
219
234
  console.log("🔧 [Bridge] initUserBridge: window is undefined, skipping");
220
235
  return;
221
236
  }
222
- console.log("🔧 [Bridge] initUserBridge: Initializing..."), console.log("🔧 [Bridge] UserAgent:", navigator.userAgent), window.processUserCredentials = y, window.processUserInfo = h, console.log("🔧 [Bridge] Exposed window.processUserCredentials and window.processUserInfo"), window.addEventListener("message", (n) => {
223
- n.data?.type === "user-credentials" && (console.log("📩 [Bridge] Received postMessage user-credentials:", n.data), y(n.data)), n.data?.type === "user-info" && (console.log("📩 [Bridge] Received postMessage user-info:", n.data), h(n.data));
237
+ console.log("🔧 [Bridge] initUserBridge: Initializing..."), console.log("🔧 [Bridge] UserAgent:", navigator.userAgent), window.processUserCredentials = w, window.processUserInfo = m, console.log("🔧 [Bridge] Exposed window.processUserCredentials and window.processUserInfo"), window.addEventListener("message", (n) => {
238
+ n.data?.type === "user-credentials" && (console.log("📩 [Bridge] Received postMessage user-credentials:", n.data), w(n.data)), n.data?.type === "user-info" && (console.log("📩 [Bridge] Received postMessage user-info:", n.data), m(n.data));
224
239
  }), console.log("🔧 [Bridge] Added message event listener"), console.log("✅ [Bridge] initUserBridge complete");
225
240
  }
226
- j();
227
- P().catch((n) => {
241
+ z();
242
+ L().catch((n) => {
228
243
  console.warn("[UserSDK] Auth check on load:", n.message);
229
244
  });
245
+ const X = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
246
+ __proto__: null,
247
+ getAuthTokenAsync: L,
248
+ getUserInfoAsync: H,
249
+ getUserInfoFromParent: x,
250
+ isInIframe: f,
251
+ processUserCredentials: w,
252
+ processUserInfo: m
253
+ }, Symbol.toStringTag, { value: "Module" }));
230
254
  export {
231
- P as getAuthTokenAsync,
232
- _ as getUserInfoAsync,
233
- H as getUserInfoFromParent,
234
- p as isInIframe,
235
- y as processUserCredentials,
236
- h as processUserInfo
255
+ K as _,
256
+ X as b,
257
+ L as g,
258
+ q as r
237
259
  };
@@ -1,6 +1,6 @@
1
1
  import "react";
2
- import { getAuthTokenAsync as a } from "./bridge-CqV1iP30.js";
3
- const r = "0.3.2", i = {
2
+ import { g as a } from "./bridge-CtB9L5kL.js";
3
+ const r = "0.4.0", i = {
4
4
  version: r
5
5
  }, o = i.version, c = "@aippy/runtime";
6
6
  function w() {
@@ -11,24 +11,24 @@ function w() {
11
11
  };
12
12
  }
13
13
  function p(n) {
14
- const { token: t, existingHeaders: e } = n, s = new Headers(e);
15
- return s.set("Aippy-Runtime-Authorization", `Bearer ${t}`), s.set("Aippy-Runtime-SDK-Version", o), typeof navigator < "u" && navigator.userAgent && s.set("Aippy-Runtime-UA", navigator.userAgent), s;
14
+ const { token: s, existingHeaders: e } = n, t = new Headers(e);
15
+ return t.set("Aippy-Runtime-Authorization", `Bearer ${s}`), t.set("Aippy-Runtime-SDK-Version", o), typeof navigator < "u" && navigator.userAgent && t.set("Aippy-Runtime-UA", navigator.userAgent), t;
16
16
  }
17
17
  async function m(n) {
18
- const t = await a();
19
- return p({ token: t, existingHeaders: n });
18
+ const s = await a();
19
+ return p({ token: s, existingHeaders: n });
20
20
  }
21
21
  function u(n) {
22
22
  if (!(typeof window > "u"))
23
23
  try {
24
- const t = window.webkit?.messageHandlers?.aippyListener;
25
- if (t)
24
+ const s = window.webkit?.messageHandlers?.aippyListener;
25
+ if (s)
26
26
  try {
27
27
  const e = {
28
28
  command: "container.message",
29
29
  parameters: n
30
30
  };
31
- t.postMessage(e), console.log("📤 [Container Message] Sent message to iOS app container:", n);
31
+ s.postMessage(e), console.log("📤 [Container Message] Sent message to iOS app container:", n);
32
32
  } catch (e) {
33
33
  console.warn("❌ [Container Message] Failed to send message to iOS app:", e);
34
34
  }
@@ -42,8 +42,8 @@ function u(n) {
42
42
  } catch (e) {
43
43
  console.warn("❌ [Container Message] Failed to send message to parent window:", e);
44
44
  }
45
- } catch (t) {
46
- console.warn("⚠️ [Container Message] Failed to send message:", t);
45
+ } catch (s) {
46
+ console.warn("⚠️ [Container Message] Failed to send message:", s);
47
47
  }
48
48
  }
49
49
  export {