@onereach/step-voice 7.0.21 → 7.0.22-deskphones.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.
@@ -29,6 +29,7 @@ interface INPUT {
29
29
  name: string;
30
30
  value: string;
31
31
  }>;
32
+ uui?: unknown;
32
33
  enableSpoofCallerId?: boolean;
33
34
  spoofCallerId?: string;
34
35
  isAMD?: boolean;
@@ -7,6 +7,7 @@
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  const tslib_1 = require("tslib");
9
9
  const voice_1 = tslib_1.__importDefault(require("./voice"));
10
+ const uui_1 = require("./uui");
10
11
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
11
12
  const timestring_1 = tslib_1.__importDefault(require("timestring"));
12
13
  const uuid = tslib_1.__importStar(require("uuid"));
@@ -47,7 +48,7 @@ class InitiateCall extends voice_1.default {
47
48
  this.exitStep('cancel');
48
49
  }
49
50
  async waitForCall() {
50
- const { asr, tts, from: botNumber, endUserNumber, gatewaySettingsMode, sipHost, sipUser, sipPassword, sipProfile, timeout, headers, enableSpoofCallerId, spoofCallerId, isAMD, otherCallRef, otherCallRefThread, handleCancel, } = this.data;
51
+ const { asr, tts, from: botNumber, endUserNumber, gatewaySettingsMode, sipHost, sipUser, sipPassword, sipProfile, timeout, headers, uui, enableSpoofCallerId, spoofCallerId, isAMD, otherCallRef, otherCallRefThread, handleCancel, } = this.data;
51
52
  const call = await this.fetchData();
52
53
  this.triggers.once(`in/voice/${call.id}/event`, async (event) => {
53
54
  switch (event.params.type) {
@@ -69,6 +70,7 @@ class InitiateCall extends voice_1.default {
69
70
  const newCall = {
70
71
  headers: event.params.headers,
71
72
  ...event.params.channel,
73
+ uui: (0, uui_1.decodeUui)(event.params.headers),
72
74
  asr: asr.getSettings(),
73
75
  tts: tts.getVoice(),
74
76
  botNumber: event.params.channel.to ?? 'unknown',
@@ -157,10 +159,19 @@ class InitiateCall extends voice_1.default {
157
159
  this.triggers.otherwise(async () => {
158
160
  await this.triggers.flush();
159
161
  const originateTimeout = (0, timestring_1.default)(`${timeout ?? 30} sec`, 'ms'); // timeout or 30 seconds
160
- const customHeaders = lodash_1.default.reduce(headers, (memo, header) => {
162
+ const customHeaders = (0, uui_1.headersWithoutUui)(lodash_1.default.reduce(headers, (memo, header) => {
161
163
  memo[header.name] = `${header.value}`;
162
164
  return memo;
163
- }, {});
165
+ }, {}));
166
+ try {
167
+ (0, uui_1.assertUuiFits)(uui);
168
+ const encoded = (0, uui_1.encodeUui)(uui);
169
+ if (encoded != null)
170
+ customHeaders['User-to-User'] = encoded;
171
+ }
172
+ catch (error) {
173
+ this.throwError(error);
174
+ }
164
175
  // GET SIP PROFILE SETTINGS
165
176
  let gateway;
166
177
  const profile = sipProfile !== "default" /* SIP_PROFILE.DEFAULT */ ? sipProfile : undefined;
@@ -7,6 +7,7 @@
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  const tslib_1 = require("tslib");
9
9
  const voice_1 = tslib_1.__importDefault(require("./voice"));
10
+ const uui_1 = require("./uui");
10
11
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
11
12
  const defaultSessionTimeout = 5 * 60 * 1000;
12
13
  class WaitForCall extends voice_1.default {
@@ -30,6 +31,7 @@ class WaitForCall extends voice_1.default {
30
31
  // @ts-expect-error
31
32
  endUserNumber: event.params.channel?.from ?? 'unknown',
32
33
  ...event.params.channel,
34
+ uui: (0, uui_1.decodeUui)(event.params.headers),
33
35
  asr: asr.getSettings(),
34
36
  tts: tts.getVoice()
35
37
  };
package/dst/uui.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare function encodeUui(uui: unknown): string | undefined;
2
+ export declare function encodedUuiLength(uui: unknown): number;
3
+ export declare function assertUuiFits(uui: unknown): void;
4
+ export declare function decodeUui(headers?: Record<string, string>): Record<string, unknown>;
5
+ export declare function headersWithoutUui(headers?: Record<string, string>): Record<string, string>;
package/dst/uui.js ADDED
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.headersWithoutUui = exports.decodeUui = exports.assertUuiFits = exports.encodedUuiLength = exports.encodeUui = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
6
+ function uuiTypeName(uui) {
7
+ if (Array.isArray(uui))
8
+ return 'array';
9
+ if (uui === null)
10
+ return 'null';
11
+ return typeof uui;
12
+ }
13
+ function encodeUui(uui) {
14
+ if (uui === undefined || uui === null)
15
+ return undefined;
16
+ if (typeof uui === 'string')
17
+ return uui === '' ? undefined : uui;
18
+ if (Array.isArray(uui) || typeof uui === 'number' || typeof uui === 'boolean') {
19
+ throw new Error(`uui must be an object or a string, got ${uuiTypeName(uui)}`);
20
+ }
21
+ if (lodash_1.default.isPlainObject(uui)) {
22
+ if (lodash_1.default.isEmpty(uui))
23
+ return undefined;
24
+ const json = JSON.stringify(uui);
25
+ if (json === '{}')
26
+ return undefined;
27
+ const payload = Buffer.from(json, 'utf8').toString('base64');
28
+ return `${payload};encoding=base64`;
29
+ }
30
+ throw new Error(`uui must be an object or a string, got ${uuiTypeName(uui)}`);
31
+ }
32
+ exports.encodeUui = encodeUui;
33
+ function encodedUuiLength(uui) {
34
+ const encoded = encodeUui(uui);
35
+ return encoded == null ? 0 : encoded.length;
36
+ }
37
+ exports.encodedUuiLength = encodedUuiLength;
38
+ function assertUuiFits(uui) {
39
+ const length = encodedUuiLength(uui);
40
+ if (length > 256) {
41
+ throw new Error(`User-to-User final header value exceeds 256 characters (${length}). The cap is the final header value (object path includes ;encoding=base64).`);
42
+ }
43
+ }
44
+ exports.assertUuiFits = assertUuiFits;
45
+ function headerValue(headers, name) {
46
+ if (headers == null)
47
+ return undefined;
48
+ const found = Object.keys(headers).find(key => key.toLowerCase() === name.toLowerCase());
49
+ if (found == null)
50
+ return undefined;
51
+ const value = headers[found];
52
+ if (typeof value !== 'string' || value === '')
53
+ return undefined;
54
+ return value;
55
+ }
56
+ function parseEncoding(header) {
57
+ const parts = header.split(';').map(part => part.trim());
58
+ const payload = parts[0] ?? '';
59
+ let encoding;
60
+ for (const part of parts.slice(1)) {
61
+ const eq = part.indexOf('=');
62
+ if (eq === -1)
63
+ continue;
64
+ const key = part.slice(0, eq).trim().toLowerCase();
65
+ const val = part.slice(eq + 1).trim();
66
+ if (key === 'encoding')
67
+ encoding = val;
68
+ }
69
+ return { payload, encoding };
70
+ }
71
+ function asJsonObjectOrRaw(text) {
72
+ try {
73
+ const parsed = JSON.parse(text);
74
+ if (lodash_1.default.isPlainObject(parsed))
75
+ return parsed;
76
+ }
77
+ catch { }
78
+ return { raw: text };
79
+ }
80
+ function decodeUui(headers) {
81
+ const header = headerValue(headers, 'User-to-User') ?? headerValue(headers, 'X-User-to-User');
82
+ if (header == null)
83
+ return {};
84
+ const { payload, encoding } = parseEncoding(header);
85
+ if (encoding != null && encoding.toLowerCase() !== 'base64') {
86
+ return { raw: header };
87
+ }
88
+ const utf8 = Buffer.from(payload, 'base64').toString('utf8');
89
+ return asJsonObjectOrRaw(utf8);
90
+ }
91
+ exports.decodeUui = decodeUui;
92
+ function headersWithoutUui(headers) {
93
+ const next = {};
94
+ for (const [key, value] of Object.entries(headers ?? {})) {
95
+ const lower = key.toLowerCase();
96
+ if (lower === 'user-to-user' || lower === 'x-user-to-user')
97
+ continue;
98
+ next[key] = value;
99
+ }
100
+ return next;
101
+ }
102
+ exports.headersWithoutUui = headersWithoutUui;
package/dst/voice.d.ts CHANGED
@@ -28,6 +28,7 @@ export interface IVoiceCall extends IConversationData {
28
28
  to?: string;
29
29
  from?: string;
30
30
  headers?: Record<string, string>;
31
+ uui?: Record<string, unknown>;
31
32
  conference?: {
32
33
  room: string;
33
34
  user: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onereach/step-voice",
3
- "version": "7.0.21",
3
+ "version": "7.0.22-deskphones.0",
4
4
  "author": "Roman Zolotarov <roman.zolotarov@onereach.com>",
5
5
  "contributors": [
6
6
  "Roman Zolotarov",