@getecho-ai/react-native-sdk 1.0.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/README.md +350 -0
- package/dist/bridge/CallbackManager.d.ts +46 -0
- package/dist/bridge/CallbackManager.js +117 -0
- package/dist/bridge/WebViewBridge.d.ts +67 -0
- package/dist/bridge/WebViewBridge.js +151 -0
- package/dist/components/EchoChat.d.ts +20 -0
- package/dist/components/EchoChat.js +45 -0
- package/dist/components/EchoChatButton.d.ts +15 -0
- package/dist/components/EchoChatButton.js +65 -0
- package/dist/components/EchoChatModal.d.ts +13 -0
- package/dist/components/EchoChatModal.js +473 -0
- package/dist/components/EchoProvider.d.ts +30 -0
- package/dist/components/EchoProvider.js +240 -0
- package/dist/hooks/useSimpleCart.d.ts +76 -0
- package/dist/hooks/useSimpleCart.js +134 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +77 -0
- package/dist/types/index.d.ts +156 -0
- package/dist/types/index.js +5 -0
- package/dist/utils/resolveApiUrl.d.ts +42 -0
- package/dist/utils/resolveApiUrl.js +82 -0
- package/package.json +54 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Echo React Native SDK - Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
export type Product = {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
priceAmount?: number;
|
|
9
|
+
currency?: string;
|
|
10
|
+
primaryImage?: string;
|
|
11
|
+
images?: string[];
|
|
12
|
+
url?: string;
|
|
13
|
+
category?: string;
|
|
14
|
+
brand?: string;
|
|
15
|
+
inStock?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type CartItem = {
|
|
18
|
+
productId: string;
|
|
19
|
+
quantity: number;
|
|
20
|
+
product?: Product;
|
|
21
|
+
};
|
|
22
|
+
export type Cart = {
|
|
23
|
+
items: CartItem[];
|
|
24
|
+
total?: number;
|
|
25
|
+
currency?: string;
|
|
26
|
+
itemCount: number;
|
|
27
|
+
};
|
|
28
|
+
export type AddToCartResult = {
|
|
29
|
+
success: boolean;
|
|
30
|
+
cartItemCount?: number;
|
|
31
|
+
error?: string;
|
|
32
|
+
};
|
|
33
|
+
export type GetCartResult = {
|
|
34
|
+
success: boolean;
|
|
35
|
+
cart?: Cart;
|
|
36
|
+
error?: string;
|
|
37
|
+
};
|
|
38
|
+
export type EchoCallbacks = {
|
|
39
|
+
/**
|
|
40
|
+
* Called when AI wants to add a product to cart
|
|
41
|
+
* Partner must implement their own add to cart logic
|
|
42
|
+
*/
|
|
43
|
+
onAddToCart: (product: Product, quantity?: number) => Promise<AddToCartResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Called when AI wants to know current cart contents
|
|
46
|
+
* Partner must return their current cart
|
|
47
|
+
*/
|
|
48
|
+
onGetCart: () => Promise<GetCartResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Optional: Called when user taps on a product
|
|
51
|
+
* Partner can navigate to their product detail screen
|
|
52
|
+
*/
|
|
53
|
+
onNavigateToProduct?: (productId: string) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Optional: Called when widget sends a generic URL navigation request
|
|
56
|
+
* Useful when productId is not available
|
|
57
|
+
*/
|
|
58
|
+
onNavigateToUrl?: (url: string) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Optional: Called when AI wants to redirect to checkout
|
|
61
|
+
* Partner can navigate to their checkout screen
|
|
62
|
+
*/
|
|
63
|
+
onNavigateToCheckout?: () => void;
|
|
64
|
+
/**
|
|
65
|
+
* Optional: Called when auth is required for an action
|
|
66
|
+
* Partner can show login screen
|
|
67
|
+
*/
|
|
68
|
+
onAuthRequired?: () => void;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* UI customization settings for the chat interface
|
|
72
|
+
* Allows platform-specific or user-specific UI control
|
|
73
|
+
*/
|
|
74
|
+
export type UISettings = {
|
|
75
|
+
/**
|
|
76
|
+
* Control sidebar (conversation history) visibility
|
|
77
|
+
* - undefined: Default behavior (false in RN, expand button controlled in web)
|
|
78
|
+
* - true: Force sidebar visible (if conversationHistoryEnabled is also true)
|
|
79
|
+
* - false: Force sidebar hidden (default for React Native)
|
|
80
|
+
*/
|
|
81
|
+
showSidebar?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Control expand/collapse button visibility in header
|
|
84
|
+
* - undefined: Use partner setting (expandButtonEnabled)
|
|
85
|
+
* - true: Force show expand button
|
|
86
|
+
* - false: Force hide expand button
|
|
87
|
+
*/
|
|
88
|
+
showExpandButton?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Control cart button visibility in header
|
|
91
|
+
* - undefined: Use partner setting (cartEnabled)
|
|
92
|
+
* - true: Force show cart button (requires getCart callback)
|
|
93
|
+
* - false: Force hide cart button
|
|
94
|
+
*/
|
|
95
|
+
showCartButton?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Control chat history/new chat button visibility in header
|
|
98
|
+
* - undefined: Use partner setting (conversationHistoryEnabled)
|
|
99
|
+
* - true: Force show history/new chat button
|
|
100
|
+
* - false: Force hide history/new chat button
|
|
101
|
+
*/
|
|
102
|
+
showHistoryButton?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Control close/minimize button visibility in header
|
|
105
|
+
* - undefined: Always show (default)
|
|
106
|
+
* - true: Show close button
|
|
107
|
+
* - false: Hide close button
|
|
108
|
+
*/
|
|
109
|
+
showCloseButton?: boolean;
|
|
110
|
+
};
|
|
111
|
+
export type EchoConfig = {
|
|
112
|
+
apiKey: string;
|
|
113
|
+
apiUrl?: string;
|
|
114
|
+
callbacks: EchoCallbacks;
|
|
115
|
+
userId?: string;
|
|
116
|
+
userEmail?: string;
|
|
117
|
+
userIdentifier?: string;
|
|
118
|
+
theme?: EchoTheme;
|
|
119
|
+
uiSettings?: UISettings;
|
|
120
|
+
};
|
|
121
|
+
export type EchoTheme = {
|
|
122
|
+
primaryColor?: string;
|
|
123
|
+
backgroundColor?: string;
|
|
124
|
+
textColor?: string;
|
|
125
|
+
fontFamily?: string;
|
|
126
|
+
};
|
|
127
|
+
export type ChatMessage = {
|
|
128
|
+
id: string;
|
|
129
|
+
role: "user" | "assistant";
|
|
130
|
+
content: string;
|
|
131
|
+
timestamp: Date;
|
|
132
|
+
products?: Product[];
|
|
133
|
+
actions?: MessageAction[];
|
|
134
|
+
};
|
|
135
|
+
export type MessageAction = {
|
|
136
|
+
type: "addToCart" | "viewProduct" | "checkout";
|
|
137
|
+
label: string;
|
|
138
|
+
productId?: string;
|
|
139
|
+
};
|
|
140
|
+
export type BridgeMessage = {
|
|
141
|
+
type: BridgeMessageType;
|
|
142
|
+
callbackId?: string;
|
|
143
|
+
payload?: any;
|
|
144
|
+
};
|
|
145
|
+
export type BridgeMessageType = "init" | "action" | "actionComplete" | "navigate" | "close" | "expand" | "collapse" | "requestWidgetState" | "chatId" | "userId" | "echo:agent-state" | "userMessage" | "setUser" | "chatReady" | "echo:request_actions" | "addToCart" | "getCart" | "redirectToCheckout";
|
|
146
|
+
export type ActionType = "addToCart" | "getCart" | "redirectToCheckout" | "getOrders" | "trackOrderState";
|
|
147
|
+
export type PendingCallback = {
|
|
148
|
+
resolve: (result: CallbackResult) => void;
|
|
149
|
+
createdAt: number;
|
|
150
|
+
timeoutId?: ReturnType<typeof setTimeout>;
|
|
151
|
+
};
|
|
152
|
+
export type CallbackResult = {
|
|
153
|
+
success: boolean;
|
|
154
|
+
data?: any;
|
|
155
|
+
error?: string;
|
|
156
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* resolveApiUrl - Platform-aware URL resolution
|
|
3
|
+
*
|
|
4
|
+
* Handles the localhost -> 10.0.2.2 conversion for Android emulator.
|
|
5
|
+
* On iOS simulator, localhost works directly.
|
|
6
|
+
* On real devices, you must use your machine's local IP or production URL.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // Development
|
|
11
|
+
* resolveApiUrl('http://localhost:3000')
|
|
12
|
+
* // Returns 'http://10.0.2.2:3000' on Android emulator
|
|
13
|
+
* // Returns 'http://localhost:3000' on iOS simulator
|
|
14
|
+
*
|
|
15
|
+
* // Production (no change)
|
|
16
|
+
* resolveApiUrl('https://api.get-echo.ai')
|
|
17
|
+
* // Returns 'https://api.get-echo.ai' on all platforms
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Resolve API URL based on platform
|
|
22
|
+
*
|
|
23
|
+
* @param configUrl - URL from config (optional)
|
|
24
|
+
* @returns Resolved URL appropriate for the current platform
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveApiUrl(configUrl?: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Check if running on Android emulator
|
|
29
|
+
* Note: This is a simple heuristic, not 100% reliable
|
|
30
|
+
*/
|
|
31
|
+
export declare function isAndroidEmulator(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Check if running on iOS simulator
|
|
34
|
+
* Note: This is a simple heuristic, not 100% reliable
|
|
35
|
+
*/
|
|
36
|
+
export declare function isIOSSimulator(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get appropriate localhost URL for current platform
|
|
39
|
+
* Useful for development setup instructions
|
|
40
|
+
*/
|
|
41
|
+
export declare function getLocalhostUrl(port?: number): string;
|
|
42
|
+
export default resolveApiUrl;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* resolveApiUrl - Platform-aware URL resolution
|
|
4
|
+
*
|
|
5
|
+
* Handles the localhost -> 10.0.2.2 conversion for Android emulator.
|
|
6
|
+
* On iOS simulator, localhost works directly.
|
|
7
|
+
* On real devices, you must use your machine's local IP or production URL.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Development
|
|
12
|
+
* resolveApiUrl('http://localhost:3000')
|
|
13
|
+
* // Returns 'http://10.0.2.2:3000' on Android emulator
|
|
14
|
+
* // Returns 'http://localhost:3000' on iOS simulator
|
|
15
|
+
*
|
|
16
|
+
* // Production (no change)
|
|
17
|
+
* resolveApiUrl('https://api.get-echo.ai')
|
|
18
|
+
* // Returns 'https://api.get-echo.ai' on all platforms
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.resolveApiUrl = resolveApiUrl;
|
|
23
|
+
exports.isAndroidEmulator = isAndroidEmulator;
|
|
24
|
+
exports.isIOSSimulator = isIOSSimulator;
|
|
25
|
+
exports.getLocalhostUrl = getLocalhostUrl;
|
|
26
|
+
const react_native_1 = require("react-native");
|
|
27
|
+
const DEFAULT_API_URL = "https://get-echo.ai";
|
|
28
|
+
/**
|
|
29
|
+
* Resolve API URL based on platform
|
|
30
|
+
*
|
|
31
|
+
* @param configUrl - URL from config (optional)
|
|
32
|
+
* @returns Resolved URL appropriate for the current platform
|
|
33
|
+
*/
|
|
34
|
+
function resolveApiUrl(configUrl) {
|
|
35
|
+
// If no URL provided, use production default
|
|
36
|
+
if (!configUrl) {
|
|
37
|
+
return DEFAULT_API_URL;
|
|
38
|
+
}
|
|
39
|
+
// On Android emulator, replace localhost with 10.0.2.2
|
|
40
|
+
if (react_native_1.Platform.OS === "android" && isLocalhost(configUrl)) {
|
|
41
|
+
return configUrl.replace(/localhost/gi, "10.0.2.2");
|
|
42
|
+
}
|
|
43
|
+
return configUrl;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if URL points to localhost
|
|
47
|
+
*/
|
|
48
|
+
function isLocalhost(url) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = new URL(url);
|
|
51
|
+
return parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// If URL parsing fails, do simple string check
|
|
55
|
+
return url.includes("localhost") || url.includes("127.0.0.1");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if running on Android emulator
|
|
60
|
+
* Note: This is a simple heuristic, not 100% reliable
|
|
61
|
+
*/
|
|
62
|
+
function isAndroidEmulator() {
|
|
63
|
+
return react_native_1.Platform.OS === "android";
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if running on iOS simulator
|
|
67
|
+
* Note: This is a simple heuristic, not 100% reliable
|
|
68
|
+
*/
|
|
69
|
+
function isIOSSimulator() {
|
|
70
|
+
return react_native_1.Platform.OS === "ios";
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get appropriate localhost URL for current platform
|
|
74
|
+
* Useful for development setup instructions
|
|
75
|
+
*/
|
|
76
|
+
function getLocalhostUrl(port = 3000) {
|
|
77
|
+
if (react_native_1.Platform.OS === "android") {
|
|
78
|
+
return `http://10.0.2.2:${port}`;
|
|
79
|
+
}
|
|
80
|
+
return `http://localhost:${port}`;
|
|
81
|
+
}
|
|
82
|
+
exports.default = resolveApiUrl;
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@getecho-ai/react-native-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Echo AI Chat SDK for React Native - AI-powered e-commerce assistant",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"watch": "tsc --watch",
|
|
13
|
+
"prepare": "npm run build",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/untetheredlabs/echo.git",
|
|
19
|
+
"directory": "mobile/sdk"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/untetheredlabs/echo/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/untetheredlabs/echo/tree/main/mobile/sdk#readme",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18.0.0",
|
|
30
|
+
"react-native": ">=0.70.0",
|
|
31
|
+
"react-native-webview": ">=13.0.0",
|
|
32
|
+
"@react-native-async-storage/async-storage": ">=1.19.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@react-native-async-storage/async-storage": "^1.19.0",
|
|
36
|
+
"@types/react": "^18.2.0",
|
|
37
|
+
"@types/react-native": "^0.72.0",
|
|
38
|
+
"react-native-webview": "^13.0.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"echo",
|
|
43
|
+
"ai",
|
|
44
|
+
"chat",
|
|
45
|
+
"chatbot",
|
|
46
|
+
"e-commerce",
|
|
47
|
+
"react-native",
|
|
48
|
+
"expo",
|
|
49
|
+
"shopping",
|
|
50
|
+
"assistant"
|
|
51
|
+
],
|
|
52
|
+
"author": "Echo AI <hello@get-echo.ai>",
|
|
53
|
+
"license": "MIT"
|
|
54
|
+
}
|