@aws-amplify/interactions 4.0.48 → 4.0.49-next.13

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/dist/aws-amplify-interactions.js +25945 -6010
  3. package/dist/aws-amplify-interactions.js.map +1 -1
  4. package/dist/aws-amplify-interactions.min.js +64 -4
  5. package/dist/aws-amplify-interactions.min.js.map +1 -1
  6. package/lib/Interactions.d.ts +2 -2
  7. package/lib/Interactions.js +37 -18
  8. package/lib/Interactions.js.map +1 -1
  9. package/lib/Providers/AWSLexProvider.d.ts +16 -3
  10. package/lib/Providers/AWSLexProvider.js +114 -68
  11. package/lib/Providers/AWSLexProvider.js.map +1 -1
  12. package/lib/Providers/AWSLexProviderHelper/commonUtils.d.ts +1 -0
  13. package/lib/Providers/AWSLexProviderHelper/{convert.native.js → commonUtils.js} +36 -18
  14. package/lib/Providers/AWSLexProviderHelper/commonUtils.js.map +1 -0
  15. package/lib/Providers/AWSLexProviderHelper/utils.d.ts +3 -0
  16. package/lib/Providers/AWSLexProviderHelper/utils.js +83 -0
  17. package/lib/Providers/AWSLexProviderHelper/utils.js.map +1 -0
  18. package/lib/Providers/AWSLexProviderHelper/utils.native.d.ts +3 -0
  19. package/lib/Providers/AWSLexProviderHelper/utils.native.js +100 -0
  20. package/lib/Providers/AWSLexProviderHelper/utils.native.js.map +1 -0
  21. package/lib/Providers/AWSLexV2Provider.d.ts +58 -0
  22. package/lib/Providers/AWSLexV2Provider.js +351 -0
  23. package/lib/Providers/AWSLexV2Provider.js.map +1 -0
  24. package/lib/Providers/index.d.ts +1 -0
  25. package/lib/Providers/index.js +1 -0
  26. package/lib/Providers/index.js.map +1 -1
  27. package/lib/index.d.ts +2 -0
  28. package/lib/index.js +2 -0
  29. package/lib/index.js.map +1 -1
  30. package/lib/types/Provider.d.ts +2 -1
  31. package/lib/types/Providers/AWSLexProvider.d.ts +10 -0
  32. package/lib/types/Providers/AWSLexProvider.js +3 -0
  33. package/lib/types/Providers/AWSLexProvider.js.map +1 -0
  34. package/lib/types/Providers/AWSLexV2Provider.d.ts +12 -0
  35. package/lib/types/Providers/AWSLexV2Provider.js +3 -0
  36. package/lib/types/Providers/AWSLexV2Provider.js.map +1 -0
  37. package/lib/types/index.d.ts +2 -0
  38. package/lib-esm/Interactions.d.ts +2 -2
  39. package/lib-esm/Interactions.js +37 -18
  40. package/lib-esm/Interactions.js.map +1 -1
  41. package/lib-esm/Providers/AWSLexProvider.d.ts +16 -3
  42. package/lib-esm/Providers/AWSLexProvider.js +113 -67
  43. package/lib-esm/Providers/AWSLexProvider.js.map +1 -1
  44. package/lib-esm/Providers/AWSLexProviderHelper/commonUtils.d.ts +1 -0
  45. package/lib-esm/Providers/AWSLexProviderHelper/{convert.native.js → commonUtils.js} +36 -18
  46. package/lib-esm/Providers/AWSLexProviderHelper/commonUtils.js.map +1 -0
  47. package/lib-esm/Providers/AWSLexProviderHelper/utils.d.ts +3 -0
  48. package/lib-esm/Providers/AWSLexProviderHelper/utils.js +81 -0
  49. package/lib-esm/Providers/AWSLexProviderHelper/utils.js.map +1 -0
  50. package/lib-esm/Providers/AWSLexProviderHelper/utils.native.d.ts +3 -0
  51. package/lib-esm/Providers/AWSLexProviderHelper/utils.native.js +98 -0
  52. package/lib-esm/Providers/AWSLexProviderHelper/utils.native.js.map +1 -0
  53. package/lib-esm/Providers/AWSLexV2Provider.d.ts +58 -0
  54. package/lib-esm/Providers/AWSLexV2Provider.js +349 -0
  55. package/lib-esm/Providers/AWSLexV2Provider.js.map +1 -0
  56. package/lib-esm/Providers/index.d.ts +1 -0
  57. package/lib-esm/Providers/index.js +1 -0
  58. package/lib-esm/Providers/index.js.map +1 -1
  59. package/lib-esm/index.d.ts +2 -0
  60. package/lib-esm/index.js +2 -0
  61. package/lib-esm/index.js.map +1 -1
  62. package/lib-esm/types/Provider.d.ts +2 -1
  63. package/lib-esm/types/Providers/AWSLexProvider.d.ts +10 -0
  64. package/lib-esm/types/Providers/AWSLexProvider.js +1 -0
  65. package/lib-esm/types/Providers/AWSLexProvider.js.map +1 -0
  66. package/lib-esm/types/Providers/AWSLexV2Provider.d.ts +12 -0
  67. package/lib-esm/types/Providers/AWSLexV2Provider.js +1 -0
  68. package/lib-esm/types/Providers/AWSLexV2Provider.js.map +1 -0
  69. package/lib-esm/types/index.d.ts +2 -0
  70. package/package.json +8 -4
  71. package/src/Interactions.ts +43 -21
  72. package/src/Providers/AWSLexProvider.ts +70 -23
  73. package/src/Providers/AWSLexProviderHelper/commonUtils.ts +27 -0
  74. package/src/Providers/AWSLexProviderHelper/utils.native.ts +56 -0
  75. package/src/Providers/AWSLexProviderHelper/utils.ts +39 -0
  76. package/src/Providers/AWSLexV2Provider.ts +343 -0
  77. package/src/Providers/index.ts +1 -0
  78. package/src/index.ts +2 -0
  79. package/src/types/Provider.ts +1 -1
  80. package/src/types/Providers/AWSLexProvider.ts +23 -0
  81. package/src/types/Providers/AWSLexV2Provider.ts +25 -0
  82. package/src/types/index.ts +2 -0
  83. package/lib/Providers/AWSLexProviderHelper/convert.d.ts +0 -3
  84. package/lib/Providers/AWSLexProviderHelper/convert.js +0 -13
  85. package/lib/Providers/AWSLexProviderHelper/convert.js.map +0 -1
  86. package/lib/Providers/AWSLexProviderHelper/convert.native.d.ts +0 -1
  87. package/lib/Providers/AWSLexProviderHelper/convert.native.js.map +0 -1
  88. package/lib-esm/Providers/AWSLexProviderHelper/convert.d.ts +0 -3
  89. package/lib-esm/Providers/AWSLexProviderHelper/convert.js +0 -11
  90. package/lib-esm/Providers/AWSLexProviderHelper/convert.js.map +0 -1
  91. package/lib-esm/Providers/AWSLexProviderHelper/convert.native.d.ts +0 -1
  92. package/lib-esm/Providers/AWSLexProviderHelper/convert.native.js.map +0 -1
  93. package/src/Providers/AWSLexProviderHelper/convert.native.ts +0 -13
  94. package/src/Providers/AWSLexProviderHelper/convert.ts +0 -12
@@ -31,7 +31,7 @@ export class InteractionsClass {
31
31
  *
32
32
  * @param {InteractionsOptions} options - Configuration object for Interactions
33
33
  */
34
- constructor(options: InteractionsOptions) {
34
+ constructor(options: InteractionsOptions = {}) {
35
35
  this._options = options;
36
36
  logger.debug('Interactions Options', this._options);
37
37
  this._pluggables = {};
@@ -44,9 +44,9 @@ export class InteractionsClass {
44
44
  /**
45
45
  *
46
46
  * @param {InteractionsOptions} options - Configuration object for Interactions
47
- * @return {Object} - The current configuration
47
+ * @return {InteractionsOptions} - The current configuration
48
48
  */
49
- configure(options: InteractionsOptions) {
49
+ public configure(options: InteractionsOptions): InteractionsOptions {
50
50
  const opt = options ? options.Interactions || options : {};
51
51
  logger.debug('configure Interactions', { opt });
52
52
  this._options = { bots: {}, ...opt, ...opt.Interactions };
@@ -63,19 +63,27 @@ export class InteractionsClass {
63
63
  }
64
64
  }
65
65
 
66
- // Check if AWSLex provider is already on pluggables
67
- if (
68
- !this._pluggables.AWSLexProvider &&
69
- bots_config &&
70
- Object.keys(bots_config)
71
- .map(key => bots_config[key])
72
- .find(bot => !bot.providerName || bot.providerName === 'AWSLexProvider')
73
- ) {
74
- this._pluggables.AWSLexProvider = new AWSLexProvider();
75
- }
66
+ // configure bots to their specific providers
67
+ Object.keys(bots_config).forEach(botKey => {
68
+ const bot = bots_config[botKey];
69
+ const providerName = bot.providerName || 'AWSLexProvider';
70
+
71
+ // add default provider if required
72
+ if (
73
+ !this._pluggables.AWSLexProvider &&
74
+ providerName === 'AWSLexProvider'
75
+ ) {
76
+ this._pluggables.AWSLexProvider = new AWSLexProvider();
77
+ }
76
78
 
77
- Object.keys(this._pluggables).map(key => {
78
- this._pluggables[key].configure(this._options.bots);
79
+ // configure bot with it's respective provider
80
+ if (this._pluggables[providerName]) {
81
+ this._pluggables[providerName].configure({ [bot.name]: bot });
82
+ } else {
83
+ logger.debug(
84
+ `bot ${bot.name} was not configured as ${providerName} provider was not found`
85
+ );
86
+ }
79
87
  });
80
88
 
81
89
  return this._options;
@@ -84,12 +92,23 @@ export class InteractionsClass {
84
92
  public addPluggable(pluggable: InteractionsProvider) {
85
93
  if (pluggable && pluggable.getCategory() === 'Interactions') {
86
94
  if (!this._pluggables[pluggable.getProviderName()]) {
87
- pluggable.configure(this._options.bots);
95
+ // configure bots for the new plugin
96
+ Object.keys(this._options.bots)
97
+ .filter(
98
+ botKey =>
99
+ this._options.bots[botKey].providerName ===
100
+ pluggable.getProviderName()
101
+ )
102
+ .forEach(botKey => {
103
+ const bot = this._options.bots[botKey];
104
+ pluggable.configure({ [bot.name]: bot });
105
+ });
106
+
88
107
  this._pluggables[pluggable.getProviderName()] = pluggable;
89
108
  return;
90
109
  } else {
91
110
  throw new Error(
92
- 'Bot ' + pluggable.getProviderName() + ' already plugged'
111
+ 'Pluggable ' + pluggable.getProviderName() + ' already plugged'
93
112
  );
94
113
  }
95
114
  }
@@ -112,14 +131,14 @@ export class InteractionsClass {
112
131
  message: string | object
113
132
  ): Promise<InteractionsResponse> {
114
133
  if (!this._options.bots || !this._options.bots[botname]) {
115
- throw new Error('Bot ' + botname + ' does not exist');
134
+ return Promise.reject('Bot ' + botname + ' does not exist');
116
135
  }
117
136
 
118
137
  const botProvider =
119
138
  this._options.bots[botname].providerName || 'AWSLexProvider';
120
139
 
121
140
  if (!this._pluggables[botProvider]) {
122
- throw new Error(
141
+ return Promise.reject(
123
142
  'Bot ' +
124
143
  botProvider +
125
144
  ' does not have valid pluggin did you try addPluggable first?'
@@ -128,7 +147,10 @@ export class InteractionsClass {
128
147
  return await this._pluggables[botProvider].sendMessage(botname, message);
129
148
  }
130
149
 
131
- public onComplete(botname: string, callback: (err, confirmation) => void) {
150
+ public onComplete(
151
+ botname: string,
152
+ callback: (err, confirmation) => void
153
+ ): void {
132
154
  if (!this._options.bots || !this._options.bots[botname]) {
133
155
  throw new Error('Bot ' + botname + ' does not exist');
134
156
  }
@@ -146,5 +168,5 @@ export class InteractionsClass {
146
168
  }
147
169
  }
148
170
 
149
- export const Interactions = new InteractionsClass(null);
171
+ export const Interactions = new InteractionsClass();
150
172
  Amplify.register(Interactions);
@@ -10,27 +10,40 @@
10
10
  * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
11
  * and limitations under the License.
12
12
  */
13
-
14
13
  import { AbstractInteractionsProvider } from './InteractionsProvider';
15
14
  import {
16
15
  InteractionsOptions,
16
+ AWSLexProviderOptions,
17
17
  InteractionsResponse,
18
18
  InteractionsMessage,
19
19
  } from '../types';
20
20
  import {
21
21
  LexRuntimeServiceClient,
22
22
  PostTextCommand,
23
+ PostTextCommandInput,
24
+ PostTextCommandOutput,
23
25
  PostContentCommand,
26
+ PostContentCommandInput,
27
+ PostContentCommandOutput,
24
28
  } from '@aws-sdk/client-lex-runtime-service';
25
29
  import {
26
30
  ConsoleLogger as Logger,
27
31
  Credentials,
28
32
  getAmplifyUserAgent,
29
33
  } from '@aws-amplify/core';
30
- import { convert } from './AWSLexProviderHelper/convert';
34
+ import { convert } from './AWSLexProviderHelper/utils';
31
35
 
32
36
  const logger = new Logger('AWSLexProvider');
33
37
 
38
+ interface PostContentCommandOutputFormatted
39
+ extends Omit<PostContentCommandOutput, 'audioStream'> {
40
+ audioStream?: Uint8Array;
41
+ }
42
+
43
+ type AWSLexProviderSendResponse =
44
+ | PostTextCommandOutput
45
+ | PostContentCommandOutputFormatted;
46
+
34
47
  export class AWSLexProvider extends AbstractInteractionsProvider {
35
48
  private lexRuntimeServiceClient: LexRuntimeServiceClient;
36
49
  private _botsCompleteCallback: object;
@@ -44,7 +57,27 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
44
57
  return 'AWSLexProvider';
45
58
  }
46
59
 
47
- reportBotStatus(data, botname) {
60
+ configure(config: AWSLexProviderOptions = {}): AWSLexProviderOptions {
61
+ const propertiesToTest = ['name', 'alias', 'region'];
62
+
63
+ Object.keys(config).forEach(botKey => {
64
+ const botConfig = config[botKey];
65
+
66
+ // is bot config correct
67
+ if (!propertiesToTest.every(x => x in botConfig)) {
68
+ throw new Error('invalid bot configuration');
69
+ }
70
+ });
71
+ return super.configure(config);
72
+ }
73
+
74
+ /**
75
+ * @private
76
+ * @deprecated
77
+ * This is used internally by 'sendMessage' to call onComplete callback
78
+ * for a bot if configured
79
+ */
80
+ reportBotStatus(data: AWSLexProviderSendResponse, botname: string) {
48
81
  // Check if state is fulfilled to resolve onFullfilment promise
49
82
  logger.debug('postContent state', data.dialogState);
50
83
  if (
@@ -52,21 +85,14 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
52
85
  data.dialogState === 'Fulfilled'
53
86
  ) {
54
87
  if (typeof this._botsCompleteCallback[botname] === 'function') {
55
- setTimeout(
56
- () =>
57
- this._botsCompleteCallback[botname](null, { slots: data.slots }),
58
- 0
59
- );
88
+ setTimeout(() => this._botsCompleteCallback[botname](null, data), 0);
60
89
  }
61
90
 
62
91
  if (
63
92
  this._config &&
64
93
  typeof this._config[botname].onComplete === 'function'
65
94
  ) {
66
- setTimeout(
67
- () => this._config[botname].onComplete(null, { slots: data.slots }),
68
- 0
69
- );
95
+ setTimeout(() => this._config[botname].onComplete(null, data), 0);
70
96
  }
71
97
  }
72
98
 
@@ -94,11 +120,16 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
94
120
  botname: string,
95
121
  message: string | InteractionsMessage
96
122
  ): Promise<InteractionsResponse> {
123
+ // check if bot exists
97
124
  if (!this._config[botname]) {
98
125
  return Promise.reject('Bot ' + botname + ' does not exist');
99
126
  }
100
- const credentials = await Credentials.get();
101
- if (!credentials) {
127
+
128
+ // check if credentials are present
129
+ let credentials;
130
+ try {
131
+ credentials = await Credentials.get();
132
+ } catch (error) {
102
133
  return Promise.reject('No credentials');
103
134
  }
104
135
 
@@ -108,7 +139,7 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
108
139
  customUserAgent: getAmplifyUserAgent(),
109
140
  });
110
141
 
111
- let params;
142
+ let params: PostTextCommandInput | PostContentCommandInput;
112
143
  if (typeof message === 'string') {
113
144
  params = {
114
145
  botAlias: this._config[botname].alias,
@@ -118,10 +149,10 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
118
149
  };
119
150
 
120
151
  logger.debug('postText to lex', message);
121
-
122
152
  try {
123
153
  const postTextCommand = new PostTextCommand(params);
124
154
  const data = await this.lexRuntimeServiceClient.send(postTextCommand);
155
+
125
156
  this.reportBotStatus(data, botname);
126
157
  return data;
127
158
  } catch (err) {
@@ -133,15 +164,24 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
133
164
  options: { messageType },
134
165
  } = message;
135
166
  if (messageType === 'voice') {
167
+ if (typeof content !== 'object') {
168
+ return Promise.reject('invalid content type');
169
+ }
170
+ const inputStream =
171
+ content instanceof Uint8Array ? content : await convert(content);
172
+
136
173
  params = {
137
174
  botAlias: this._config[botname].alias,
138
175
  botName: botname,
139
- contentType: 'audio/x-l16; sample-rate=16000',
140
- inputStream: content,
176
+ contentType: 'audio/x-l16; sample-rate=16000; channel-count=1',
141
177
  userId: credentials.identityId,
142
178
  accept: 'audio/mpeg',
179
+ inputStream,
143
180
  };
144
181
  } else {
182
+ if (typeof content !== 'string')
183
+ return Promise.reject('invalid content type');
184
+
145
185
  params = {
146
186
  botAlias: this._config[botname].alias,
147
187
  botName: botname,
@@ -157,18 +197,25 @@ export class AWSLexProvider extends AbstractInteractionsProvider {
157
197
  const data = await this.lexRuntimeServiceClient.send(
158
198
  postContentCommand
159
199
  );
160
- const audioArray = await convert(data.audioStream);
161
- this.reportBotStatus(data, botname);
162
- return { ...data, ...{ audioStream: audioArray } };
200
+
201
+ const audioArray = data.audioStream
202
+ ? await convert(data.audioStream)
203
+ : undefined;
204
+
205
+ const response = { ...data, ...{ audioStream: audioArray } };
206
+
207
+ this.reportBotStatus(response, botname);
208
+ return response;
163
209
  } catch (err) {
164
210
  return Promise.reject(err);
165
211
  }
166
212
  }
167
213
  }
168
214
 
169
- onComplete(botname: string, callback) {
215
+ onComplete(botname: string, callback: (err, confirmation) => void) {
216
+ // does bot exist
170
217
  if (!this._config[botname]) {
171
- throw new ErrorEvent('Bot ' + botname + ' does not exist');
218
+ throw new Error('Bot ' + botname + ' does not exist');
172
219
  }
173
220
  this._botsCompleteCallback[botname] = callback;
174
221
  }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright 2017-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
+ * the License. A copy of the License is located at
6
+ *
7
+ * http://aws.amazon.com/apache2.0/
8
+ *
9
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+ import { base64ToArrayBuffer, gzipDecompressToString } from './utils';
14
+
15
+ export const unGzipBase64AsJson = async (gzipBase64: string | undefined) => {
16
+ if (typeof gzipBase64 === 'undefined') return undefined;
17
+
18
+ try {
19
+ const decodedArrayBuffer = base64ToArrayBuffer(gzipBase64);
20
+
21
+ const objString: string = await gzipDecompressToString(decodedArrayBuffer);
22
+
23
+ return JSON.parse(objString);
24
+ } catch (error) {
25
+ return Promise.reject('unable to decode and decompress ' + error);
26
+ }
27
+ };
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright 2017-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
+ * the License. A copy of the License is located at
6
+ *
7
+ * http://aws.amazon.com/apache2.0/
8
+ *
9
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+
14
+ import { decode } from 'base-64';
15
+ import { ungzip } from 'pako';
16
+
17
+ export const convert = async (stream: object): Promise<Uint8Array> => {
18
+ if (!(stream instanceof Blob)) {
19
+ return Promise.reject('Invalid content type');
20
+ }
21
+
22
+ return new Promise(async (resolve, reject) => {
23
+ try {
24
+ const fileReaderInstance = new FileReader();
25
+ fileReaderInstance.readAsDataURL(stream);
26
+ fileReaderInstance.onload = async () => {
27
+ const blobURL = fileReaderInstance.result as string;
28
+
29
+ const base64Blob = blobURL.split(/,(.*)/s)[1];
30
+
31
+ const decodedArrayBuffer = base64ToArrayBuffer(base64Blob);
32
+ resolve(decodedArrayBuffer);
33
+ };
34
+ } catch (error) {
35
+ reject('unable to convert blob to arrayBuffer: ' + error);
36
+ }
37
+ });
38
+ };
39
+
40
+ export const base64ToArrayBuffer = (base64: string): Uint8Array => {
41
+ const binaryString: string = decode(base64);
42
+ return Uint8Array.from(binaryString, c => c.charCodeAt(0));
43
+ };
44
+
45
+ export const gzipDecompressToString = async (
46
+ data: Uint8Array
47
+ ): Promise<string> => {
48
+ return new Promise((resolve, reject) => {
49
+ try {
50
+ const result: string = ungzip(data, { to: 'string' });
51
+ resolve(result);
52
+ } catch (error) {
53
+ reject('unable to decompress' + error);
54
+ }
55
+ });
56
+ };
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright 2017-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
+ * the License. A copy of the License is located at
6
+ *
7
+ * http://aws.amazon.com/apache2.0/
8
+ *
9
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+
14
+ import { gunzip, strFromU8 } from 'fflate';
15
+
16
+ export const convert = async (stream: object): Promise<Uint8Array> => {
17
+ if (stream instanceof Blob || stream instanceof ReadableStream) {
18
+ return new Response(stream)
19
+ .arrayBuffer()
20
+ .then(buffer => new Uint8Array(buffer));
21
+ } else {
22
+ return Promise.reject('Invalid content type');
23
+ }
24
+ };
25
+
26
+ export const base64ToArrayBuffer = (base64: string): Uint8Array => {
27
+ return Uint8Array.from(window.atob(base64), c => c.charCodeAt(0));
28
+ };
29
+
30
+ export const gzipDecompressToString = async (
31
+ data: Uint8Array
32
+ ): Promise<string> => {
33
+ return await new Promise((resolve, reject) => {
34
+ gunzip(data, (err, resp) => {
35
+ if (err) reject(err);
36
+ else resolve(strFromU8(resp));
37
+ });
38
+ });
39
+ };