@dereekb/nestjs 13.0.0 → 13.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +136 -118
- package/index.cjs.mjs +2 -0
- package/index.esm.js +136 -118
- package/mailgun/index.cjs.default.js +1 -0
- package/mailgun/index.cjs.js +496 -503
- package/mailgun/index.cjs.mjs +2 -0
- package/mailgun/index.esm.js +496 -503
- package/mailgun/package.json +19 -20
- package/openai/index.cjs.default.js +1 -0
- package/openai/index.cjs.js +194 -161
- package/openai/index.cjs.mjs +2 -0
- package/openai/index.esm.js +194 -161
- package/openai/package.json +19 -20
- package/package.json +32 -55
- package/stripe/index.cjs.default.js +1 -0
- package/stripe/index.cjs.js +158 -128
- package/stripe/index.cjs.mjs +2 -0
- package/stripe/index.esm.js +158 -128
- package/stripe/package.json +19 -20
- package/typeform/index.cjs.default.js +1 -0
- package/typeform/index.cjs.js +257 -240
- package/typeform/index.cjs.mjs +2 -0
- package/typeform/index.esm.js +257 -240
- package/typeform/package.json +19 -20
- package/vapiai/index.cjs.default.js +1 -0
- package/vapiai/index.cjs.js +203 -190
- package/vapiai/index.cjs.mjs +2 -0
- package/vapiai/index.esm.js +203 -190
- package/vapiai/package.json +19 -20
package/vapiai/index.esm.js
CHANGED
|
@@ -12,32 +12,32 @@ import { VapiClient } from '@vapi-ai/server-sdk';
|
|
|
12
12
|
* @returns
|
|
13
13
|
*/
|
|
14
14
|
function vapiAiWebhookEvent(event) {
|
|
15
|
-
|
|
15
|
+
return event;
|
|
16
16
|
}
|
|
17
|
-
const vapiaiEventHandlerFactory = handlerFactory(x => x.type, {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
const vapiaiEventHandlerFactory = handlerFactory((x) => x.type, {
|
|
18
|
+
defaultResult: {
|
|
19
|
+
handled: true,
|
|
20
|
+
response: undefined
|
|
21
|
+
},
|
|
22
|
+
negativeResult: {
|
|
23
|
+
handled: true,
|
|
24
|
+
response: undefined
|
|
25
|
+
}
|
|
26
26
|
});
|
|
27
27
|
const vapiaiEventHandlerConfigurerFactory = handlerConfigurerFactory({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
configurerForAccessor: (accessor) => {
|
|
29
|
+
// eslint-disable-next-line
|
|
30
|
+
const fnWithKey = handlerMappedSetFunctionFactory(accessor, vapiAiWebhookEvent);
|
|
31
|
+
const configurer = {
|
|
32
|
+
...accessor,
|
|
33
|
+
handleAssistantRequest: fnWithKey('assistant-request'),
|
|
34
|
+
handleStatusUpdate: fnWithKey('status-update'),
|
|
35
|
+
handleFunctionCall: fnWithKey('function-call'),
|
|
36
|
+
handleEndOfCallReport: fnWithKey('end-of-call-report'),
|
|
37
|
+
handleHang: fnWithKey('hang')
|
|
38
|
+
};
|
|
39
|
+
return configurer;
|
|
40
|
+
}
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
/******************************************************************************
|
|
@@ -84,55 +84,42 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
84
84
|
* @returns A function that verifies a VapiAi webhook event.
|
|
85
85
|
*/
|
|
86
86
|
function vapiAiWebhookEventVerifier(config) {
|
|
87
|
-
|
|
88
|
-
verificationType:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const verify = verificationType === 'hmac' ? verifyHmac : verificationType === 'secret' ? verifySecret : verifyNone;
|
|
123
|
-
return async (request, rawBody) => {
|
|
124
|
-
const requestBodyString = String(request.body);
|
|
125
|
-
const valid = verify({
|
|
126
|
-
request,
|
|
127
|
-
requestBodyString
|
|
128
|
-
});
|
|
129
|
-
const requestBody = JSON.parse(requestBodyString);
|
|
130
|
-
const result = {
|
|
131
|
-
valid,
|
|
132
|
-
event: requestBody.message
|
|
87
|
+
const { verificationType: inputVerificationType, secret: inputSecret, hmacSecret: inputHmacSecret, signaturePrefix: inputSignaturePrefix } = config;
|
|
88
|
+
const verificationType = inputVerificationType ?? (inputHmacSecret != null ? 'hmac' : 'secret'); // default to secret always, never default to none
|
|
89
|
+
const secretToken = (verificationType === 'hmac' ? (inputHmacSecret ?? inputSecret) : inputSecret) ?? '';
|
|
90
|
+
const signaturePrefix = inputSignaturePrefix ?? '';
|
|
91
|
+
function verifyNone(input) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
function verifySecret(input) {
|
|
95
|
+
const { request } = input;
|
|
96
|
+
const headers = request.headers;
|
|
97
|
+
const vapiSecret = headers['x-vapi-secret'];
|
|
98
|
+
const valid = vapiSecret === secretToken;
|
|
99
|
+
return valid;
|
|
100
|
+
}
|
|
101
|
+
function verifyHmac(input) {
|
|
102
|
+
const { request, requestBodyString } = input;
|
|
103
|
+
const headers = request.headers;
|
|
104
|
+
const timestamp = headers['x-timestamp'];
|
|
105
|
+
const vapiSignature = headers['x-signature'];
|
|
106
|
+
const message = `${timestamp}.${requestBodyString}`;
|
|
107
|
+
const hashForVerify = createHmac('sha256', secretToken).update(message).digest('hex');
|
|
108
|
+
const signature = `${signaturePrefix}${hashForVerify}`;
|
|
109
|
+
const valid = vapiSignature === signature;
|
|
110
|
+
return valid;
|
|
111
|
+
}
|
|
112
|
+
const verify = verificationType === 'hmac' ? verifyHmac : verificationType === 'secret' ? verifySecret : verifyNone;
|
|
113
|
+
return async (request, rawBody) => {
|
|
114
|
+
const requestBodyString = String(request.body);
|
|
115
|
+
const valid = verify({ request, requestBodyString });
|
|
116
|
+
const requestBody = JSON.parse(requestBodyString);
|
|
117
|
+
const result = {
|
|
118
|
+
valid,
|
|
119
|
+
event: requestBody.message
|
|
120
|
+
};
|
|
121
|
+
return result;
|
|
133
122
|
};
|
|
134
|
-
return result;
|
|
135
|
-
};
|
|
136
123
|
}
|
|
137
124
|
|
|
138
125
|
const VAPI_AI_WEBHOOK_SECRET_TOKEN_ENV_VAR = 'VAPI_AI_WEBHOOK_SECRET_TOKEN';
|
|
@@ -143,155 +130,181 @@ const VAPI_AI_WEBHOOK_SIGNATURE_PREFIX_ENV_VAR = 'VAPI_AI_WEBHOOK_SIGNATURE_PREF
|
|
|
143
130
|
* Configuration for VapiAiService
|
|
144
131
|
*/
|
|
145
132
|
class VapiAiWebhookServiceConfig {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
133
|
+
webhookConfig;
|
|
134
|
+
static assertValidConfig(config) {
|
|
135
|
+
if (!config.webhookConfig.secret && !config.webhookConfig.hmacSecret) {
|
|
136
|
+
throw new Error('No Vapi.ai webhook secret token specified.');
|
|
137
|
+
}
|
|
150
138
|
}
|
|
151
|
-
}
|
|
152
139
|
}
|
|
153
140
|
|
|
154
141
|
/**
|
|
155
142
|
* Service that makes system changes based on VapiAi webhook events.
|
|
156
143
|
*/
|
|
157
144
|
let VapiAiWebhookService = class VapiAiWebhookService {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
async updateForWebhook(req, rawBody) {
|
|
166
|
-
const {
|
|
167
|
-
valid,
|
|
168
|
-
event
|
|
169
|
-
} = await this._verifier(req, rawBody);
|
|
170
|
-
let result = {
|
|
171
|
-
handled: false
|
|
172
|
-
};
|
|
173
|
-
if (!valid) {
|
|
174
|
-
this.logger.warn('Received invalid Vapi.ai event: ', event);
|
|
175
|
-
} else {
|
|
176
|
-
result = await this.updateForVapiAiEvent(event);
|
|
145
|
+
logger = new Logger('VapiAiWebhookService');
|
|
146
|
+
_verifier;
|
|
147
|
+
handler = vapiaiEventHandlerFactory();
|
|
148
|
+
configure = vapiaiEventHandlerConfigurerFactory(this.handler);
|
|
149
|
+
constructor(vapiAiWebhookServiceConfig) {
|
|
150
|
+
this._verifier = vapiAiWebhookEventVerifier(vapiAiWebhookServiceConfig.webhookConfig);
|
|
177
151
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
152
|
+
async updateForWebhook(req, rawBody) {
|
|
153
|
+
const { valid, event } = await this._verifier(req, rawBody);
|
|
154
|
+
let result = {
|
|
155
|
+
handled: false
|
|
156
|
+
};
|
|
157
|
+
if (!valid) {
|
|
158
|
+
this.logger.warn('Received invalid Vapi.ai event: ', event);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
result = await this.updateForVapiAiEvent(event);
|
|
162
|
+
}
|
|
163
|
+
const response = {
|
|
164
|
+
valid,
|
|
165
|
+
event,
|
|
166
|
+
...result
|
|
167
|
+
};
|
|
168
|
+
return response;
|
|
169
|
+
}
|
|
170
|
+
async updateForVapiAiEvent(event) {
|
|
171
|
+
const result = await this.handler(event);
|
|
172
|
+
if (!result.handled) {
|
|
173
|
+
this.logger.warn('Received unexpected/unhandled Vapi.ai event: ', event);
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
189
176
|
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
177
|
};
|
|
193
|
-
VapiAiWebhookService = __decorate([
|
|
178
|
+
VapiAiWebhookService = __decorate([
|
|
179
|
+
Injectable(),
|
|
180
|
+
__param(0, Inject(VapiAiWebhookServiceConfig)),
|
|
181
|
+
__metadata("design:paramtypes", [VapiAiWebhookServiceConfig])
|
|
182
|
+
], VapiAiWebhookService);
|
|
194
183
|
|
|
195
184
|
let VapiAiWebhookController = class VapiAiWebhookController {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
response.json({});
|
|
185
|
+
_vapiaiWebhookService;
|
|
186
|
+
constructor(vapiaiWebhookService) {
|
|
187
|
+
this._vapiaiWebhookService = vapiaiWebhookService;
|
|
188
|
+
}
|
|
189
|
+
async handleVapiAiWebhook(res, req, rawBody) {
|
|
190
|
+
const { valid, response: responseData } = await this._vapiaiWebhookService.updateForWebhook(req, rawBody);
|
|
191
|
+
const response = res.status(200); // always return a 200 status code
|
|
192
|
+
if (valid && responseData) {
|
|
193
|
+
response.json(responseData);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
response.json({});
|
|
197
|
+
}
|
|
210
198
|
}
|
|
211
|
-
}
|
|
212
199
|
};
|
|
213
|
-
__decorate([
|
|
214
|
-
|
|
200
|
+
__decorate([
|
|
201
|
+
Post(),
|
|
202
|
+
__param(0, Res()),
|
|
203
|
+
__param(1, Req()),
|
|
204
|
+
__param(2, RawBody()),
|
|
205
|
+
__metadata("design:type", Function),
|
|
206
|
+
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
207
|
+
__metadata("design:returntype", Promise)
|
|
208
|
+
], VapiAiWebhookController.prototype, "handleVapiAiWebhook", null);
|
|
209
|
+
VapiAiWebhookController = __decorate([
|
|
210
|
+
Controller('/webhook/vapiai'),
|
|
211
|
+
__param(0, Inject(VapiAiWebhookService)),
|
|
212
|
+
__metadata("design:paramtypes", [VapiAiWebhookService])
|
|
213
|
+
], VapiAiWebhookController);
|
|
215
214
|
|
|
216
215
|
function vapiaiWebhookServiceConfigFactory(configService) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
216
|
+
const config = {
|
|
217
|
+
webhookConfig: {
|
|
218
|
+
secret: configService.get(VAPI_AI_WEBHOOK_SECRET_TOKEN_ENV_VAR),
|
|
219
|
+
hmacSecret: configService.get(VAPI_AI_WEBHOOK_HMAC_SECRET_TOKEN_ENV_VAR),
|
|
220
|
+
verificationType: configService.get(VAPI_AI_WEBHOOK_SECRET_VERIFICATION_TYPE_ENV_VAR),
|
|
221
|
+
signaturePrefix: configService.get(VAPI_AI_WEBHOOK_SIGNATURE_PREFIX_ENV_VAR)
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
VapiAiWebhookServiceConfig.assertValidConfig(config);
|
|
225
|
+
return config;
|
|
227
226
|
}
|
|
228
|
-
let VapiAiWebhookModule = class VapiAiWebhookModule {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
227
|
+
let VapiAiWebhookModule = class VapiAiWebhookModule {
|
|
228
|
+
};
|
|
229
|
+
VapiAiWebhookModule = __decorate([
|
|
230
|
+
Module({
|
|
231
|
+
imports: [ConfigModule],
|
|
232
|
+
controllers: [VapiAiWebhookController],
|
|
233
|
+
providers: [
|
|
234
|
+
{
|
|
235
|
+
provide: VapiAiWebhookServiceConfig,
|
|
236
|
+
inject: [ConfigService],
|
|
237
|
+
useFactory: vapiaiWebhookServiceConfigFactory
|
|
238
|
+
},
|
|
239
|
+
VapiAiWebhookService
|
|
240
|
+
],
|
|
241
|
+
exports: [VapiAiWebhookService]
|
|
242
|
+
})
|
|
243
|
+
], VapiAiWebhookModule);
|
|
239
244
|
|
|
240
245
|
const VAPI_AI_SECRET_TOKEN_ENV_VAR = 'VAPI_AI_SECRET_TOKEN';
|
|
241
246
|
/**
|
|
242
247
|
* Configuration for VapiAiService
|
|
243
248
|
*/
|
|
244
249
|
class VapiAiServiceConfig {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
250
|
+
vapiai;
|
|
251
|
+
static assertValidConfig(config) {
|
|
252
|
+
if (!config.vapiai.config.token) {
|
|
253
|
+
throw new Error('No Vapi.ai secret/token specified.');
|
|
254
|
+
}
|
|
249
255
|
}
|
|
250
|
-
}
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
let VapiAiApi = class VapiAiApi {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
});
|
|
271
|
-
}
|
|
259
|
+
config;
|
|
260
|
+
vapiClient;
|
|
261
|
+
constructor(config) {
|
|
262
|
+
this.config = config;
|
|
263
|
+
this.vapiClient = new VapiClient(config.vapiai.config);
|
|
264
|
+
}
|
|
265
|
+
// MARK: Accessors
|
|
266
|
+
/**
|
|
267
|
+
* Gets a call by ID.
|
|
268
|
+
*
|
|
269
|
+
* @param callId
|
|
270
|
+
* @returns
|
|
271
|
+
*/
|
|
272
|
+
getCall(callId) {
|
|
273
|
+
return this.vapiClient.calls.get({ id: callId });
|
|
274
|
+
}
|
|
272
275
|
};
|
|
273
|
-
VapiAiApi = __decorate([
|
|
276
|
+
VapiAiApi = __decorate([
|
|
277
|
+
Injectable(),
|
|
278
|
+
__param(0, Inject(VapiAiServiceConfig)),
|
|
279
|
+
__metadata("design:paramtypes", [VapiAiServiceConfig])
|
|
280
|
+
], VapiAiApi);
|
|
274
281
|
|
|
275
282
|
function vapiaiServiceConfigFactory(configService) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
283
|
+
const config = {
|
|
284
|
+
vapiai: {
|
|
285
|
+
config: {
|
|
286
|
+
token: configService.get(VAPI_AI_SECRET_TOKEN_ENV_VAR)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
VapiAiServiceConfig.assertValidConfig(config);
|
|
291
|
+
return config;
|
|
285
292
|
}
|
|
286
|
-
let VapiAiModule = class VapiAiModule {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
293
|
+
let VapiAiModule = class VapiAiModule {
|
|
294
|
+
};
|
|
295
|
+
VapiAiModule = __decorate([
|
|
296
|
+
Module({
|
|
297
|
+
imports: [ConfigModule],
|
|
298
|
+
providers: [
|
|
299
|
+
{
|
|
300
|
+
provide: VapiAiServiceConfig,
|
|
301
|
+
inject: [ConfigService],
|
|
302
|
+
useFactory: vapiaiServiceConfigFactory
|
|
303
|
+
},
|
|
304
|
+
VapiAiApi
|
|
305
|
+
],
|
|
306
|
+
exports: [VapiAiApi]
|
|
307
|
+
})
|
|
308
|
+
], VapiAiModule);
|
|
296
309
|
|
|
297
310
|
export { VAPI_AI_SECRET_TOKEN_ENV_VAR, VapiAiApi, VapiAiModule, VapiAiServiceConfig, VapiAiWebhookController, VapiAiWebhookModule, VapiAiWebhookService, vapiAiWebhookEvent, vapiAiWebhookEventVerifier, vapiaiEventHandlerConfigurerFactory, vapiaiEventHandlerFactory, vapiaiServiceConfigFactory, vapiaiWebhookServiceConfigFactory };
|
package/vapiai/package.json
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/nestjs/vapiai",
|
|
3
|
-
"version": "13.0.
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
"version": "13.0.2",
|
|
4
|
+
"peerDependencies": {
|
|
5
|
+
"@dereekb/date": "13.0.2",
|
|
6
|
+
"@dereekb/model": "13.0.2",
|
|
7
|
+
"@dereekb/nestjs": "13.0.2",
|
|
8
|
+
"@dereekb/rxjs": "13.0.2",
|
|
9
|
+
"@dereekb/util": "13.0.2",
|
|
10
|
+
"@nestjs/common": "^11.0.0",
|
|
11
|
+
"@nestjs/config": "^4.0.0",
|
|
12
|
+
"@vapi-ai/server-sdk": "^0.11.0",
|
|
13
|
+
"express": "^5.0.0"
|
|
14
|
+
},
|
|
7
15
|
"exports": {
|
|
16
|
+
"./package.json": "./package.json",
|
|
8
17
|
".": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
"browser": {
|
|
14
|
-
"require": "./index.cjs.js",
|
|
15
|
-
"import": "./index.esm.js"
|
|
16
|
-
},
|
|
18
|
+
"module": "./index.esm.js",
|
|
19
|
+
"types": "./index.d.ts",
|
|
20
|
+
"import": "./index.cjs.mjs",
|
|
17
21
|
"default": "./index.cjs.js"
|
|
18
22
|
}
|
|
19
23
|
},
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"@dereekb/model": "13.0.0",
|
|
24
|
-
"@dereekb/rxjs": "13.0.0",
|
|
25
|
-
"@dereekb/util": "13.0.0",
|
|
26
|
-
"core-js": "^3.0.0"
|
|
27
|
-
}
|
|
24
|
+
"module": "./index.esm.js",
|
|
25
|
+
"main": "./index.cjs.js",
|
|
26
|
+
"types": "./index.d.ts"
|
|
28
27
|
}
|