@robylon/react-native-sdk 2.1.1-staging.3 → 2.1.3-staging.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/.claude/settings.local.json +25 -0
- package/README.md +332 -5
- package/lib/commonjs/Chatbotsdk.js +3 -3
- package/lib/commonjs/Chatbotsdk.js.map +1 -1
- package/lib/commonjs/hooks/useChatbotEvents.js +1 -1
- package/lib/commonjs/hooks/useChatbotEvents.js.map +1 -1
- package/lib/commonjs/utils/session.js +2 -0
- package/lib/commonjs/utils/session.js.map +1 -0
- package/lib/commonjs/versions/version.staging.js +1 -1
- package/lib/module/Chatbotsdk.js +3 -3
- package/lib/module/Chatbotsdk.js.map +1 -1
- package/lib/module/hooks/useChatbotEvents.js +1 -1
- package/lib/module/hooks/useChatbotEvents.js.map +1 -1
- package/lib/module/utils/session.js +2 -0
- package/lib/module/utils/session.js.map +1 -0
- package/lib/module/versions/version.staging.js +1 -1
- package/lib/typescript/Chatbotsdk.d.ts +4 -0
- package/lib/typescript/Chatbotsdk.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatbotEvents.d.ts.map +1 -1
- package/lib/typescript/utils/session.d.ts +21 -0
- package/lib/typescript/utils/session.d.ts.map +1 -0
- package/lib/typescript/versions/version.staging.d.ts +1 -1
- package/package.json +2 -2
- package/robylon-react-native-sdk-2.1.1-staging.3.tgz +0 -0
- package/scripts/setup-git-hooks.js +22 -10
- package/src/Chatbotsdk.tsx +96 -2
- package/src/hooks/useChatbotEvents.ts +29 -5
- package/src/utils/session.ts +26 -0
- package/src/versions/version.staging.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatbotEvents.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatbotEvents.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAGzB,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,GAAG,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,eAAO,MAAM,gBAAgB,mEAM1B,cAAc;
|
|
1
|
+
{"version":3,"file":"useChatbotEvents.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatbotEvents.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAGzB,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,GAAG,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,eAAO,MAAM,gBAAgB,mEAM1B,cAAc;sBA0EN,gBAAgB,SAAS,GAAG;iCAxDtB,aAAa,mBACR,OAAO,MAAM,EAAE,GAAG,CAAC;CAyExC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session id pass-through between the chatbot web app and the SDK client.
|
|
3
|
+
*
|
|
4
|
+
* The session id travels on its own message type so that it never reaches
|
|
5
|
+
* `onEvent`, `onMessage` or the internal `/users/sdk/record-logs/` endpoint.
|
|
6
|
+
* Its only exits from the SDK are the `onSession` prop and `getSessionId()`
|
|
7
|
+
* on the ref, both of which the client has to opt into explicitly.
|
|
8
|
+
*/
|
|
9
|
+
/** Message the web app posts whenever the active session id changes. */
|
|
10
|
+
export declare const SESSION_UPDATED_MESSAGE_TYPE = "SESSION_UPDATED";
|
|
11
|
+
/** Key carrying the resume target inside the `registerUserId` payload. */
|
|
12
|
+
export declare const RESUME_SESSION_KEY = "sessionId";
|
|
13
|
+
/**
|
|
14
|
+
* Pulls the session id out of a `SESSION_UPDATED` payload.
|
|
15
|
+
*
|
|
16
|
+
* Accepts the snake_case, camelCase and nested spellings so a naming slip on
|
|
17
|
+
* the web side degrades to a no-op rather than a broken build. Anything that
|
|
18
|
+
* is not a non-empty string is dropped.
|
|
19
|
+
*/
|
|
20
|
+
export declare const extractSessionId: (data: any) => string | undefined;
|
|
21
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/utils/session.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,wEAAwE;AACxE,eAAO,MAAM,4BAA4B,oBAAoB,CAAC;AAE9D,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAE9C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,SAAU,GAAG,KAAG,MAAM,GAAG,SAGrD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.1.
|
|
1
|
+
export declare const SDK_VERSION = "2.1.3-staging.0";
|
|
2
2
|
//# sourceMappingURL=version.staging.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robylon/react-native-sdk",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3-staging.0",
|
|
4
4
|
"description": "React Native SDK for Robylon",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"publish:staging": "npm version $(node scripts/get-next-version.js staging) && node scripts/update-version.js staging && npm run build:staging && npm publish --tag staging",
|
|
26
26
|
"publish:production": "node scripts/validate-publish.js production && npm run build:production && npm publish",
|
|
27
27
|
"publish:hotfix": "node scripts/validate-publish.js hotfix && npm version $(node scripts/get-next-version.js hotfix) && node scripts/update-version.js production && npm run build:production && npm publish --tag hotfix",
|
|
28
|
-
"postinstall": "node scripts/setup-git-hooks.js",
|
|
28
|
+
"postinstall": "node scripts/setup-git-hooks.js || exit 0",
|
|
29
29
|
"branch": "node scripts/create-branch.js",
|
|
30
30
|
"tag": "node scripts/create-version-tag.js"
|
|
31
31
|
},
|
|
Binary file
|
|
@@ -2,17 +2,29 @@ const fs = require("fs");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const { execSync } = require("child_process");
|
|
4
4
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
// This runs from postinstall, which also fires when the SDK is installed as a
|
|
6
|
+
// dependency. Bail out unless we are in the SDK's own checkout, so consumers
|
|
7
|
+
// do not get a stray .git/hooks directory inside node_modules.
|
|
8
|
+
const gitDir = path.join(__dirname, "../.git");
|
|
9
|
+
if (!fs.existsSync(gitDir)) {
|
|
10
|
+
process.exit(0);
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
13
|
+
try {
|
|
14
|
+
const hooksDir = path.join(gitDir, "hooks");
|
|
15
|
+
if (!fs.existsSync(hooksDir)) {
|
|
16
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
17
|
+
}
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
// Copy the validate-branch-name script
|
|
20
|
+
const sourcePath = path.join(__dirname, "validate-branch-name.sh");
|
|
21
|
+
const targetPath = path.join(hooksDir, "commit-msg");
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
24
|
+
fs.chmodSync(targetPath, "755");
|
|
25
|
+
|
|
26
|
+
console.log("Git hooks installed successfully!");
|
|
27
|
+
} catch (error) {
|
|
28
|
+
// Never fail an install over developer tooling.
|
|
29
|
+
console.warn("Skipped git hook setup:", error.message);
|
|
30
|
+
}
|
package/src/Chatbotsdk.tsx
CHANGED
|
@@ -49,6 +49,11 @@ import {
|
|
|
49
49
|
} from "./utils/webViewStorage";
|
|
50
50
|
import { animateWebViewOpen, animateWebViewClose } from "./utils/animations";
|
|
51
51
|
import { handleDownloadRequest, DownloadRequest } from "./utils/fileDownload";
|
|
52
|
+
import {
|
|
53
|
+
SESSION_UPDATED_MESSAGE_TYPE,
|
|
54
|
+
RESUME_SESSION_KEY,
|
|
55
|
+
extractSessionId,
|
|
56
|
+
} from "./utils/session";
|
|
52
57
|
|
|
53
58
|
export interface ChatbotProps {
|
|
54
59
|
api_key: string;
|
|
@@ -61,10 +66,16 @@ export interface ChatbotProps {
|
|
|
61
66
|
is_test_user?: boolean;
|
|
62
67
|
[key: string | number]: any;
|
|
63
68
|
};
|
|
69
|
+
session_id?: string;
|
|
70
|
+
session_context?: Record<string, any>;
|
|
64
71
|
onEvent?: ChatbotEventHandler;
|
|
65
72
|
onOpen?: () => void;
|
|
66
73
|
onClose?: () => void;
|
|
67
74
|
onReady?: () => void;
|
|
75
|
+
onSession?: (
|
|
76
|
+
session_id: string,
|
|
77
|
+
session_context?: Record<string, any>,
|
|
78
|
+
) => void;
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
export interface ChatbotRef {
|
|
@@ -72,6 +83,7 @@ export interface ChatbotRef {
|
|
|
72
83
|
close: () => void;
|
|
73
84
|
toggle: () => void;
|
|
74
85
|
isReady: () => boolean;
|
|
86
|
+
getSessionId: () => string | undefined;
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
interface InternalChatbotProps extends ChatbotProps {
|
|
@@ -151,6 +163,9 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
151
163
|
onClose: externalOnClose,
|
|
152
164
|
onReady,
|
|
153
165
|
user_profile,
|
|
166
|
+
session_id,
|
|
167
|
+
session_context,
|
|
168
|
+
onSession,
|
|
154
169
|
},
|
|
155
170
|
ref,
|
|
156
171
|
) => {
|
|
@@ -171,6 +186,18 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
171
186
|
const [systemInfo, setSystemInfo] = useState({ os: "", browser: "" });
|
|
172
187
|
const systemInfoRef = useRef({ os: "", browser: "" });
|
|
173
188
|
|
|
189
|
+
// Session id pass-through. All four are refs so that client-supplied values
|
|
190
|
+
// never enter handleMessage's dependency array: adding them would rebuild
|
|
191
|
+
// the handler on every client re-render, omitting them without a ref would
|
|
192
|
+
// capture a stale closure.
|
|
193
|
+
const sessionIdRef = useRef<string | undefined>(undefined);
|
|
194
|
+
const onSessionRef = useRef(onSession);
|
|
195
|
+
const sessionContextRef = useRef(session_context);
|
|
196
|
+
const resumeSessionRef = useRef(session_id);
|
|
197
|
+
onSessionRef.current = onSession;
|
|
198
|
+
sessionContextRef.current = session_context;
|
|
199
|
+
resumeSessionRef.current = session_id;
|
|
200
|
+
|
|
174
201
|
// Initialize animated values
|
|
175
202
|
const animatedValues = useRef({
|
|
176
203
|
scale: new Animated.Value(1),
|
|
@@ -221,10 +248,37 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
221
248
|
}
|
|
222
249
|
},
|
|
223
250
|
isReady: () => isInitialized,
|
|
251
|
+
getSessionId: () => sessionIdRef.current,
|
|
224
252
|
}),
|
|
225
253
|
[isInitialized, isWebViewVisible],
|
|
226
254
|
);
|
|
227
255
|
|
|
256
|
+
// Hands the session id to the client. Deduped so that a re-emission on
|
|
257
|
+
// reopen does not fire client side effects twice, and wrapped so that a
|
|
258
|
+
// throwing client handler cannot break message handling.
|
|
259
|
+
const emitSession = useCallback((data: any) => {
|
|
260
|
+
const sessionId = extractSessionId(data);
|
|
261
|
+
if (!sessionId || sessionId === sessionIdRef.current) return;
|
|
262
|
+
sessionIdRef.current = sessionId;
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
onSessionRef.current?.(sessionId, sessionContextRef.current ?? {});
|
|
266
|
+
} catch (error) {
|
|
267
|
+
errorTracker.trackError(
|
|
268
|
+
error instanceof Error
|
|
269
|
+
? error
|
|
270
|
+
: new Error("onSession handler threw an error"),
|
|
271
|
+
"ChatbotSDK",
|
|
272
|
+
{
|
|
273
|
+
// The session id itself is deliberately left out of the report so
|
|
274
|
+
// that it stays confined to the two opt-in client channels.
|
|
275
|
+
type: ErrorTypes.RUNTIME_ERROR,
|
|
276
|
+
context: { source: SESSION_UPDATED_MESSAGE_TYPE },
|
|
277
|
+
},
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
}, []);
|
|
281
|
+
|
|
228
282
|
const triggerAppInit = () => {
|
|
229
283
|
if (webViewRef.current) {
|
|
230
284
|
webViewRef.current?.injectJavaScript(getBrowserAndOSInfoScript());
|
|
@@ -308,6 +362,15 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
308
362
|
return;
|
|
309
363
|
}
|
|
310
364
|
|
|
365
|
+
// Returns before the switch below so the session id never reaches
|
|
366
|
+
// emitEvent (and through it onEvent and /users/sdk/record-logs/) or
|
|
367
|
+
// the default branch's onMessage. Clients who registered neither
|
|
368
|
+
// onSession nor getSessionId cannot observe it.
|
|
369
|
+
if (parsedData?.type === SESSION_UPDATED_MESSAGE_TYPE) {
|
|
370
|
+
emitSession(parsedData?.data);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
311
374
|
if (parsedData?.type === "APP_READY") {
|
|
312
375
|
emitEvent(ChatbotEventType.CHATBOT_APP_READY);
|
|
313
376
|
if (webViewRef.current && isWebViewVisible) {
|
|
@@ -318,6 +381,7 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
318
381
|
action: "registerUserId",
|
|
319
382
|
data: {
|
|
320
383
|
userId: effectiveUserId,
|
|
384
|
+
[RESUME_SESSION_KEY]: resumeSessionRef.current || undefined,
|
|
321
385
|
token: user_token ? `${user_token}` : undefined,
|
|
322
386
|
userProfile: {
|
|
323
387
|
...user_profile,
|
|
@@ -328,7 +392,21 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
328
392
|
},
|
|
329
393
|
},
|
|
330
394
|
};
|
|
331
|
-
logger.debug
|
|
395
|
+
// logger.debug is an unconditional console.log, so the session id
|
|
396
|
+
// is redacted here rather than printed into every client's
|
|
397
|
+
// production console.
|
|
398
|
+
logger.debug(
|
|
399
|
+
"messageData====>",
|
|
400
|
+
JSON.stringify({
|
|
401
|
+
...messageData,
|
|
402
|
+
data: {
|
|
403
|
+
...messageData.data,
|
|
404
|
+
[RESUME_SESSION_KEY]: resumeSessionRef.current
|
|
405
|
+
? "[redacted]"
|
|
406
|
+
: undefined,
|
|
407
|
+
},
|
|
408
|
+
}),
|
|
409
|
+
);
|
|
332
410
|
webViewRef.current?.injectJavaScript(`
|
|
333
411
|
window.postMessage(${JSON.stringify({
|
|
334
412
|
name: "openFrame",
|
|
@@ -411,6 +489,7 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
411
489
|
},
|
|
412
490
|
[
|
|
413
491
|
emitEvent,
|
|
492
|
+
emitSession,
|
|
414
493
|
isWebViewVisible,
|
|
415
494
|
onMessage,
|
|
416
495
|
systemInfo,
|
|
@@ -470,6 +549,11 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
470
549
|
const endpointUrl = `${API_URL}/chat/chatbot/get/`;
|
|
471
550
|
const payload = {
|
|
472
551
|
client_user_id: effectiveUserId,
|
|
552
|
+
// Read from the ref rather than the prop so that a later change
|
|
553
|
+
// does not re-trigger the config fetch. Consistent with session_id
|
|
554
|
+
// being an initialization-time input. JSON.stringify drops the key
|
|
555
|
+
// when there is nothing to resume.
|
|
556
|
+
resumable_session_id: resumeSessionRef.current || undefined,
|
|
473
557
|
org_id: api_key,
|
|
474
558
|
token: user_token,
|
|
475
559
|
extra_info: {},
|
|
@@ -728,7 +812,17 @@ const Chatbot = forwardRef<ChatbotRef, InternalChatbotProps>(
|
|
|
728
812
|
|
|
729
813
|
return (
|
|
730
814
|
<ErrorBoundary componentName="ChatbotSDK">
|
|
731
|
-
|
|
815
|
+
{/*
|
|
816
|
+
This root view is flex: 1 and stays mounted while the chat is closed.
|
|
817
|
+
Left hit-testable, it sits invisibly over whatever the host renders
|
|
818
|
+
behind it and swallows every tap. "box-none" exempts the container
|
|
819
|
+
itself while leaving its children interactive, which is what the
|
|
820
|
+
floating button and the dev-only debug button need. The WebView
|
|
821
|
+
wrapper below manages its own pointerEvents.
|
|
822
|
+
*/}
|
|
823
|
+
<View
|
|
824
|
+
style={styles?.mainContainer}
|
|
825
|
+
pointerEvents={isWebViewVisible ? "auto" : "box-none"}>
|
|
732
826
|
{!loading && (
|
|
733
827
|
<>
|
|
734
828
|
<ErrorBoundary componentName="FloatingButton">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback } from "react";
|
|
1
|
+
import { useCallback, useRef } from "react";
|
|
2
2
|
import { getSystemInfo } from "../utils/systemInfo";
|
|
3
3
|
import { logger } from "../utils/logger";
|
|
4
4
|
import {
|
|
@@ -23,6 +23,21 @@ export const useChatbotEvents = ({
|
|
|
23
23
|
onEvent,
|
|
24
24
|
systemInfo,
|
|
25
25
|
}: EventHookProps) => {
|
|
26
|
+
// Held in refs so that emitEvent keeps a stable identity across renders.
|
|
27
|
+
// Host apps routinely pass an inline onEvent and an inline user_profile
|
|
28
|
+
// object literal; with those in the dependency arrays, emitEvent changed
|
|
29
|
+
// identity on every render, which re-ran the effects keyed on it, which
|
|
30
|
+
// re-emitted events, which re-rendered the host. That loop also POSTed to
|
|
31
|
+
// /users/sdk/record-logs/ on every iteration.
|
|
32
|
+
const onEventRef = useRef(onEvent);
|
|
33
|
+
const chatbotConfigRef = useRef(chatbotConfig);
|
|
34
|
+
const userProfileRef = useRef(user_profile);
|
|
35
|
+
const systemInfoRef = useRef(systemInfo);
|
|
36
|
+
onEventRef.current = onEvent;
|
|
37
|
+
chatbotConfigRef.current = chatbotConfig;
|
|
38
|
+
userProfileRef.current = user_profile;
|
|
39
|
+
systemInfoRef.current = systemInfo;
|
|
40
|
+
|
|
26
41
|
const onInternalEvent = useCallback(
|
|
27
42
|
async (
|
|
28
43
|
eventType: AllEventTypes,
|
|
@@ -30,9 +45,12 @@ export const useChatbotEvents = ({
|
|
|
30
45
|
) => {
|
|
31
46
|
if (!api_key) return;
|
|
32
47
|
|
|
48
|
+
const chatbotConfig = chatbotConfigRef.current;
|
|
49
|
+
const user_profile = userProfileRef.current;
|
|
50
|
+
|
|
33
51
|
try {
|
|
34
52
|
const apiUrl = API_URL;
|
|
35
|
-
const sysInfo = getSystemInfo(
|
|
53
|
+
const sysInfo = getSystemInfo(systemInfoRef.current);
|
|
36
54
|
|
|
37
55
|
const eventData = {
|
|
38
56
|
trigger_time: Date.now(),
|
|
@@ -74,16 +92,22 @@ export const useChatbotEvents = ({
|
|
|
74
92
|
logger.error("Failed to send internal event:", error);
|
|
75
93
|
}
|
|
76
94
|
},
|
|
77
|
-
[api_key
|
|
95
|
+
[api_key]
|
|
78
96
|
);
|
|
79
97
|
|
|
80
98
|
const emitEvent = useCallback(
|
|
81
99
|
(type: ChatbotEventType, data?: any) => {
|
|
82
100
|
const timestamp = Date.now();
|
|
83
|
-
|
|
101
|
+
// Isolated so that a throwing host handler cannot prevent the internal
|
|
102
|
+
// event from being recorded, or break the caller.
|
|
103
|
+
try {
|
|
104
|
+
onEventRef.current?.({ type, timestamp, data });
|
|
105
|
+
} catch (error) {
|
|
106
|
+
logger.error("onEvent handler threw an error:", error);
|
|
107
|
+
}
|
|
84
108
|
onInternalEvent(type, { ...data, timestamp });
|
|
85
109
|
},
|
|
86
|
-
[
|
|
110
|
+
[onInternalEvent]
|
|
87
111
|
);
|
|
88
112
|
|
|
89
113
|
return {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session id pass-through between the chatbot web app and the SDK client.
|
|
3
|
+
*
|
|
4
|
+
* The session id travels on its own message type so that it never reaches
|
|
5
|
+
* `onEvent`, `onMessage` or the internal `/users/sdk/record-logs/` endpoint.
|
|
6
|
+
* Its only exits from the SDK are the `onSession` prop and `getSessionId()`
|
|
7
|
+
* on the ref, both of which the client has to opt into explicitly.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Message the web app posts whenever the active session id changes. */
|
|
11
|
+
export const SESSION_UPDATED_MESSAGE_TYPE = "SESSION_UPDATED";
|
|
12
|
+
|
|
13
|
+
/** Key carrying the resume target inside the `registerUserId` payload. */
|
|
14
|
+
export const RESUME_SESSION_KEY = "sessionId";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Pulls the session id out of a `SESSION_UPDATED` payload.
|
|
18
|
+
*
|
|
19
|
+
* Accepts the snake_case, camelCase and nested spellings so a naming slip on
|
|
20
|
+
* the web side degrades to a no-op rather than a broken build. Anything that
|
|
21
|
+
* is not a non-empty string is dropped.
|
|
22
|
+
*/
|
|
23
|
+
export const extractSessionId = (data: any): string | undefined => {
|
|
24
|
+
const raw = data?.session_id ?? data?.sessionId ?? data?.session?.id;
|
|
25
|
+
return typeof raw === "string" && raw.length > 0 ? raw : undefined;
|
|
26
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not modify it manually.
|
|
2
|
-
export const SDK_VERSION = '2.1.
|
|
2
|
+
export const SDK_VERSION = '2.1.3-staging.0';
|