@fonoster/voice 0.6.2 → 0.7.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,5 +1,5 @@
1
- import { DialOptions, GatherOptions, GatherResponse, MuteOptions, PlayOptions, PlayResponse, PlaybackControlAction, RecordOptions, RecordResponse, SayOptions, SayResponse, StreamOptions, VerbResponse, VoiceRequest, VoiceSessionStreamServer } from "@fonoster/common";
2
- import { DialStatusStream, Stream } from "./verbs";
1
+ import { DialOptions, GatherOptions, GatherResponse, MuteOptions, PlayOptions, PlayResponse, PlaybackControlAction, RecordOptions, RecordResponse, SayOptions, SayResponse, StreamGatherOptions, StreamOptions, VerbResponse, VoiceRequest, VoiceSessionStreamServer } from "@fonoster/common";
2
+ import { DialStatusStream, Stream, StreamGatherStream } from "./verbs";
3
3
  /**
4
4
  * @classdesc Use the VoiceResponse object, to construct advance Interactive
5
5
  * Voice Response (IVR) applications.
@@ -11,11 +11,10 @@ import { DialStatusStream, Stream } from "./verbs";
11
11
  *
12
12
  * async function handler (request, response) {
13
13
  * await response.answer();
14
- * await response.play("sound:hello-world");
14
+ * await response.play("https://soundsserver:9000/sounds/hello-world.wav");
15
15
  * }
16
16
  *
17
- * const voiceServer = new VoiceServer({base: '/voiceapp'})
18
- * voiceServer.listen(handler, { port: 3000 })
17
+ * new VoiceServer().listen(handler, { port: 3000 })
19
18
  */
20
19
  declare class VoiceResponse {
21
20
  voice: VoiceSessionStreamServer;
@@ -186,6 +185,24 @@ declare class VoiceResponse {
186
185
  * }
187
186
  */
188
187
  stream(options: StreamOptions): Promise<Stream>;
188
+ /**
189
+ * Starts a server-side stream gather operation which sends transcription data to the voice server.
190
+ *
191
+ * @param {StreamGatherOptions} options - Options to control the stream gather operation
192
+ * @param {StreamGatherSource} options.source - The source to gather data from (DTMF, SPEECH, SPEECH_AND_DTMF). Default is SPEECH
193
+ * @return {Promise<StreamGatherStream>} The stream gather object
194
+ * @see Gather
195
+ * @example
196
+ *
197
+ * async function handler (request, response) {
198
+ * await response.answer();
199
+ * const sGather = await response.streamGather({ source: StreamGatherSource.SPEECH });
200
+ * sGather.onPayload((payload) => {
201
+ * console.log("Payload: %s", payload);
202
+ * });
203
+ * }
204
+ */
205
+ sgather(options: StreamGatherOptions): Promise<StreamGatherStream>;
189
206
  /**
190
207
  * Mutes a call.
191
208
  *
@@ -42,11 +42,10 @@ const verbs_1 = require("./verbs");
42
42
  *
43
43
  * async function handler (request, response) {
44
44
  * await response.answer();
45
- * await response.play("sound:hello-world");
45
+ * await response.play("https://soundsserver:9000/sounds/hello-world.wav");
46
46
  * }
47
47
  *
48
- * const voiceServer = new VoiceServer({base: '/voiceapp'})
49
- * voiceServer.listen(handler, { port: 3000 })
48
+ * new VoiceServer().listen(handler, { port: 3000 })
50
49
  */
51
50
  class VoiceResponse {
52
51
  /**
@@ -304,6 +303,42 @@ class VoiceResponse {
304
303
  return stream;
305
304
  });
306
305
  }
306
+ /**
307
+ * Starts a server-side stream gather operation which sends transcription data to the voice server.
308
+ *
309
+ * @param {StreamGatherOptions} options - Options to control the stream gather operation
310
+ * @param {StreamGatherSource} options.source - The source to gather data from (DTMF, SPEECH, SPEECH_AND_DTMF). Default is SPEECH
311
+ * @return {Promise<StreamGatherStream>} The stream gather object
312
+ * @see Gather
313
+ * @example
314
+ *
315
+ * async function handler (request, response) {
316
+ * await response.answer();
317
+ * const sGather = await response.streamGather({ source: StreamGatherSource.SPEECH });
318
+ * sGather.onPayload((payload) => {
319
+ * console.log("Payload: %s", payload);
320
+ * });
321
+ * }
322
+ */
323
+ sgather(options) {
324
+ return __awaiter(this, void 0, void 0, function* () {
325
+ const stream = new verbs_1.StreamGatherStream();
326
+ const startStreamGather = new verbs_1.StartStreamGather(this.request, this.voice);
327
+ const stopStreamGather = new verbs_1.StopStreamGather(this.request, this.voice);
328
+ yield startStreamGather.run(Object.assign({ sessionRef: this.request.sessionRef }, options));
329
+ this.voice.on(common_1.StreamEvent.DATA, (result) => {
330
+ if (result.streamGatherPayload) {
331
+ stream.emit("data", result.streamGatherPayload);
332
+ }
333
+ });
334
+ stream.cleanup(() => {
335
+ stopStreamGather.run({
336
+ sessionRef: this.request.sessionRef
337
+ });
338
+ });
339
+ return stream;
340
+ });
341
+ }
307
342
  /**
308
343
  * Mutes a call.
309
344
  *
@@ -29,16 +29,25 @@ exports.createSession = createSession;
29
29
  * limitations under the License.
30
30
  */
31
31
  const common_1 = require("@fonoster/common");
32
+ const logger_1 = require("@fonoster/logger");
32
33
  const VoiceResponse_1 = require("./VoiceResponse");
34
+ const logger = (0, logger_1.getLogger)({ service: "voice", filePath: __filename });
33
35
  function createSession(handler) {
34
36
  return (voice) => new Promise((resolve) => {
35
- voice.on(common_1.StreamEvent.DATA, (params) => __awaiter(this, void 0, void 0, function* () {
37
+ let sessionRef;
38
+ voice.once(common_1.StreamEvent.DATA, (params) => __awaiter(this, void 0, void 0, function* () {
36
39
  const { request } = params;
37
40
  if (params.request) {
41
+ sessionRef = params.request.sessionRef;
38
42
  const response = new VoiceResponse_1.VoiceResponse(request, voice);
39
43
  yield handler(request, response);
40
44
  resolve();
41
45
  }
42
46
  }));
47
+ voice.once(common_1.StreamEvent.END, () => {
48
+ logger.verbose("session ended", { sessionRef });
49
+ voice.end();
50
+ resolve();
51
+ });
43
52
  });
44
53
  }
package/dist/demo.js CHANGED
@@ -34,12 +34,10 @@ const common_1 = require("@fonoster/common");
34
34
  const logger_1 = require("@fonoster/logger");
35
35
  const VoiceServer_1 = __importDefault(require("./VoiceServer"));
36
36
  const logger = (0, logger_1.getLogger)({ service: "voice", filePath: __filename });
37
- const config = {
38
- // Only do this for testing
39
- skipIdentity: true
40
- };
41
- new VoiceServer_1.default(config).listen((req, res) => __awaiter(void 0, void 0, void 0, function* () {
42
- logger.verbose("voice request", JSON.stringify(req, null, 2));
37
+ // Only skip identity for local development
38
+ new VoiceServer_1.default({ skipIdentity: true }).listen((req, res) => __awaiter(void 0, void 0, void 0, function* () {
39
+ const { ingressNumber, sessionRef, appRef } = req;
40
+ logger.verbose("voice request", { ingressNumber, sessionRef, appRef });
43
41
  yield res.answer();
44
42
  yield res.say("Hi there! What's your name?");
45
43
  const { speech: name } = yield res.gather({
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@
2
2
  import { AzureVoice, AzureVoiceDetails, GoogleVoice, GoogleVoiceDetails } from "@fonoster/common";
3
3
  import VoiceServer from "./VoiceServer";
4
4
  export default VoiceServer;
5
+ export * from "./VoiceResponse";
5
6
  export * from "./types";
6
7
  export { GoogleVoice, GoogleVoiceDetails, AzureVoice, AzureVoiceDetails };
package/dist/index.js CHANGED
@@ -44,4 +44,5 @@ Object.defineProperty(exports, "GoogleVoice", { enumerable: true, get: function
44
44
  Object.defineProperty(exports, "GoogleVoiceDetails", { enumerable: true, get: function () { return common_1.GoogleVoiceDetails; } });
45
45
  const VoiceServer_1 = __importDefault(require("./VoiceServer"));
46
46
  exports.default = VoiceServer_1.default;
47
+ __exportStar(require("./VoiceResponse"), exports);
47
48
  __exportStar(require("./types"), exports);
@@ -0,0 +1,19 @@
1
+ import { Stream as StreamObj } from "stream";
2
+ import { StartStreamGatherRequest, StreamGatherPayload, VerbRequest } from "@fonoster/common";
3
+ import { z } from "zod";
4
+ import { Verb } from "./Verb";
5
+ declare class StartStreamGather extends Verb<StartStreamGatherRequest> {
6
+ getValidationSchema(): z.Schema;
7
+ }
8
+ declare class StopStreamGather extends Verb<VerbRequest> {
9
+ getValidationSchema(): z.Schema;
10
+ }
11
+ declare class StreamGatherStream {
12
+ stream: StreamObj;
13
+ constructor();
14
+ close(): void;
15
+ onPayload(callback: (payload: StreamGatherPayload) => void): void;
16
+ emit(event: "data", payload: StreamGatherPayload): void;
17
+ cleanup(callback: () => void): void;
18
+ }
19
+ export { StartStreamGather, StopStreamGather, StreamGatherStream };
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StreamGatherStream = exports.StopStreamGather = exports.StartStreamGather = void 0;
4
+ /*
5
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
6
+ * http://github.com/fonoster/fonoster
7
+ *
8
+ * This file is part of Fonoster
9
+ *
10
+ * Licensed under the MIT License (the "License");
11
+ * you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at
13
+ *
14
+ * https://opensource.org/licenses/MIT
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ const stream_1 = require("stream");
23
+ const common_1 = require("@fonoster/common");
24
+ const zod_1 = require("zod");
25
+ const Verb_1 = require("./Verb");
26
+ class StartStreamGather extends Verb_1.Verb {
27
+ getValidationSchema() {
28
+ return zod_1.z.object({
29
+ source: zod_1.z.optional(zod_1.z.nativeEnum(common_1.StreamGatherSource))
30
+ });
31
+ }
32
+ }
33
+ exports.StartStreamGather = StartStreamGather;
34
+ class StopStreamGather extends Verb_1.Verb {
35
+ getValidationSchema() {
36
+ return zod_1.z.object({
37
+ sessionRef: zod_1.z.string()
38
+ });
39
+ }
40
+ }
41
+ exports.StopStreamGather = StopStreamGather;
42
+ class StreamGatherStream {
43
+ constructor() {
44
+ this.stream = new stream_1.Stream();
45
+ }
46
+ close() {
47
+ this.stream.removeAllListeners();
48
+ }
49
+ // TODO: We should hide this method from the public API
50
+ // Private API
51
+ onPayload(callback) {
52
+ this.stream.on("data", (payload) => {
53
+ callback(payload);
54
+ });
55
+ }
56
+ // Private API
57
+ emit(event, payload) {
58
+ this.stream.emit(event, payload);
59
+ }
60
+ // Private API
61
+ cleanup(callback) {
62
+ this.stream.on("close", callback);
63
+ }
64
+ }
65
+ exports.StreamGatherStream = StreamGatherStream;
@@ -9,6 +9,7 @@ export * from "./PlaybackControl";
9
9
  export * from "./Record";
10
10
  export * from "./Say";
11
11
  export * from "./Stream";
12
+ export * from "./StreamGather";
12
13
  export * from "./Unmute";
13
14
  export * from "./validateRequest";
14
15
  export * from "./Verb";
@@ -43,6 +43,7 @@ __exportStar(require("./PlaybackControl"), exports);
43
43
  __exportStar(require("./Record"), exports);
44
44
  __exportStar(require("./Say"), exports);
45
45
  __exportStar(require("./Stream"), exports);
46
+ __exportStar(require("./StreamGather"), exports);
46
47
  __exportStar(require("./Unmute"), exports);
47
48
  __exportStar(require("./validateRequest"), exports);
48
49
  __exportStar(require("./Verb"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/voice",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "Voice Server for Fonoster",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/fonoster#readme",
@@ -20,9 +20,9 @@
20
20
  "fonoster": "./dist/index.js"
21
21
  },
22
22
  "dependencies": {
23
- "@fonoster/common": "^0.6.2",
24
- "@fonoster/identity": "^0.6.2",
25
- "@fonoster/logger": "^0.6.2",
23
+ "@fonoster/common": "^0.7.0",
24
+ "@fonoster/identity": "^0.7.0",
25
+ "@fonoster/logger": "^0.7.0",
26
26
  "@grpc/grpc-js": "~1.10.6",
27
27
  "deepmerge": "^4.3.1",
28
28
  "grpc-health-check": "^2.0.2",
@@ -43,5 +43,5 @@
43
43
  "bugs": {
44
44
  "url": "https://github.com/fonoster/fonoster/issues"
45
45
  },
46
- "gitHead": "9b55399d2906479d826a53a5e3bd10206aaaa86d"
46
+ "gitHead": "afa950ace3b1d022b6dc8be0c3b87a6b8a5ba3c5"
47
47
  }