@parlr/react-native 0.1.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/LICENSE +21 -0
- package/README.md +918 -0
- package/lib/commonjs/components/AttachmentPicker.js +292 -0
- package/lib/commonjs/components/AttachmentPicker.js.map +1 -0
- package/lib/commonjs/components/AttachmentPreview.js +200 -0
- package/lib/commonjs/components/AttachmentPreview.js.map +1 -0
- package/lib/commonjs/components/ChatBubble.js +391 -0
- package/lib/commonjs/components/ChatBubble.js.map +1 -0
- package/lib/commonjs/components/EmptyState.js +115 -0
- package/lib/commonjs/components/EmptyState.js.map +1 -0
- package/lib/commonjs/components/ParlrChat.js +745 -0
- package/lib/commonjs/components/ParlrChat.js.map +1 -0
- package/lib/commonjs/components/ParlrConversationList.js +509 -0
- package/lib/commonjs/components/ParlrConversationList.js.map +1 -0
- package/lib/commonjs/components/PreChatForm.js +263 -0
- package/lib/commonjs/components/PreChatForm.js.map +1 -0
- package/lib/commonjs/components/RichMessage.js +284 -0
- package/lib/commonjs/components/RichMessage.js.map +1 -0
- package/lib/commonjs/components/SatisfactionSurvey.js +292 -0
- package/lib/commonjs/components/SatisfactionSurvey.js.map +1 -0
- package/lib/commonjs/components/TypingIndicator.js +86 -0
- package/lib/commonjs/components/TypingIndicator.js.map +1 -0
- package/lib/commonjs/core/api.js +310 -0
- package/lib/commonjs/core/api.js.map +1 -0
- package/lib/commonjs/core/config.js +40 -0
- package/lib/commonjs/core/config.js.map +1 -0
- package/lib/commonjs/core/errors.js +73 -0
- package/lib/commonjs/core/errors.js.map +1 -0
- package/lib/commonjs/core/offlineQueue.js +89 -0
- package/lib/commonjs/core/offlineQueue.js.map +1 -0
- package/lib/commonjs/core/pushNotifications.js +21 -0
- package/lib/commonjs/core/pushNotifications.js.map +1 -0
- package/lib/commonjs/core/session.js +130 -0
- package/lib/commonjs/core/session.js.map +1 -0
- package/lib/commonjs/core/theme.js +110 -0
- package/lib/commonjs/core/theme.js.map +1 -0
- package/lib/commonjs/core/types.js +6 -0
- package/lib/commonjs/core/types.js.map +1 -0
- package/lib/commonjs/core/websocket.js +245 -0
- package/lib/commonjs/core/websocket.js.map +1 -0
- package/lib/commonjs/hooks/useChat.js +462 -0
- package/lib/commonjs/hooks/useChat.js.map +1 -0
- package/lib/commonjs/hooks/useParlr.js +44 -0
- package/lib/commonjs/hooks/useParlr.js.map +1 -0
- package/lib/commonjs/index.js +185 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/provider/ParlrContext.js +38 -0
- package/lib/commonjs/provider/ParlrContext.js.map +1 -0
- package/lib/commonjs/provider/ParlrProvider.js +256 -0
- package/lib/commonjs/provider/ParlrProvider.js.map +1 -0
- package/lib/module/components/AttachmentPicker.js +287 -0
- package/lib/module/components/AttachmentPicker.js.map +1 -0
- package/lib/module/components/AttachmentPreview.js +195 -0
- package/lib/module/components/AttachmentPreview.js.map +1 -0
- package/lib/module/components/ChatBubble.js +386 -0
- package/lib/module/components/ChatBubble.js.map +1 -0
- package/lib/module/components/EmptyState.js +110 -0
- package/lib/module/components/EmptyState.js.map +1 -0
- package/lib/module/components/ParlrChat.js +740 -0
- package/lib/module/components/ParlrChat.js.map +1 -0
- package/lib/module/components/ParlrConversationList.js +504 -0
- package/lib/module/components/ParlrConversationList.js.map +1 -0
- package/lib/module/components/PreChatForm.js +258 -0
- package/lib/module/components/PreChatForm.js.map +1 -0
- package/lib/module/components/RichMessage.js +280 -0
- package/lib/module/components/RichMessage.js.map +1 -0
- package/lib/module/components/SatisfactionSurvey.js +287 -0
- package/lib/module/components/SatisfactionSurvey.js.map +1 -0
- package/lib/module/components/TypingIndicator.js +81 -0
- package/lib/module/components/TypingIndicator.js.map +1 -0
- package/lib/module/core/api.js +305 -0
- package/lib/module/core/api.js.map +1 -0
- package/lib/module/core/config.js +36 -0
- package/lib/module/core/config.js.map +1 -0
- package/lib/module/core/errors.js +64 -0
- package/lib/module/core/errors.js.map +1 -0
- package/lib/module/core/offlineQueue.js +82 -0
- package/lib/module/core/offlineQueue.js.map +1 -0
- package/lib/module/core/pushNotifications.js +16 -0
- package/lib/module/core/pushNotifications.js.map +1 -0
- package/lib/module/core/session.js +122 -0
- package/lib/module/core/session.js.map +1 -0
- package/lib/module/core/theme.js +105 -0
- package/lib/module/core/theme.js.map +1 -0
- package/lib/module/core/types.js +4 -0
- package/lib/module/core/types.js.map +1 -0
- package/lib/module/core/websocket.js +241 -0
- package/lib/module/core/websocket.js.map +1 -0
- package/lib/module/hooks/useChat.js +458 -0
- package/lib/module/hooks/useChat.js.map +1 -0
- package/lib/module/hooks/useParlr.js +40 -0
- package/lib/module/hooks/useParlr.js.map +1 -0
- package/lib/module/index.js +58 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/provider/ParlrContext.js +35 -0
- package/lib/module/provider/ParlrContext.js.map +1 -0
- package/lib/module/provider/ParlrProvider.js +251 -0
- package/lib/module/provider/ParlrProvider.js.map +1 -0
- package/lib/typescript/commonjs/components/AttachmentPicker.d.ts +23 -0
- package/lib/typescript/commonjs/components/AttachmentPicker.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/AttachmentPreview.d.ts +16 -0
- package/lib/typescript/commonjs/components/AttachmentPreview.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/ChatBubble.d.ts +14 -0
- package/lib/typescript/commonjs/components/ChatBubble.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/EmptyState.d.ts +10 -0
- package/lib/typescript/commonjs/components/EmptyState.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/ParlrChat.d.ts +34 -0
- package/lib/typescript/commonjs/components/ParlrChat.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/ParlrConversationList.d.ts +17 -0
- package/lib/typescript/commonjs/components/ParlrConversationList.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/PreChatForm.d.ts +20 -0
- package/lib/typescript/commonjs/components/PreChatForm.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/RichMessage.d.ts +41 -0
- package/lib/typescript/commonjs/components/RichMessage.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/SatisfactionSurvey.d.ts +17 -0
- package/lib/typescript/commonjs/components/SatisfactionSurvey.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/TypingIndicator.d.ts +7 -0
- package/lib/typescript/commonjs/components/TypingIndicator.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/api.d.ts +37 -0
- package/lib/typescript/commonjs/core/api.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/config.d.ts +9 -0
- package/lib/typescript/commonjs/core/config.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/errors.d.ts +35 -0
- package/lib/typescript/commonjs/core/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/offlineQueue.d.ts +16 -0
- package/lib/typescript/commonjs/core/offlineQueue.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/pushNotifications.d.ts +6 -0
- package/lib/typescript/commonjs/core/pushNotifications.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/session.d.ts +15 -0
- package/lib/typescript/commonjs/core/session.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/theme.d.ts +43 -0
- package/lib/typescript/commonjs/core/theme.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/types.d.ts +185 -0
- package/lib/typescript/commonjs/core/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/websocket.d.ts +17 -0
- package/lib/typescript/commonjs/core/websocket.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/useChat.d.ts +35 -0
- package/lib/typescript/commonjs/hooks/useChat.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/useParlr.d.ts +11 -0
- package/lib/typescript/commonjs/hooks/useParlr.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +30 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/provider/ParlrContext.d.ts +13 -0
- package/lib/typescript/commonjs/provider/ParlrContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/provider/ParlrProvider.d.ts +5 -0
- package/lib/typescript/commonjs/provider/ParlrProvider.d.ts.map +1 -0
- package/lib/typescript/module/components/AttachmentPicker.d.ts +23 -0
- package/lib/typescript/module/components/AttachmentPicker.d.ts.map +1 -0
- package/lib/typescript/module/components/AttachmentPreview.d.ts +16 -0
- package/lib/typescript/module/components/AttachmentPreview.d.ts.map +1 -0
- package/lib/typescript/module/components/ChatBubble.d.ts +14 -0
- package/lib/typescript/module/components/ChatBubble.d.ts.map +1 -0
- package/lib/typescript/module/components/EmptyState.d.ts +10 -0
- package/lib/typescript/module/components/EmptyState.d.ts.map +1 -0
- package/lib/typescript/module/components/ParlrChat.d.ts +34 -0
- package/lib/typescript/module/components/ParlrChat.d.ts.map +1 -0
- package/lib/typescript/module/components/ParlrConversationList.d.ts +17 -0
- package/lib/typescript/module/components/ParlrConversationList.d.ts.map +1 -0
- package/lib/typescript/module/components/PreChatForm.d.ts +20 -0
- package/lib/typescript/module/components/PreChatForm.d.ts.map +1 -0
- package/lib/typescript/module/components/RichMessage.d.ts +41 -0
- package/lib/typescript/module/components/RichMessage.d.ts.map +1 -0
- package/lib/typescript/module/components/SatisfactionSurvey.d.ts +17 -0
- package/lib/typescript/module/components/SatisfactionSurvey.d.ts.map +1 -0
- package/lib/typescript/module/components/TypingIndicator.d.ts +7 -0
- package/lib/typescript/module/components/TypingIndicator.d.ts.map +1 -0
- package/lib/typescript/module/core/api.d.ts +37 -0
- package/lib/typescript/module/core/api.d.ts.map +1 -0
- package/lib/typescript/module/core/config.d.ts +9 -0
- package/lib/typescript/module/core/config.d.ts.map +1 -0
- package/lib/typescript/module/core/errors.d.ts +35 -0
- package/lib/typescript/module/core/errors.d.ts.map +1 -0
- package/lib/typescript/module/core/offlineQueue.d.ts +16 -0
- package/lib/typescript/module/core/offlineQueue.d.ts.map +1 -0
- package/lib/typescript/module/core/pushNotifications.d.ts +6 -0
- package/lib/typescript/module/core/pushNotifications.d.ts.map +1 -0
- package/lib/typescript/module/core/session.d.ts +15 -0
- package/lib/typescript/module/core/session.d.ts.map +1 -0
- package/lib/typescript/module/core/theme.d.ts +43 -0
- package/lib/typescript/module/core/theme.d.ts.map +1 -0
- package/lib/typescript/module/core/types.d.ts +185 -0
- package/lib/typescript/module/core/types.d.ts.map +1 -0
- package/lib/typescript/module/core/websocket.d.ts +17 -0
- package/lib/typescript/module/core/websocket.d.ts.map +1 -0
- package/lib/typescript/module/hooks/useChat.d.ts +35 -0
- package/lib/typescript/module/hooks/useChat.d.ts.map +1 -0
- package/lib/typescript/module/hooks/useParlr.d.ts +11 -0
- package/lib/typescript/module/hooks/useParlr.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +30 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/provider/ParlrContext.d.ts +13 -0
- package/lib/typescript/module/provider/ParlrContext.d.ts.map +1 -0
- package/lib/typescript/module/provider/ParlrProvider.d.ts +5 -0
- package/lib/typescript/module/provider/ParlrProvider.d.ts.map +1 -0
- package/package.json +120 -0
- package/src/components/AttachmentPicker.tsx +310 -0
- package/src/components/AttachmentPreview.tsx +209 -0
- package/src/components/ChatBubble.tsx +424 -0
- package/src/components/EmptyState.tsx +118 -0
- package/src/components/ParlrChat.tsx +863 -0
- package/src/components/ParlrConversationList.tsx +559 -0
- package/src/components/PreChatForm.tsx +313 -0
- package/src/components/RichMessage.tsx +353 -0
- package/src/components/SatisfactionSurvey.tsx +333 -0
- package/src/components/TypingIndicator.tsx +89 -0
- package/src/core/api.ts +406 -0
- package/src/core/config.ts +39 -0
- package/src/core/errors.ts +68 -0
- package/src/core/offlineQueue.ts +94 -0
- package/src/core/pushNotifications.ts +22 -0
- package/src/core/session.ts +156 -0
- package/src/core/theme.ts +133 -0
- package/src/core/types.ts +237 -0
- package/src/core/websocket.ts +270 -0
- package/src/hooks/useChat.ts +534 -0
- package/src/hooks/useParlr.ts +43 -0
- package/src/index.ts +98 -0
- package/src/provider/ParlrContext.ts +40 -0
- package/src/provider/ParlrProvider.tsx +338 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parlr React Native SDK - REST API Client
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
//
|
|
7
|
+
// Wraps all widget-facing REST endpoints with automatic retry, exponential
|
|
8
|
+
// backoff, session-token injection, and response validation.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
import axios from 'axios';
|
|
12
|
+
import { ParlrAuthError, ParlrNetworkError, ParlrValidationError } from "./errors.js";
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Retry configuration
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
const MAX_RETRIES = 3;
|
|
18
|
+
const BASE_DELAY_MS = 500;
|
|
19
|
+
const RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
|
|
20
|
+
function delay(ms) {
|
|
21
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
22
|
+
}
|
|
23
|
+
function isRetryable(error) {
|
|
24
|
+
if (!error.response) return true; // network error
|
|
25
|
+
return RETRYABLE_STATUS.has(error.response.status);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Response validators
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
function validateSession(data) {
|
|
33
|
+
if (!data || typeof data !== 'object') {
|
|
34
|
+
throw new ParlrValidationError('Invalid session response: expected an object');
|
|
35
|
+
}
|
|
36
|
+
const d = data;
|
|
37
|
+
// Accept both "token" and "sessionToken" from the server.
|
|
38
|
+
const token = typeof d.token === 'string' ? d.token : d.sessionToken;
|
|
39
|
+
if (typeof token !== 'string' || typeof d.contactId !== 'string' || typeof d.workspaceId !== 'string' || typeof d.expiresAt !== 'string') {
|
|
40
|
+
throw new ParlrValidationError('Invalid session response: missing required fields (token, contactId, workspaceId, expiresAt)');
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
token,
|
|
44
|
+
contactId: d.contactId,
|
|
45
|
+
workspaceId: d.workspaceId,
|
|
46
|
+
expiresAt: d.expiresAt
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function validateMessage(data) {
|
|
50
|
+
if (!data || typeof data !== 'object') {
|
|
51
|
+
throw new ParlrValidationError('Invalid message response: expected an object');
|
|
52
|
+
}
|
|
53
|
+
const d = data;
|
|
54
|
+
if (typeof d.id !== 'string' || typeof d.conversationId !== 'string' || typeof d.senderType !== 'string') {
|
|
55
|
+
throw new ParlrValidationError('Invalid message response: missing required fields (id, conversationId, senderType)');
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
id: d.id,
|
|
59
|
+
conversationId: d.conversationId,
|
|
60
|
+
content: typeof d.content === 'string' ? d.content : '',
|
|
61
|
+
contentType: typeof d.contentType === 'string' ? d.contentType : 'text',
|
|
62
|
+
senderType: d.senderType,
|
|
63
|
+
senderName: typeof d.senderName === 'string' ? d.senderName : undefined,
|
|
64
|
+
senderAvatarUrl: typeof d.senderAvatarUrl === 'string' ? d.senderAvatarUrl : undefined,
|
|
65
|
+
createdAt: typeof d.createdAt === 'string' ? d.createdAt : new Date().toISOString(),
|
|
66
|
+
clientId: typeof d.clientId === 'string' ? d.clientId : undefined,
|
|
67
|
+
attachments: Array.isArray(d.attachments) ? d.attachments : [],
|
|
68
|
+
status: 'sent'
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function validateConversation(data) {
|
|
72
|
+
if (!data || typeof data !== 'object') {
|
|
73
|
+
throw new ParlrValidationError('Invalid conversation response: expected an object');
|
|
74
|
+
}
|
|
75
|
+
const d = data;
|
|
76
|
+
if (typeof d.id !== 'string' || typeof d.status !== 'string') {
|
|
77
|
+
throw new ParlrValidationError('Invalid conversation response: missing required fields (id, status)');
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
id: d.id,
|
|
81
|
+
status: d.status,
|
|
82
|
+
subject: typeof d.subject === 'string' ? d.subject : null,
|
|
83
|
+
lastMessageAt: typeof d.lastMessageAt === 'string' ? d.lastMessageAt : null,
|
|
84
|
+
unreadCount: typeof d.unreadCount === 'number' ? d.unreadCount : 0,
|
|
85
|
+
assignee: d.assignee && typeof d.assignee === 'object' ? d.assignee : null
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Error mapper
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
function mapAxiosError(error) {
|
|
94
|
+
if (!error.response) {
|
|
95
|
+
return new ParlrNetworkError(error.message || 'Network request failed', undefined, {
|
|
96
|
+
cause: error
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const status = error.response.status;
|
|
100
|
+
if (status === 401 || status === 403) {
|
|
101
|
+
return new ParlrAuthError(`Authentication failed (HTTP ${status})`, {
|
|
102
|
+
cause: error
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return new ParlrNetworkError(`HTTP ${status}: ${error.message}`, status, {
|
|
106
|
+
cause: error
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// Client factory
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Create a configured API client bound to a resolved config and an optional
|
|
116
|
+
* session token accessor (so the token can be refreshed externally).
|
|
117
|
+
*/
|
|
118
|
+
export function createApiClient(config, getToken) {
|
|
119
|
+
const http = axios.create({
|
|
120
|
+
baseURL: config.apiBaseUrl,
|
|
121
|
+
timeout: 15_000,
|
|
122
|
+
headers: {
|
|
123
|
+
'Content-Type': 'application/json',
|
|
124
|
+
Accept: 'application/json',
|
|
125
|
+
'X-Workspace-Id': config.workspaceId
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// --- Inject session token and identity token on every request --------------
|
|
130
|
+
http.interceptors.request.use(req => {
|
|
131
|
+
const token = getToken();
|
|
132
|
+
if (token) {
|
|
133
|
+
req.headers.set('X-Session-Token', token);
|
|
134
|
+
}
|
|
135
|
+
if (config.identityToken) {
|
|
136
|
+
req.headers.set('X-Identity-Token', config.identityToken);
|
|
137
|
+
}
|
|
138
|
+
return req;
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// --- Retry interceptor -----------------------------------------------------
|
|
142
|
+
http.interceptors.response.use(undefined, async error => {
|
|
143
|
+
const requestConfig = error.config;
|
|
144
|
+
if (!requestConfig) throw mapAxiosError(error);
|
|
145
|
+
requestConfig._retryCount = requestConfig._retryCount ?? 0;
|
|
146
|
+
if (requestConfig._retryCount >= MAX_RETRIES || !isRetryable(error)) {
|
|
147
|
+
throw mapAxiosError(error);
|
|
148
|
+
}
|
|
149
|
+
requestConfig._retryCount += 1;
|
|
150
|
+
const jitter = Math.random() * 200;
|
|
151
|
+
const backoff = BASE_DELAY_MS * Math.pow(2, requestConfig._retryCount - 1) + jitter;
|
|
152
|
+
if (config.debug) {
|
|
153
|
+
console.log(`[@parlr/react-native] Retry #${requestConfig._retryCount} after ${Math.round(backoff)}ms`);
|
|
154
|
+
}
|
|
155
|
+
await delay(backoff);
|
|
156
|
+
return http.request(requestConfig);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// --- Public API methods ----------------------------------------------------
|
|
160
|
+
return {
|
|
161
|
+
async createSession() {
|
|
162
|
+
const {
|
|
163
|
+
data
|
|
164
|
+
} = await http.post('/sessions', {
|
|
165
|
+
workspaceId: config.workspaceId
|
|
166
|
+
});
|
|
167
|
+
return validateSession(data);
|
|
168
|
+
},
|
|
169
|
+
async identify(user) {
|
|
170
|
+
await http.post('/identify', user);
|
|
171
|
+
},
|
|
172
|
+
async listConversations(page = 1) {
|
|
173
|
+
const {
|
|
174
|
+
data
|
|
175
|
+
} = await http.get('/conversations', {
|
|
176
|
+
params: {
|
|
177
|
+
page
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
// Handle both paginated ({ data: [...], meta: {...} }) and plain array responses.
|
|
181
|
+
if (Array.isArray(data)) {
|
|
182
|
+
const convs = data.map(validateConversation);
|
|
183
|
+
return {
|
|
184
|
+
data: convs,
|
|
185
|
+
meta: {
|
|
186
|
+
total: convs.length,
|
|
187
|
+
page: 1,
|
|
188
|
+
perPage: convs.length,
|
|
189
|
+
hasMore: false
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return data;
|
|
194
|
+
},
|
|
195
|
+
async createConversation(initialMessage) {
|
|
196
|
+
const {
|
|
197
|
+
data
|
|
198
|
+
} = await http.post('/conversations', {
|
|
199
|
+
...(initialMessage ? {
|
|
200
|
+
message: initialMessage
|
|
201
|
+
} : {})
|
|
202
|
+
});
|
|
203
|
+
return validateConversation(data);
|
|
204
|
+
},
|
|
205
|
+
async getMessages(conversationId, page = 1) {
|
|
206
|
+
const {
|
|
207
|
+
data
|
|
208
|
+
} = await http.get(`/conversations/${encodeURIComponent(conversationId)}/messages`, {
|
|
209
|
+
params: {
|
|
210
|
+
page
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
// Handle both paginated ({ data: [...], meta: {...} }) and plain array responses.
|
|
214
|
+
if (Array.isArray(data)) {
|
|
215
|
+
const messages = data.map(validateMessage);
|
|
216
|
+
return {
|
|
217
|
+
data: messages,
|
|
218
|
+
meta: {
|
|
219
|
+
total: messages.length,
|
|
220
|
+
page: 1,
|
|
221
|
+
perPage: messages.length,
|
|
222
|
+
hasMore: false
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return data;
|
|
227
|
+
},
|
|
228
|
+
async sendMessage(conversationId, content, clientId) {
|
|
229
|
+
const {
|
|
230
|
+
data
|
|
231
|
+
} = await http.post(`/conversations/${encodeURIComponent(conversationId)}/messages`, {
|
|
232
|
+
content,
|
|
233
|
+
clientId
|
|
234
|
+
});
|
|
235
|
+
return validateMessage(data);
|
|
236
|
+
},
|
|
237
|
+
async sendTypingIndicator(conversationId, isTyping) {
|
|
238
|
+
await http.post(`/conversations/${encodeURIComponent(conversationId)}/typing`, {
|
|
239
|
+
isTyping
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
async closeConversation(conversationId) {
|
|
243
|
+
const {
|
|
244
|
+
data
|
|
245
|
+
} = await http.post(`/conversations/${encodeURIComponent(conversationId)}/close`);
|
|
246
|
+
return validateConversation(data);
|
|
247
|
+
},
|
|
248
|
+
async reopenConversation(conversationId) {
|
|
249
|
+
const {
|
|
250
|
+
data
|
|
251
|
+
} = await http.post(`/conversations/${encodeURIComponent(conversationId)}/reopen`);
|
|
252
|
+
return validateConversation(data);
|
|
253
|
+
},
|
|
254
|
+
async uploadAttachment(conversationId, formData) {
|
|
255
|
+
const {
|
|
256
|
+
data
|
|
257
|
+
} = await http.post(`/conversations/${encodeURIComponent(conversationId)}/attachments`, formData, {
|
|
258
|
+
headers: {
|
|
259
|
+
'Content-Type': 'multipart/form-data'
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
return data;
|
|
263
|
+
},
|
|
264
|
+
async subscribePush(token, platform) {
|
|
265
|
+
await http.post('/push/subscribe', {
|
|
266
|
+
token,
|
|
267
|
+
platform
|
|
268
|
+
});
|
|
269
|
+
},
|
|
270
|
+
async unsubscribePush(token) {
|
|
271
|
+
await http.post('/push/unsubscribe', {
|
|
272
|
+
token
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
async submitRating(conversationId, score, comment) {
|
|
276
|
+
await http.post(`/conversations/${encodeURIComponent(conversationId)}/rating`, {
|
|
277
|
+
score,
|
|
278
|
+
comment
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
async searchMessages(conversationId, query) {
|
|
282
|
+
const {
|
|
283
|
+
data
|
|
284
|
+
} = await http.get(`/conversations/${encodeURIComponent(conversationId)}/messages/search`, {
|
|
285
|
+
params: {
|
|
286
|
+
q: query
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
if (Array.isArray(data)) {
|
|
290
|
+
const messages = data.map(validateMessage);
|
|
291
|
+
return {
|
|
292
|
+
data: messages,
|
|
293
|
+
meta: {
|
|
294
|
+
total: messages.length,
|
|
295
|
+
page: 1,
|
|
296
|
+
perPage: messages.length,
|
|
297
|
+
hasMore: false
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
return data;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["axios","ParlrAuthError","ParlrNetworkError","ParlrValidationError","MAX_RETRIES","BASE_DELAY_MS","RETRYABLE_STATUS","Set","delay","ms","Promise","resolve","setTimeout","isRetryable","error","response","has","status","validateSession","data","d","token","sessionToken","contactId","workspaceId","expiresAt","validateMessage","id","conversationId","senderType","content","contentType","senderName","undefined","senderAvatarUrl","createdAt","Date","toISOString","clientId","attachments","Array","isArray","validateConversation","subject","lastMessageAt","unreadCount","assignee","mapAxiosError","message","cause","createApiClient","config","getToken","http","create","baseURL","apiBaseUrl","timeout","headers","Accept","interceptors","request","use","req","set","identityToken","requestConfig","_retryCount","jitter","Math","random","backoff","pow","debug","console","log","round","createSession","post","identify","user","listConversations","page","get","params","convs","map","meta","total","length","perPage","hasMore","createConversation","initialMessage","getMessages","encodeURIComponent","messages","sendMessage","sendTypingIndicator","isTyping","closeConversation","reopenConversation","uploadAttachment","formData","subscribePush","platform","unsubscribePush","submitRating","score","comment","searchMessages","query","q"],"sourceRoot":"../../../src","sources":["core/api.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parlr React Native SDK - Configuration
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
const DEFAULTS = {
|
|
8
|
+
apiBaseUrl: 'https://api.parlr.chat/api/v1/widget',
|
|
9
|
+
// WebSocket disabled by default — the Java backend uses STOMP protocol,
|
|
10
|
+
// not the custom JSON protocol this SDK expects. Enable when the Rust
|
|
11
|
+
// Gateway is deployed: wsUrl: 'wss://ws.parlr.chat/ws'
|
|
12
|
+
wsUrl: '',
|
|
13
|
+
locale: 'fr',
|
|
14
|
+
debug: false
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a partial user-supplied config into a fully-qualified config with
|
|
19
|
+
* all defaults applied.
|
|
20
|
+
*
|
|
21
|
+
* @throws {Error} if `workspaceId` is missing or empty.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveConfig(partial) {
|
|
24
|
+
if (!partial.workspaceId || partial.workspaceId.trim().length === 0) {
|
|
25
|
+
throw new Error('[@parlr/react-native] workspaceId is required. ' + 'Pass it as a prop to <ParlrProvider workspaceId="ws_xxx" />.');
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
workspaceId: partial.workspaceId.trim(),
|
|
29
|
+
apiBaseUrl: (partial.apiBaseUrl ?? DEFAULTS.apiBaseUrl).replace(/\/+$/, ''),
|
|
30
|
+
wsUrl: (partial.wsUrl ?? DEFAULTS.wsUrl).replace(/\/+$/, ''),
|
|
31
|
+
locale: partial.locale ?? DEFAULTS.locale,
|
|
32
|
+
debug: partial.debug ?? DEFAULTS.debug,
|
|
33
|
+
identityToken: partial.identityToken
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DEFAULTS","apiBaseUrl","wsUrl","locale","debug","resolveConfig","partial","workspaceId","trim","length","Error","replace","identityToken"],"sourceRoot":"../../../src","sources":["core/config.ts"],"mappings":";;AAAA;AACA;AACA;;AAIA,MAAMA,QAAQ,GAAG;EACfC,UAAU,EAAE,sCAAsC;EAClD;EACA;EACA;EACAC,KAAK,EAAE,EAAE;EACTC,MAAM,EAAE,IAAI;EACZC,KAAK,EAAE;AACT,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,aAAaA,CAACC,OAAoB,EAAkB;EAClE,IAAI,CAACA,OAAO,CAACC,WAAW,IAAID,OAAO,CAACC,WAAW,CAACC,IAAI,CAAC,CAAC,CAACC,MAAM,KAAK,CAAC,EAAE;IACnE,MAAM,IAAIC,KAAK,CACb,iDAAiD,GAC/C,8DACJ,CAAC;EACH;EAEA,OAAO;IACLH,WAAW,EAAED,OAAO,CAACC,WAAW,CAACC,IAAI,CAAC,CAAC;IACvCP,UAAU,EAAE,CAACK,OAAO,CAACL,UAAU,IAAID,QAAQ,CAACC,UAAU,EAAEU,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAC3ET,KAAK,EAAE,CAACI,OAAO,CAACJ,KAAK,IAAIF,QAAQ,CAACE,KAAK,EAAES,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAC5DR,MAAM,EAAEG,OAAO,CAACH,MAAM,IAAIH,QAAQ,CAACG,MAAM;IACzCC,KAAK,EAAEE,OAAO,CAACF,KAAK,IAAIJ,QAAQ,CAACI,KAAK;IACtCQ,aAAa,EAAEN,OAAO,CAACM;EACzB,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parlr React Native SDK - Error Hierarchy
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
//
|
|
7
|
+
// Typed error classes for structured error handling throughout the SDK.
|
|
8
|
+
// Consumers can use `instanceof` checks to differentiate error types.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base error class for all Parlr SDK errors.
|
|
13
|
+
*/
|
|
14
|
+
export class ParlrError extends Error {
|
|
15
|
+
constructor(message, options) {
|
|
16
|
+
super(message, options);
|
|
17
|
+
this.name = 'ParlrError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Network-level error (timeout, DNS failure, no internet).
|
|
23
|
+
*/
|
|
24
|
+
export class ParlrNetworkError extends ParlrError {
|
|
25
|
+
constructor(message, statusCode, options) {
|
|
26
|
+
super(message, options);
|
|
27
|
+
this.name = 'ParlrNetworkError';
|
|
28
|
+
this.statusCode = statusCode;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Authentication / session error (expired token, invalid session).
|
|
34
|
+
*/
|
|
35
|
+
export class ParlrAuthError extends ParlrError {
|
|
36
|
+
constructor(message, options) {
|
|
37
|
+
super(message, options);
|
|
38
|
+
this.name = 'ParlrAuthError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validation error (invalid payload from API or WebSocket).
|
|
44
|
+
*/
|
|
45
|
+
export class ParlrValidationError extends ParlrError {
|
|
46
|
+
constructor(message, field, options) {
|
|
47
|
+
super(message, options);
|
|
48
|
+
this.name = 'ParlrValidationError';
|
|
49
|
+
this.field = field;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* WebSocket connection error (failed to connect, unexpected close).
|
|
55
|
+
*/
|
|
56
|
+
export class ParlrConnectionError extends ParlrError {
|
|
57
|
+
constructor(message, code, reason, options) {
|
|
58
|
+
super(message, options);
|
|
59
|
+
this.name = 'ParlrConnectionError';
|
|
60
|
+
this.code = code;
|
|
61
|
+
this.reason = reason;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ParlrError","Error","constructor","message","options","name","ParlrNetworkError","statusCode","ParlrAuthError","ParlrValidationError","field","ParlrConnectionError","code","reason"],"sourceRoot":"../../../src","sources":["core/errors.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO,MAAMA,UAAU,SAASC,KAAK,CAAC;EACpCC,WAAWA,CAACC,OAAe,EAAEC,OAAsB,EAAE;IACnD,KAAK,CAACD,OAAO,EAAEC,OAAO,CAAC;IACvB,IAAI,CAACC,IAAI,GAAG,YAAY;EAC1B;AACF;;AAEA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,SAASN,UAAU,CAAC;EAGhDE,WAAWA,CAACC,OAAe,EAAEI,UAAmB,EAAEH,OAAsB,EAAE;IACxE,KAAK,CAACD,OAAO,EAAEC,OAAO,CAAC;IACvB,IAAI,CAACC,IAAI,GAAG,mBAAmB;IAC/B,IAAI,CAACE,UAAU,GAAGA,UAAU;EAC9B;AACF;;AAEA;AACA;AACA;AACA,OAAO,MAAMC,cAAc,SAASR,UAAU,CAAC;EAC7CE,WAAWA,CAACC,OAAe,EAAEC,OAAsB,EAAE;IACnD,KAAK,CAACD,OAAO,EAAEC,OAAO,CAAC;IACvB,IAAI,CAACC,IAAI,GAAG,gBAAgB;EAC9B;AACF;;AAEA;AACA;AACA;AACA,OAAO,MAAMI,oBAAoB,SAAST,UAAU,CAAC;EAGnDE,WAAWA,CAACC,OAAe,EAAEO,KAAc,EAAEN,OAAsB,EAAE;IACnE,KAAK,CAACD,OAAO,EAAEC,OAAO,CAAC;IACvB,IAAI,CAACC,IAAI,GAAG,sBAAsB;IAClC,IAAI,CAACK,KAAK,GAAGA,KAAK;EACpB;AACF;;AAEA;AACA;AACA;AACA,OAAO,MAAMC,oBAAoB,SAASX,UAAU,CAAC;EAInDE,WAAWA,CAACC,OAAe,EAAES,IAAa,EAAEC,MAAe,EAAET,OAAsB,EAAE;IACnF,KAAK,CAACD,OAAO,EAAEC,OAAO,CAAC;IACvB,IAAI,CAACC,IAAI,GAAG,sBAAsB;IAClC,IAAI,CAACO,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACC,MAAM,GAAGA,MAAM;EACtB;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parlr React Native SDK - Offline Message Queue
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
//
|
|
7
|
+
// AsyncStorage-based queue for messages sent while offline. Messages are
|
|
8
|
+
// persisted and flushed automatically when connectivity is restored.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const QUEUE_KEY = '@parlr/offline_queue';
|
|
12
|
+
|
|
13
|
+
// In-memory queue that mirrors persistent storage.
|
|
14
|
+
let memoryQueue = [];
|
|
15
|
+
|
|
16
|
+
// Lazy AsyncStorage accessor — returns null when unavailable.
|
|
17
|
+
function getAsyncStorage() {
|
|
18
|
+
try {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
20
|
+
return require('@react-native-async-storage/async-storage').default;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function persist() {
|
|
26
|
+
try {
|
|
27
|
+
const storage = getAsyncStorage();
|
|
28
|
+
if (storage) {
|
|
29
|
+
await storage.setItem(QUEUE_KEY, JSON.stringify(memoryQueue));
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
// Persistence is best-effort — the in-memory queue is always available.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function hydrate() {
|
|
36
|
+
try {
|
|
37
|
+
const storage = getAsyncStorage();
|
|
38
|
+
if (storage) {
|
|
39
|
+
const raw = await storage.getItem(QUEUE_KEY);
|
|
40
|
+
if (raw) {
|
|
41
|
+
memoryQueue = JSON.parse(raw);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// Start with an empty queue if hydration fails.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Hydrate on module load (non-blocking).
|
|
50
|
+
hydrate();
|
|
51
|
+
|
|
52
|
+
/** Enqueue a message for later delivery. */
|
|
53
|
+
export async function queueMessage(msg) {
|
|
54
|
+
memoryQueue.push(msg);
|
|
55
|
+
await persist();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Return all currently queued messages. */
|
|
59
|
+
export async function getQueuedMessages() {
|
|
60
|
+
return [...memoryQueue];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Remove a single message from the queue by clientId. */
|
|
64
|
+
export async function removeFromQueue(clientId) {
|
|
65
|
+
memoryQueue = memoryQueue.filter(m => m.clientId !== clientId);
|
|
66
|
+
await persist();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Attempt to send all queued messages via the API, removing successful ones. */
|
|
70
|
+
export async function flushQueue(api) {
|
|
71
|
+
const snapshot = [...memoryQueue];
|
|
72
|
+
for (const msg of snapshot) {
|
|
73
|
+
try {
|
|
74
|
+
await api.sendMessage(msg.conversationId, msg.content, msg.clientId);
|
|
75
|
+
await removeFromQueue(msg.clientId);
|
|
76
|
+
} catch {
|
|
77
|
+
// Leave failed messages in the queue for the next flush attempt.
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=offlineQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["QUEUE_KEY","memoryQueue","getAsyncStorage","require","default","persist","storage","setItem","JSON","stringify","hydrate","raw","getItem","parse","queueMessage","msg","push","getQueuedMessages","removeFromQueue","clientId","filter","m","flushQueue","api","snapshot","sendMessage","conversationId","content"],"sourceRoot":"../../../src","sources":["core/offlineQueue.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAWA,MAAMA,SAAS,GAAG,sBAAsB;;AAExC;AACA,IAAIC,WAA4B,GAAG,EAAE;;AAErC;AACA,SAASC,eAAeA,CAAA,EAGf;EACP,IAAI;IACF;IACA,OAAOC,OAAO,CAAC,2CAA2C,CAAC,CAACC,OAAO;EACrE,CAAC,CAAC,MAAM;IACN,OAAO,IAAI;EACb;AACF;AAEA,eAAeC,OAAOA,CAAA,EAAkB;EACtC,IAAI;IACF,MAAMC,OAAO,GAAGJ,eAAe,CAAC,CAAC;IACjC,IAAII,OAAO,EAAE;MACX,MAAMA,OAAO,CAACC,OAAO,CAACP,SAAS,EAAEQ,IAAI,CAACC,SAAS,CAACR,WAAW,CAAC,CAAC;IAC/D;EACF,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;AAEA,eAAeS,OAAOA,CAAA,EAAkB;EACtC,IAAI;IACF,MAAMJ,OAAO,GAAGJ,eAAe,CAAC,CAAC;IACjC,IAAII,OAAO,EAAE;MACX,MAAMK,GAAG,GAAG,MAAML,OAAO,CAACM,OAAO,CAACZ,SAAS,CAAC;MAC5C,IAAIW,GAAG,EAAE;QACPV,WAAW,GAAGO,IAAI,CAACK,KAAK,CAACF,GAAG,CAAoB;MAClD;IACF;EACF,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;;AAEA;AACAD,OAAO,CAAC,CAAC;;AAET;AACA,OAAO,eAAeI,YAAYA,CAACC,GAAkB,EAAiB;EACpEd,WAAW,CAACe,IAAI,CAACD,GAAG,CAAC;EACrB,MAAMV,OAAO,CAAC,CAAC;AACjB;;AAEA;AACA,OAAO,eAAeY,iBAAiBA,CAAA,EAA6B;EAClE,OAAO,CAAC,GAAGhB,WAAW,CAAC;AACzB;;AAEA;AACA,OAAO,eAAeiB,eAAeA,CAACC,QAAgB,EAAiB;EACrElB,WAAW,GAAGA,WAAW,CAACmB,MAAM,CAAEC,CAAC,IAAKA,CAAC,CAACF,QAAQ,KAAKA,QAAQ,CAAC;EAChE,MAAMd,OAAO,CAAC,CAAC;AACjB;;AAEA;AACA,OAAO,eAAeiB,UAAUA,CAACC,GAAmB,EAAiB;EACnE,MAAMC,QAAQ,GAAG,CAAC,GAAGvB,WAAW,CAAC;EAEjC,KAAK,MAAMc,GAAG,IAAIS,QAAQ,EAAE;IAC1B,IAAI;MACF,MAAMD,GAAG,CAACE,WAAW,CAACV,GAAG,CAACW,cAAc,EAAEX,GAAG,CAACY,OAAO,EAAEZ,GAAG,CAACI,QAAQ,CAAC;MACpE,MAAMD,eAAe,CAACH,GAAG,CAACI,QAAQ,CAAC;IACrC,CAAC,CAAC,MAAM;MACN;MACA;IACF;EACF;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parlr React Native SDK - Push Notification Helpers
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
/** Register a device push token with the Parlr backend. */
|
|
8
|
+
export async function registerPushToken(api, token, platform) {
|
|
9
|
+
await api.subscribePush(token, platform);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Unregister a previously registered push token. */
|
|
13
|
+
export async function unregisterPushToken(api, token) {
|
|
14
|
+
await api.unsubscribePush(token);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=pushNotifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["registerPushToken","api","token","platform","subscribePush","unregisterPushToken","unsubscribePush"],"sourceRoot":"../../../src","sources":["core/pushNotifications.ts"],"mappings":";;AAAA;AACA;AACA;;AAIA;AACA,OAAO,eAAeA,iBAAiBA,CACrCC,GAAmB,EACnBC,KAAa,EACbC,QAA2B,EACZ;EACf,MAAMF,GAAG,CAACG,aAAa,CAACF,KAAK,EAAEC,QAAQ,CAAC;AAC1C;;AAEA;AACA,OAAO,eAAeE,mBAAmBA,CACvCJ,GAAmB,EACnBC,KAAa,EACE;EACf,MAAMD,GAAG,CAACK,eAAe,CAACJ,KAAK,CAAC;AAClC","ignoreList":[]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parlr React Native SDK - Session Manager
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
//
|
|
7
|
+
// Manages the widget session lifecycle. Uses expo-secure-store when available,
|
|
8
|
+
// falls back to in-memory storage otherwise.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const STORE_KEY_PREFIX = 'parlr_session_';
|
|
12
|
+
function storeKey(workspaceId) {
|
|
13
|
+
return `${STORE_KEY_PREFIX}${workspaceId}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Storage abstraction with fallback
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
/** In-memory fallback when expo-secure-store is not available. */
|
|
21
|
+
const memoryStore = new Map();
|
|
22
|
+
const memoryAdapter = {
|
|
23
|
+
async getItem(key) {
|
|
24
|
+
return memoryStore.get(key) ?? null;
|
|
25
|
+
},
|
|
26
|
+
async setItem(key, value) {
|
|
27
|
+
memoryStore.set(key, value);
|
|
28
|
+
},
|
|
29
|
+
async deleteItem(key) {
|
|
30
|
+
memoryStore.delete(key);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
let _adapter = null;
|
|
34
|
+
function getAdapter() {
|
|
35
|
+
if (_adapter) return _adapter;
|
|
36
|
+
try {
|
|
37
|
+
// Dynamic import to keep expo-secure-store truly optional.
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
+
const SecureStore = require('expo-secure-store');
|
|
40
|
+
if (SecureStore?.setItemAsync) {
|
|
41
|
+
_adapter = {
|
|
42
|
+
getItem: key => SecureStore.getItemAsync(key),
|
|
43
|
+
setItem: (key, value) => SecureStore.setItemAsync(key, value),
|
|
44
|
+
deleteItem: key => SecureStore.deleteItemAsync(key)
|
|
45
|
+
};
|
|
46
|
+
return _adapter;
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
// expo-secure-store not available — use memory fallback.
|
|
50
|
+
}
|
|
51
|
+
_adapter = memoryAdapter;
|
|
52
|
+
return _adapter;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Public API
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
/** Persist session to secure storage (or memory fallback). */
|
|
60
|
+
export async function saveSession(workspaceId, session) {
|
|
61
|
+
const adapter = getAdapter();
|
|
62
|
+
await adapter.setItem(storeKey(workspaceId), JSON.stringify(session));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Retrieve persisted session, or null if none exists. */
|
|
66
|
+
export async function loadSession(workspaceId) {
|
|
67
|
+
const adapter = getAdapter();
|
|
68
|
+
try {
|
|
69
|
+
const raw = await adapter.getItem(storeKey(workspaceId));
|
|
70
|
+
if (!raw) return null;
|
|
71
|
+
const session = JSON.parse(raw);
|
|
72
|
+
|
|
73
|
+
// Validate required fields.
|
|
74
|
+
if (typeof session.token !== 'string' || typeof session.contactId !== 'string' || typeof session.expiresAt !== 'string') {
|
|
75
|
+
console.warn('[@parlr/react-native] Stored session has invalid shape, clearing.');
|
|
76
|
+
await clearSession(workspaceId);
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return session;
|
|
80
|
+
} catch (err) {
|
|
81
|
+
// Corrupted data — clear and return null.
|
|
82
|
+
console.warn('[@parlr/react-native] Failed to load session, clearing:', err);
|
|
83
|
+
await clearSession(workspaceId);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns true when the session token has not yet expired.
|
|
90
|
+
* Adds a 60-second safety margin to avoid edge-case failures.
|
|
91
|
+
*/
|
|
92
|
+
export function isSessionValid(session) {
|
|
93
|
+
try {
|
|
94
|
+
const expiresAt = new Date(session.expiresAt).getTime();
|
|
95
|
+
if (isNaN(expiresAt)) {
|
|
96
|
+
console.warn('[@parlr/react-native] Invalid expiresAt date:', session.expiresAt);
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const margin = 60_000; // 60 s
|
|
100
|
+
return Date.now() < expiresAt - margin;
|
|
101
|
+
} catch (err) {
|
|
102
|
+
console.warn('[@parlr/react-native] Error checking session validity:', err);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Delete persisted session for a workspace. */
|
|
108
|
+
export async function clearSession(workspaceId) {
|
|
109
|
+
const adapter = getAdapter();
|
|
110
|
+
try {
|
|
111
|
+
await adapter.deleteItem(storeKey(workspaceId));
|
|
112
|
+
} catch {
|
|
113
|
+
// Best-effort — nothing to do if deletion fails.
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Reset the storage adapter (for testing). */
|
|
118
|
+
export function _resetAdapter() {
|
|
119
|
+
_adapter = null;
|
|
120
|
+
memoryStore.clear();
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=session.js.map
|