@aippy/runtime 0.3.2 → 0.3.3-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.js +15 -13
- package/dist/ai/shared/config.d.ts +8 -0
- package/dist/audio/AudioSilenceDetector.d.ts +0 -3
- package/dist/audio/index.d.ts +5 -2
- package/dist/audio/index.js +6 -5
- package/dist/audio/patchAudioContext.d.ts +8 -30
- package/dist/audio/types.d.ts +2 -13
- package/dist/audio/useAudioContext.d.ts +11 -41
- package/dist/audio/useSound.d.ts +69 -0
- package/dist/{bridge-CqV1iP30.js → bridge-CtB9L5kL.js} +81 -59
- package/dist/{container-message-CueWm_GX.js → container-message-Cs_jZALO.js} +11 -11
- package/dist/core/config.d.ts +6 -1
- package/dist/core/env.d.ts +17 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +25 -22
- package/dist/{helper-DHOIfdTx.js → helper-ByQNcvgR.js} +70 -67
- package/dist/{hooks-CDo6slfY.js → hooks-D5lkty5r.js} +1 -1
- package/dist/index/index.js +93 -88
- package/dist/useSound-jHl7rkaq.js +380 -0
- package/dist/user/index.js +2 -2
- package/package.json +1 -1
- package/dist/useAudioContext-D9F3x80Y.js +0 -219
package/dist/ai/index.d.ts
CHANGED
|
@@ -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
|
|
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-ByQNcvgR.js";
|
|
2
2
|
import "react";
|
|
3
|
-
import "../bridge-
|
|
3
|
+
import "../bridge-CtB9L5kL.js";
|
|
4
4
|
export {
|
|
5
5
|
i as DEFAULT_BASE_URL,
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
U as
|
|
18
|
-
t as
|
|
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>;
|
package/dist/audio/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Audio module for iOS-compatible Web Audio API
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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';
|
package/dist/audio/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { c as i,
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
*
|
|
10
|
-
*
|
|
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
|
-
*
|
|
16
|
-
*
|
|
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;
|
package/dist/audio/types.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
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
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
10
|
-
Object.assign(
|
|
24
|
+
function P(n) {
|
|
25
|
+
Object.assign(B, n);
|
|
11
26
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
27
|
+
function D(n) {
|
|
28
|
+
B.authToken = n;
|
|
14
29
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
30
|
+
function O(n) {
|
|
31
|
+
B.currentUserId = n;
|
|
17
32
|
}
|
|
18
|
-
const
|
|
33
|
+
const b = 3e3, T = 50, g = 500, c = { uid: "", token: "" };
|
|
19
34
|
let l = null, u = !1, a = null, t = null;
|
|
20
|
-
function
|
|
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
|
|
45
|
+
return O(i.uid), D(o), s && P({ apiBaseUrl: s }), i;
|
|
31
46
|
}
|
|
32
|
-
function
|
|
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
|
|
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
|
|
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"),
|
|
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 =
|
|
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
|
|
99
|
+
function M(n = g) {
|
|
85
100
|
return new Promise((e) => {
|
|
86
|
-
if (!
|
|
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(
|
|
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
|
|
104
|
-
async function
|
|
105
|
-
if (!
|
|
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
|
|
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
|
|
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"),
|
|
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 =
|
|
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
|
|
171
|
+
function A(n = g) {
|
|
157
172
|
return new Promise((e) => {
|
|
158
|
-
if (!
|
|
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(
|
|
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
|
|
176
|
-
const { envCheck: n } =
|
|
190
|
+
async function L() {
|
|
191
|
+
const { envCheck: n } = k("userCredentials");
|
|
177
192
|
switch (n.type) {
|
|
178
193
|
case "new_app": {
|
|
179
|
-
const e = await
|
|
180
|
-
if (!e?.token) throw
|
|
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
|
|
199
|
+
const e = await M(T);
|
|
185
200
|
if (e?.token) return e.token;
|
|
186
|
-
throw
|
|
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
|
|
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 } =
|
|
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
|
|
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
|
|
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
|
|
206
|
-
return
|
|
220
|
+
async function x(n = g) {
|
|
221
|
+
return f() ? await A(n) : null;
|
|
207
222
|
}
|
|
208
|
-
function
|
|
209
|
-
const e =
|
|
223
|
+
function w(n) {
|
|
224
|
+
const e = I(n);
|
|
210
225
|
e && a && (a.resolve(e), a = null);
|
|
211
226
|
}
|
|
212
|
-
function
|
|
227
|
+
function m(n) {
|
|
213
228
|
console.log("📩 [Bridge] window.processUserInfo called with:", n), console.log("📩 [Bridge] pendingUserInfoRequest exists:", !!t);
|
|
214
|
-
const e =
|
|
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
|
|
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 =
|
|
223
|
-
n.data?.type === "user-credentials" && (console.log("📩 [Bridge] Received postMessage user-credentials:", 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
|
-
|
|
227
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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 {
|
|
3
|
-
const r = "0.3.
|
|
2
|
+
import { g as a } from "./bridge-CtB9L5kL.js";
|
|
3
|
+
const r = "0.3.3-dev.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:
|
|
15
|
-
return
|
|
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
|
|
19
|
-
return p({ token:
|
|
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
|
|
25
|
-
if (
|
|
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
|
-
|
|
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 (
|
|
46
|
-
console.warn("⚠️ [Container Message] Failed to send message:",
|
|
45
|
+
} catch (s) {
|
|
46
|
+
console.warn("⚠️ [Container Message] Failed to send message:", s);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
export {
|