From 1dbab84781fc19db769421adca15f5b3ca95d594 Mon Sep 17 00:00:00 2001 From: Logan Patino Date: Mon, 27 Jan 2020 15:47:30 -0500 Subject: [PATCH 1/2] refactor: Pipe synthesize result to client side --- app.js | 149 +++---------- package-lock.json | 204 ++++-------------- package.json | 6 +- .../ServiceContainer/ServiceContainer.js | 53 +++-- src/components/ServiceContainer/utils.js | 37 ++++ 5 files changed, 143 insertions(+), 306 deletions(-) create mode 100644 src/components/ServiceContainer/utils.js diff --git a/app.js b/app.js index 557c301..347422e 100644 --- a/app.js +++ b/app.js @@ -1,117 +1,17 @@ const TextToSpeechV1 = require('ibm-watson/text-to-speech/v1.js'); -const { - BearerTokenAuthenticator, - CloudPakForDataAuthenticator, - Cp4dTokenManager, - IamAuthenticator, - IamTokenManager, -} = require('ibm-watson/auth'); const path = require('path'); const express = require('express'); -const vcapServices = require('vcap_services'); const app = express(); require('./config/express')(app); -let url = process.env.TEXT_TO_SPEECH_URL; -let authUrl = process.env.TEXT_TO_SPEECH_AUTH_URL; - -// Supply the API key for IAM authentication. -let apikey = process.env.TEXT_TO_SPEECH_APIKEY; - -// Supply the bearer token + URL for an instance on CPD (see the README for more details). -let bearerToken = process.env.TEXT_TO_SPEECH_BEARER_TOKEN; - -// Supply the username + password + URL as an alternative for an instance on CPD. -let username = process.env.TEXT_TO_SPEECH_USERNAME; -let password = process.env.TEXT_TO_SPEECH_PASSWORD; - -// On Cloud Foundry, we'll have a VCAP_SERVICES environment variable with credentials. -let vcapCredentials = vcapServices.getCredentials('text_to_speech'); - -// Create appropriate token manager and client. +// Create Text to Speech client. let client; -let tokenManager; -if (vcapCredentials || apikey) { - // Choose credentials from VCAP if they exist. - apikey = (vcapCredentials && vcapCredentials.apikey) || apikey; - url = (vcapCredentials && vcapCredentials.url) || url; - - try { - tokenManager = new IamTokenManager({ apikey }); - client = new TextToSpeechV1({ - serviceUrl: url, - authenticator: new IamAuthenticator({ apikey }), - }); - } catch (err) { - console.error('Error creating IAM token manager and client: ', err); - } -} else if (username && password && url) { - try { - tokenManager = new Cp4dTokenManager({ username, password, url: authUrl }); - client = new TextToSpeechV1({ - serviceUrl: url, - disableSslVerification: true, - authenticator: new CloudPakForDataAuthenticator({ - username, - password, - url: authUrl, - disableSslVerification: true, - }), - }); - } catch (err) { - console.error('Error creating CP4D token manager: ', err); - } -} else if (bearerToken) { - client = new TextToSpeechV1({ - serviceUrl: url, - disableSslVerification: true, - authenticator: new BearerTokenAuthenticator({ bearerToken }), - }); +try { + client = new TextToSpeechV1({}); +} catch (err) { + console.error('Error creating service client: ', err); } -const getToken = async () => { - let tokenResponse = {}; - - try { - if (tokenManager) { - const token = await tokenManager.getToken(); - tokenResponse = { - ...tokenResponse, - accessToken: token, - url, - }; - } else if (bearerToken && url) { - tokenResponse = { - ...tokenResponse, - accessToken: bearerToken, - url, - }; - } else { - tokenResponse = { - ...tokenResponse, - error: { - title: 'No valid credentials found', - description: - 'Could not find valid credentials for the Text to Speech service.', - statusCode: 401, - }, - }; - } - } catch (err) { - tokenResponse = { - ...tokenResponse, - error: { - title: 'Authentication error', - description: - 'There was a problem authenticating with the Text to Speech service.', - statusCode: 400, - }, - }; - } - - return tokenResponse; -}; - app.get('/', (_, res) => { res.sendFile(path.join(__dirname, 'build', 'index.html')); }); @@ -120,34 +20,37 @@ app.get('/health', (_, res) => { res.json({ status: 'UP' }); }); -app.get('/api/auth', async (_, res, next) => { - const token = await getToken(); - - if (token.error) { - console.error(token.error); - next(token.error); - } else { - return res.json(token); - } -}); - app.get('/api/voices', async (_, res, next) => { try { const { result } = await client.listVoices(); return res.json(result); - } catch (error) { - console.error(error); + } catch (err) { + console.error(err); if (!client) { - error.statusCode = 401; - error.description = + err.statusCode = 401; + err.description = 'Could not find valid credentials for the Text to Speech service.'; - error.title = 'Invalid credentials'; + err.title = 'Invalid credentials'; } - next(error); + next(err); } }); -app.pos; +app.get('/api/synthesize', async (req, res, next) => { + try { + const { result } = await client.synthesize(req.query); + result.pipe(res); + } catch (err) { + console.error(err); + if (!client) { + err.statusCode = 401; + err.description = + 'Could not find valid credentials for the Text to Speech service.'; + err.title = 'Invalid credentials'; + } + next(err); + } +}); // error-handler settings for all other routes require('./config/error-handler')(app); diff --git a/package-lock.json b/package-lock.json index 4054a4e..28b528a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -958,15 +958,6 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, - "@babel/polyfill": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.7.0.tgz", - "integrity": "sha512-/TS23MVvo34dFmf8mwCisCbWGrfhbiWZSwBo6HkADTBhUa2Q/jWltyY/tpofz/b6/RIhqaqQcquptCirqIhOaQ==", - "requires": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.2" - } - }, "@babel/preset-env": { "version": "7.7.7", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.7.tgz", @@ -3456,7 +3447,8 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true }, "buffer-indexof": { "version": "1.1.1", @@ -3993,11 +3985,6 @@ "wrap-ansi": "^5.1.0" } }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" - }, "clone-deep": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", @@ -4185,6 +4172,7 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -4364,7 +4352,8 @@ "core-js": { "version": "2.6.11", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true }, "core-js-compat": { "version": "3.6.2", @@ -4393,7 +4382,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "cosmiconfig": { "version": "5.2.1", @@ -4964,25 +4954,11 @@ "ip-regex": "^2.1.0" } }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - } - } - }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -5389,6 +5365,7 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, "requires": { "iconv-lite": "~0.4.13" } @@ -5501,7 +5478,8 @@ "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true }, "es6-promisify": { "version": "5.0.0", @@ -7460,7 +7438,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", @@ -7556,11 +7535,6 @@ "pump": "^3.0.0" } }, - "get-user-media-promise": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/get-user-media-promise/-/get-user-media-promise-1.1.4.tgz", - "integrity": "sha512-k49YuV2z0d3gKHLPTFKYfzEA9kduuQk7YBf8ev2dxrKk+DhMyuzfQnK9ZSxkEhE/jv3BZY62M0eICWa7lak9nw==" - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -7829,7 +7803,8 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -8610,7 +8585,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "ini": { "version": "1.3.5", @@ -9054,7 +9030,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-string": { "version": "1.0.5", @@ -9106,7 +9083,8 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, "isexe": { "version": "2.0.0", @@ -9122,6 +9100,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "dev": true, "requires": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" @@ -10816,11 +10795,6 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, - "lodash.pullallwith": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.pullallwith/-/lodash.pullallwith-4.7.0.tgz", - "integrity": "sha1-ZX5CAHENi1nWlO5SE2Yq4FEdEXA=" - }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -11315,27 +11289,6 @@ "to-regex": "^3.0.2" } }, - "microphone-stream": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/microphone-stream/-/microphone-stream-5.0.1.tgz", - "integrity": "sha512-hHblbrtWNZEOz6I3RR3vO9fVmN2e2PyR5TpBi+m6hRtTh7LT/hw4Pt5LIf6NSpL+HSMQ40I3CdLEq9alI4BG0w==", - "requires": { - "buffer-from": "^1.1.1", - "readable-stream": "^3.3.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -11670,6 +11623,7 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, "requires": { "encoding": "^0.1.11", "is-stream": "^1.0.1" @@ -11902,17 +11856,6 @@ } } }, - "nodeify-fetch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nodeify-fetch/-/nodeify-fetch-1.0.1.tgz", - "integrity": "sha1-D457ShEnNQ68mkz3cfT1sSMUAM4=", - "requires": { - "concat-stream": "^1.6.0", - "inherits": "^2.0.3", - "isomorphic-fetch": "^2.2.1", - "readable-stream": "^2.2.6" - } - }, "nodemon": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz", @@ -12105,7 +12048,8 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object-path": { "version": "0.11.4", @@ -12126,6 +12070,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -12535,15 +12480,6 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, "path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", @@ -13892,12 +13828,14 @@ "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true }, "progress": { "version": "2.0.3", @@ -14614,18 +14552,11 @@ "read-pkg": "^3.0.0" } }, - "readable-blob-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readable-blob-stream/-/readable-blob-stream-1.1.0.tgz", - "integrity": "sha1-2xpUjo5wrjMg8tJAFFSoSmnD34A=", - "requires": { - "inherits": "^2.0.1" - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -14639,7 +14570,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -14703,7 +14635,8 @@ "regenerator-runtime": { "version": "0.13.3", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true }, "regenerator-transform": { "version": "0.14.1", @@ -16341,6 +16274,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -16348,7 +16282,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -16927,7 +16862,8 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true }, "typedarray-to-buffer": { "version": "3.1.5", @@ -17264,6 +17200,7 @@ "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, "requires": { "inherits": "2.0.1" }, @@ -17271,14 +17208,16 @@ "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true } } }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "util.promisify": { "version": "1.0.0", @@ -17327,11 +17266,6 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "vcap_services": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/vcap_services/-/vcap_services-0.7.1.tgz", - "integrity": "sha512-Xo9lMYbQKYZCTKAAkfEoAEeP1aZZuO5VunT15XlB4mkwFrhlesT3A4R/FXBqOO8KLQ0j5scEQwJU6lLV/yIv/A==" - }, "vendors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", @@ -17526,51 +17460,6 @@ } } }, - "watson-speech": { - "version": "0.37.2", - "resolved": "https://registry.npmjs.org/watson-speech/-/watson-speech-0.37.2.tgz", - "integrity": "sha512-oeTBGLKuG2SF4HXMgty0GkxuyQDiXyuGeaCBc0Xbe/TH//yWilD1ZQPbhaI3p5+77UFTIbQrN/FyDqF0cwJihA==", - "requires": { - "@babel/polyfill": "^7.6.0", - "buffer-from": "^1.1.1", - "camelcase": "^5.3.1", - "clone": "^2.1.2", - "core-js": "^3.3.3", - "defaults": "^1.0.3", - "get-user-media-promise": "^1.1.4", - "lodash.pullallwith": "^4.7.0", - "microphone-stream": "^5.0.1", - "nodeify-fetch": "^1.0.1", - "object.assign": "^4.1.0", - "path": "^0.12.7", - "readable-blob-stream": "^1.1.0", - "readable-stream": "^3.4.0", - "websocket": "^1.0.30", - "whatwg-fetch": "^2.0.4" - }, - "dependencies": { - "core-js": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.2.tgz", - "integrity": "sha512-hIE5dXkRzRvnZ5vhkRfQxUvDxQZmD9oueA08jDYRBKJHx+VIl/Pne/e0A4x9LObEEthC/TqiZybUoNM4tRgnKg==" - }, - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "whatwg-fetch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" - } - } - }, "wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", @@ -18139,7 +18028,8 @@ "whatwg-fetch": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "dev": true }, "whatwg-mimetype": { "version": "2.3.0", diff --git a/package.json b/package.json index e3bf147..f6f9685 100644 --- a/package.json +++ b/package.json @@ -8,17 +8,13 @@ "concurrently": "^5.0.2", "cross-env": "^6.0.3", "dotenv": "^8.2.0", - "es6-promise": "^4.2.8", "express": "^4.17.1", "express-rate-limit": "^5.0.0", "express-secure-only": "^0.2.1", "helmet": "^3.21.2", "ibm-watson": "^5.2.1", - "isomorphic-fetch": "^2.2.1", "morgan": "^1.9.1", - "use-data-api": "^1.0.1", - "vcap_services": "^0.7.1", - "watson-speech": "^0.37.2" + "use-data-api": "^1.0.1" }, "scripts": { "dev": "concurrently \"npm:client\" \"npm:server\"", diff --git a/src/components/ServiceContainer/ServiceContainer.js b/src/components/ServiceContainer/ServiceContainer.js index 3083343..bc07946 100644 --- a/src/components/ServiceContainer/ServiceContainer.js +++ b/src/components/ServiceContainer/ServiceContainer.js @@ -1,12 +1,10 @@ import React, { useRef, useState } from 'react'; -import fetch from 'isomorphic-fetch'; -import synthesize from 'watson-speech/text-to-speech/synthesize'; import ControlContainer from '../ControlContainer'; import OutputContainer from '../OutputContainer'; import Toast from '../Toast'; import { createError } from '../../utils'; +import { canPlayAudioFormat, getSearchParams } from './utils'; -const TOKEN_ERROR_TITLE = 'Authentication error'; const SYNTHESIZE_ERROR_TITLE = 'Text synthesis error'; const GDPR_DISCLAIMER = 'This system is for demonstration purposes only and is not intended to process Personal Data. No Personal Data is to be entered into this system as it may not have the necessary controls in place to meet the requirements of the General Data Protection Regulation (EU) 2016/679.'; @@ -15,26 +13,39 @@ export const ServiceContainer = () => { const [error, setError] = useState(); let audioElementRef = useRef(null); - const onSynthesize = async (text, voice) => { - let authResponse; - let authJson; - authResponse = await fetch('/api/auth'); - authJson = await authResponse.json(); - if (!authResponse.ok) { - setError(createError(TOKEN_ERROR_TITLE, authJson)); + const getSynthesizeUrl = (text, voice) => { + const params = getSearchParams(); + + params.set('text', text); + params.set('voice', voice.id); + + let accept; + if (canPlayAudioFormat('audio/mp3', audioElementRef.current)) { + accept = 'audio/mp3'; + } else if ( + canPlayAudioFormat('audio/ogg;codec=opus', audioElementRef.current) + ) { + accept = 'audio/ogg;codec=opus'; + } else if (canPlayAudioFormat('audio/wav', audioElementRef.current)) { + accept = 'audio/wav'; + } + if (accept) { + params.set('accept', accept); } - const audio = await synthesize({ - accessToken: authJson.accessToken, - autoPlay: false, - element: audioElementRef.current, - text, - voice: voice.id, - }); - audio.play().catch(error => { - console.log('ERROR', error); - setError(createError(SYNTHESIZE_ERROR_TITLE, error.message)); - }); + return `/api/synthesize?${params.toString()}`; + }; + + const onSynthesize = async (text, voice) => { + try { + audioElementRef.current.setAttribute( + 'src', + getSynthesizeUrl(text, voice), + ); + await audioElementRef.current.play(); + } catch (err) { + setError(createError(SYNTHESIZE_ERROR_TITLE, err.message)); + } }; return ( diff --git a/src/components/ServiceContainer/utils.js b/src/components/ServiceContainer/utils.js new file mode 100644 index 0000000..019865b --- /dev/null +++ b/src/components/ServiceContainer/utils.js @@ -0,0 +1,37 @@ +export const canPlayAudioFormat = (mimeType, audioElement) => { + if (!audioElement) { + audioElement = document.createElement('audio'); + } + + if (audioElement) { + return ( + typeof audioElement.canPlayType === 'function' && + audioElement.canPlayType(mimeType) !== '' + ); + } + return false; +}; + +/** + * @return {Function} A polyfill for URLSearchParams + */ +export const getSearchParams = () => { + if (typeof URLSearchParams === 'function') { + return new URLSearchParams(); + } + + // Simple polyfill for URLSearchparams + const SearchParams = function SearchParams() {}; + + SearchParams.prototype.set = function set(key, value) { + this[key] = value; + }; + + SearchParams.prototype.toString = function toString() { + return Object.keys(this) + .map(v => `${encodeURI(v)}=${encodeURI(this[v])}`) + .join('&'); + }; + + return new SearchParams(); +}; From 6a5dd8b80ece31023aa06533a91eb58364d7bc6f Mon Sep 17 00:00:00 2001 From: Logan Patino Date: Mon, 27 Jan 2020 15:48:16 -0500 Subject: [PATCH 2/2] fix(Header): Fix incorrect getting started link --- src/App.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index 5194ded..4e80d4a 100644 --- a/src/App.js +++ b/src/App.js @@ -48,7 +48,7 @@ const HEADER_LINKS = [ key="ibm-cloud-link" target="_blank" rel="noopener noreferrer" - href="https://cloud.ibm.com/registration?target=%2Fcatalog%2Fservices%text-to-speech%3FhideTours%3Dtrue%26cm_mmc%3D-_-Watson%2BCore_Watson%2BCore%2B-%2BPlatform-_-WW_WW-_-wdc-ref%26cm_mmc%3D-_-Watson%2BCore_Watson%2BCore%2B-%2BPlatform-_-WW_WW-_-wdc-ref%26cm_mmca1%3D000000OF%26cm_mmca2%3D10000409&_ga=2.158846578.918027017.1572271296-1405764752.1539884377&_gac=1.250083700.1571850605.Cj0KCQjw3JXtBRC8ARIsAEBHg4m4g1PSkKQRoI6YUe4A-6ysul0ziiWU0DVbqlbWAQpq3721u-bxkd0aAkV3EALw_wcB&cm_mc_uid=83381689395615475202389&cm_mc_sid_50200000=82214471572470185115&cm_mc_sid_52640000=21949701572470185117&cm_mmc=Earned-_-Watson%20Core%20-%20Platform-_-WW_WW-_-intercom&cm_mmca1=000000OF&cm_mmca2=10000409" + href="https://cloud.ibm.com/registration?target=%2Fdeveloper%2Fwatson%2Flaunch-service%2Ftext-to-speech%3FhideTours%3Dtrue" >