@fonoster/apiserver 0.7.24 → 0.7.25

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 (39) hide show
  1. package/dist/applications/createGetFnUtil.d.ts +6 -6
  2. package/dist/applications/deleteApplication.js +1 -1
  3. package/dist/applications/getApplication.js +1 -1
  4. package/dist/applications/utils/getApplicationValidationSchema.d.ts +6 -6
  5. package/dist/applications/utils/getApplicationValidationSchema.js +3 -1
  6. package/dist/core/allowList.js +3 -0
  7. package/dist/core/{filesServer.d.ts → httpBridge.d.ts} +2 -2
  8. package/dist/core/{filesServer.js → httpBridge.js} +26 -4
  9. package/dist/core/identityConfig.d.ts +9 -0
  10. package/dist/core/identityConfig.js +9 -0
  11. package/dist/core/runServices.js +2 -2
  12. package/dist/core/services.d.ts +9 -0
  13. package/dist/envs.d.ts +8 -2
  14. package/dist/envs.js +21 -9
  15. package/dist/secrets/createGetFnUtil.d.ts +2 -2
  16. package/dist/secrets/createGetFnUtil.js +1 -1
  17. package/dist/secrets/deleteSecret.js +1 -1
  18. package/dist/secrets/getSecret.js +1 -1
  19. package/dist/voice/handlers/PlaybackControl.js +4 -2
  20. package/dist/voice/handlers/Say.js +3 -3
  21. package/dist/voice/handlers/Stream.js +6 -2
  22. package/dist/voice/handlers/StreamGather.js +3 -1
  23. package/dist/voice/handlers/dial/Dial.js +4 -3
  24. package/dist/voice/handlers/dial/handleStasisStart.js +1 -0
  25. package/dist/voice/handlers/gather/Gather.js +15 -4
  26. package/dist/voice/handlers/utils/textChunksByClause.d.ts +2 -0
  27. package/dist/voice/handlers/utils/textChunksByClause.js +42 -0
  28. package/dist/voice/handlers/utils/withErrorHandling.js +4 -2
  29. package/dist/voice/integrations/makeCreateContainer.js +1 -1
  30. package/dist/voice/stt/Deepgram.js +8 -2
  31. package/dist/voice/stt/Google.js +3 -1
  32. package/dist/voice/tts/Azure.js +1 -1
  33. package/dist/voice/tts/Deepgram.d.ts +3 -2
  34. package/dist/voice/tts/Deepgram.js +41 -6
  35. package/dist/voice/tts/ElevenLabs.js +3 -1
  36. package/dist/voice/tts/Google.js +3 -1
  37. package/dist/voice/tts/streamToBuffer.d.ts +2 -0
  38. package/dist/voice/tts/streamToBuffer.js +61 -0
  39. package/package.json +6 -6
@@ -6,28 +6,28 @@ declare function createGetFnUtil(prisma: Prisma): (ref: string) => Promise<{
6
6
  textToSpeech: {
7
7
  ref: string;
8
8
  config: import("@prisma/client/runtime/library").JsonValue;
9
- applicationRef: string;
10
9
  productRef: string;
10
+ applicationRef: string;
11
11
  };
12
12
  speechToText: {
13
13
  ref: string;
14
14
  config: import("@prisma/client/runtime/library").JsonValue;
15
- applicationRef: string;
16
15
  productRef: string;
16
+ applicationRef: string;
17
17
  };
18
18
  intelligence: {
19
19
  ref: string;
20
- credentials: string;
21
20
  config: import("@prisma/client/runtime/library").JsonValue;
22
- applicationRef: string;
21
+ credentials: string;
23
22
  productRef: string;
23
+ applicationRef: string;
24
24
  };
25
25
  name: string;
26
26
  type: "EXTERNAL";
27
+ endpoint: string;
27
28
  ref: string;
29
+ accessKeyId: string;
28
30
  createdAt: Date;
29
31
  updatedAt: Date;
30
- endpoint: string;
31
- accessKeyId: string;
32
32
  }>;
33
33
  export { createGetFnUtil };
@@ -41,5 +41,5 @@ function deleteApplication(prisma) {
41
41
  yield prisma.application.delete({ where: { ref } });
42
42
  return { ref };
43
43
  });
44
- return (0, common_1.withErrorHandlingAndValidation)((0, identity_1.withAccess)(fn, (ref) => getFn(ref)), common_1.Validators.baseApiObjectSchema);
44
+ return (0, common_1.withErrorHandlingAndValidation)((0, identity_1.withAccess)(fn, (ref) => getFn(ref)), common_1.Validators.emptySchema);
45
45
  }
@@ -42,5 +42,5 @@ function getApplication(prisma) {
42
42
  const result = yield getFn(ref);
43
43
  return result ? (0, applicationWithEncodedStruct_1.applicationWithEncodedStruct)(result) : null;
44
44
  });
45
- return (0, withErrorHandlingAndValidationAndAccess_1.withErrorHandlingAndValidationAndAccess)(fn, (ref) => getFn(ref), common_1.Validators.baseApiObjectSchema);
45
+ return (0, withErrorHandlingAndValidationAndAccess_1.withErrorHandlingAndValidationAndAccess)(fn, (ref) => getFn(ref), common_1.Validators.emptySchema);
46
46
  }
@@ -8,7 +8,7 @@ declare function getApplicationValidationSchema(request: {
8
8
  EXTERNAL: "EXTERNAL";
9
9
  }>;
10
10
  endpoint: z.ZodEffects<z.ZodOptional<z.ZodString>, string, string>;
11
- textToSpeech: z.ZodUndefined | z.ZodObject<{
11
+ textToSpeech: z.ZodObject<{
12
12
  productRef: z.ZodString;
13
13
  config: any;
14
14
  }, "strip", z.ZodTypeAny, {
@@ -19,7 +19,7 @@ declare function getApplicationValidationSchema(request: {
19
19
  [x: string]: any;
20
20
  productRef?: unknown;
21
21
  config?: unknown;
22
- }>;
22
+ }> | z.ZodUndefined;
23
23
  speechToText: z.ZodUndefined | z.ZodObject<{
24
24
  productRef: z.ZodString;
25
25
  config: any;
@@ -33,9 +33,6 @@ declare function getApplicationValidationSchema(request: {
33
33
  config?: unknown;
34
34
  }>;
35
35
  }, "strip", z.ZodTypeAny, {
36
- name?: string;
37
- type?: "EXTERNAL";
38
- endpoint?: string;
39
36
  textToSpeech?: {
40
37
  [x: string]: any;
41
38
  productRef?: unknown;
@@ -46,10 +43,10 @@ declare function getApplicationValidationSchema(request: {
46
43
  productRef?: unknown;
47
44
  config?: unknown;
48
45
  };
49
- }, {
50
46
  name?: string;
51
47
  type?: "EXTERNAL";
52
48
  endpoint?: string;
49
+ }, {
53
50
  textToSpeech?: {
54
51
  [x: string]: any;
55
52
  productRef?: unknown;
@@ -60,5 +57,8 @@ declare function getApplicationValidationSchema(request: {
60
57
  productRef?: unknown;
61
58
  config?: unknown;
62
59
  };
60
+ name?: string;
61
+ type?: "EXTERNAL";
62
+ endpoint?: string;
63
63
  }>;
64
64
  export { getApplicationValidationSchema };
@@ -55,7 +55,9 @@ function getApplicationValidationSchema(request) {
55
55
  const { ttsEngineName, sttEngineName } = request;
56
56
  return zod_1.z.object({
57
57
  name: zod_1.z.string().max(255, MAX_NAME_MESSAGE),
58
- type: zod_1.z.nativeEnum(client_1.ApplicationType),
58
+ type: zod_1.z.nativeEnum(client_1.ApplicationType, {
59
+ message: "Invalid application type."
60
+ }),
59
61
  endpoint: common_1.hostOrHostPortSchema,
60
62
  textToSpeech: ttsEngineName
61
63
  ? zod_1.z.object({
@@ -25,7 +25,10 @@ const allowList = [
25
25
  "/fonoster.identity.v1beta2.Identity/CreateWorkspace",
26
26
  "/fonoster.identity.v1beta2.Identity/ExchangeApiKey",
27
27
  "/fonoster.identity.v1beta2.Identity/ExchangeCredentials",
28
+ "/fonoster.identity.v1beta2.Identity/ExchangeOauth2Code",
28
29
  "/fonoster.identity.v1beta2.Identity/ExchangeRefreshToken",
30
+ "/fonoster.identity.v1beta2.Identity/SendVerificationCode",
31
+ "/fonoster.identity.v1beta2.Identity/VerifyCode",
29
32
  "/fonoster.identity.v1beta2.Identity/GetPublicKey"
30
33
  ];
31
34
  exports.allowList = allowList;
@@ -1,9 +1,9 @@
1
1
  import { Readable } from "stream";
2
- declare function filesServer(params: {
2
+ declare function httpBridge(params: {
3
3
  port: number;
4
4
  }): {
5
5
  addStream: (id: string, stream: Readable) => void;
6
6
  removeStream: (id: string) => void;
7
7
  getStream: (id: string) => Readable;
8
8
  };
9
- export { filesServer };
9
+ export { httpBridge };
@@ -1,18 +1,30 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
13
  };
5
14
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.filesServer = filesServer;
15
+ exports.httpBridge = httpBridge;
16
+ const identity_1 = require("@fonoster/identity");
7
17
  const logger_1 = require("@fonoster/logger");
8
18
  const express_1 = __importDefault(require("express"));
19
+ const identityConfig_1 = require("./identityConfig");
20
+ const envs_1 = require("../envs");
9
21
  const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
10
22
  const CONTENT_TYPE = "audio/L16;rate=16000;channels=1";
11
- function filesServer(params) {
23
+ function httpBridge(params) {
12
24
  const { port } = params;
13
25
  const app = (0, express_1.default)();
14
26
  const streamMap = new Map();
15
- app.get("/sounds/:id", (req, res) => {
27
+ app.get("/api/sounds/:id", (req, res) => {
16
28
  const idWithoutExtension = req.params.id.split(".")[0];
17
29
  const stream = streamMap.get(idWithoutExtension);
18
30
  if (!stream) {
@@ -32,8 +44,18 @@ function filesServer(params) {
32
44
  });
33
45
  stream.pipe(res);
34
46
  });
47
+ app.get("/api/identity/accept-invite", (req, res) => __awaiter(this, void 0, void 0, function* () {
48
+ try {
49
+ yield (0, identity_1.updateMembershipStatus)(identityConfig_1.identityConfig)(req.query.token);
50
+ res.redirect(envs_1.APP_URL);
51
+ }
52
+ catch (error) {
53
+ logger.verbose("error updating membership status", error);
54
+ res.redirect(envs_1.IDENTITY_WORKSPACE_INVITATION_FAIL_URL);
55
+ }
56
+ }));
35
57
  app.listen(port, () => {
36
- logger.info(`Files server is running on port ${port}`);
58
+ logger.info(`HTTP bridge is running on port ${port}`);
37
59
  });
38
60
  return {
39
61
  addStream: (id, stream) => {
@@ -17,5 +17,14 @@ declare const identityConfig: {
17
17
  pass: string;
18
18
  };
19
19
  };
20
+ twilioSmsConfig: {
21
+ accountSid: string;
22
+ authToken: string;
23
+ sender: string;
24
+ };
25
+ githubOauth2Config: {
26
+ clientId: string;
27
+ clientSecret: string;
28
+ };
20
29
  };
21
30
  export { identityConfig };
@@ -38,6 +38,15 @@ const identityConfig = {
38
38
  user: envs_1.SMTP_AUTH_USER,
39
39
  pass: envs_1.SMTP_AUTH_PASS
40
40
  }
41
+ },
42
+ twilioSmsConfig: {
43
+ accountSid: envs_1.TWILIO_ACCOUNT_SID,
44
+ authToken: envs_1.TWILIO_AUTH_TOKEN,
45
+ sender: envs_1.TWILIO_PHONE_NUMBER
46
+ },
47
+ githubOauth2Config: {
48
+ clientId: envs_1.IDENTITY_OAUTH2_GITHUB_CLIENT_ID,
49
+ clientSecret: envs_1.IDENTITY_OAUTH2_GITHUB_CLIENT_SECRET
41
50
  }
42
51
  };
43
52
  exports.identityConfig = identityConfig;
@@ -59,7 +59,7 @@ const logger_1 = require("@fonoster/logger");
59
59
  const grpc = __importStar(require("@grpc/grpc-js"));
60
60
  const grpc_health_check_1 = require("grpc-health-check");
61
61
  const allowList_1 = require("./allowList");
62
- const filesServer_1 = require("./filesServer");
62
+ const httpBridge_1 = require("./httpBridge");
63
63
  const loadServices_1 = __importDefault(require("./loadServices"));
64
64
  const services_1 = __importDefault(require("./services"));
65
65
  const runCallManager_1 = require("../calls/runCallManager");
@@ -79,7 +79,7 @@ function runServices() {
79
79
  // Load the remaining services
80
80
  (0, loadServices_1.default)(server, yield services_1.default);
81
81
  // Connecting to Asterisk ARI
82
- yield (0, connectToAri_1.connectToAri)((0, filesServer_1.filesServer)({ port: envs_1.FILES_SERVER_PORT }));
82
+ yield (0, connectToAri_1.connectToAri)((0, httpBridge_1.httpBridge)({ port: envs_1.HTTP_BRIDGE_PORT }));
83
83
  // Additional Call Managers subscriber may be added here to handle call events
84
84
  yield (0, runCallManager_1.createCreateCallSubscriber)({
85
85
  natsUrl: envs_1.NATS_URL,
@@ -129,12 +129,21 @@ declare const services: Promise<[{
129
129
  exchangeCredentials: (call: {
130
130
  request: unknown;
131
131
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
132
+ exchangeOauth2Code: (call: {
133
+ request: unknown;
134
+ }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
132
135
  exchangeRefreshToken: (call: {
133
136
  request: unknown;
134
137
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
135
138
  getPublicKey: (_: unknown, callback: (error: import("@fonoster/common").GrpcErrorMessage, response?: {
136
139
  publicKey: string;
137
140
  }) => void) => Promise<void>;
141
+ sendVerificationCode: (call: {
142
+ request: unknown;
143
+ }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
144
+ verifyCode: (call: {
145
+ request: unknown;
146
+ }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
138
147
  };
139
148
  }, {
140
149
  definition: {
package/dist/envs.d.ts CHANGED
@@ -10,15 +10,17 @@ export declare const CALLS_CREATE_SUBJECT = "calls.create";
10
10
  export declare const CALLS_TRACK_CALL_SUBJECT = "calls.track";
11
11
  export declare const CLOAK_ENCRYPTION_KEY: string;
12
12
  export declare const DEFAULT_NATS_QUEUE_GROUP = "apiserver";
13
- export declare const EMAIL_TEMPLATES_DIR: string;
14
- export declare const FILES_SERVER_PORT: number;
13
+ export declare const HTTP_BRIDGE_PORT: number;
15
14
  export declare const IDENTITY_ACCESS_TOKEN_EXPIRES_IN: string;
16
15
  export declare const IDENTITY_AUDIENCE: string;
17
16
  export declare const IDENTITY_ID_TOKEN_EXPIRES_IN: string;
18
17
  export declare const IDENTITY_ISSUER: string;
18
+ export declare const IDENTITY_OAUTH2_GITHUB_CLIENT_ID: string;
19
+ export declare const IDENTITY_OAUTH2_GITHUB_CLIENT_SECRET: string;
19
20
  export declare const IDENTITY_PRIVATE_KEY: string;
20
21
  export declare const IDENTITY_PUBLIC_KEY: string;
21
22
  export declare const IDENTITY_REFRESH_TOKEN_EXPIRES_IN: string;
23
+ export declare const IDENTITY_WORKSPACE_INVITATION_FAIL_URL: string;
22
24
  export declare const INFLUXDB_BUCKET: string;
23
25
  export declare const INFLUXDB_ORG: string;
24
26
  export declare const INFLUXDB_PASSWORD: string;
@@ -41,3 +43,7 @@ export declare const SMTP_HOST: string;
41
43
  export declare const SMTP_PORT: number;
42
44
  export declare const SMTP_SECURE: boolean;
43
45
  export declare const SMTP_SENDER: string;
46
+ export declare const TEMPLATES_DIR: string;
47
+ export declare const TWILIO_ACCOUNT_SID: string;
48
+ export declare const TWILIO_AUTH_TOKEN: string;
49
+ export declare const TWILIO_PHONE_NUMBER: string;
package/dist/envs.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  var _a;
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.SMTP_SENDER = exports.SMTP_SECURE = exports.SMTP_PORT = exports.SMTP_HOST = exports.SMTP_AUTH_USER = exports.SMTP_AUTH_PASS = exports.ROUTR_DEFAULT_PEER_USERNAME = exports.ROUTR_DEFAULT_PEER_PASSWORD = exports.ROUTR_DEFAULT_PEER_NAME = exports.ROUTR_DEFAULT_PEER_AOR = exports.ROUTR_API_ENDPOINT = exports.OWNER_PASSWORD = exports.OWNER_NAME = exports.OWNER_EMAIL = exports.NATS_URL = exports.INTEGRATIONS_FILE = exports.INFLUXDB_USERNAME = exports.INFLUXDB_URL = exports.INFLUXDB_TOKEN = exports.INFLUXDB_PASSWORD = exports.INFLUXDB_ORG = exports.INFLUXDB_BUCKET = exports.IDENTITY_REFRESH_TOKEN_EXPIRES_IN = exports.IDENTITY_PUBLIC_KEY = exports.IDENTITY_PRIVATE_KEY = exports.IDENTITY_ISSUER = exports.IDENTITY_ID_TOKEN_EXPIRES_IN = exports.IDENTITY_AUDIENCE = exports.IDENTITY_ACCESS_TOKEN_EXPIRES_IN = exports.FILES_SERVER_PORT = exports.EMAIL_TEMPLATES_DIR = exports.DEFAULT_NATS_QUEUE_GROUP = exports.CLOAK_ENCRYPTION_KEY = exports.CALLS_TRACK_CALL_SUBJECT = exports.CALLS_CREATE_SUBJECT = exports.ASTERISK_TRUNK = exports.ASTERISK_SYSTEM_DOMAIN = exports.ASTERISK_ARI_USERNAME = exports.ASTERISK_ARI_SECRET = exports.ASTERISK_ARI_PROXY_URL = exports.APP_URL = exports.APISERVER_HOST = exports.APISERVER_BIND_ADDR = void 0;
7
+ exports.TWILIO_PHONE_NUMBER = exports.TWILIO_AUTH_TOKEN = exports.TWILIO_ACCOUNT_SID = exports.TEMPLATES_DIR = exports.SMTP_SENDER = exports.SMTP_SECURE = exports.SMTP_PORT = exports.SMTP_HOST = exports.SMTP_AUTH_USER = exports.SMTP_AUTH_PASS = exports.ROUTR_DEFAULT_PEER_USERNAME = exports.ROUTR_DEFAULT_PEER_PASSWORD = exports.ROUTR_DEFAULT_PEER_NAME = exports.ROUTR_DEFAULT_PEER_AOR = exports.ROUTR_API_ENDPOINT = exports.OWNER_PASSWORD = exports.OWNER_NAME = exports.OWNER_EMAIL = exports.NATS_URL = exports.INTEGRATIONS_FILE = exports.INFLUXDB_USERNAME = exports.INFLUXDB_URL = exports.INFLUXDB_TOKEN = exports.INFLUXDB_PASSWORD = exports.INFLUXDB_ORG = exports.INFLUXDB_BUCKET = exports.IDENTITY_WORKSPACE_INVITATION_FAIL_URL = exports.IDENTITY_REFRESH_TOKEN_EXPIRES_IN = exports.IDENTITY_PUBLIC_KEY = exports.IDENTITY_PRIVATE_KEY = exports.IDENTITY_OAUTH2_GITHUB_CLIENT_SECRET = exports.IDENTITY_OAUTH2_GITHUB_CLIENT_ID = exports.IDENTITY_ISSUER = exports.IDENTITY_ID_TOKEN_EXPIRES_IN = exports.IDENTITY_AUDIENCE = exports.IDENTITY_ACCESS_TOKEN_EXPIRES_IN = exports.HTTP_BRIDGE_PORT = exports.DEFAULT_NATS_QUEUE_GROUP = exports.CLOAK_ENCRYPTION_KEY = exports.CALLS_TRACK_CALL_SUBJECT = exports.CALLS_CREATE_SUBJECT = exports.ASTERISK_TRUNK = exports.ASTERISK_SYSTEM_DOMAIN = exports.ASTERISK_ARI_USERNAME = exports.ASTERISK_ARI_SECRET = exports.ASTERISK_ARI_PROXY_URL = exports.APP_URL = exports.APISERVER_HOST = exports.APISERVER_BIND_ADDR = void 0;
8
8
  /*
9
9
  * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
10
10
  * http://github.com/fonoster/fonoster
@@ -39,6 +39,7 @@ const e = process.env;
39
39
  "SMTP_AUTH_USER",
40
40
  "SMTP_AUTH_PASS",
41
41
  "IDENTITY_DATABASE_URL",
42
+ "IDENTITY_WORKSPACE_INVITATION_FAIL_URL",
42
43
  "DATABASE_URL",
43
44
  "INFLUXDB_URL",
44
45
  "INFLUXDB_INIT_USERNAME",
@@ -53,8 +54,6 @@ const e = process.env;
53
54
  ]);
54
55
  const IDENTITY_PRIVATE_KEY_PATH = e.IDENTITY_PRIVATE_KEY_PATH || "/opt/fonoster/keys/private.pem";
55
56
  const IDENTITY_PUBLIC_KEY_PATH = e.IDENTITY_PUBLIC_KEY_PATH || "/opt/fonoster/keys/public.pem";
56
- (0, common_1.assertFileExists)(IDENTITY_PRIVATE_KEY_PATH);
57
- (0, common_1.assertFileExists)(IDENTITY_PUBLIC_KEY_PATH);
58
57
  exports.APISERVER_BIND_ADDR = e.APISERVER_BIND_ADDR || "0.0.0.0:50051";
59
58
  exports.APISERVER_HOST = e.APISERVER_HOST || "apiserver";
60
59
  // Frontend configurations
@@ -69,24 +68,31 @@ exports.CALLS_TRACK_CALL_SUBJECT = "calls.track";
69
68
  // Other configurations
70
69
  exports.CLOAK_ENCRYPTION_KEY = e.CLOAK_ENCRYPTION_KEY;
71
70
  exports.DEFAULT_NATS_QUEUE_GROUP = "apiserver";
72
- // Custom email templates
73
- exports.EMAIL_TEMPLATES_DIR = e.EMAIL_TEMPLATES_DIR;
74
- exports.FILES_SERVER_PORT = e.FILES_SERVER_PORT
75
- ? parseInt(e.FILES_SERVER_PORT)
71
+ exports.HTTP_BRIDGE_PORT = e.HTTP_BRIDGE_PORT
72
+ ? parseInt(e.HTTP_BRIDGE_PORT)
76
73
  : 9876;
74
+ // Identity configurations
77
75
  exports.IDENTITY_ACCESS_TOKEN_EXPIRES_IN = e.IDENTITY_ACCESS_TOKEN_EXPIRES_IN || "15m";
78
76
  exports.IDENTITY_AUDIENCE = e.IDENTITY_AUDIENCE || "api";
79
77
  exports.IDENTITY_ID_TOKEN_EXPIRES_IN = e.IDENTITY_ID_TOKEN_EXPIRES_IN || "15m";
80
- // Identity configurations
81
78
  exports.IDENTITY_ISSUER = e.IDENTITY_ISSUER || "https://fonoster.local";
79
+ exports.IDENTITY_OAUTH2_GITHUB_CLIENT_ID = e.IDENTITY_OAUTH2_GITHUB_CLIENT_ID;
80
+ exports.IDENTITY_OAUTH2_GITHUB_CLIENT_SECRET = e.IDENTITY_OAUTH2_GITHUB_CLIENT_SECRET;
82
81
  exports.IDENTITY_PRIVATE_KEY = fs_1.default.readFileSync(IDENTITY_PRIVATE_KEY_PATH, "utf8");
83
82
  exports.IDENTITY_PUBLIC_KEY = fs_1.default.readFileSync(IDENTITY_PUBLIC_KEY_PATH, "utf8");
84
83
  exports.IDENTITY_REFRESH_TOKEN_EXPIRES_IN = e.IDENTITY_REFRESH_TOKEN_EXPIRES_IN || "24h";
84
+ exports.IDENTITY_WORKSPACE_INVITATION_FAIL_URL = e.IDENTITY_WORKSPACE_INVITATION_FAIL_URL;
85
+ if (e.IDENTITY_OAUTH2_GITHUB_ENABLED === "true") {
86
+ (0, common_1.assertEnvsAreSet)([
87
+ "IDENTITY_OAUTH2_GITHUB_CLIENT_ID",
88
+ "IDENTITY_OAUTH2_GITHUB_CLIENT_SECRET"
89
+ ]);
90
+ }
91
+ // InfluxDB configurations
85
92
  exports.INFLUXDB_BUCKET = e.INFLUXDB_INIT_BUCKET;
86
93
  exports.INFLUXDB_ORG = e.INFLUXDB_INIT_ORG;
87
94
  exports.INFLUXDB_PASSWORD = e.INFLUXDB_INIT_PASSWORD;
88
95
  exports.INFLUXDB_TOKEN = e.INFLUXDB_INIT_TOKEN;
89
- // InfluxDB configurations
90
96
  exports.INFLUXDB_URL = e.INFLUXDB_URL;
91
97
  exports.INFLUXDB_USERNAME = e.INFLUXDB_INIT_USERNAME;
92
98
  exports.INTEGRATIONS_FILE = e.INTEGRATIONS_FILE || "/opt/fonoster/integrations.json";
@@ -107,3 +113,9 @@ exports.SMTP_HOST = e.SMTP_HOST;
107
113
  exports.SMTP_PORT = e.SMTP_PORT ? parseInt(e.SMTP_PORT) : 587;
108
114
  exports.SMTP_SECURE = ((_a = e.SMTP_SECURE) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "true";
109
115
  exports.SMTP_SENDER = e.SMTP_SENDER;
116
+ // Custom templates
117
+ exports.TEMPLATES_DIR = e.TEMPLATES_DIR;
118
+ // Twilio configurations
119
+ exports.TWILIO_ACCOUNT_SID = e.TWILIO_ACCOUNT_SID;
120
+ exports.TWILIO_AUTH_TOKEN = e.TWILIO_AUTH_TOKEN;
121
+ exports.TWILIO_PHONE_NUMBER = e.TWILIO_PHONE_NUMBER;
@@ -3,12 +3,12 @@ declare function createGetFnUtil(prisma: Prisma): (ref: string) => Promise<{
3
3
  extended: {
4
4
  accessKeyId: string;
5
5
  };
6
- name: string;
7
6
  secret: string;
7
+ name: string;
8
8
  ref: string;
9
+ accessKeyId: string;
9
10
  createdAt: Date;
10
11
  updatedAt: Date;
11
- accessKeyId: string;
12
12
  } & {
13
13
  createdAt: number;
14
14
  updatedAt: number;
@@ -36,7 +36,7 @@ function createGetFnUtil(prisma) {
36
36
  where: { ref }
37
37
  });
38
38
  if (!response) {
39
- throw (0, notFoundError_1.notFoundError)(`Secret not found: ${ref}`);
39
+ throw (0, notFoundError_1.notFoundError)(`Resource not found: ${ref}`);
40
40
  }
41
41
  return (0, common_1.datesMapper)(Object.assign(Object.assign({}, response), { extended: {
42
42
  accessKeyId: response.accessKeyId
@@ -41,5 +41,5 @@ function deleteSecret(prisma) {
41
41
  yield prisma.secret.delete({ where: { ref } });
42
42
  return { ref };
43
43
  });
44
- return (0, withErrorHandlingAndValidationAndAccess_1.withErrorHandlingAndValidationAndAccess)(fn, (ref) => getFn(ref), common_1.Validators.baseApiObjectSchema);
44
+ return (0, withErrorHandlingAndValidationAndAccess_1.withErrorHandlingAndValidationAndAccess)(fn, (ref) => getFn(ref), common_1.Validators.emptySchema);
45
45
  }
@@ -40,5 +40,5 @@ function getSecret(prisma) {
40
40
  logger.verbose("call to getSecret", { ref });
41
41
  return yield getFn(ref);
42
42
  });
43
- return (0, withErrorHandlingAndValidationAndAccess_1.withErrorHandlingAndValidationAndAccess)(fn, (ref) => getFn(ref), common_1.Validators.baseApiObjectSchema);
43
+ return (0, withErrorHandlingAndValidationAndAccess_1.withErrorHandlingAndValidationAndAccess)(fn, (ref) => getFn(ref), common_1.Validators.emptySchema);
44
44
  }
@@ -33,8 +33,10 @@ const zod_1 = require("zod");
33
33
  const withErrorHandling_1 = require("./utils/withErrorHandling");
34
34
  const requestSchema = zod_1.z.object({
35
35
  sessionRef: zod_1.z.string(),
36
- playbackRef: zod_1.z.string().optional().nullable(),
37
- action: zod_1.z.nativeEnum(common_1.PlaybackControlAction)
36
+ playbackRef: zod_1.z.string().optional(),
37
+ action: zod_1.z.nativeEnum(common_1.PlaybackControlAction, {
38
+ message: "Invalid playback control action."
39
+ })
38
40
  });
39
41
  function playbackControlHandler(ari, voiceClient) {
40
42
  return (0, withErrorHandling_1.withErrorHandling)((playbackControlReq) => __awaiter(this, void 0, void 0, function* () {
@@ -19,10 +19,10 @@ const envs_1 = require("../../envs");
19
19
  const sayRequestSchema = zod_1.z.object({
20
20
  text: zod_1.z.string(),
21
21
  sessionRef: zod_1.z.string(),
22
- playbackRef: zod_1.z.string().optional().nullable(),
23
- options: zod_1.z.record(zod_1.z.unknown()).optional().nullable()
22
+ playbackRef: zod_1.z.string().optional(),
23
+ options: zod_1.z.record(zod_1.z.unknown()).optional()
24
24
  });
25
- const getMediaUrl = (filename) => `sound:http://${envs_1.APISERVER_HOST}:${envs_1.FILES_SERVER_PORT}/sounds/${filename}.sln16`;
25
+ const getMediaUrl = (filename) => `sound:http://${envs_1.APISERVER_HOST}:${envs_1.HTTP_BRIDGE_PORT}/api/sounds/${filename}.sln16`;
26
26
  function sayHandler(ari, voiceClient) {
27
27
  return (0, withErrorHandling_1.withErrorHandling)((request) => __awaiter(this, void 0, void 0, function* () {
28
28
  const { sessionRef: channelId } = request;
@@ -32,8 +32,12 @@ const common_1 = require("@fonoster/common");
32
32
  const zod_1 = require("zod");
33
33
  const withErrorHandling_1 = require("./utils/withErrorHandling");
34
34
  const streamRequestSchema = zod_1.z.object({
35
- direction: zod_1.z.nativeEnum(common_1.StreamDirection).optional(),
36
- format: zod_1.z.nativeEnum(common_1.StreamAudioFormat).optional()
35
+ direction: zod_1.z
36
+ .nativeEnum(common_1.StreamDirection, { message: "Invalid stream direction" })
37
+ .optional(),
38
+ format: zod_1.z
39
+ .nativeEnum(common_1.StreamAudioFormat, { message: "Invalid stream audio format" })
40
+ .optional()
37
41
  });
38
42
  function streamHandler(voiceClient) {
39
43
  return (0, withErrorHandling_1.withErrorHandling)((request) => __awaiter(this, void 0, void 0, function* () {
@@ -32,7 +32,9 @@ const common_1 = require("@fonoster/common");
32
32
  const zod_1 = require("zod");
33
33
  const withErrorHandling_1 = require("./utils/withErrorHandling");
34
34
  const gatherRequestSchema = zod_1.z.object({
35
- source: zod_1.z.optional(zod_1.z.nativeEnum(common_1.StreamGatherSource))
35
+ source: zod_1.z.optional(zod_1.z.nativeEnum(common_1.StreamGatherSource, {
36
+ message: "Invalid stream gather source."
37
+ }))
36
38
  });
37
39
  function streamGatherHandler(voiceClient) {
38
40
  return (0, withErrorHandling_1.withErrorHandling)((request) => __awaiter(this, void 0, void 0, function* () {
@@ -40,14 +40,14 @@ const makeGetChannelVar_1 = require("../../utils/makeGetChannelVar");
40
40
  // TODO: Needs request validation
41
41
  function dialHandler(ari, voiceClient) {
42
42
  return (request) => __awaiter(this, void 0, void 0, function* () {
43
- const { sessionRef, destination, timeout } = request;
43
+ const { sessionRef: channelId, destination, timeout } = request;
44
44
  const bridge = yield ari.bridges.create({
45
45
  type: "mixing"
46
46
  });
47
47
  // eslint-disable-next-line new-cap
48
48
  const dialed = ari.Channel();
49
- yield bridge.addChannel({ channel: sessionRef });
50
- const callerChannel = yield ari.channels.get({ channelId: sessionRef });
49
+ yield bridge.addChannel({ channel: channelId });
50
+ const callerChannel = yield ari.channels.get({ channelId });
51
51
  const getChannelVar = (0, makeGetChannelVar_1.makeGetChannelVar)(callerChannel);
52
52
  const ingressNumber = (yield getChannelVar(types_1.ChannelVar.INGRESS_NUMBER))
53
53
  .value;
@@ -62,6 +62,7 @@ function dialHandler(ari, voiceClient) {
62
62
  "PJSIP_HEADER(add,X-Is-Api-Originated-Type)": "true"
63
63
  }
64
64
  });
65
+ yield ari.channels.ring({ channelId });
65
66
  dialed.once(types_1.AriEvent.STASIS_START, (0, handleStasisStart_1.handleStasisStart)({ ari, request, bridge, dialed }));
66
67
  dialed.once(types_1.AriEvent.CHANNEL_LEFT_BRIDGE, (0, handleChannelLeftBridge_1.handleChannelLeftBridge)({ bridge, dialed }));
67
68
  dialed.once(types_1.AriEvent.STASIS_END, (0, handleStasisEnd_1.handleStasisEnd)(request));
@@ -36,6 +36,7 @@ function handleStasisStart(params) {
36
36
  return (_, channel) => __awaiter(this, void 0, void 0, function* () {
37
37
  try {
38
38
  yield bridge.addChannel({ channel: dialed.id });
39
+ yield ari.channels.ringStop({ channelId: channel.id });
39
40
  if ([common_1.DialRecordDirection.IN, common_1.DialRecordDirection.BOTH].includes(recordDirection)) {
40
41
  (0, recordChannel_1.recordChannel)(ari, common_1.DialRecordDirection.IN, channel.id);
41
42
  }
@@ -29,17 +29,28 @@ exports.gatherHandler = gatherHandler;
29
29
  * limitations under the License.
30
30
  */
31
31
  const common_1 = require("@fonoster/common");
32
+ const messages_1 = require("@fonoster/common/src/messages");
32
33
  const zod_1 = require("zod");
33
34
  const getTimeoutPromise_1 = require("./getTimeoutPromise");
34
35
  const utils_1 = require("../utils");
35
36
  const withErrorHandling_1 = require("../utils/withErrorHandling");
36
37
  const gatherRequestSchema = zod_1.z.object({
37
- source: zod_1.z.optional(zod_1.z.nativeEnum(common_1.GatherSource)),
38
- maxDigits: zod_1.z.number().optional().nullable(),
38
+ source: zod_1.z
39
+ .optional(zod_1.z.nativeEnum(common_1.GatherSource, { message: "Invalid gather source" }))
40
+ .optional(),
41
+ maxDigits: zod_1.z
42
+ .number()
43
+ .int({
44
+ message: messages_1.POSITIVE_INTEGER_MESSAGE
45
+ })
46
+ .positive({
47
+ message: messages_1.POSITIVE_INTEGER_MESSAGE
48
+ })
49
+ .optional(),
39
50
  finishOnKey: zod_1.z
40
51
  .string()
41
- .regex(/^[0-9*#]$/) // Ensure it's a valid DTMF character
42
- .max(1)
52
+ .regex(/^[0-9*#]$/)
53
+ .max(1, { message: messages_1.MUST_BE_A_SINGLE_CHARACTER })
43
54
  .optional()
44
55
  });
45
56
  function gatherHandler(voiceClient) {
@@ -0,0 +1,2 @@
1
+ declare function textChunkTextByClause(text: string): any[];
2
+ export { textChunkTextByClause };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.textChunkTextByClause = textChunkTextByClause;
4
+ /* eslint-disable no-loops/no-loops */
5
+ /*
6
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
7
+ * http://github.com/fonoster/fonoster
8
+ *
9
+ * This file is part of Fonoster
10
+ *
11
+ * Licensed under the MIT License (the "License");
12
+ * you may not use this file except in compliance with
13
+ * the License. You may obtain a copy of the License at
14
+ *
15
+ * https://opensource.org/licenses/MIT
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ */
23
+ const CLAUSE_BOUNDARIES = /[.?!;]+/g;
24
+ function textChunkTextByClause(text) {
25
+ const boundaries = [...text.matchAll(CLAUSE_BOUNDARIES)];
26
+ const chunks = [];
27
+ let start = 0;
28
+ for (let i = 0; i < boundaries.length; i++) {
29
+ if (chunks.length >= 2) {
30
+ break;
31
+ }
32
+ const boundary = boundaries[i];
33
+ const end = boundary.index + boundary[0].length;
34
+ chunks.push(text.slice(start, end).trim());
35
+ start = end;
36
+ }
37
+ const remainingText = text.slice(start).trim();
38
+ if (remainingText.length > 0) {
39
+ chunks.push(remainingText);
40
+ }
41
+ return chunks;
42
+ }
@@ -21,8 +21,10 @@ function withErrorHandling(fn) {
21
21
  }
22
22
  catch (err) {
23
23
  if (err instanceof zod_1.z.ZodError) {
24
- const validationError = (0, zod_validation_error_1.fromError)(err);
25
- logger.error("Validation error:", {
24
+ const validationError = (0, zod_validation_error_1.fromError)(err, {
25
+ prefix: null
26
+ });
27
+ logger.error("Error:", {
26
28
  message: validationError.toString()
27
29
  });
28
30
  }
@@ -56,7 +56,7 @@ function makeCreateContainer(prisma, pathToIntegrations) {
56
56
  }
57
57
  catch (e) {
58
58
  // fatal error
59
- const message = (0, zod_validation_error_1.fromError)(e);
59
+ const message = (0, zod_validation_error_1.fromError)(e, { prefix: null }).toString();
60
60
  logger.error("integrations config is invalid", { message });
61
61
  process.exit(1);
62
62
  }
@@ -126,8 +126,14 @@ class Deepgram extends AbstractSpeechToText_1.AbstractSpeechToText {
126
126
  }
127
127
  static getConfigValidationSchema() {
128
128
  return z.object({
129
- languageCode: z.nativeEnum(common_1.VoiceLanguage).optional().nullable(),
130
- model: z.nativeEnum(types_1.DeepgramModel).optional().nullable()
129
+ languageCode: z
130
+ .nativeEnum(common_1.VoiceLanguage, {
131
+ message: common_1.Messages.VALID_LANGUAGE_CODE
132
+ })
133
+ .optional(),
134
+ model: z
135
+ .nativeEnum(types_1.DeepgramModel, { message: "Invalid Deepgram model" })
136
+ .optional()
131
137
  });
132
138
  }
133
139
  static getCredentialsValidationSchema() {
@@ -86,7 +86,9 @@ class Google extends AbstractSpeechToText_1.AbstractSpeechToText {
86
86
  }
87
87
  static getConfigValidationSchema() {
88
88
  return z.object({
89
- languageCode: z.nativeEnum(common_1.VoiceLanguage).optional().nullable()
89
+ languageCode: z
90
+ .nativeEnum(common_1.VoiceLanguage, { message: common_1.Messages.VALID_LANGUAGE_CODE })
91
+ .optional()
90
92
  });
91
93
  }
92
94
  static getCredentialsValidationSchema() {
@@ -103,7 +103,7 @@ class Azure extends AbstractTextToSpeech_1.AbstractTextToSpeech {
103
103
  }
104
104
  static getConfigValidationSchema() {
105
105
  return z.object({
106
- voice: z.nativeEnum(common_1.AzureVoice)
106
+ voice: z.nativeEnum(common_1.AzureVoice, { message: "Invalid Azure voice" })
107
107
  });
108
108
  }
109
109
  static getCredentialsValidationSchema() {
@@ -1,8 +1,8 @@
1
1
  import { Readable } from "stream";
2
+ import { DeepgramClient } from "@deepgram/sdk";
2
3
  import * as z from "zod";
3
4
  import { AbstractTextToSpeech } from "./AbstractTextToSpeech";
4
5
  import { SynthOptions } from "./types";
5
- declare const DeepgramClient: any;
6
6
  declare const ENGINE_NAME = "tts.deepgram";
7
7
  type DeepgramTtsConfig = {
8
8
  [key: string]: Record<string, string>;
@@ -11,7 +11,7 @@ type DeepgramTtsConfig = {
11
11
  };
12
12
  };
13
13
  declare class Deepgram extends AbstractTextToSpeech<typeof ENGINE_NAME> {
14
- client: typeof DeepgramClient;
14
+ client: DeepgramClient;
15
15
  engineConfig: DeepgramTtsConfig;
16
16
  readonly engineName = "tts.deepgram";
17
17
  protected readonly OUTPUT_FORMAT = "sln16";
@@ -23,6 +23,7 @@ declare class Deepgram extends AbstractTextToSpeech<typeof ENGINE_NAME> {
23
23
  ref: string;
24
24
  stream: Readable;
25
25
  }>;
26
+ private doSynthesize;
26
27
  static getConfigValidationSchema(): z.Schema;
27
28
  static getCredentialsValidationSchema(): z.Schema;
28
29
  }
@@ -33,6 +33,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
35
  exports.ENGINE_NAME = exports.Deepgram = void 0;
36
+ /* eslint-disable no-loops/no-loops */
36
37
  /*
37
38
  * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
38
39
  * http://github.com/fonoster/fonoster
@@ -52,13 +53,14 @@ exports.ENGINE_NAME = exports.Deepgram = void 0;
52
53
  * limitations under the License.
53
54
  */
54
55
  const stream_1 = require("stream");
56
+ const sdk_1 = require("@deepgram/sdk");
55
57
  const common_1 = require("@fonoster/common");
56
58
  const logger_1 = require("@fonoster/logger");
57
59
  const z = __importStar(require("zod"));
58
60
  const AbstractTextToSpeech_1 = require("./AbstractTextToSpeech");
59
61
  const isSsml_1 = require("./isSsml");
60
- // eslint-disable-next-line @typescript-eslint/no-var-requires
61
- const { DeepgramClient, createClient } = require("@deepgram/sdk");
62
+ const streamToBuffer_1 = require("./streamToBuffer");
63
+ const textChunksByClause_1 = require("../handlers/utils/textChunksByClause");
62
64
  const ENGINE_NAME = "tts.deepgram";
63
65
  exports.ENGINE_NAME = ENGINE_NAME;
64
66
  const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
@@ -70,26 +72,59 @@ class Deepgram extends AbstractTextToSpeech_1.AbstractTextToSpeech {
70
72
  this.CACHING_FIELDS = ["voice"];
71
73
  this.AUDIO_ENCODING = "linear16";
72
74
  this.SAMPLE_RATE_HERTZ = 16000;
73
- this.client = createClient(config.credentials.apiKey);
75
+ this.client = (0, sdk_1.createClient)(config.credentials.apiKey);
74
76
  this.engineConfig = config;
75
77
  }
76
78
  synthesize(text, options) {
77
79
  return __awaiter(this, void 0, void 0, function* () {
78
80
  logger.verbose(`synthesize [input: ${text}, isSsml=${(0, isSsml_1.isSsml)(text)} options: ${JSON.stringify(options)}]`);
79
81
  const { voice } = this.engineConfig.config;
82
+ const ref = this.createMediaReference();
83
+ const chunks = (0, textChunksByClause_1.textChunkTextByClause)(text);
84
+ const stream = new stream_1.Readable({ read() { } });
85
+ const results = new Array(chunks.length);
86
+ let nextIndexToPush = 0;
87
+ function observeQueue() {
88
+ if (nextIndexToPush < results.length &&
89
+ results[nextIndexToPush] !== undefined) {
90
+ stream.push(results[nextIndexToPush]);
91
+ nextIndexToPush++;
92
+ setImmediate(observeQueue);
93
+ }
94
+ else if (nextIndexToPush < results.length) {
95
+ setTimeout(observeQueue, 10);
96
+ }
97
+ else {
98
+ stream.push(null);
99
+ }
100
+ }
101
+ observeQueue();
102
+ chunks.forEach((text, index) => {
103
+ this.doSynthesize(text, voice)
104
+ .then((synthesizedText) => {
105
+ results[index] = synthesizedText;
106
+ })
107
+ .catch((error) => {
108
+ stream.emit("error", error);
109
+ });
110
+ });
111
+ return { ref, stream };
112
+ });
113
+ }
114
+ doSynthesize(text, voice) {
115
+ return __awaiter(this, void 0, void 0, function* () {
80
116
  const response = yield this.client.speak.request({ text }, {
81
117
  model: voice || common_1.DeepgramVoice.AURA_ASTERIA_EN,
82
118
  encoding: this.AUDIO_ENCODING,
83
119
  sample_rate: this.SAMPLE_RATE_HERTZ,
84
120
  container: "none"
85
121
  });
86
- const ref = this.createMediaReference();
87
- return { ref, stream: stream_1.Readable.from(yield response.getStream()) };
122
+ return (yield (0, streamToBuffer_1.streamToBuffer)(yield response.getStream()));
88
123
  });
89
124
  }
90
125
  static getConfigValidationSchema() {
91
126
  return z.object({
92
- voice: z.nativeEnum(common_1.DeepgramVoice)
127
+ voice: z.nativeEnum(common_1.DeepgramVoice, { message: "Invalid Deepgram voice" })
93
128
  });
94
129
  }
95
130
  static getCredentialsValidationSchema() {
@@ -72,7 +72,9 @@ class ElevenLabs extends AbstractTextToSpeech_1.AbstractTextToSpeech {
72
72
  }
73
73
  static getConfigValidationSchema() {
74
74
  return z.object({
75
- voice: z.nativeEnum(common_1.ElevenLabsVoice)
75
+ voice: z.nativeEnum(common_1.ElevenLabsVoice, {
76
+ message: "Invalid ElevenLabs voice."
77
+ })
76
78
  });
77
79
  }
78
80
  static getCredentialsValidationSchema() {
@@ -95,7 +95,9 @@ class Google extends AbstractTextToSpeech_1.AbstractTextToSpeech {
95
95
  }
96
96
  static getConfigValidationSchema() {
97
97
  return z.object({
98
- voice: z.nativeEnum(common_1.GoogleVoice)
98
+ voice: z
99
+ .nativeEnum(common_1.GoogleVoice, { message: "Invalid Google voice" })
100
+ .optional()
99
101
  });
100
102
  }
101
103
  static getCredentialsValidationSchema() {
@@ -0,0 +1,2 @@
1
+ declare function streamToBuffer(readableStream: any): Promise<Buffer>;
2
+ export { streamToBuffer };
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.streamToBuffer = streamToBuffer;
20
+ /* eslint-disable no-loops/no-loops */
21
+ /*
22
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
23
+ * http://github.com/fonoster/fonoster
24
+ *
25
+ * This file is part of Fonoster
26
+ *
27
+ * Licensed under the MIT License (the "License");
28
+ * you may not use this file except in compliance with
29
+ * the License. You may obtain a copy of the License at
30
+ *
31
+ * https://opensource.org/licenses/MIT
32
+ *
33
+ * Unless required by applicable law or agreed to in writing, software
34
+ * distributed under the License is distributed on an "AS IS" BASIS,
35
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
+ * See the License for the specific language governing permissions and
37
+ * limitations under the License.
38
+ */
39
+ function streamToBuffer(readableStream) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ var _a, readableStream_1, readableStream_1_1;
42
+ var _b, e_1, _c, _d;
43
+ const chunks = [];
44
+ try {
45
+ for (_a = true, readableStream_1 = __asyncValues(readableStream); readableStream_1_1 = yield readableStream_1.next(), _b = readableStream_1_1.done, !_b; _a = true) {
46
+ _d = readableStream_1_1.value;
47
+ _a = false;
48
+ const chunk = _d;
49
+ chunks.push(chunk);
50
+ }
51
+ }
52
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
53
+ finally {
54
+ try {
55
+ if (!_a && !_b && (_c = readableStream_1.return)) yield _c.call(readableStream_1);
56
+ }
57
+ finally { if (e_1) throw e_1.error; }
58
+ }
59
+ return Buffer.concat(chunks);
60
+ });
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/apiserver",
3
- "version": "0.7.24",
3
+ "version": "0.7.25",
4
4
  "description": "APIServer for Fonoster",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/fonoster#readme",
@@ -21,12 +21,12 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@deepgram/sdk": "^3.5.1",
24
- "@fonoster/common": "^0.7.22",
25
- "@fonoster/identity": "^0.7.22",
24
+ "@fonoster/common": "^0.7.25",
25
+ "@fonoster/identity": "^0.7.25",
26
26
  "@fonoster/logger": "^0.7.22",
27
- "@fonoster/sipnet": "^0.7.22",
27
+ "@fonoster/sipnet": "^0.7.25",
28
28
  "@fonoster/streams": "^0.7.22",
29
- "@fonoster/types": "^0.7.22",
29
+ "@fonoster/types": "^0.7.25",
30
30
  "@google-cloud/speech": "^6.6.0",
31
31
  "@google-cloud/text-to-speech": "^5.3.0",
32
32
  "@grpc/grpc-js": "~1.10.6",
@@ -72,5 +72,5 @@
72
72
  "@types/uuid": "^9.0.8",
73
73
  "@types/validator": "^13.12.0"
74
74
  },
75
- "gitHead": "58b141dc01f99f0aa903cad5497d12cd474f79df"
75
+ "gitHead": "f5dbfe479bd50b105ce3eb4b3c260503ef718f57"
76
76
  }