@botfabrik/engine-webclient 4.121.7 → 4.122.1

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.
@@ -13,7 +13,7 @@
13
13
  <meta name="theme-color" content="#000000" />
14
14
  <meta name="google" content="notranslate" />
15
15
  <title>Bubble Chat Client</title>
16
- <script type="module" crossorigin src="./assets/index-u0WiQbPl.js"></script>
16
+ <script type="module" crossorigin src="./assets/index-CxHubEDR.js"></script>
17
17
  <link rel="stylesheet" crossorigin href="./assets/index-Q0uFG8V2.css">
18
18
  </head>
19
19
 
@@ -1,12 +1,16 @@
1
1
  import { CLIENT_TYPE } from './constants.js';
2
- const createSessionInfoBase = async (userId, querystrings, headers, clientName, environment, sessionInfo, locale, authenticatedUser, props) => {
2
+ const createSessionInfo = (socket, clientName, environment, sessionInfo, userId, locale, querystrings, authenticatedUser, props) => async () => {
3
+ const headers = socket.request.headers;
4
+ const ip = extractIpFromSocket(socket);
3
5
  const client = {
4
6
  ...sessionInfo.client,
5
7
  name: clientName,
6
8
  type: CLIENT_TYPE,
7
9
  payload: {
8
10
  ...sessionInfo.client.payload,
9
- referrer: decodeURIComponent(querystrings['referrer'] || headers['referer'] || 'unknown'),
11
+ referrer: decodeURIComponent(querystrings['referrer'] ||
12
+ headers['referer'] ||
13
+ 'unknown'),
10
14
  querystrings,
11
15
  },
12
16
  };
@@ -29,17 +33,17 @@ const createSessionInfoBase = async (userId, querystrings, headers, clientName,
29
33
  locale,
30
34
  };
31
35
  const contexts = sessionInfo.contexts;
32
- // enhance user infos
33
- if (props.requestUserInfos) {
34
- const userInfos = await props.requestUserInfos(querystrings);
35
- user = Object.assign({}, user, userInfos);
36
+ if (props.enrichUserInfo) {
37
+ const userInfos = await props.enrichUserInfo({
38
+ user,
39
+ querystrings,
40
+ headers,
41
+ ip,
42
+ });
43
+ user = { ...user, ...userInfos };
36
44
  }
37
45
  return { client, user, contexts, environment };
38
46
  };
39
- const createSessionInfo = (socket, clientName, environment, sessionInfo, userId, locale, querystrings, authenticatedUser, props) => async () => {
40
- const request = socket.request;
41
- return await createSessionInfoBase(userId, querystrings, request.headers, clientName, environment, sessionInfo, locale, authenticatedUser, props);
42
- };
43
47
  const guestNamesFromEMail = (email) => {
44
48
  try {
45
49
  const namePart = email?.split('@')[0];
@@ -61,4 +65,15 @@ const capitalize = (s) => {
61
65
  return '';
62
66
  return s.charAt(0).toUpperCase() + s.slice(1);
63
67
  };
68
+ const extractIpFromSocket = (socket) => {
69
+ const headers = socket.handshake.headers;
70
+ const forwarded = headers['x-forwarded-for'];
71
+ if (typeof forwarded === 'string') {
72
+ return forwarded.split(',')[0]?.trim();
73
+ }
74
+ if (Array.isArray(forwarded) && forwarded.length > 0) {
75
+ return forwarded[0];
76
+ }
77
+ return socket.handshake.address;
78
+ };
64
79
  export default createSessionInfo;
@@ -22,6 +22,7 @@ describe('create session info', () => {
22
22
  },
23
23
  handshake: {
24
24
  query: querystrings,
25
+ headers,
25
26
  },
26
27
  };
27
28
  const webClientProps = {
@@ -54,7 +55,7 @@ describe('create session info', () => {
54
55
  expect(sessionInfo.user.payload).toStrictEqual({});
55
56
  });
56
57
  it('with enhanced user data', async () => {
57
- const requestUserInfos = async () => {
58
+ const enrichUserInfo = async () => {
58
59
  const userProfile = {
59
60
  username: 'hans.muster',
60
61
  domain: 'PRIMARY',
@@ -69,7 +70,7 @@ describe('create session info', () => {
69
70
  };
70
71
  const props = {
71
72
  ...webClientProps,
72
- requestUserInfos,
73
+ enrichUserInfo,
73
74
  };
74
75
  const sessionInfo = await createSessionInfo(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, undefined, props)();
75
76
  expect(sessionInfo.user.id).toBe('hans.muster@PRIMARY');
package/dist/types.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { Action, SessionInfoUser } from '@botfabrik/engine-domain';
2
+ import { IncomingHttpHeaders } from 'node:http';
3
+ import { ParsedUrlQuery } from 'node:querystring';
2
4
  export type SessionInfoClientPayload = {
3
5
  querystrings: any;
4
6
  referrer: string;
@@ -10,9 +12,26 @@ export type ConversationRating = {
10
12
  };
11
13
  export type SessionInfoUserPayload = object;
12
14
  export type WebclientMiddlewareState = object;
13
- export type RequestUserInfos = (querystrings: any) => Promise<Partial<SessionInfoUser<SessionInfoUserPayload>>>;
15
+ /**
16
+ * Callback to enrich the user's session info with additional data from an external source.
17
+ *
18
+ * Called during session initialization with the current user, query strings, and HTTP headers.
19
+ * The returned partial object is merged into the existing user info.
20
+ *
21
+ * @param props.user - The current session user object built from authentication and query parameters.
22
+ * @param props.querystrings - The parsed query string parameters from the client URL.
23
+ * @param props.headers - The incoming HTTP request headers.
24
+ * @param props.ip - The client's IP address, extracted from the socket connection.
25
+ * @returns A promise resolving to a partial user info object whose properties will be merged into the session user.
26
+ */
27
+ export type EnrichUserInfo = (props: {
28
+ user: SessionInfoUser<SessionInfoUserPayload>;
29
+ querystrings: ParsedUrlQuery;
30
+ headers: IncomingHttpHeaders;
31
+ ip: string | undefined;
32
+ }) => Promise<Partial<SessionInfoUser<SessionInfoUserPayload>>>;
14
33
  export type RequestSessionRecordQuery = (params: {
15
- querystrings: any;
34
+ querystrings: ParsedUrlQuery;
16
35
  sessionId: string;
17
36
  }) => Promise<Record<string, unknown>>;
18
37
  export type MenuItemType = 'link' | 'action';
@@ -87,7 +106,11 @@ export type Auth = {
87
106
  };
88
107
  export interface WebClientProps {
89
108
  getStartedAction?: Action;
90
- requestUserInfos?: RequestUserInfos;
109
+ /**
110
+ * Optional callback to enrich the user's session info with additional data.
111
+ * See {@link EnrichUserInfo} for details.
112
+ */
113
+ enrichUserInfo?: EnrichUserInfo;
91
114
  requestSessionRecordQuery?: RequestSessionRecordQuery;
92
115
  speech?: SpeechToTextProps | undefined;
93
116
  expandChatWindowAtStart?: Devices;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botfabrik/engine-webclient",
3
- "version": "4.121.7",
3
+ "version": "4.122.1",
4
4
  "description": "Webclient for Botfabriks Bot Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,9 +31,9 @@
31
31
  "dev:embed": "tsx --watch ./run-embed-local.ts"
32
32
  },
33
33
  "dependencies": {
34
- "@botfabrik/engine-domain": "^4.121.5",
35
- "@botfabrik/engine-transcript-export": "^4.121.5",
36
- "@botfabrik/engine-utils": "^4.121.5",
34
+ "@botfabrik/engine-domain": "^4.122.1",
35
+ "@botfabrik/engine-transcript-export": "^4.122.1",
36
+ "@botfabrik/engine-utils": "^4.122.1",
37
37
  "@google-cloud/speech": "^7.3.1",
38
38
  "@node-saml/passport-saml": "^5.1.0",
39
39
  "@types/cors": "^2.8.19",
@@ -55,5 +55,5 @@
55
55
  "tsx": "^4.22.3",
56
56
  "typescript": "6.0.3"
57
57
  },
58
- "gitHead": "35ddae6f6e337b775ebde3567f67d3878fde1dc1"
58
+ "gitHead": "a2c4a38b4d6a98f9d5225f0f7009889a3563c7cc"
59
59
  }