From e329122b13f74c348a398198eb9b220da3a0460f Mon Sep 17 00:00:00 2001 From: Igor Reshniov Date: Mon, 31 Jul 2023 19:00:44 +0200 Subject: [PATCH] improve execute interface to allow headers like event-UUID --- src/esl/Connection.ts | 29 ++++++++++++++++++----------- src/index.ts | 2 +- test/spec/esl/connection.test.ts | 22 +++++++++++++++------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/esl/Connection.ts b/src/esl/Connection.ts index a6196a5..1441cf6 100644 --- a/src/esl/Connection.ts +++ b/src/esl/Connection.ts @@ -45,6 +45,10 @@ export enum ConnectionEvent Ready = 'esl::ready', } +export type ExecuteArg = { + 'execute-app-arg'?: string, + [key: string]: string | undefined }; + /** * ESLconnection * @@ -513,11 +517,11 @@ export class Connection extends EventEmitter2 * or "-ERR [Error Message]" on failure. */ execute(app: string, cb?: IEventCallback): string; - execute(app: string, arg: string, cb?: IEventCallback): string; - execute(app: string, arg: string, uuid: string, cb?: IEventCallback): string; - execute(app: string, argOrCallback?: string | IEventCallback, uuidOrCallback?: string | IEventCallback, cb?: IEventCallback): string + execute(app: string, arg: ExecuteArg, cb?: IEventCallback): string; + execute(app: string, arg: ExecuteArg, uuid: string, cb?: IEventCallback): string; + execute(app: string, argOrCallback?: ExecuteArg | IEventCallback, uuidOrCallback?: string | IEventCallback, cb?: IEventCallback): string { - let arg = ''; + let arg: ExecuteArg = {}; let uniqueId = uuid.v4(); if (typeof argOrCallback === 'function') @@ -539,12 +543,15 @@ export class Connection extends EventEmitter2 } } + const { 'execute-app-arg': executeAppArg, ...headers }: ExecuteArg = arg; + const options: IDictionary = { 'execute-app-name': app, + ...headers }; - if (typeof arg !== 'undefined' && arg.toString().length > 0) - options['execute-app-arg'] = arg.toString(); + if (typeof executeAppArg !== 'undefined' && executeAppArg.toString().length > 0) + options['execute-app-arg'] = executeAppArg.toString(); if (this.type === ConnectionType.Inbound) { @@ -568,14 +575,14 @@ export class Connection extends EventEmitter2 * "async: true" header in the message sent to the channel. */ executeAsync(app: string, cb?: IEventCallback): string; - executeAsync(app: string, arg: string, cb?: IEventCallback): string; - executeAsync(app: string, arg: string, uuid: string, cb?: IEventCallback): string; - executeAsync(app: string, argOrCallback?: string | IEventCallback, uuidOrCallback?: string | IEventCallback, cb?: IEventCallback): string + executeAsync(app: string, arg: ExecuteArg, cb?: IEventCallback): string; + executeAsync(app: string, arg: ExecuteArg, uuid: string, cb?: IEventCallback): string; + executeAsync(app: string, argOrCallback?: ExecuteArg | IEventCallback, uuidOrCallback?: string | IEventCallback, cb?: IEventCallback): string { const oldAsyncValue = this.execAsync; this.execAsync = true; - const eventUuid = this.execute(app, argOrCallback as string, uuidOrCallback as string, cb); + const eventUuid = this.execute(app, argOrCallback as ExecuteArg, uuidOrCallback as string, cb); this.execAsync = oldAsyncValue; @@ -792,7 +799,7 @@ export class Connection extends EventEmitter2 // this method of event tracking is based on: // http://lists.freeswitch.org/pipermail/freeswitch-users/2013-May/095329.html - const eventUuid = uuid.v4(); + const eventUuid = args['Event-UUID'] ?? uuid.v4(); args['Event-UUID'] = eventUuid; const eventName = `esl::event::CHANNEL_EXECUTE_COMPLETE::${uniqueId}`; diff --git a/src/index.ts b/src/index.ts index e38fd2b..dc5903e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,7 @@ * ESL Object * @see https://freeswitch.org/confluence/display/FREESWITCH/Event+Socket+Library#EventSocketLibrary-ESLObject */ -export { Connection } from './esl/Connection'; +export { Connection, ExecuteArg, IEventCallback } from './esl/Connection'; export { Event } from './esl/Event'; export { Parser } from './esl/Parser'; export { Server } from './esl/Server'; diff --git a/test/spec/esl/connection.test.ts b/test/spec/esl/connection.test.ts index 8047f87..061839f 100644 --- a/test/spec/esl/connection.test.ts +++ b/test/spec/esl/connection.test.ts @@ -4,7 +4,7 @@ import * as sinon from 'sinon'; import { expect } from 'chai'; import { getEchoServerAndSocket, getInboundConnection, ITestSendArgs } from '../../fixtures/helpers'; import { setupSinonChai } from '../../fixtures/setup'; -import { Connection } from '../../../src/esl/Connection'; +import { Connection, ExecuteArg } from '../../../src/esl/Connection'; import { ICallback } from '../../../src/utils'; import { Event } from '../../../src/esl/Event'; import { cmdReply } from '../../fixtures/data'; @@ -129,7 +129,9 @@ describe('esl.Connection', function () it('Invokes the callback', function (done) { - testChannelExecute(testConnection, 'playback', 'foo', id0, function (evt) + testChannelExecute(testConnection, 'playback', { + 'execute-app-arg': 'foo' + }, id0, function (evt) { expect(evt.getHeader('Application')).to.equal('playback'); done(); @@ -138,7 +140,9 @@ describe('esl.Connection', function () it('Invokes the callback only once for the same session', function (done) { - testChannelExecute(testConnection, 'hangup', '', id0, function (evt) + testChannelExecute(testConnection, 'hangup', { + 'execute-app-arg': '' + }, id0, function (evt) { expect(evt.getHeader('Application')).to.equal('hangup'); done(); @@ -147,7 +151,9 @@ describe('esl.Connection', function () it('Invokes the callback again for a new session', function (done) { - testChannelExecute(testConnection, 'hangup', '', id1, function (evt) + testChannelExecute(testConnection, 'hangup', { + 'execute-app-arg': '', + }, id1, function (evt) { expect(evt.getHeader('Application')).to.equal('hangup'); done(); @@ -456,7 +462,7 @@ function sendChannelExecuteResponse(conn: Connection, appUuid: string, appName: conn.socket.write(resp); } -function testChannelExecute(conn: Connection, appName: string, appArg: string, requestId: string, cb: ICallback) +function testChannelExecute(conn: Connection, appName: string, appArg: ExecuteArg, requestId: string, cb: ICallback) { conn.socket.once('data', function (data) { @@ -468,9 +474,11 @@ function testChannelExecute(conn: Connection, appName: string, appArg: string, r expect(lines).to.contain(`execute-app-name: ${appName}`); expect(lines.some(x => x.includes('Event-UUID: '))).to.be.true; - if (appArg) + const arg: string | undefined = appArg['execute-app-arg']; + + if (arg) { - expect(lines).to.contain(`execute-app-arg: ${appArg}`); + expect(lines).to.contain(`execute-app-arg: ${arg}`); } else {