@botfabrik/engine-webclient 4.101.2 → 4.101.3-alpha.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.
@@ -1,8 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setAuthPageHeaders = setAuthPageHeaders;
4
- exports.renderAuthSuccessPage = renderAuthSuccessPage;
5
- exports.renderAuthErrorPage = renderAuthErrorPage;
6
1
  const STRINGS = {
7
2
  de: {
8
3
  successTitle: 'Login erfolgreich',
@@ -41,13 +36,13 @@ const STRINGS = {
41
36
  closeWindow: 'Chiudi finestra',
42
37
  },
43
38
  };
44
- function setAuthPageHeaders(res) {
39
+ export function setAuthPageHeaders(res) {
45
40
  res.setHeader('Content-Type', 'text/html; charset=utf-8');
46
41
  res.setHeader('Content-Security-Policy', "default-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'; img-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'");
47
42
  res.setHeader('Referrer-Policy', 'no-referrer');
48
43
  res.setHeader('X-Content-Type-Options', 'nosniff');
49
44
  }
50
- function renderAuthSuccessPage(lang) {
45
+ export function renderAuthSuccessPage(lang) {
51
46
  const t = STRINGS[lang];
52
47
  return `<!doctype html>
53
48
  <html lang="${lang}">
@@ -74,7 +69,7 @@ function renderAuthSuccessPage(lang) {
74
69
  </body>
75
70
  </html>`;
76
71
  }
77
- function renderAuthErrorPage(lang) {
72
+ export function renderAuthErrorPage(lang) {
78
73
  const t = STRINGS[lang];
79
74
  return `<!doctype html>
80
75
  <html lang="${lang}">
@@ -1,6 +1,6 @@
1
1
  import type { BotInstance, Logger } from '@botfabrik/engine-domain';
2
2
  import type { Namespace } from 'socket.io';
3
- import type { Auth } from '../types';
3
+ import type { Auth } from '../types.js';
4
4
  export type AuthenticatedUser = {
5
5
  email: string;
6
6
  firstName: string | undefined;
@@ -1,66 +1,58 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.setUpSamlAuth = setUpSamlAuth;
7
- exports.storeLoginRequestToken = storeLoginRequestToken;
8
- exports.verifyLoginToken = verifyLoginToken;
9
- const passport_saml_1 = require("@node-saml/passport-saml");
10
- const express_1 = __importDefault(require("express"));
11
- const jsonwebtoken_1 = require("jsonwebtoken");
12
- const passport_1 = __importDefault(require("passport"));
13
- const auth_pages_1 = require("./auth-pages");
14
- const relay_state_1 = require("./relay-state");
15
- const ttl_cache_1 = require("./ttl-cache");
1
+ import { Strategy, } from '@node-saml/passport-saml';
2
+ import express from 'express';
3
+ import { sign, verify } from 'jsonwebtoken';
4
+ import passport from 'passport';
5
+ import { renderAuthErrorPage, renderAuthSuccessPage, setAuthPageHeaders, } from './auth-pages.js';
6
+ import { signRelayState, verifyRelayState } from './relay-state.js';
7
+ import { TtlCache } from './ttl-cache.js';
16
8
  const E_MAIL_CLAIM = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress';
17
9
  const FIRST_NAME_CLAIM = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname';
18
10
  const LAST_NAME_CLAIM = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname';
19
- const loginTokenCache = new ttl_cache_1.TtlCache({
11
+ const loginTokenCache = new TtlCache({
20
12
  defaultTtlMs: 5 * 60 * 1000, // 5 minutes
21
13
  });
22
- function setUpSamlAuth(bot, auth, clientName, nsp) {
14
+ export function setUpSamlAuth(bot, auth, clientName, nsp) {
23
15
  bot.logger.info(`Setting up SAML authentication for ${clientName}`);
24
16
  const strategyName = `${clientName}-saml`;
25
17
  const callbackUrl = `/${clientName}/auth/saml/login/callback`;
26
- const samlStrategy = new passport_saml_1.Strategy({
18
+ const samlStrategy = new Strategy({
27
19
  callbackUrl: `${bot.webserver.baseUrl}${callbackUrl}`,
28
20
  entryPoint: auth.saml.entryPoint,
29
21
  issuer: auth.saml.issuer,
30
22
  idpCert: fixUnwantedEscapeCharacters(auth.saml.idpCert),
31
23
  ...(auth.saml.options || {}),
32
24
  }, signonVerify, logoutVerify);
33
- passport_1.default.use(strategyName, samlStrategy);
25
+ passport.use(strategyName, samlStrategy);
34
26
  bot.webserver.express.get(`/${clientName}/auth/login`, (req, res, next) => {
35
27
  const { loginRequestToken } = req.query;
36
- const relayState = (0, relay_state_1.signRelayState)(String(loginRequestToken), auth.jwtSecret);
28
+ const relayState = signRelayState(String(loginRequestToken), auth.jwtSecret);
37
29
  const options = {
38
30
  session: false,
39
31
  additionalParams: { RelayState: relayState },
40
32
  };
41
- const authenticateFn = passport_1.default.authenticate(strategyName, options);
33
+ const authenticateFn = passport.authenticate(strategyName, options);
42
34
  authenticateFn(req, res, next);
43
35
  });
44
- bot.webserver.express.post(callbackUrl, express_1.default.urlencoded({ extended: false }), (req, res, next) => {
45
- const authenticatorFn = passport_1.default.authenticate(strategyName, { session: false }, (err, user) => {
36
+ bot.webserver.express.post(callbackUrl, express.urlencoded({ extended: false }), (req, res, next) => {
37
+ const authenticatorFn = passport.authenticate(strategyName, { session: false }, (err, user) => {
46
38
  const lang = getLang(req);
47
- (0, auth_pages_1.setAuthPageHeaders)(res);
39
+ setAuthPageHeaders(res);
48
40
  try {
49
41
  if (err) {
50
42
  bot.logger.error('SAML callback error:', err);
51
- return res.status(500).send((0, auth_pages_1.renderAuthErrorPage)(lang));
43
+ return res.status(500).send(renderAuthErrorPage(lang));
52
44
  }
53
45
  const relayState = req.body?.RelayState;
54
46
  if (!relayState) {
55
47
  bot.logger.warn('Missing RelayState');
56
- return res.status(400).send((0, auth_pages_1.renderAuthErrorPage)(lang));
48
+ return res.status(400).send(renderAuthErrorPage(lang));
57
49
  }
58
- const loginRequestToken = (0, relay_state_1.verifyRelayState)(relayState, auth.jwtSecret);
50
+ const loginRequestToken = verifyRelayState(relayState, auth.jwtSecret);
59
51
  const { socketId } = consumeLoginRequestToken(loginRequestToken);
60
52
  if (!user) {
61
- return res.status(401).send((0, auth_pages_1.renderAuthErrorPage)(lang));
53
+ return res.status(401).send(renderAuthErrorPage(lang));
62
54
  }
63
- const loginToken = (0, jsonwebtoken_1.sign)(user, auth.jwtSecret, {
55
+ const loginToken = sign(user, auth.jwtSecret, {
64
56
  expiresIn: '1m',
65
57
  });
66
58
  const socket = nsp.sockets.get(socketId);
@@ -70,17 +62,17 @@ function setUpSamlAuth(bot, auth, clientName, nsp) {
70
62
  else {
71
63
  bot.logger.warn('Target socket not found', { socketId });
72
64
  }
73
- return res.send((0, auth_pages_1.renderAuthSuccessPage)(lang));
65
+ return res.send(renderAuthSuccessPage(lang));
74
66
  }
75
67
  catch (e) {
76
68
  bot.logger.error('Callback handling failure:', e);
77
- return res.status(500).send((0, auth_pages_1.renderAuthErrorPage)(lang));
69
+ return res.status(500).send(renderAuthErrorPage(lang));
78
70
  }
79
71
  });
80
72
  authenticatorFn(req, res, next);
81
73
  });
82
74
  }
83
- function storeLoginRequestToken(loginRequestToken, socketId) {
75
+ export function storeLoginRequestToken(loginRequestToken, socketId) {
84
76
  // associate socketId with loginRequestToken and store it in memory cache
85
77
  loginTokenCache.set(loginRequestToken, { loginRequestToken, socketId });
86
78
  }
@@ -97,10 +89,10 @@ function consumeLoginRequestToken(loginRequestToken) {
97
89
  loginTokenCache.delete(loginRequestToken);
98
90
  return { socketId: cachedLoginRequest.socketId };
99
91
  }
100
- function verifyLoginToken(token, auth, logger) {
92
+ export function verifyLoginToken(token, auth, logger) {
101
93
  try {
102
94
  if (auth) {
103
- const verified = (0, jsonwebtoken_1.verify)(token || '', auth.jwtSecret);
95
+ const verified = verify(token || '', auth.jwtSecret);
104
96
  return {
105
97
  email: verified['email'],
106
98
  firstName: verified['firstName'],
@@ -1,24 +1,14 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.signRelayState = signRelayState;
7
- exports.verifyRelayState = verifyRelayState;
8
- const crypto_1 = __importDefault(require("crypto"));
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
9
2
  const STATE_TTL_MS = 5 * 60 * 1000; // 5 minutes
10
- function signRelayState(rawToken, secret) {
3
+ export function signRelayState(rawToken, secret) {
11
4
  if (!/^[\w-]{16,128}$/.test(rawToken))
12
5
  throw new Error('bad token format');
13
6
  const exp = Date.now() + STATE_TTL_MS;
14
7
  const payload = `${rawToken}.${exp}`;
15
- const mac = crypto_1.default
16
- .createHmac('sha256', secret)
17
- .update(payload)
18
- .digest('base64url');
8
+ const mac = createHmac('sha256', secret).update(payload).digest('base64url');
19
9
  return Buffer.from(`${payload}.${mac}`, 'utf8').toString('base64url');
20
10
  }
21
- function verifyRelayState(stateB64, secret) {
11
+ export function verifyRelayState(stateB64, secret) {
22
12
  const raw = Buffer.from(stateB64, 'base64url').toString('utf8');
23
13
  const [token, expStr, mac] = raw.split('.');
24
14
  if (!token || !expStr || !mac) {
@@ -28,11 +18,10 @@ function verifyRelayState(stateB64, secret) {
28
18
  if (!Number.isFinite(exp) || exp < Date.now()) {
29
19
  throw new Error('state expired');
30
20
  }
31
- const expected = crypto_1.default
32
- .createHmac('sha256', secret)
21
+ const expected = createHmac('sha256', secret)
33
22
  .update(`${token}.${exp}`)
34
23
  .digest('base64url');
35
- if (!crypto_1.default.timingSafeEqual(Buffer.from(mac), Buffer.from(expected))) {
24
+ if (!timingSafeEqual(Buffer.from(mac), Buffer.from(expected))) {
36
25
  throw new Error('state tampered');
37
26
  }
38
27
  return token;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TtlCache = void 0;
4
- class TtlCache {
1
+ export class TtlCache {
5
2
  data = new Map();
6
3
  timers = new Map();
7
4
  defaultTtlMs;
@@ -49,4 +46,3 @@ class TtlCache {
49
46
  this.data.clear();
50
47
  }
51
48
  }
52
- exports.TtlCache = TtlCache;
package/dist/constants.js CHANGED
@@ -1,4 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CLIENT_TYPE = void 0;
4
- exports.CLIENT_TYPE = 'webclient';
1
+ export const CLIENT_TYPE = 'webclient';
@@ -1,7 +1,7 @@
1
1
  import type { Environment, SessionInfo } from '@botfabrik/engine-domain';
2
2
  import type { ParsedUrlQuery } from 'node:querystring';
3
3
  import type { Socket } from 'socket.io';
4
- import { AuthenticatedUser } from './auth';
5
- import type { SessionInfoClientPayload, SessionInfoUserPayload, WebClientProps } from './types';
4
+ import { AuthenticatedUser } from './auth/index.js';
5
+ import type { SessionInfoClientPayload, SessionInfoUserPayload, WebClientProps } from './types.js';
6
6
  declare const createSessionInfo: (socket: Socket, clientName: string, environment: Environment, sessionInfo: SessionInfo<SessionInfoClientPayload, SessionInfoUserPayload>, userId: string, locale: string | undefined, querystrings: ParsedUrlQuery, authenticatedUser: AuthenticatedUser | undefined, props: WebClientProps) => () => Promise<SessionInfo<SessionInfoClientPayload, SessionInfoUserPayload>>;
7
7
  export default createSessionInfo;
@@ -1,11 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const constants_1 = require("./constants");
1
+ import { CLIENT_TYPE } from './constants.js';
4
2
  const createSessionInfoBase = async (userId, querystrings, headers, clientName, environment, sessionInfo, locale, authenticatedUser, props) => {
5
3
  const client = {
6
4
  ...sessionInfo.client,
7
5
  name: clientName,
8
- type: constants_1.CLIENT_TYPE,
6
+ type: CLIENT_TYPE,
9
7
  payload: {
10
8
  ...sessionInfo.client.payload,
11
9
  referrer: decodeURIComponent(querystrings['referrer'] || headers['referer'] || 'unknown'),
@@ -63,4 +61,4 @@ const capitalize = (s) => {
63
61
  return '';
64
62
  return s.charAt(0).toUpperCase() + s.slice(1);
65
63
  };
66
- exports.default = createSessionInfo;
64
+ export default createSessionInfo;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,11 +1,6 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const globals_1 = require("@jest/globals");
7
- const createSessionInfo_1 = __importDefault(require("./createSessionInfo"));
8
- (0, globals_1.describe)('create session info', () => {
1
+ import { describe, expect, it } from 'vitest';
2
+ import createSessionInfo from './createSessionInfo.js';
3
+ describe('create session info', () => {
9
4
  const querystrings = {};
10
5
  const headers = {
11
6
  host: 'fluance-chatbot.scapp.io',
@@ -42,19 +37,19 @@ const createSessionInfo_1 = __importDefault(require("./createSessionInfo"));
42
37
  contexts: [],
43
38
  environment: 'PROD',
44
39
  };
45
- (0, globals_1.it)('without user payload', async () => {
46
- const sessionInfo = await (0, createSessionInfo_1.default)(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', { email: 'hans@example.com' }, undefined, {})();
40
+ it('without user payload', async () => {
41
+ const sessionInfo = await createSessionInfo(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', { email: 'hans@example.com' }, undefined, {})();
47
42
  // client
48
- (0, globals_1.expect)(sessionInfo.client.name).toBe('my-client');
49
- (0, globals_1.expect)(sessionInfo.client.type).toBe('webclient');
50
- (0, globals_1.expect)(sessionInfo.client.payload.querystrings.email).toBe('hans@example.com');
43
+ expect(sessionInfo.client.name).toBe('my-client');
44
+ expect(sessionInfo.client.type).toBe('webclient');
45
+ expect(sessionInfo.client.payload.querystrings.email).toBe('hans@example.com');
51
46
  // user
52
- (0, globals_1.expect)(sessionInfo.user.id).toBe('my-user-id');
53
- (0, globals_1.expect)(sessionInfo.user.displayName).not.toBeDefined();
54
- (0, globals_1.expect)(sessionInfo.user.locale).toBe('de_DE');
55
- (0, globals_1.expect)(sessionInfo.user.payload).toStrictEqual({});
47
+ expect(sessionInfo.user.id).toBe('my-user-id');
48
+ expect(sessionInfo.user.displayName).not.toBeDefined();
49
+ expect(sessionInfo.user.locale).toBe('de_DE');
50
+ expect(sessionInfo.user.payload).toStrictEqual({});
56
51
  });
57
- (0, globals_1.it)('with enhanced user data', async () => {
52
+ it('with enhanced user data', async () => {
58
53
  const requestUserInfos = async () => {
59
54
  const userProfile = {
60
55
  username: 'hans.muster',
@@ -71,49 +66,49 @@ const createSessionInfo_1 = __importDefault(require("./createSessionInfo"));
71
66
  const props = {
72
67
  requestUserInfos,
73
68
  };
74
- const sessionInfo = await (0, createSessionInfo_1.default)(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, undefined, props)();
75
- (0, globals_1.expect)(sessionInfo.user.id).toBe('hans.muster@PRIMARY');
76
- (0, globals_1.expect)(sessionInfo.user.displayName).toBe('Hans Muster');
77
- (0, globals_1.expect)(sessionInfo.user.payload.username).toBe('hans.muster');
78
- (0, globals_1.expect)(sessionInfo.user.payload.firstName).toBe('Hans');
79
- (0, globals_1.expect)(sessionInfo.user.payload.lastName).toBe('Muster');
69
+ const sessionInfo = await createSessionInfo(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, undefined, props)();
70
+ expect(sessionInfo.user.id).toBe('hans.muster@PRIMARY');
71
+ expect(sessionInfo.user.displayName).toBe('Hans Muster');
72
+ expect(sessionInfo.user.payload.username).toBe('hans.muster');
73
+ expect(sessionInfo.user.payload.firstName).toBe('Hans');
74
+ expect(sessionInfo.user.payload.lastName).toBe('Muster');
80
75
  });
81
- (0, globals_1.it)('with undefined enhanced user data', async () => {
76
+ it('with undefined enhanced user data', async () => {
82
77
  const requestUserInfos = async () => {
83
78
  return {};
84
79
  };
85
80
  const props = {
86
81
  requestUserInfos,
87
82
  };
88
- const sessionInfo = await (0, createSessionInfo_1.default)(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, undefined, props)();
89
- (0, globals_1.expect)(sessionInfo.user.id).toBe('my-user-id');
90
- (0, globals_1.expect)(sessionInfo.user.displayName).not.toBeDefined();
91
- (0, globals_1.expect)(sessionInfo.user.locale).toBe('de_DE');
92
- (0, globals_1.expect)(sessionInfo.user.payload).toStrictEqual({});
93
- (0, globals_1.expect)(sessionInfo.environment).toBe('TEST');
83
+ const sessionInfo = await createSessionInfo(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, undefined, props)();
84
+ expect(sessionInfo.user.id).toBe('my-user-id');
85
+ expect(sessionInfo.user.displayName).not.toBeDefined();
86
+ expect(sessionInfo.user.locale).toBe('de_DE');
87
+ expect(sessionInfo.user.payload).toStrictEqual({});
88
+ expect(sessionInfo.environment).toBe('TEST');
94
89
  });
95
- (0, globals_1.it)('with authenticated user', async () => {
96
- const sessionInfo = await (0, createSessionInfo_1.default)(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, {
90
+ it('with authenticated user', async () => {
91
+ const sessionInfo = await createSessionInfo(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, {
97
92
  email: 'hans.muster@example.com',
98
93
  firstName: 'Hans',
99
94
  lastName: 'Muster',
100
95
  }, {})();
101
- (0, globals_1.expect)(sessionInfo.user.id).toBe('my-user-id');
102
- (0, globals_1.expect)(sessionInfo.user.displayName).toBe('Hans Muster');
103
- (0, globals_1.expect)(sessionInfo.user.firstName).toBe('Hans');
104
- (0, globals_1.expect)(sessionInfo.user.lastName).toBe('Muster');
105
- (0, globals_1.expect)(sessionInfo.user.email).toBe('hans.muster@example.com');
96
+ expect(sessionInfo.user.id).toBe('my-user-id');
97
+ expect(sessionInfo.user.displayName).toBe('Hans Muster');
98
+ expect(sessionInfo.user.firstName).toBe('Hans');
99
+ expect(sessionInfo.user.lastName).toBe('Muster');
100
+ expect(sessionInfo.user.email).toBe('hans.muster@example.com');
106
101
  });
107
- (0, globals_1.it)('with authenticated user and guessed name', async () => {
108
- const sessionInfo = await (0, createSessionInfo_1.default)(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, {
102
+ it('with authenticated user and guessed name', async () => {
103
+ const sessionInfo = await createSessionInfo(socket, 'my-client', 'TEST', defaultSessionInfo, 'my-user-id', 'de_DE', {}, {
109
104
  email: 'hans.muster@example.com',
110
105
  firstName: undefined,
111
106
  lastName: undefined,
112
107
  }, {})();
113
- (0, globals_1.expect)(sessionInfo.user.id).toBe('my-user-id');
114
- (0, globals_1.expect)(sessionInfo.user.displayName).toBe('Hans Muster');
115
- (0, globals_1.expect)(sessionInfo.user.firstName).toBe('Hans');
116
- (0, globals_1.expect)(sessionInfo.user.lastName).toBe('Muster');
117
- (0, globals_1.expect)(sessionInfo.user.email).toBe('hans.muster@example.com');
108
+ expect(sessionInfo.user.id).toBe('my-user-id');
109
+ expect(sessionInfo.user.displayName).toBe('Hans Muster');
110
+ expect(sessionInfo.user.firstName).toBe('Hans');
111
+ expect(sessionInfo.user.lastName).toBe('Muster');
112
+ expect(sessionInfo.user.email).toBe('hans.muster@example.com');
118
113
  });
119
114
  });
@@ -1,13 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const accept_language_parser_1 = require("accept-language-parser");
1
+ import { parse } from 'accept-language-parser';
4
2
  const extractLocale = (parsedUrlQuery, acceptLanguage = '') => {
5
3
  let locale = undefined;
6
4
  if (parsedUrlQuery['lang']) {
7
5
  locale = parsedUrlQuery['lang'];
8
6
  }
9
7
  else {
10
- const languages = (0, accept_language_parser_1.parse)(acceptLanguage);
8
+ const languages = parse(acceptLanguage);
11
9
  if (languages !== undefined && languages[0]) {
12
10
  const code = languages[0].code;
13
11
  const region = languages[0].region;
@@ -16,4 +14,4 @@ const extractLocale = (parsedUrlQuery, acceptLanguage = '') => {
16
14
  }
17
15
  return locale;
18
16
  };
19
- exports.default = extractLocale;
17
+ export default extractLocale;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,25 +1,20 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const globals_1 = require("@jest/globals");
7
- const extractLocale_1 = __importDefault(require("./extractLocale"));
8
- (0, globals_1.describe)('should extract locale from accept-language header', () => {
9
- (0, globals_1.it)('undefined header value', () => {
10
- (0, globals_1.expect)((0, extractLocale_1.default)({}, undefined)).toBe(undefined);
1
+ import { describe, expect, it } from 'vitest';
2
+ import extractLocale from './extractLocale.js';
3
+ describe('should extract locale from accept-language header', () => {
4
+ it('undefined header value', () => {
5
+ expect(extractLocale({}, undefined)).toBe(undefined);
11
6
  });
12
- (0, globals_1.it)('lang via query parameer', () => {
13
- (0, globals_1.expect)((0, extractLocale_1.default)({ lang: 'de' }, '')).toBe('de');
7
+ it('lang via query parameer', () => {
8
+ expect(extractLocale({ lang: 'de' }, '')).toBe('de');
14
9
  });
15
- (0, globals_1.it)('empty header value', () => {
16
- (0, globals_1.expect)((0, extractLocale_1.default)({}, '')).toBe(undefined);
10
+ it('empty header value', () => {
11
+ expect(extractLocale({}, '')).toBe(undefined);
17
12
  });
18
- (0, globals_1.it)('header value with one value', () => {
19
- (0, globals_1.expect)((0, extractLocale_1.default)({}, 'de-CH')).toBe('de_CH');
13
+ it('header value with one value', () => {
14
+ expect(extractLocale({}, 'de-CH')).toBe('de_CH');
20
15
  });
21
- (0, globals_1.it)('header value with several values', () => {
16
+ it('header value with several values', () => {
22
17
  const header = 'de-CH,de;q=0.8,en-US;q=0.6,en;q=0.4';
23
- (0, globals_1.expect)((0, extractLocale_1.default)({}, header)).toBe('de_CH');
18
+ expect(extractLocale({}, header)).toBe('de_CH');
24
19
  });
25
20
  });
@@ -1,5 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
1
  const getSupportedClientLocale = (userLocale) => {
4
2
  // Prüfe, ob der Webclient für diese Sprache eine Übersetzung hat
5
3
  const supportedLocales = ['de', 'en', 'fr', 'it'];
@@ -15,4 +13,4 @@ const getSupportedClientLocale = (userLocale) => {
15
13
  // default locale
16
14
  return 'de';
17
15
  };
18
- exports.default = getSupportedClientLocale;
16
+ export default getSupportedClientLocale;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,23 +1,18 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const globals_1 = require("@jest/globals");
7
- const getSupportedClientLocale_1 = __importDefault(require("./getSupportedClientLocale"));
8
- (0, globals_1.describe)('get client locale', () => {
9
- (0, globals_1.it)('should return supported client language', () => {
10
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('de')).toBe('de');
11
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('de-ch')).toBe('de');
12
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('en')).toBe('en');
13
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('en-us')).toBe('en');
14
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('fr')).toBe('fr');
15
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('fr-ch')).toBe('fr');
16
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('it')).toBe('it');
1
+ import { describe, expect, it } from 'vitest';
2
+ import getSupportedClientLocale from './getSupportedClientLocale.js';
3
+ describe('get client locale', () => {
4
+ it('should return supported client language', () => {
5
+ expect(getSupportedClientLocale('de')).toBe('de');
6
+ expect(getSupportedClientLocale('de-ch')).toBe('de');
7
+ expect(getSupportedClientLocale('en')).toBe('en');
8
+ expect(getSupportedClientLocale('en-us')).toBe('en');
9
+ expect(getSupportedClientLocale('fr')).toBe('fr');
10
+ expect(getSupportedClientLocale('fr-ch')).toBe('fr');
11
+ expect(getSupportedClientLocale('it')).toBe('it');
17
12
  });
18
- (0, globals_1.it)('should return "de" as default locale', () => {
19
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('ru')).toBe('de');
20
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('ru-de')).toBe('de');
21
- (0, globals_1.expect)((0, getSupportedClientLocale_1.default)('sp')).toBe('de');
13
+ it('should return "de" as default locale', () => {
14
+ expect(getSupportedClientLocale('ru')).toBe('de');
15
+ expect(getSupportedClientLocale('ru-de')).toBe('de');
16
+ expect(getSupportedClientLocale('sp')).toBe('de');
22
17
  });
23
18
  });
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Client, type Environment } from '@botfabrik/engine-domain';
2
- import { type WebclientMiddlewareState, type WebClientProps } from './types';
3
- export * from './types';
2
+ import { type WebclientMiddlewareState, type WebClientProps } from './types.js';
3
+ export * from './types.js';
4
4
  declare const _default: (clientName: string, environment: Environment, props: WebClientProps) => Client<WebclientMiddlewareState>;
5
5
  export default _default;
package/dist/index.js CHANGED
@@ -1,47 +1,28 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- var __importDefault = (this && this.__importDefault) || function (mod) {
17
- return (mod && mod.__esModule) ? mod : { "default": mod };
18
- };
19
- Object.defineProperty(exports, "__esModule", { value: true });
20
- const engine_domain_1 = require("@botfabrik/engine-domain");
21
- const engine_transcript_export_1 = require("@botfabrik/engine-transcript-export");
22
- const express_1 = require("express");
23
- const package_json_1 = require("../package.json");
24
- const auth_1 = require("./auth");
25
- const constants_1 = require("./constants");
26
- const createSessionInfo_1 = __importDefault(require("./createSessionInfo"));
27
- const extractLocale_1 = __importDefault(require("./extractLocale"));
28
- const getSupportedClientLocale_1 = __importDefault(require("./getSupportedClientLocale"));
29
- const loadPreviousConversation_1 = __importDefault(require("./loadPreviousConversation"));
30
- const middleware_1 = __importDefault(require("./middleware"));
31
- const requestSessionData_1 = __importDefault(require("./requestSessionData"));
32
- const setTranslations_1 = __importDefault(require("./setTranslations"));
33
- const speechToText_1 = __importDefault(require("./speechToText"));
34
- const types_1 = require("./types");
35
- const views_1 = __importDefault(require("./views"));
36
- __exportStar(require("./types"), exports);
37
- exports.default = (clientName, environment, props) => async (bot) => {
38
- const logger = bot.logger.child({ clientType: constants_1.CLIENT_TYPE, clientName });
1
+ import { Actions, ActionTypes, BotUser, TextMessage, } from '@botfabrik/engine-domain';
2
+ import { getPdf } from '@botfabrik/engine-transcript-export';
3
+ import { static as serveStatic } from 'express';
4
+ import { setUpSamlAuth, storeLoginRequestToken, verifyLoginToken, } from './auth/index.js';
5
+ import { CLIENT_TYPE } from './constants.js';
6
+ import createSessionInfo from './createSessionInfo.js';
7
+ import extractLocale from './extractLocale.js';
8
+ import getSupportedClientLocale from './getSupportedClientLocale.js';
9
+ import loadPreviousConversation from './loadPreviousConversation.js';
10
+ import middleware from './middleware/index.js';
11
+ import requestSessionData from './requestSessionData.js';
12
+ import setTranslations from './setTranslations.js';
13
+ import speechToText from './speechToText.js';
14
+ import { Devices, } from './types.js';
15
+ import { version } from './version.js';
16
+ import index from './views/index.js';
17
+ export * from './types.js';
18
+ export default (clientName, environment, props) => async (bot) => {
19
+ const logger = bot.logger.child({ clientType: CLIENT_TYPE, clientName });
39
20
  // serve transcript pdf
40
21
  bot.webserver.express.use('/transcript-pdf/:sessionId', async (req, res) => {
41
22
  const sessionId = req.params['sessionId'];
42
23
  if (sessionId?.length) {
43
24
  const session = await bot.createSession(sessionId);
44
- const pdf = await (0, engine_transcript_export_1.getPdf)(session);
25
+ const pdf = await getPdf(session);
45
26
  res.set('Content-Type', 'application/pdf');
46
27
  res.set('Content-Disposition', 'attachment; filename="Transcript.pdf"');
47
28
  res.end(pdf);
@@ -64,7 +45,7 @@ exports.default = (clientName, environment, props) => async (bot) => {
64
45
  }
65
46
  }
66
47
  res.set('Content-Type', 'text/html; charset=utf-8');
67
- res.write((0, views_1.default)(serverUrl.toString(), `${server}/embed/bundle.js`));
48
+ res.write(index(serverUrl.toString(), `${server}/embed/bundle.js`));
68
49
  res.end();
69
50
  });
70
51
  if (!isFabVisible(props)) {
@@ -80,7 +61,7 @@ exports.default = (clientName, environment, props) => async (bot) => {
80
61
  }
81
62
  });
82
63
  }
83
- bot.webserver.express.use(`/${clientName}/embed`, (0, express_1.static)(__dirname + '/embed', serveStaticOptions));
64
+ bot.webserver.express.use(`/${clientName}/embed`, serveStatic(__dirname + '/embed', serveStaticOptions));
84
65
  bot.webserver.express.get(`/${clientName}/logo.svg`, (_req, res) => {
85
66
  res.redirect(`/cms/chatbot/design/logo.svg?client=${clientName}`);
86
67
  });
@@ -91,7 +72,7 @@ exports.default = (clientName, environment, props) => async (bot) => {
91
72
  res.redirect(`/cms/chatbot/design/fab.svg?client=${clientName}`);
92
73
  });
93
74
  // serve chat client resources
94
- bot.webserver.express.use(`/${clientName}`, (0, express_1.static)(__dirname + '/client', serveStaticOptions));
75
+ bot.webserver.express.use(`/${clientName}`, serveStatic(__dirname + '/client', serveStaticOptions));
95
76
  logger.info(`Webclient will be available on route: /${clientName}`);
96
77
  const nsp = bot.webserver.socket.of(`/${clientName}/chat`);
97
78
  nsp.on('connection', async (socket) => {
@@ -101,23 +82,23 @@ exports.default = (clientName, environment, props) => async (bot) => {
101
82
  socket.on('terminate-session', onTerminateSession(socket, bot));
102
83
  if (props.auth) {
103
84
  socket.on('login-requested', (data) => {
104
- (0, auth_1.storeLoginRequestToken)(data.loginRequestToken, socket.id);
85
+ storeLoginRequestToken(data.loginRequestToken, socket.id);
105
86
  });
106
87
  }
107
88
  }
108
89
  catch (error) {
109
90
  logger.error('Error while connecting webclient with backend.');
110
91
  logger.error(error);
111
- const errorMessage = new engine_domain_1.TextMessage('Sorry I can’t talk at the moment. Please try again later.', new engine_domain_1.BotUser());
112
- socket.emit('action', engine_domain_1.Actions.sendMessageToGuest(errorMessage));
92
+ const errorMessage = new TextMessage('Sorry I can’t talk at the moment. Please try again later.', new BotUser());
93
+ socket.emit('action', Actions.sendMessageToGuest(errorMessage));
113
94
  }
114
95
  });
115
96
  if (props.auth) {
116
- (0, auth_1.setUpSamlAuth)(bot, props.auth, clientName, nsp);
97
+ setUpSamlAuth(bot, props.auth, clientName, nsp);
117
98
  }
118
99
  const client = {
119
100
  name: `${clientName}Webclient`,
120
- middleware: (0, middleware_1.default)(clientName, nsp),
101
+ middleware: middleware(clientName, nsp),
121
102
  };
122
103
  return client;
123
104
  };
@@ -133,7 +114,7 @@ const serveStaticOptions = {
133
114
  res.setHeader('Cache-Control', 'max-age=31536000');
134
115
  }
135
116
  else {
136
- res.setHeader('ETag', package_json_1.version);
117
+ res.setHeader('ETag', version);
137
118
  }
138
119
  },
139
120
  };
@@ -142,21 +123,21 @@ const onTerminateSession = (socket, bot) => async ({ sessionId, // passed if the
142
123
  }) => {
143
124
  const session = await bot.createSession(sessionId);
144
125
  socket.leave(sessionId);
145
- await session.dispatch(engine_domain_1.Actions.guestDisconnected(sessionId));
126
+ await session.dispatch(Actions.guestDisconnected(sessionId));
146
127
  };
147
128
  const onStartChat = (socket, props, bot, clientName, environment, logger) => async ({ sessionId: sessionIdFromClient, userId: defaultUserId, querystrings, loginToken, }) => {
148
129
  try {
149
- const authenticatedUser = (0, auth_1.verifyLoginToken)(loginToken, props.auth, logger);
150
- const locale = (0, extractLocale_1.default)(querystrings, socket.request.headers['accept-language']);
130
+ const authenticatedUser = verifyLoginToken(loginToken, props.auth, logger);
131
+ const locale = extractLocale(querystrings, socket.request.headers['accept-language']);
151
132
  const sessionsCollection = bot.store.db.collection('sessions');
152
- const { sessionId, sessionInfo: defaultSessionInfo, isNew, } = await (0, requestSessionData_1.default)(sessionIdFromClient, querystrings, sessionsCollection, clientName, props);
133
+ const { sessionId, sessionInfo: defaultSessionInfo, isNew, } = await requestSessionData(sessionIdFromClient, querystrings, sessionsCollection, clientName, props);
153
134
  // create a channel for each session
154
135
  socket.join(sessionId);
155
- const sessionInfo = await (0, createSessionInfo_1.default)(socket, clientName, environment, defaultSessionInfo, defaultUserId, locale, querystrings, authenticatedUser, props)();
136
+ const sessionInfo = await createSessionInfo(socket, clientName, environment, defaultSessionInfo, defaultUserId, locale, querystrings, authenticatedUser, props)();
156
137
  const session = await bot.createSession(sessionId, sessionInfo);
157
138
  sendConfigurationToClient(socket, props, bot, clientName);
158
139
  // sending persisted state to client
159
- const previousConversations = await (0, loadPreviousConversation_1.default)(bot.store, sessionId);
140
+ const previousConversations = await loadPreviousConversation(bot.store, sessionId);
160
141
  socket.emit('restore-client-state', {
161
142
  sessionId,
162
143
  messages: previousConversations,
@@ -168,7 +149,7 @@ const onStartChat = (socket, props, bot, clientName, environment, logger) => asy
168
149
  });
169
150
  }
170
151
  // Notify middlewares about a connected or reconnected guest
171
- await session.dispatch(engine_domain_1.Actions.guestConnected(sessionId));
152
+ await session.dispatch(Actions.guestConnected(sessionId));
172
153
  if (isNew && props.getStartedAction) {
173
154
  await session.dispatch(props.getStartedAction);
174
155
  }
@@ -176,24 +157,24 @@ const onStartChat = (socket, props, bot, clientName, environment, logger) => asy
176
157
  await session.dispatch(JSON.parse(action));
177
158
  });
178
159
  registerListener(socket, 'disconnect', async () => {
179
- await session.dispatch(engine_domain_1.Actions.guestDisconnected(sessionId));
160
+ await session.dispatch(Actions.guestDisconnected(sessionId));
180
161
  });
181
162
  registerListener(socket, 'conversation-rating', async (rating) => {
182
163
  sessionsCollection.updateOne({ _id: sessionId }, {
183
164
  $set: { 'sessionInfo.client.payload.conversationRating': rating },
184
165
  });
185
166
  session.dispatch({
186
- type: engine_domain_1.ActionTypes.CONVERSATION_RATING_FROM_GUEST,
167
+ type: ActionTypes.CONVERSATION_RATING_FROM_GUEST,
187
168
  payload: { rating },
188
169
  });
189
170
  });
190
171
  registerListener(socket, 'audio-message', async (buffer) => {
191
172
  if (props.speech) {
192
173
  try {
193
- const text = await (0, speechToText_1.default)(props.speech, session.translator.locale, buffer);
174
+ const text = await speechToText(props.speech, session.translator.locale, buffer);
194
175
  if (text && text.length) {
195
176
  socket.emit('speech-transcription', text);
196
- session.dispatch(engine_domain_1.Actions.receiveTextMessageFromGuest(text));
177
+ session.dispatch(Actions.receiveTextMessageFromGuest(text));
197
178
  }
198
179
  }
199
180
  catch (error) {
@@ -215,12 +196,12 @@ const registerListener = (socket, event, listener) => {
215
196
  };
216
197
  const sendConfigurationToClient = (socket, props, bot, clientName) => {
217
198
  // sending active language and translations to client
218
- const locale = (0, extractLocale_1.default)(socket.handshake.query, socket.request.headers['accept-language']);
199
+ const locale = extractLocale(socket.handshake.query, socket.request.headers['accept-language']);
219
200
  const supportedLocale = bot.translation.detectSupportedLocale(locale);
220
- const clientLocale = (0, getSupportedClientLocale_1.default)(supportedLocale);
221
- (0, setTranslations_1.default)(socket, bot, clientLocale, clientName);
201
+ const clientLocale = getSupportedClientLocale(supportedLocale);
202
+ setTranslations(socket, bot, clientLocale, clientName);
222
203
  const settings = {
223
- version: package_json_1.version,
204
+ version,
224
205
  requiresUserAuthentication: !!props.auth,
225
206
  enableStartScreen: !!props.enableStartScreen || !!props.auth,
226
207
  enableStandaloneView: !!props.enableStandaloneView,
@@ -233,7 +214,7 @@ const sendConfigurationToClient = (socket, props, bot, clientName) => {
233
214
  };
234
215
  socket.emit('set-settings', settings);
235
216
  if (props.expandChatWindowAtStart &&
236
- props.expandChatWindowAtStart !== types_1.Devices.None) {
217
+ props.expandChatWindowAtStart !== Devices.None) {
237
218
  socket.emit('expand-window', {
238
219
  devices: props.expandChatWindowAtStart,
239
220
  initial: true,
@@ -1,6 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const engine_domain_1 = require("@botfabrik/engine-domain");
1
+ import { ActionTypes, } from '@botfabrik/engine-domain';
4
2
  const loadPreviousConversations = async (store, sessionId) => {
5
3
  const actionLogs = await store.db
6
4
  .collection('actionlog')
@@ -9,9 +7,9 @@ const loadPreviousConversations = async (store, sessionId) => {
9
7
  { _sessionId: sessionId },
10
8
  {
11
9
  $or: [
12
- { type: engine_domain_1.ActionTypes.MESSAGE_FROM_GUEST },
13
- { type: engine_domain_1.ActionTypes.MESSAGE_WITHOUT_ANALYSIS_FROM_GUEST },
14
- { type: engine_domain_1.ActionTypes.MESSAGE_TO_GUEST },
10
+ { type: ActionTypes.MESSAGE_FROM_GUEST },
11
+ { type: ActionTypes.MESSAGE_WITHOUT_ANALYSIS_FROM_GUEST },
12
+ { type: ActionTypes.MESSAGE_TO_GUEST },
15
13
  ],
16
14
  },
17
15
  ],
@@ -34,4 +32,4 @@ const loadPreviousConversations = async (store, sessionId) => {
34
32
  });
35
33
  return messages;
36
34
  };
37
- exports.default = loadPreviousConversations;
35
+ export default loadPreviousConversations;
@@ -1,5 +1,5 @@
1
1
  import { type Middleware } from '@botfabrik/engine-domain';
2
2
  import type { Namespace } from 'socket.io';
3
- import { type WebclientMiddlewareState } from '../types';
3
+ import { type WebclientMiddlewareState } from '../types.js';
4
4
  declare const _default: (clientName: string, nsp: Namespace) => Middleware<WebclientMiddlewareState>;
5
5
  export default _default;
@@ -1,40 +1,35 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const engine_domain_1 = require("@botfabrik/engine-domain");
7
- const engine_utils_1 = require("@botfabrik/engine-utils");
8
- const setTranslations_1 = __importDefault(require("../setTranslations"));
9
- const types_1 = require("../types");
10
- exports.default = (clientName, nsp) => async (bot) => {
1
+ import { ActionTypes, } from '@botfabrik/engine-domain';
2
+ import { waitFor, waitForTyping } from '@botfabrik/engine-utils';
3
+ import setTranslations from '../setTranslations.js';
4
+ import { Devices, } from '../types.js';
5
+ export default (clientName, nsp) => async (bot) => {
11
6
  return async (next, _state, action, session) => {
12
7
  const sessionInfo = session.getSessionInfo();
13
8
  const clientInfo = sessionInfo.client;
14
9
  if (clientInfo.type === 'webclient' && clientInfo.name === clientName) {
15
10
  switch (action.type) {
16
- case engine_domain_1.ActionTypes.MESSAGE_TO_GUEST:
11
+ case ActionTypes.MESSAGE_TO_GUEST:
17
12
  await emitMessageToGuestAction(nsp, session, action);
18
13
  break;
19
- case engine_domain_1.ActionTypes.TYPING_ON:
20
- case engine_domain_1.ActionTypes.TYPING_OFF:
21
- case engine_domain_1.ActionTypes.EVENT_TO_GUEST:
22
- case engine_domain_1.ActionTypes.MESSAGE_FROM_GUEST:
23
- case engine_domain_1.ActionTypes.MESSAGE_WITHOUT_ANALYSIS_FROM_GUEST:
24
- case engine_domain_1.ActionTypes.DRAWER_OPEN:
25
- case engine_domain_1.ActionTypes.DRAWER_CLOSE:
14
+ case ActionTypes.TYPING_ON:
15
+ case ActionTypes.TYPING_OFF:
16
+ case ActionTypes.EVENT_TO_GUEST:
17
+ case ActionTypes.MESSAGE_FROM_GUEST:
18
+ case ActionTypes.MESSAGE_WITHOUT_ANALYSIS_FROM_GUEST:
19
+ case ActionTypes.DRAWER_OPEN:
20
+ case ActionTypes.DRAWER_CLOSE:
26
21
  await sendToChatClient(nsp, session, action);
27
22
  break;
28
23
  case 'webclient.window.expand':
29
24
  expandChatWindow(nsp, session, action);
30
25
  break;
31
- case engine_domain_1.ActionTypes.RESTART_CHAT_REQUEST:
26
+ case ActionTypes.RESTART_CHAT_REQUEST:
32
27
  restartChat(nsp, session);
33
28
  break;
34
- case engine_domain_1.ActionTypes.GUEST_LOCALE_CHANGED:
29
+ case ActionTypes.GUEST_LOCALE_CHANGED:
35
30
  {
36
31
  const { locale } = session.translator;
37
- (0, setTranslations_1.default)(nsp, bot, locale, clientName);
32
+ setTranslations(nsp, bot, locale, clientName);
38
33
  await sendToChatClient(nsp, session, action);
39
34
  }
40
35
  break;
@@ -46,18 +41,18 @@ exports.default = (clientName, nsp) => async (bot) => {
46
41
  const emitMessageToGuestAction = async (nsp, session, action) => {
47
42
  const useTyping = !action.noTypingDelay;
48
43
  if (useTyping) {
49
- nsp.to(session.id).emit('action', { type: engine_domain_1.ActionTypes.TYPING_ON });
50
- await (0, engine_utils_1.waitForTyping)(action['message']);
44
+ nsp.to(session.id).emit('action', { type: ActionTypes.TYPING_ON });
45
+ await waitForTyping(action['message']);
51
46
  }
52
47
  await sendToChatClient(nsp, session, action);
53
- await (0, engine_utils_1.waitFor)(500);
48
+ await waitFor(500);
54
49
  };
55
50
  const sendToChatClient = async (nsp, session, action) => {
56
51
  nsp.to(session.id).emit('action', action);
57
52
  };
58
53
  const expandChatWindow = (nsp, session, action) => {
59
54
  const devices = action.payload?.devices;
60
- if (!!devices && devices !== types_1.Devices.None) {
55
+ if (!!devices && devices !== Devices.None) {
61
56
  nsp
62
57
  .to(session.id)
63
58
  .emit('expand-window', { devices: action.payload.devices });
@@ -1,5 +1,5 @@
1
1
  import type { SessionInfo } from '@botfabrik/engine-domain';
2
- import type { SessionInfoClientPayload, SessionInfoUserPayload, WebClientProps } from './types';
2
+ import type { SessionInfoClientPayload, SessionInfoUserPayload, WebClientProps } from './types.js';
3
3
  interface SessionData {
4
4
  sessionId: string;
5
5
  sessionInfo: SessionInfo<SessionInfoClientPayload, SessionInfoUserPayload>;
@@ -1,10 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const crypto_1 = require("crypto");
4
- const constants_1 = require("./constants");
1
+ import { randomUUID } from 'node:crypto';
2
+ import { CLIENT_TYPE } from './constants.js';
5
3
  const requestSessionData = async (sessionId, querystrings, sessionsCollection, clientName, props) => {
6
4
  const baseQuery = {
7
- 'sessionInfo.client.type': constants_1.CLIENT_TYPE,
5
+ 'sessionInfo.client.type': CLIENT_TYPE,
8
6
  'sessionInfo.client.name': clientName,
9
7
  };
10
8
  let findSessionRecordQuery;
@@ -31,7 +29,7 @@ const requestSessionData = async (sessionId, querystrings, sessionsCollection, c
31
29
  isNew = false;
32
30
  }
33
31
  else {
34
- sesId = (0, crypto_1.randomUUID)();
32
+ sesId = randomUUID();
35
33
  sessionInfo = {
36
34
  client: {},
37
35
  user: {},
@@ -45,4 +43,4 @@ const requestSessionData = async (sessionId, querystrings, sessionsCollection, c
45
43
  isNew,
46
44
  };
47
45
  };
48
- exports.default = requestSessionData;
46
+ export default requestSessionData;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,107 +1,97 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const globals_1 = require("@jest/globals");
7
- const requestSessionData_1 = __importDefault(require("./requestSessionData"));
8
- globals_1.jest.mock('crypto', () => {
9
- const original = globals_1.jest.requireActual('crypto');
10
- return {
11
- v4: globals_1.jest.fn(() => 'uuid'),
12
- ...original,
13
- randomUUID: globals_1.jest.fn(() => 'some-uuid'),
14
- };
15
- });
16
- (0, globals_1.describe)('request session id', () => {
17
- (0, globals_1.beforeEach)(() => {
18
- globals_1.jest.clearAllMocks();
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import requestSessionData from './requestSessionData.js';
3
+ vi.mock('node:crypto', () => ({
4
+ randomUUID: vi.fn(() => 'some-uuid'),
5
+ }));
6
+ describe('request session id', () => {
7
+ beforeEach(() => {
8
+ vi.clearAllMocks();
19
9
  });
20
10
  const querystrings = {
21
11
  accessToken: 'access-token',
22
12
  };
23
- (0, globals_1.it)('when sessionId has been passed by query param but does not exists in db', async () => {
24
- const findOne = globals_1.jest.fn();
13
+ it('when sessionId has been passed by query param but does not exists in db', async () => {
14
+ const findOne = vi.fn();
25
15
  findOne.mockReturnValueOnce(undefined);
26
16
  const sessionsCollection = {
27
17
  findOne,
28
18
  };
29
- const { sessionId, isNew } = await (0, requestSessionData_1.default)('session-id', querystrings, sessionsCollection, 'test-bot', {});
30
- (0, globals_1.expect)(findOne).toHaveBeenCalledTimes(1);
31
- (0, globals_1.expect)(findOne).toHaveBeenCalledWith({
19
+ const { sessionId, isNew } = await requestSessionData('session-id', querystrings, sessionsCollection, 'test-bot', {});
20
+ expect(findOne).toHaveBeenCalledTimes(1);
21
+ expect(findOne).toHaveBeenCalledWith({
32
22
  _id: 'session-id',
33
23
  'sessionInfo.client.name': 'test-bot',
34
24
  'sessionInfo.client.type': 'webclient',
35
25
  }, { _id: 1, sessionInfo: 1 });
36
- (0, globals_1.expect)(sessionId).toBe('some-uuid');
37
- (0, globals_1.expect)(isNew).toBe(true);
26
+ expect(sessionId).toBe('some-uuid');
27
+ expect(isNew).toBe(true);
38
28
  });
39
- (0, globals_1.it)('when sessionId has been passed by query param and exists in db', async () => {
40
- const findOne = globals_1.jest.fn();
29
+ it('when sessionId has been passed by query param and exists in db', async () => {
30
+ const findOne = vi.fn();
41
31
  findOne.mockReturnValueOnce({ _id: 'session-id' });
42
32
  const sessionsCollection = {
43
33
  findOne,
44
34
  };
45
- const { sessionId, isNew } = await (0, requestSessionData_1.default)('session-id', querystrings, sessionsCollection, 'test-bot', {});
46
- (0, globals_1.expect)(findOne).toHaveBeenCalledTimes(1);
47
- (0, globals_1.expect)(findOne).toHaveBeenCalledWith({
35
+ const { sessionId, isNew } = await requestSessionData('session-id', querystrings, sessionsCollection, 'test-bot', {});
36
+ expect(findOne).toHaveBeenCalledTimes(1);
37
+ expect(findOne).toHaveBeenCalledWith({
48
38
  _id: 'session-id',
49
39
  'sessionInfo.client.name': 'test-bot',
50
40
  'sessionInfo.client.type': 'webclient',
51
41
  }, { _id: 1, sessionInfo: 1 });
52
- (0, globals_1.expect)(sessionId).toBe('session-id');
53
- (0, globals_1.expect)(isNew).toBe(false);
42
+ expect(sessionId).toBe('session-id');
43
+ expect(isNew).toBe(false);
54
44
  });
55
- (0, globals_1.it)('when requestSessionRecordQuery has been passed as webclient property but no such session exists in db', async () => {
56
- const findOne = globals_1.jest.fn();
45
+ it('when requestSessionRecordQuery has been passed as webclient property but no such session exists in db', async () => {
46
+ const findOne = vi.fn();
57
47
  findOne.mockReturnValueOnce(undefined);
58
48
  const sessionsCollection = {
59
49
  findOne,
60
50
  };
61
- const requestSessionRecordQuery = globals_1.jest.fn();
51
+ const requestSessionRecordQuery = vi.fn();
62
52
  const props = {
63
53
  requestSessionRecordQuery,
64
54
  };
65
55
  requestSessionRecordQuery.mockReturnValueOnce(Promise.resolve({ 'sessionInfo.user.id': 'hans@apptiva.ch' }));
66
- const { sessionId, isNew } = await (0, requestSessionData_1.default)('session-id', querystrings, sessionsCollection, 'test-bot', props);
67
- (0, globals_1.expect)(requestSessionRecordQuery).toHaveBeenCalledTimes(1);
68
- (0, globals_1.expect)(requestSessionRecordQuery).toHaveBeenCalledWith({
56
+ const { sessionId, isNew } = await requestSessionData('session-id', querystrings, sessionsCollection, 'test-bot', props);
57
+ expect(requestSessionRecordQuery).toHaveBeenCalledTimes(1);
58
+ expect(requestSessionRecordQuery).toHaveBeenCalledWith({
69
59
  querystrings,
70
60
  sessionId: 'session-id',
71
61
  });
72
- (0, globals_1.expect)(findOne).toHaveBeenCalledTimes(1);
73
- (0, globals_1.expect)(findOne).toHaveBeenCalledWith({
62
+ expect(findOne).toHaveBeenCalledTimes(1);
63
+ expect(findOne).toHaveBeenCalledWith({
74
64
  'sessionInfo.client.name': 'test-bot',
75
65
  'sessionInfo.client.type': 'webclient',
76
66
  'sessionInfo.user.id': 'hans@apptiva.ch',
77
67
  }, { _id: 1, sessionInfo: 1 });
78
- (0, globals_1.expect)(sessionId).toBe('some-uuid');
79
- (0, globals_1.expect)(isNew).toBe(true);
68
+ expect(sessionId).toBe('some-uuid');
69
+ expect(isNew).toBe(true);
80
70
  });
81
- (0, globals_1.it)('when requestSessionRecordQuery has been passed as webclient property and session exists in db', async () => {
82
- const findOne = globals_1.jest.fn();
71
+ it('when requestSessionRecordQuery has been passed as webclient property and session exists in db', async () => {
72
+ const findOne = vi.fn();
83
73
  findOne.mockReturnValueOnce({ _id: 'session-id' });
84
74
  const sessionsCollection = {
85
75
  findOne,
86
76
  };
87
- const requestSessionRecordQuery = globals_1.jest.fn();
77
+ const requestSessionRecordQuery = vi.fn();
88
78
  const props = {
89
79
  requestSessionRecordQuery,
90
80
  };
91
81
  requestSessionRecordQuery.mockReturnValueOnce(Promise.resolve({ 'sessionInfo.user.id': 'hans@apptiva.ch' }));
92
- const { sessionId, isNew } = await (0, requestSessionData_1.default)('session-id', querystrings, sessionsCollection, 'test-bot', props);
93
- (0, globals_1.expect)(requestSessionRecordQuery).toHaveBeenCalledTimes(1);
94
- (0, globals_1.expect)(requestSessionRecordQuery).toHaveBeenCalledWith({
82
+ const { sessionId, isNew } = await requestSessionData('session-id', querystrings, sessionsCollection, 'test-bot', props);
83
+ expect(requestSessionRecordQuery).toHaveBeenCalledTimes(1);
84
+ expect(requestSessionRecordQuery).toHaveBeenCalledWith({
95
85
  querystrings,
96
86
  sessionId: 'session-id',
97
87
  });
98
- (0, globals_1.expect)(findOne).toHaveBeenCalledTimes(1);
99
- (0, globals_1.expect)(findOne).toHaveBeenCalledWith({
88
+ expect(findOne).toHaveBeenCalledTimes(1);
89
+ expect(findOne).toHaveBeenCalledWith({
100
90
  'sessionInfo.client.name': 'test-bot',
101
91
  'sessionInfo.client.type': 'webclient',
102
92
  'sessionInfo.user.id': 'hans@apptiva.ch',
103
93
  }, { _id: 1, sessionInfo: 1 });
104
- (0, globals_1.expect)(sessionId).toBe('session-id');
105
- (0, globals_1.expect)(isNew).toBe(false);
94
+ expect(sessionId).toBe('session-id');
95
+ expect(isNew).toBe(false);
106
96
  });
107
97
  });
@@ -1,6 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const flat_1 = require("flat");
1
+ import { flatten } from 'flat';
4
2
  const TRANSLATION_KEY = 'website-messenger';
5
3
  const setTranslations = (socket, bot, clientLocale, clientName) => {
6
4
  socket.emit('set-translations', clientLocale, getTranslationsByClient(bot, clientLocale, clientName));
@@ -9,9 +7,9 @@ const getTranslationsByClient = (bot, clientLocale, clientName) => {
9
7
  const webMessengerTranslations = bot.translation.getResourceBundle(clientLocale)[TRANSLATION_KEY] || {};
10
8
  const defaults = webMessengerTranslations['defaults'] || {};
11
9
  const overrides = webMessengerTranslations['overrides']?.[clientName] || {};
12
- const defaultFlat = (0, flat_1.flatten)(defaults);
13
- const overrideFlat = (0, flat_1.flatten)(overrides);
10
+ const defaultFlat = flatten(defaults);
11
+ const overrideFlat = flatten(overrides);
14
12
  const mergedTranslations = { ...defaultFlat, ...overrideFlat };
15
13
  return mergedTranslations;
16
14
  };
17
- exports.default = setTranslations;
15
+ export default setTranslations;
@@ -1,3 +1,3 @@
1
- import type { SpeechToTextProps } from './types';
1
+ import type { SpeechToTextProps } from './types.js';
2
2
  declare const speechToText: (speechProps: SpeechToTextProps, locale: string, speechBytes: any) => Promise<string>;
3
3
  export default speechToText;
@@ -1,6 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const speech_1 = require("@google-cloud/speech");
1
+ import { SpeechClient } from '@google-cloud/speech';
4
2
  const speechToText = (speechProps, locale, speechBytes) => {
5
3
  return new Promise((resolve, reject) => {
6
4
  const speechConfig = {
@@ -9,7 +7,7 @@ const speechToText = (speechProps, locale, speechBytes) => {
9
7
  client_email: speechProps.clientEmail,
10
8
  },
11
9
  };
12
- const client = new speech_1.SpeechClient(speechConfig);
10
+ const client = new SpeechClient(speechConfig);
13
11
  // The audio file's encoding, sample rate in hertz, and BCP-47 language code
14
12
  const audio = {
15
13
  content: speechBytes,
@@ -45,4 +43,4 @@ const speechToText = (speechProps, locale, speechBytes) => {
45
43
  .catch(reject);
46
44
  });
47
45
  };
48
- exports.default = speechToText;
46
+ export default speechToText;
package/dist/types.js CHANGED
@@ -1,10 +1,7 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Devices = void 0;
4
- var Devices;
1
+ export var Devices;
5
2
  (function (Devices) {
6
3
  Devices["All"] = "all";
7
4
  Devices["Mobile"] = "mobile";
8
5
  Devices["Desktop"] = "desktop";
9
6
  Devices["None"] = "none";
10
- })(Devices || (exports.Devices = Devices = {}));
7
+ })(Devices || (Devices = {}));
@@ -0,0 +1 @@
1
+ export declare const version: string;
@@ -0,0 +1,2 @@
1
+ import pkg from '../package.json' with { type: 'json' };
2
+ export const version = pkg.version;
@@ -1,5 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
1
  const index = (server, scriptUrl) => `<!DOCTYPE html>
4
2
  <html lang="de">
5
3
  <head>
@@ -166,4 +164,4 @@ const index = (server, scriptUrl) => `<!DOCTYPE html>
166
164
  </body>
167
165
  </html>
168
166
  `;
169
- exports.default = index;
167
+ export default index;
package/package.json CHANGED
@@ -1,9 +1,19 @@
1
1
  {
2
2
  "name": "@botfabrik/engine-webclient",
3
- "version": "4.101.2",
3
+ "version": "4.101.3-alpha.0",
4
4
  "description": "Webclient for Botfabriks Bot Engine",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "types": "./dist/index.d.ts",
14
+ "files": [
15
+ "dist"
16
+ ],
7
17
  "scripts": {
8
18
  "build": "npm run clean && npm run build:client && npm run build:server && npm run build:script-tag && npm run copy:client && npm run copy:script-tag",
9
19
  "build:script-tag": "(cd ./script-tag && npm run build && cd ..)",
@@ -12,17 +22,18 @@
12
22
  "copy:script-tag": "copyfiles -u 2 ./script-tag/dist/bundle.js ./dist/embed",
13
23
  "copy:client": "copyfiles -u 2 ./client/dist/** ./dist/client && copyfiles -u 2 ./client/dist/**/*.* ./dist/client",
14
24
  "clean": "rimraf ./dist",
15
- "test": "jest --verbose",
16
- "test:watch": "jest --watch",
25
+ "test": "vitest run --reporter=verbose",
26
+ "test:ci": "vitest run --reporter=verbose",
27
+ "test:watch": "vitest --watch --reporter=verbose",
17
28
  "prepare": "(cd client && npm install); (cd script-tag && npm install)",
18
29
  "prepublishOnly": "npm run build",
19
30
  "update": "npx npm-check-updates -i",
20
31
  "dev:embed": "tsx --watch ./run-embed-local.ts"
21
32
  },
22
33
  "dependencies": {
23
- "@botfabrik/engine-domain": "^4.101.2",
24
- "@botfabrik/engine-transcript-export": "^4.101.2",
25
- "@botfabrik/engine-utils": "^4.101.2",
34
+ "@botfabrik/engine-domain": "^4.101.3-alpha.0",
35
+ "@botfabrik/engine-transcript-export": "^4.101.3-alpha.0",
36
+ "@botfabrik/engine-utils": "^4.101.3-alpha.0",
26
37
  "@google-cloud/speech": "^7.2.1",
27
38
  "@node-saml/passport-saml": "^5.1.0",
28
39
  "accept-language-parser": "^1.5.0",
@@ -43,5 +54,5 @@
43
54
  "tsx": "^4.20.6",
44
55
  "typescript": "5.9.3"
45
56
  },
46
- "gitHead": "c3845efabb642e4d1bd09af8bfda89cce7702236"
57
+ "gitHead": "668bb5e26c514e7d091febc092c784db0dd65210"
47
58
  }