├── .gitignore ├── LICENSE ├── README.md ├── bin └── ari-transcriber ├── lib ├── ari-controller.js ├── ari-transcriber.js ├── google-speech-provider.js └── rtp-udp-server.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .checkstyle 2 | .jshintrc 3 | .project 4 | .sublime-project 5 | .tern-project 6 | .settings 7 | node_modules 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Asterisk External Media Sample 4 | 5 | This package demonstrates how to use the ARI External Media feature to transcribe 6 | the audio from a bridge using the Google Speech APIs. 7 | 8 | ## Installation 9 | 10 | #### Prerequisites 11 | * A functional Asterisk 16.6.0+ installation. 12 | * A conference bridge or phone configured. 13 | * Node.JS version 10 or greater. 14 | * Google Speech API credentials set in environment variable GOOGLE_APPLICATION_CREDENTIALS. 15 | See https://cloud.google.com/speech-to-text/docs/ for more information. 16 | 17 | Run `npm install` from the top of the source tree. 18 | This will install the required npm packages including `node-ari-client` and `@google-cloud/speech`. 19 | You can then run the transcriber as `bin/ari-transcriber`. If you add the `-g` 20 | option to `npm install` to install system wide, you can just run `ari-transcriber`. 21 | 22 | ## Usage 23 | 24 | ``` 25 | $ ari-transcriber --help 26 | ari-transcriber [options] 27 | 28 | Start the transcription server 29 | 30 | Positionals: 31 | dialstring Extension to dial such as "Local/1234" 32 | 33 | Incoming Audio Server 34 | --format, -f Asterisk format/codec [string] [choices: "ulaw", "slin16"] [default: "ulaw"] 35 | --listenServer, -l Address and port on which to listen for audio from Asterisk [string] [default: "127.0.0.1:9999"] 36 | 37 | Speech 38 | --speechModel Google Speech API model [string] [choices: "phone_call", "video", "default"] [default: "default"] 39 | --speechLang BCP-47 Language code. en-US, fr-CA, etc. [string] [choices: "en-US", "fr-CA"] [default: "en-US"] 40 | --speakerDiarization Outputs words associated to speaker index to the console. [boolean] [default: false] 41 | 42 | ARI 43 | --ariServerUrl, -a The URL for the Asterisk instance [string] [default: "http://127.0.0.1:8088"] 44 | --ariUser, -u The user configured in ari.conf [string] [default: "asterisk"] 45 | --ariPassword, -p The password for the user configured in ari.conf [string] [default: "asterisk"] 46 | 47 | Transcription WebSocket 48 | --sslCert WebSocket secure server (wss) certificate. If omitted, a non-secures (ws) websocket server will be created [string] 49 | --sslKey WebSocket secure server key. Must be supplied if sslCert is ssplied [string] 50 | --wssPort WebSocket server port. If omitted, no websocket server will be started [number] 51 | 52 | Options: 53 | --version Show version number [boolean] 54 | --help Show help [boolean] 55 | --audioOutput, -o A file into which the raw audio from Asterisk can be written [string] 56 | 57 | Examples: 58 | ari-transcriber --format=slin16 --sslCert=/etc/letsencrypt/live/myserver/fullchain.pem 59 | --sslKey=/etc/letsencrypt/live/myserver/privkey.pem --wssPort=39990 --speakerDiarization 'Local/1234' 60 | ``` 61 | 62 | The ari-transcriber performs several tasks: 63 | * Creates an ari-client instance 64 | * Creates a WebSocket server from which the live transcription can be accessed 65 | * Starts an audio server to receive the audio from Asterisk 66 | * Creates an instance of Google Speech Provider that takes the audio from the server, transcribes it, and sends the transcription out the websocket 67 | * Uses the ARI instance to: 68 | * Create a mixing bridge 69 | * Create a Local channel which dials the conference bridge to be monitored 70 | * Place the local channel into the mixing bridge 71 | * Create an External Media channel that directs the audio to the audio server 72 | * Place the External Media channel into the mixing bridge 73 | 74 | Why the Local channel and bridge? To keep the sample as simple as possible, 75 | it's assumes that a conference bridge is already available. Since that 76 | bridge wouldn't be controlled by ARI/Stasis, we can't just add the External 77 | Media channel directly to it. Instead we have to create a Local channel that _dials_ 78 | the conference bridge, then bridge _that_ channel with the External Media 79 | channel. If you were ading External Media capabilities to your own application, 80 | chances are that your app would already control the participant bridge and you 81 | wouldn't need the Local channel and mixing bridge. 82 | 83 | ## Try It! 84 | 85 | You don't need the WebSocket transcription server to try this. 86 | Just a phone to call. 87 | 88 | ``` 89 | $ export GOOGLE_APPLICATION_CREDENTIALS= 90 | $ ari-transcriber --format=slin16 'Local/1234' 91 | ```` 92 | -------------------------------------------------------------------------------- /bin/ari-transcriber: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | * Copyright 2019 Sangoma Technologies Corporation 4 | * George Joseph 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /* 20 | * This script processes the command line arguments and calls 21 | * the transcriber. 22 | */ 23 | 24 | var transcriber = require('../lib/ari-transcriber.js'); 25 | 26 | process.title = 'ari-transcriber'; 27 | require(`yargs`) 28 | .example(`node $0`) 29 | .recommendCommands() 30 | .help() 31 | .command(`$0 [options] `, "Start the transcription server", 32 | (yargs) => { 33 | yargs.example("$0 --help --format=slin16 --sslCert=/etc/letsencrypt/live/myserver/fullchain.pem --sslKey=/etc/letsencrypt/live/myserver/privkey.pem --wssPort=39990 --speakerDiarization 'Local/1170' ") 34 | yargs.wrap(yargs.terminalWidth()); 35 | yargs.positional('dialstring', {describe: 'Extension to dial such as "Local/1234"'}); 36 | }, 37 | opts => { 38 | new transcriber.AriTranscriber(opts); 39 | } 40 | ) 41 | .options({ 42 | format: { 43 | alias: 'f', 44 | default: 'ulaw', 45 | global: true, 46 | requiresArg: true, 47 | description: "Asterisk format/codec", 48 | choices: ['ulaw', 'slin16'], 49 | group: "Incoming Audio Server", 50 | type: 'string', 51 | }, 52 | listenServer: { 53 | alias: 'l', 54 | default: '127.0.0.1:9999', 55 | global: true, 56 | requiresArg: true, 57 | description: "Address and port on which to listen for audio from Asterisk", 58 | group: "Incoming Audio Server", 59 | type: 'string', 60 | }, 61 | speechModel: { 62 | default: 'default', 63 | choices: ['phone_call', 'video', 'default'], 64 | global: true, 65 | requiresArg: true, 66 | description: "Google Speech API model", 67 | group: "Speech", 68 | type: 'string', 69 | }, 70 | speechLang: { 71 | default: 'en-US', 72 | choices: ['en-US', 'fr-CA'], 73 | global: true, 74 | requiresArg: true, 75 | description: "BCP-47 Language code. en-US, fr-CA, etc.", 76 | group: "Speech", 77 | type: 'string', 78 | }, 79 | speakerDiarization: { 80 | default: false, 81 | global: true, 82 | requiresArg: false, 83 | group: "Speech", 84 | description: "Outputs words associated to speaker index to console", 85 | type: 'boolean', 86 | }, 87 | ariServerUrl: { 88 | alias: 'a', 89 | default: 'http://127.0.0.1:8088', 90 | global: true, 91 | requiresArg: true, 92 | description: "The URL for the Asterisk instance", 93 | group: "ARI", 94 | type: 'string', 95 | }, 96 | ariUser: { 97 | alias: 'u', 98 | default: 'asterisk', 99 | global: true, 100 | requiresArg: true, 101 | description: "The user configured in ari.conf", 102 | group: "ARI", 103 | type: 'string', 104 | }, 105 | ariPassword: { 106 | alias: 'p', 107 | default: 'asterisk', 108 | global: true, 109 | requiresArg: true, 110 | description: "The password for the user configured in ari.conf", 111 | group: "ARI", 112 | type: 'string', 113 | }, 114 | audioOutput: { 115 | alias: 'o', 116 | global: true, 117 | requiresArg: true, 118 | description: "A file into which the raw audio from Asterisk can be written", 119 | type: 'string', 120 | }, 121 | sslCert: { 122 | global: true, 123 | requiresArg: true, 124 | group: "Transcription WebSocket", 125 | description: "WebSocket secure server (wss) certificate. If omitted, a non-secures (ws) websocket server will be created", 126 | implies: "sslKey", 127 | type: 'string', 128 | }, 129 | sslKey: { 130 | global: true, 131 | requiresArg: true, 132 | group: "Transcription WebSocket", 133 | description: "WebSocket secure server key. Must be supplied if sslCert is ssplied", 134 | implies: "sslCert", 135 | type: 'string', 136 | }, 137 | wssPort: { 138 | global: true, 139 | requiresArg: true, 140 | description: "WebSocket server port. If omitted, no websocket server will be started", 141 | group: "Transcription WebSocket", 142 | type: 'number', 143 | } 144 | }) 145 | .strict().argv; 146 | -------------------------------------------------------------------------------- /lib/ari-controller.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Sangoma Technologies Corporation 3 | * George Joseph 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /** 19 | * The ari controller handles the control interaction with Asterisk. 20 | * For simplicity's sake, this example just dials an extension rather 21 | * that trying to create conference bridges, etc. For that reason, 22 | * we need to create a local channel and a simple mixing bridge as 23 | * well as the external media channel. 24 | */ 25 | 26 | const client = require('ari-client'); 27 | const EventEmitter = require('events'); 28 | 29 | class AriController extends EventEmitter { 30 | 31 | constructor(options) { 32 | super(); 33 | this.options = Object.assign({}, options); 34 | } 35 | 36 | async close() { 37 | if (this.closing) { 38 | return; 39 | } 40 | this.closing = true; 41 | 42 | if (this.localChannel) { 43 | console.log("Hanging up local channel"); 44 | try { 45 | await this.localChannel.hangup(); 46 | } catch(error) { 47 | } 48 | delete this.localChannel; 49 | } 50 | if (this.externalChannel) { 51 | console.log("Hanging up external media channel"); 52 | try { 53 | await this.externalChannel.hangup(); 54 | } catch(error) { 55 | } 56 | delete this.externalChannel; 57 | } 58 | if (this.bridge) { 59 | console.log("Destroying bridge"); 60 | try { 61 | await this.bridge.destroy(); 62 | } catch(error) { 63 | } 64 | delete this.bridge; 65 | } 66 | 67 | if (this.options.closeCallback) { 68 | this.options.closeCallback(); 69 | } 70 | await this.ari.stop(); 71 | this.emit('close'); 72 | } 73 | 74 | async connect() { 75 | this.ari = await client.connect( 76 | this.options.ariServerUrl, this.options.ariUser, this.options.ariPassword); 77 | 78 | await this.ari.start("externalMedia"); 79 | 80 | // Create a simple bridge that is controlled by ARI/Stasis 81 | this.bridge = this.ari.Bridge(); 82 | try { 83 | await this.bridge.create({type: "mixing"}); 84 | } catch(error) { 85 | console.error(error); 86 | this.close(); 87 | } 88 | this.bridge.on('BridgeDestroyed', (event) => { 89 | this.close(); 90 | }); 91 | 92 | /* 93 | * Create the local channel. This actually creates 2 94 | * back to back channels, one that's controlled by ARI/Stasis 95 | * that we can put into the bridge we created above and 96 | * another one the one that dials a phone, confbridge, etc. 97 | * and joins _that_ bridge. 98 | * 99 | * localChannel below is actually the first channel. 100 | */ 101 | this.localChannel = this.ari.Channel(); 102 | this.localChannel.on('StasisStart', (event, chan) => { 103 | this.bridge.addChannel({channel: chan.id}); 104 | }); 105 | this.localChannel.on('StasisEnd', (event, chan) => { 106 | this.close(); 107 | }); 108 | 109 | // Call the phone or confbridge specified in dialstring 110 | try { 111 | await this.localChannel.originate({ 112 | endpoint: this.options.dialstring, formats: this.options.format, app: "externalMedia", 113 | }); 114 | } catch (error) { 115 | this.close(); 116 | } 117 | 118 | // Now we create the External Media channel. 119 | this.externalChannel = this.ari.Channel(); 120 | this.externalChannel.on('StasisStart', (event, chan) => { 121 | this.bridge.addChannel({channel: chan.id}); 122 | }); 123 | this.externalChannel.on('StasisEnd', (event, chan) => { 124 | this.close(); 125 | }); 126 | 127 | /* 128 | * We give the external channel the address of the listener 129 | * we already set up and the format it should stream in. 130 | */ 131 | try { 132 | let resp = await this.externalChannel.externalMedia({ 133 | app: "externalMedia", 134 | external_host: this.options.listenServer, 135 | format: this.options.format 136 | }); 137 | this.emit('ready'); 138 | } catch(error) { 139 | this.close(); 140 | } 141 | } 142 | } 143 | 144 | module.exports.AriController = AriController; -------------------------------------------------------------------------------- /lib/ari-transcriber.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Sangoma Technologies Corporation 3 | * George Joseph 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | const rtp = require('./rtp-udp-server'); 19 | const provider = require('./google-speech-provider'); 20 | const ari = require('./ari-controller'); 21 | const WebSocket = require('ws'); 22 | const fs = require('fs'); 23 | const https = require('https'); 24 | const http = require('http'); 25 | 26 | class AriTranscriber { 27 | constructor(opts) { 28 | this.opts = opts; 29 | // Run it. 30 | this.transcriber(); 31 | } 32 | 33 | // The WebSocket server serves up the transcription. 34 | startWebsocketServer() { 35 | this.webServer = this.opts.sslCert ? 36 | https.createServer({ 37 | cert: fs.readFileSync(this.opts.sslCert), 38 | key: fs.readFileSync(this.opts.sslKey) 39 | }) : https.createServer(); 40 | 41 | this.wssServer = new WebSocket.Server({ server: this.webServer }); 42 | this.wssServer.on('connection', function(ws, req) { 43 | console.log("Connection from: ", req.connection.remoteAddress); 44 | }); 45 | 46 | this.webServer.listen(this.opts.wssPort); 47 | } 48 | 49 | /* 50 | * The transcriptCallback simply passes any text received from the 51 | * speech provider to any client connected to the WebSocket server. 52 | */ 53 | transcriptCallback(text, isFinal) { 54 | if (isFinal && this.wssServer) { 55 | this.wssServer.clients.forEach(function each(client) { 56 | if (client.readyState === WebSocket.OPEN) { 57 | client.send(text); 58 | } 59 | }); 60 | } 61 | } 62 | 63 | /* 64 | * The resultsCallback is just an example of how Google identifies 65 | * speakers if you have speakerDiarization enabled. We don't do 66 | * anything with this other than display the raw results on the console. 67 | */ 68 | resultsCallback(results) { 69 | if (results[0].isFinal) { 70 | const transcription = results 71 | .map(result => result.alternatives[0].transcript) 72 | .join('\n'); 73 | console.log(`Transcription: ${transcription}`); 74 | const wordsInfo = results[0].alternatives[0].words; 75 | wordsInfo.forEach(a => 76 | console.log(` word: ${a.word}, speakerTag: ${a.speakerTag}`) 77 | ); 78 | } 79 | } 80 | 81 | // The main wrapper 82 | async transcriber() { 83 | let speechEncoding; 84 | let speechRate; 85 | let swap16 = false; 86 | 87 | switch(this.opts.format) { 88 | case "ulaw": 89 | speechEncoding = "MULAW"; 90 | speechRate = 8000; 91 | break; 92 | case "slin16": 93 | speechEncoding = "LINEAR16"; 94 | speechRate = 16000; 95 | swap16 = true; 96 | break; 97 | default: 98 | console.error(`Unknown format ${this.opts.format}`); 99 | return; 100 | } 101 | 102 | // Create the ARI Controller instance but don't start it yet. 103 | console.log(`Creating ARI Controller to Asterisk instance ${this.opts.ariServerUrl}`); 104 | this.ariController = new ari.AriController(this.opts); 105 | this.ariController.on('close', () => { 106 | this.audioServer.close(); 107 | if (this.webServer) { 108 | this.webServer.close(); 109 | } 110 | process.exit(0); 111 | }); 112 | 113 | // Catch CTRL-C so we can hang up any channels and destroy any bridges. 114 | process.on('SIGINT', async () => { 115 | await this.ariController.close(); 116 | process.exit(0); 117 | }); 118 | 119 | // If wssPort was specified, start the WebSocket server. 120 | if (this.opts.wssPort > 0) { 121 | console.log(`Starting ${this.opts.sslCert ? "secure " : ""}transcription websocket server on port ${this.opts.wssPort}`); 122 | this.startWebsocketServer(); 123 | } 124 | 125 | // Start the server that receives audio from Asterisk. 126 | console.log(`Starting audio listener on ${this.opts.listenServer}`); 127 | this.audioServer = new rtp.RtpUdpServerSocket(this.opts.listenServer, swap16, 128 | this.opts.audioOutput || false); 129 | 130 | 131 | console.log("Starting speech provider"); 132 | let config = { 133 | encoding: speechEncoding, 134 | sampleRateHertz: speechRate, 135 | languageCode: this.opts.speechLang, 136 | audioChannelCount: 1, 137 | model: this.opts.speechModel, 138 | useEnhanced: true, 139 | profanityFilter: false, 140 | enableAutomaticPunctuation: true, 141 | enableWordTimeOffsets: true, 142 | metadata: { 143 | interactionType: 'DISCUSSION', 144 | microphoneDistance: 'MIDFIELD', 145 | originalMediaType: 'AUDIO', 146 | recordingDeviceName: 'ConferenceCall', 147 | } 148 | }; 149 | if (this.opts.speakerDiarization) { 150 | config.enableSpeakerDiarization = true; 151 | config.diarizationSpeakerCount = 5; 152 | } 153 | 154 | // Start the speech provider passing in the audio server socket. 155 | this.speechProvider = new provider.GoogleSpeechProvider(config, this.audioServer, 156 | (text, isFinal) => { 157 | this.transcriptCallback(text, isFinal); 158 | }, 159 | (results) => { 160 | if (this.opts.speakerDiarization) { 161 | this.resultsCallback(results); 162 | } 163 | }, 164 | ); 165 | 166 | // Kick the whole process off by creating the channels and bridges. 167 | console.log("Creating Bridge and Channels"); 168 | await this.ariController.connect(); 169 | 170 | console.log("Processing"); 171 | } 172 | } 173 | 174 | module.exports.AriTranscriber = AriTranscriber; 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /lib/google-speech-provider.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * Updates specific to the Sangoma Asterisk External Media Sample: 17 | * Copyright (C) 2019, Sangoma Technologies Corporation 18 | * George Joseph 19 | * 20 | * Also licensed under the Apache 2.0 license. 21 | * 22 | */ 23 | 24 | /** 25 | * This application demonstrates how to perform infinite streaming using the 26 | * streamingRecognize operation with the Google Cloud Speech API. 27 | * Before the streaming time limit is met, the program uses the 28 | * 'result end time' parameter to calculate the last 'isFinal' transcription. 29 | * When the time limit is met, the unfinalized audio from the previous session 30 | * is resent all at once to the API, before continuing the real-time stream 31 | * and resetting the clock, so the process can repeat. 32 | * Incoming audio should not be dropped / lost during reset, and context from 33 | * previous sessions should be maintained as long the utterance returns an 34 | * isFinal response before 2 * streamingLimit has expired. 35 | * The output text is color-coded: 36 | * red - unfinalized transcript 37 | * green - finalized transcript 38 | * yellow/orange - API request restarted 39 | */ 40 | 41 | /** 42 | * Most of this code is directly from the Google Speech API 43 | * example for continuous streaming of audio. It was originally 44 | * written to take input directly from the computer microphone but 45 | * it's been adapted to read from a socket instead. 46 | * 47 | * See https://github.com/googleapis/nodejs-speech/blob/master/samples/infiniteStreaming.js 48 | * for the original source. 49 | * 50 | * As the transcription is received, printed on the console and 51 | * passed back to the caller via transcriptCallback, which provides 52 | * just the transcribed text, and resultsCallback whic provides the 53 | * full results structure. 54 | */ 55 | 56 | const chalk = require('chalk'); 57 | const {Transform} = require('stream'); 58 | const speech = require('@google-cloud/speech').v1p1beta1; 59 | 60 | class GoogleSpeechProvider { 61 | constructor(config, socket, transcriptCallback, resultsCallback) { 62 | this.speechClient = new speech.SpeechClient(); 63 | this.request = { 64 | config, 65 | interimResults: true, 66 | }; 67 | this.recognizeStream = null; 68 | this.restartCounter = 0; 69 | this.audioInput = []; 70 | this.lastAudioInput = []; 71 | this.resultEndTime = 0; 72 | this.isFinalEndTime = 0; 73 | this.finalRequestEndTime = 0; 74 | this.newStream = true; 75 | this.bridgingOffset = 0; 76 | this.lastTranscriptWasFinal = false; 77 | this.streamingLimit = 25000; 78 | 79 | this.audioInputStreamTransform = new Transform({ 80 | transform: (chunk, encoding, callback) => { 81 | this.transformer(chunk, encoding, callback); 82 | } 83 | }); 84 | 85 | this.transcriptCallback = transcriptCallback; 86 | this.resultsCallback = resultsCallback; 87 | this.startStream(); 88 | this.socket = socket; 89 | // This connects the socket to the Stream Transform 90 | socket.pipe(this.audioInputStreamTransform); 91 | } 92 | 93 | startStream() { 94 | // Clear current audioInput 95 | this.audioInput = []; 96 | 97 | // This callback sends the transcript back to the ari-transcriber 98 | this.cb = (stream) => { 99 | let results = this.speechCallback(stream); 100 | if (this.transcriptCallback && results[0] && results[0].alternatives[0]) { 101 | this.transcriptCallback(results[0].alternatives[0].transcript, 102 | results[0].isFinal); 103 | } 104 | if (this.resultsCallback) { 105 | this.resultsCallback(results); 106 | } 107 | }; 108 | 109 | // Initiate (Reinitiate) a recognize stream 110 | this.recognizeStream = this.speechClient 111 | .streamingRecognize(this.request) 112 | .on('error', err => { 113 | if (err.code === 11) { 114 | // this.restartStream(); 115 | } else { 116 | console.error('API request error ' + err); 117 | } 118 | }) 119 | .on('data', this.cb); 120 | 121 | // Restart stream when streamingLimit expires 122 | setTimeout(() => { 123 | this.restartStream(); 124 | }, this.streamingLimit); 125 | } 126 | 127 | speechCallback(stream) { 128 | this.resultEndTime = 129 | stream.results[0].resultEndTime.seconds * 1000 + 130 | Math.round(stream.results[0].resultEndTime.nanos / 1000000); 131 | 132 | // Calculate correct time based on offset from audio sent twice 133 | const correctedTime = 134 | this.resultEndTime - this.bridgingOffset + this.streamingLimit * this.restartCounter; 135 | 136 | process.stdout.clearLine(); 137 | process.stdout.cursorTo(0); 138 | 139 | let stdoutText = ''; 140 | if (stream.results[0] && stream.results[0].alternatives[0]) { 141 | stdoutText = stream.results[0].alternatives[0].transcript; 142 | } 143 | 144 | if (stream.results[0].isFinal) { 145 | this.isFinalEndTime = this.resultEndTime; 146 | process.stdout.write(chalk.green(`${stdoutText}\n`)); 147 | this.lastTranscriptWasFinal = true; 148 | } else { 149 | // Make sure transcript does not exceed console character length 150 | if (stdoutText.length > process.stdout.columns) { 151 | stdoutText = stdoutText.substring(0, process.stdout.columns - 4) + '...'; 152 | } 153 | process.stdout.write(chalk.red(`${stdoutText}`)); 154 | this.lastTranscriptWasFinal = false; 155 | } 156 | return stream.results; 157 | } 158 | 159 | /* 160 | * The transformer accumulates and keeps track 161 | * of the audio chunks to make sure we don't lose anything 162 | * when we restart the stream. 163 | */ 164 | transformer (chunk, encoding, callback) { 165 | if (this.newStream && this.lastAudioInput.length !== 0) { 166 | // Approximate math to calculate time of chunks 167 | const chunkTime = this.streamingLimit / this.lastAudioInput.length; 168 | if (chunkTime !== 0) { 169 | if (this.bridgingOffset < 0) { 170 | this.bridgingOffset = 0; 171 | } 172 | if (this.bridgingOffset > this.finalRequestEndTime) { 173 | this.bridgingOffset = this.finalRequestEndTime; 174 | } 175 | const chunksFromMS = Math.floor( 176 | (this.finalRequestEndTime - this.bridgingOffset) / chunkTime 177 | ); 178 | this.bridgingOffset = Math.floor( 179 | (this.lastAudioInput.length - chunksFromMS) * chunkTime 180 | ); 181 | for (let i = chunksFromMS; i < this.lastAudioInput.length; i++) { 182 | this.recognizeStream.write(this.lastAudioInput[i]); 183 | } 184 | } 185 | this.newStream = false; 186 | } 187 | this.audioInput.push(chunk); 188 | 189 | if (this.recognizeStream) { 190 | this.recognizeStream.write(chunk); 191 | } 192 | 193 | callback(); 194 | } 195 | 196 | restartStream() { 197 | if (this.recognizeStream) { 198 | this.recognizeStream.removeListener('data', this.cb); 199 | this.recognizeStream = null; 200 | } 201 | 202 | if (this.resultEndTime > 0) { 203 | this.finalRequestEndTime = this.isFinalEndTime; 204 | } 205 | this.resultEndTime = 0; 206 | this.lastAudioInput = []; 207 | this.lastAudioInput = this.audioInput; 208 | 209 | this.restartCounter++; 210 | 211 | if (!this.lastTranscriptWasFinal) { 212 | process.stdout.write("\n"); 213 | } 214 | process.stdout.write( 215 | chalk.yellow(`${this.streamingLimit * this.restartCounter}: RESTARTING REQUEST\n`) 216 | ); 217 | 218 | this.newStream = true; 219 | 220 | this.startStream(); 221 | } 222 | } 223 | 224 | module.exports.GoogleSpeechProvider = GoogleSpeechProvider; 225 | -------------------------------------------------------------------------------- /lib/rtp-udp-server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Sangoma Technologies Corporation 3 | * George Joseph 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /** 19 | * This is a simple UDP listener that... 20 | * * Receives raw RTP packets 21 | * * Strips off the the 12 byte RTP header 22 | * * Swaps the byte ordering if the audio is SLIN 23 | * (RTP SLIN is big-endian but most providers expect little-endian) 24 | * * Writes the audio to a debug file path is provided. 25 | * * Emits the 'data' event. 26 | * 27 | * Datagram sockets don't normally implement streaming capabilities 28 | * like piping but piping would be very handy to use with a speech 29 | * provider. Fortunately it's easy to just add the Stream 'pipe' 30 | * method to the socket. It listens for 'data' events and just writes 31 | * the data out to the stream provided in the 'pipe' call. The ari-transcriber 32 | * passes the socket to the speech provider who makes that pipe call. 33 | */ 34 | 35 | const fs = require('fs'); 36 | const dgram = require('dgram'); 37 | const pipe = require('stream').prototype.pipe; 38 | 39 | class RtpUdpServerSocket { 40 | constructor(host, swap16, alsoWritePath) { 41 | this.server = dgram.createSocket('udp4'); 42 | // Add the Stream.pipe() method to the socket 43 | this.server.pipe = pipe; 44 | 45 | this.swap16 = swap16 || false; 46 | this.alsoWritePath = alsoWritePath; 47 | this.address = host.split(':')[0]; 48 | this.port = host.split(':')[1]; 49 | 50 | if (this.alsoWritePath) { 51 | this.fileStream = fs.createWriteStream(this.alsoWritePath, { 52 | autoClose: true 53 | }); 54 | } 55 | 56 | this.server.on('error', (err) => { 57 | console.log(`server error:\n${err.stack}`); 58 | this.server.close(); 59 | if (this.fileStream) { 60 | this.fileStream.close(); 61 | } 62 | }); 63 | 64 | this.server.on('close', (err) => { 65 | console.log(`server socket closed`); 66 | if (this.fileStream) { 67 | this.fileStream.close(); 68 | } 69 | }); 70 | 71 | this.server.on('message', (msg, rinfo) => { 72 | /* Strip the 12 byte RTP header */ 73 | let buf = msg.slice(12); 74 | if (this.swap16) { 75 | buf.swap16(); 76 | } 77 | if (this.fileStream) { 78 | this.fileStream.write(buf); 79 | } 80 | this.server.emit('data', buf); 81 | }); 82 | 83 | this.server.on('listening', () => { 84 | const address = this.server.address(); 85 | console.log(`server listening ${address.address}:${address.port}`); 86 | }); 87 | 88 | this.server.bind(this.port, this.address); 89 | return this.server; 90 | } 91 | } 92 | 93 | module.exports.RtpUdpServerSocket = RtpUdpServerSocket; 94 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asterisk-external-media", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "asterisk-external-media", 9 | "version": "0.1.0", 10 | "license": "Apache-2.0", 11 | "dependencies": { 12 | "@google-cloud/speech": "^3.3.1", 13 | "ari-client": "^2.2.0", 14 | "chalk": "^2.4.2", 15 | "datagram-stream": "^1.1.1", 16 | "ws": "^7.4.6", 17 | "yargs": "^14.2.0" 18 | }, 19 | "bin": { 20 | "ari-transcriber": "bin/ari-transcriber" 21 | }, 22 | "engines": { 23 | "node": ">=10" 24 | }, 25 | "optionalDependencies": { 26 | "bufferutil": "^4.0.1" 27 | } 28 | }, 29 | "node_modules/@google-cloud/common": { 30 | "version": "2.2.2", 31 | "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.2.2.tgz", 32 | "integrity": "sha512-AgMdDgLeYlEG17tXtMCowE7mplm907pcugtfJYYAp06HNe9RDnunUIY5KMnn9yikYl7NXNofARC+hwG77Zsa4g==", 33 | "dependencies": { 34 | "@google-cloud/projectify": "^1.0.0", 35 | "@google-cloud/promisify": "^1.0.0", 36 | "arrify": "^2.0.0", 37 | "duplexify": "^3.6.0", 38 | "ent": "^2.2.0", 39 | "extend": "^3.0.2", 40 | "google-auth-library": "^5.0.0", 41 | "retry-request": "^4.0.0", 42 | "teeny-request": "^5.2.1" 43 | }, 44 | "engines": { 45 | "node": ">=8.10.0" 46 | } 47 | }, 48 | "node_modules/@google-cloud/projectify": { 49 | "version": "1.0.1", 50 | "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.1.tgz", 51 | "integrity": "sha512-xknDOmsMgOYHksKc1GPbwDLsdej8aRNIA17SlSZgQdyrcC0lx0OGo4VZgYfwoEU1YS8oUxF9Y+6EzDOb0eB7Xg==", 52 | "engines": { 53 | "node": ">=8.10.0" 54 | } 55 | }, 56 | "node_modules/@google-cloud/promisify": { 57 | "version": "1.0.2", 58 | "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.2.tgz", 59 | "integrity": "sha512-7WfV4R/3YV5T30WRZW0lqmvZy9hE2/p9MvpI34WuKa2Wz62mLu5XplGTFEMK6uTbJCLWUxTcZ4J4IyClKucE5g==", 60 | "engines": { 61 | "node": ">=8.10.0" 62 | } 63 | }, 64 | "node_modules/@google-cloud/speech": { 65 | "version": "3.3.1", 66 | "resolved": "https://registry.npmjs.org/@google-cloud/speech/-/speech-3.3.1.tgz", 67 | "integrity": "sha512-pt3ASbIOouvohuBeT0+AKIDjNcS7mdjqG0UxH73Vokryoc0PohrZBQOVfvmbYojgXsTNbus4tTWFO7Msp9INvQ==", 68 | "dependencies": { 69 | "@google-cloud/common": "^2.0.0", 70 | "google-gax": "^1.6.3", 71 | "protobufjs": "^6.8.6", 72 | "pumpify": "^2.0.0", 73 | "stream-events": "^1.0.4" 74 | }, 75 | "engines": { 76 | "node": ">=8.10.0" 77 | } 78 | }, 79 | "node_modules/@grpc/grpc-js": { 80 | "version": "0.6.9", 81 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.6.9.tgz", 82 | "integrity": "sha512-r1nDOEEiYmAsVYBaS4DPPqdwPOXPw7YhVOnnpPdWhlNtKbYzPash6DqWTTza9gBiYMA5d2Wiq6HzrPqsRaP4yA==", 83 | "dependencies": { 84 | "semver": "^6.2.0" 85 | }, 86 | "engines": { 87 | "node": "^8.13.0 || >=10.10.0" 88 | } 89 | }, 90 | "node_modules/@grpc/proto-loader": { 91 | "version": "0.5.2", 92 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.2.tgz", 93 | "integrity": "sha512-eBKD/FPxQoY1x6QONW2nBd54QUEyzcFP9FenujmoeDPy1rutVSHki1s/wR68F6O1QfCNDx+ayBH1O2CVNMzyyw==", 94 | "dependencies": { 95 | "lodash.camelcase": "^4.3.0", 96 | "protobufjs": "^6.8.6" 97 | }, 98 | "engines": { 99 | "node": ">=6" 100 | } 101 | }, 102 | "node_modules/@protobufjs/aspromise": { 103 | "version": "1.1.2", 104 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 105 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" 106 | }, 107 | "node_modules/@protobufjs/base64": { 108 | "version": "1.1.2", 109 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 110 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 111 | }, 112 | "node_modules/@protobufjs/codegen": { 113 | "version": "2.0.4", 114 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 115 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 116 | }, 117 | "node_modules/@protobufjs/eventemitter": { 118 | "version": "1.1.0", 119 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 120 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" 121 | }, 122 | "node_modules/@protobufjs/fetch": { 123 | "version": "1.1.0", 124 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 125 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", 126 | "dependencies": { 127 | "@protobufjs/aspromise": "^1.1.1", 128 | "@protobufjs/inquire": "^1.1.0" 129 | } 130 | }, 131 | "node_modules/@protobufjs/float": { 132 | "version": "1.0.2", 133 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 134 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" 135 | }, 136 | "node_modules/@protobufjs/inquire": { 137 | "version": "1.1.0", 138 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 139 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" 140 | }, 141 | "node_modules/@protobufjs/path": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 144 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" 145 | }, 146 | "node_modules/@protobufjs/pool": { 147 | "version": "1.1.0", 148 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 149 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" 150 | }, 151 | "node_modules/@protobufjs/utf8": { 152 | "version": "1.1.0", 153 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 154 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" 155 | }, 156 | "node_modules/abort-controller": { 157 | "version": "3.0.0", 158 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 159 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 160 | "dependencies": { 161 | "event-target-shim": "^5.0.0" 162 | }, 163 | "engines": { 164 | "node": ">=6.5" 165 | } 166 | }, 167 | "node_modules/agent-base": { 168 | "version": "4.3.0", 169 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", 170 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", 171 | "dependencies": { 172 | "es6-promisify": "^5.0.0" 173 | }, 174 | "engines": { 175 | "node": ">= 4.0.0" 176 | } 177 | }, 178 | "node_modules/ajv": { 179 | "version": "6.12.6", 180 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 181 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 182 | "dependencies": { 183 | "fast-deep-equal": "^3.1.1", 184 | "fast-json-stable-stringify": "^2.0.0", 185 | "json-schema-traverse": "^0.4.1", 186 | "uri-js": "^4.2.2" 187 | }, 188 | "funding": { 189 | "type": "github", 190 | "url": "https://github.com/sponsors/epoberezkin" 191 | } 192 | }, 193 | "node_modules/ajv/node_modules/fast-deep-equal": { 194 | "version": "3.1.3", 195 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 196 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 197 | }, 198 | "node_modules/ansi-regex": { 199 | "version": "4.1.0", 200 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 201 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 202 | "engines": { 203 | "node": ">=6" 204 | } 205 | }, 206 | "node_modules/ansi-styles": { 207 | "version": "3.2.1", 208 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 209 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 210 | "dependencies": { 211 | "color-convert": "^1.9.0" 212 | }, 213 | "engines": { 214 | "node": ">=4" 215 | } 216 | }, 217 | "node_modules/ari-client": { 218 | "version": "2.2.0", 219 | "resolved": "https://registry.npmjs.org/ari-client/-/ari-client-2.2.0.tgz", 220 | "integrity": "sha512-DPz+vC/dZyvy5HqBrEzYpNH6X2hDb+AIyRith6f8IVLHyveRWaHPO0S7rF1Q91qry/U8G+504KUZfeaBPwzIVQ==", 221 | "dependencies": { 222 | "backoff-func": "^0.1.2", 223 | "bluebird": "^3.5.2", 224 | "lodash": "^4.17.10", 225 | "request": "^2.34.0", 226 | "swagger-client": "2.0.26", 227 | "uuid": "^3.0.0", 228 | "ws": "^6.0.0" 229 | }, 230 | "engines": { 231 | "node": ">=8" 232 | } 233 | }, 234 | "node_modules/ari-client/node_modules/ws": { 235 | "version": "6.2.1", 236 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", 237 | "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", 238 | "dependencies": { 239 | "async-limiter": "~1.0.0" 240 | } 241 | }, 242 | "node_modules/arrify": { 243 | "version": "2.0.1", 244 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 245 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", 246 | "engines": { 247 | "node": ">=8" 248 | } 249 | }, 250 | "node_modules/asn1": { 251 | "version": "0.2.4", 252 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 253 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 254 | "dependencies": { 255 | "safer-buffer": "~2.1.0" 256 | } 257 | }, 258 | "node_modules/assert-plus": { 259 | "version": "1.0.0", 260 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 261 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 262 | "engines": { 263 | "node": ">=0.8" 264 | } 265 | }, 266 | "node_modules/async-limiter": { 267 | "version": "1.0.1", 268 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 269 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 270 | }, 271 | "node_modules/asynckit": { 272 | "version": "0.4.0", 273 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 274 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 275 | }, 276 | "node_modules/aws-sign2": { 277 | "version": "0.7.0", 278 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 279 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 280 | "engines": { 281 | "node": "*" 282 | } 283 | }, 284 | "node_modules/aws4": { 285 | "version": "1.8.0", 286 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 287 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 288 | }, 289 | "node_modules/ax": { 290 | "version": "0.1.8", 291 | "resolved": "https://registry.npmjs.org/ax/-/ax-0.1.8.tgz", 292 | "integrity": "sha1-J8qac/pMeKR41i2CfK2GCiT91Jc=" 293 | }, 294 | "node_modules/backoff-func": { 295 | "version": "0.1.2", 296 | "resolved": "https://registry.npmjs.org/backoff-func/-/backoff-func-0.1.2.tgz", 297 | "integrity": "sha1-VMP64rreWHI0utXbh+NBLJ+ph4M=" 298 | }, 299 | "node_modules/base64-js": { 300 | "version": "1.3.1", 301 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 302 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 303 | }, 304 | "node_modules/bcrypt-pbkdf": { 305 | "version": "1.0.2", 306 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 307 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 308 | "dependencies": { 309 | "tweetnacl": "^0.14.3" 310 | } 311 | }, 312 | "node_modules/bignumber.js": { 313 | "version": "7.2.1", 314 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", 315 | "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==", 316 | "engines": { 317 | "node": "*" 318 | } 319 | }, 320 | "node_modules/bluebird": { 321 | "version": "3.7.1", 322 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", 323 | "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" 324 | }, 325 | "node_modules/btoa": { 326 | "version": "1.1.1", 327 | "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.1.1.tgz", 328 | "integrity": "sha1-J8gQYmMQjp3UH/L6qtKhcEXjXro=", 329 | "bin": { 330 | "btoa": "bin/btoa.js" 331 | }, 332 | "engines": { 333 | "node": ">= 0.4.0" 334 | } 335 | }, 336 | "node_modules/buffer-equal-constant-time": { 337 | "version": "1.0.1", 338 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 339 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 340 | }, 341 | "node_modules/bufferutil": { 342 | "version": "4.0.1", 343 | "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", 344 | "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", 345 | "hasInstallScript": true, 346 | "optional": true, 347 | "dependencies": { 348 | "node-gyp-build": "~3.7.0" 349 | } 350 | }, 351 | "node_modules/camelcase": { 352 | "version": "5.3.1", 353 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 354 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 355 | "engines": { 356 | "node": ">=6" 357 | } 358 | }, 359 | "node_modules/caseless": { 360 | "version": "0.12.0", 361 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 362 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 363 | }, 364 | "node_modules/chalk": { 365 | "version": "2.4.2", 366 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 367 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 368 | "dependencies": { 369 | "ansi-styles": "^3.2.1", 370 | "escape-string-regexp": "^1.0.5", 371 | "supports-color": "^5.3.0" 372 | }, 373 | "engines": { 374 | "node": ">=4" 375 | } 376 | }, 377 | "node_modules/cliui": { 378 | "version": "5.0.0", 379 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 380 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 381 | "dependencies": { 382 | "string-width": "^3.1.0", 383 | "strip-ansi": "^5.2.0", 384 | "wrap-ansi": "^5.1.0" 385 | } 386 | }, 387 | "node_modules/color-convert": { 388 | "version": "1.9.3", 389 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 390 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 391 | "dependencies": { 392 | "color-name": "1.1.3" 393 | } 394 | }, 395 | "node_modules/color-name": { 396 | "version": "1.1.3", 397 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 398 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 399 | }, 400 | "node_modules/combined-stream": { 401 | "version": "1.0.8", 402 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 403 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 404 | "dependencies": { 405 | "delayed-stream": "~1.0.0" 406 | }, 407 | "engines": { 408 | "node": ">= 0.8" 409 | } 410 | }, 411 | "node_modules/cookiejar": { 412 | "version": "1.3.1", 413 | "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-1.3.1.tgz", 414 | "integrity": "sha1-wEsEj2iPgBYjrNkM1YSMK/iJGhc=" 415 | }, 416 | "node_modules/core-util-is": { 417 | "version": "1.0.2", 418 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 419 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 420 | }, 421 | "node_modules/dashdash": { 422 | "version": "1.14.1", 423 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 424 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 425 | "dependencies": { 426 | "assert-plus": "^1.0.0" 427 | }, 428 | "engines": { 429 | "node": ">=0.10" 430 | } 431 | }, 432 | "node_modules/datagram-stream": { 433 | "version": "1.1.1", 434 | "resolved": "https://registry.npmjs.org/datagram-stream/-/datagram-stream-1.1.1.tgz", 435 | "integrity": "sha1-qn2ElZo6GxpeQ9THwDRh9AqP+30=" 436 | }, 437 | "node_modules/debug": { 438 | "version": "3.2.6", 439 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 440 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 441 | "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", 442 | "dependencies": { 443 | "ms": "^2.1.1" 444 | } 445 | }, 446 | "node_modules/decamelize": { 447 | "version": "1.2.0", 448 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 449 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 450 | "engines": { 451 | "node": ">=0.10.0" 452 | } 453 | }, 454 | "node_modules/delayed-stream": { 455 | "version": "1.0.0", 456 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 457 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 458 | "engines": { 459 | "node": ">=0.4.0" 460 | } 461 | }, 462 | "node_modules/duplexify": { 463 | "version": "3.7.1", 464 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", 465 | "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", 466 | "dependencies": { 467 | "end-of-stream": "^1.0.0", 468 | "inherits": "^2.0.1", 469 | "readable-stream": "^2.0.0", 470 | "stream-shift": "^1.0.0" 471 | } 472 | }, 473 | "node_modules/ecc-jsbn": { 474 | "version": "0.1.2", 475 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 476 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 477 | "dependencies": { 478 | "jsbn": "~0.1.0", 479 | "safer-buffer": "^2.1.0" 480 | } 481 | }, 482 | "node_modules/ecdsa-sig-formatter": { 483 | "version": "1.0.11", 484 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 485 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 486 | "dependencies": { 487 | "safe-buffer": "^5.0.1" 488 | } 489 | }, 490 | "node_modules/emoji-regex": { 491 | "version": "7.0.3", 492 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 493 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" 494 | }, 495 | "node_modules/end-of-stream": { 496 | "version": "1.4.4", 497 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 498 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 499 | "dependencies": { 500 | "once": "^1.4.0" 501 | } 502 | }, 503 | "node_modules/ent": { 504 | "version": "2.2.0", 505 | "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", 506 | "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" 507 | }, 508 | "node_modules/es6-promise": { 509 | "version": "4.2.8", 510 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", 511 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" 512 | }, 513 | "node_modules/es6-promisify": { 514 | "version": "5.0.0", 515 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", 516 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", 517 | "dependencies": { 518 | "es6-promise": "^4.0.3" 519 | } 520 | }, 521 | "node_modules/escape-string-regexp": { 522 | "version": "1.0.5", 523 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 524 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 525 | "engines": { 526 | "node": ">=0.8.0" 527 | } 528 | }, 529 | "node_modules/event-target-shim": { 530 | "version": "5.0.1", 531 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 532 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 533 | "engines": { 534 | "node": ">=6" 535 | } 536 | }, 537 | "node_modules/extend": { 538 | "version": "3.0.2", 539 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 540 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 541 | }, 542 | "node_modules/extsprintf": { 543 | "version": "1.3.0", 544 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 545 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 546 | "engines": [ 547 | "node >=0.6.0" 548 | ] 549 | }, 550 | "node_modules/fast-json-stable-stringify": { 551 | "version": "2.0.0", 552 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 553 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 554 | }, 555 | "node_modules/fast-text-encoding": { 556 | "version": "1.0.0", 557 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", 558 | "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" 559 | }, 560 | "node_modules/find-up": { 561 | "version": "3.0.0", 562 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 563 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 564 | "dependencies": { 565 | "locate-path": "^3.0.0" 566 | }, 567 | "engines": { 568 | "node": ">=6" 569 | } 570 | }, 571 | "node_modules/forever-agent": { 572 | "version": "0.6.1", 573 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 574 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 575 | "engines": { 576 | "node": "*" 577 | } 578 | }, 579 | "node_modules/form-data": { 580 | "version": "2.3.3", 581 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 582 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 583 | "dependencies": { 584 | "asynckit": "^0.4.0", 585 | "combined-stream": "^1.0.6", 586 | "mime-types": "^2.1.12" 587 | }, 588 | "engines": { 589 | "node": ">= 0.12" 590 | } 591 | }, 592 | "node_modules/gaxios": { 593 | "version": "2.0.1", 594 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.0.1.tgz", 595 | "integrity": "sha512-c1NXovTxkgRJTIgB2FrFmOFg4YIV6N/bAa4f/FZ4jIw13Ql9ya/82x69CswvotJhbV3DiGnlTZwoq2NVXk2Irg==", 596 | "dependencies": { 597 | "abort-controller": "^3.0.0", 598 | "extend": "^3.0.2", 599 | "https-proxy-agent": "^2.2.1", 600 | "node-fetch": "^2.3.0" 601 | }, 602 | "engines": { 603 | "node": ">=8" 604 | } 605 | }, 606 | "node_modules/gcp-metadata": { 607 | "version": "3.2.0", 608 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.2.0.tgz", 609 | "integrity": "sha512-ympv+yQ6k5QuWCuwQqnGEvFGS7MBKdcQdj1i188v3bW9QLFIchTGaBCEZxSQapT0jffdn1vdt8oJhB5VBWQO1Q==", 610 | "dependencies": { 611 | "gaxios": "^2.0.1", 612 | "json-bigint": "^0.3.0" 613 | }, 614 | "engines": { 615 | "node": ">=8.10.0" 616 | } 617 | }, 618 | "node_modules/get-caller-file": { 619 | "version": "2.0.5", 620 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 621 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 622 | "engines": { 623 | "node": "6.* || 8.* || >= 10.*" 624 | } 625 | }, 626 | "node_modules/getpass": { 627 | "version": "0.1.7", 628 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 629 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 630 | "dependencies": { 631 | "assert-plus": "^1.0.0" 632 | } 633 | }, 634 | "node_modules/google-auth-library": { 635 | "version": "5.5.0", 636 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.5.0.tgz", 637 | "integrity": "sha512-TNeraw4miu6/FhO0jDrHiJuRx3SBrAhxHSPj7+rhif43bKE34UItXX9lejKxo3E8FNytuY4LIVIvpcqMQHSYZw==", 638 | "dependencies": { 639 | "arrify": "^2.0.0", 640 | "base64-js": "^1.3.0", 641 | "fast-text-encoding": "^1.0.0", 642 | "gaxios": "^2.0.0", 643 | "gcp-metadata": "^3.2.0", 644 | "gtoken": "^4.1.0", 645 | "jws": "^3.1.5", 646 | "lru-cache": "^5.0.0" 647 | }, 648 | "engines": { 649 | "node": ">=8.10.0" 650 | } 651 | }, 652 | "node_modules/google-gax": { 653 | "version": "1.7.5", 654 | "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.7.5.tgz", 655 | "integrity": "sha512-Tz2DFs8umzDcCBTi2W1cY4vEgAKaYRj70g6Hh/MiiZaJizrly7PgyxsIYUGi7sOpEuAbARQymYKvy5mNi8hEbg==", 656 | "dependencies": { 657 | "@grpc/grpc-js": "0.6.9", 658 | "@grpc/proto-loader": "^0.5.1", 659 | "abort-controller": "^3.0.0", 660 | "duplexify": "^3.6.0", 661 | "google-auth-library": "^5.0.0", 662 | "is-stream-ended": "^0.1.4", 663 | "lodash.at": "^4.6.0", 664 | "lodash.has": "^4.5.2", 665 | "node-fetch": "^2.6.0", 666 | "protobufjs": "^6.8.8", 667 | "retry-request": "^4.0.0", 668 | "semver": "^6.0.0", 669 | "walkdir": "^0.4.0" 670 | }, 671 | "bin": { 672 | "compileProtos": "build/tools/compileProtos.js" 673 | }, 674 | "engines": { 675 | "node": ">=8.10.0" 676 | } 677 | }, 678 | "node_modules/google-p12-pem": { 679 | "version": "2.0.2", 680 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.2.tgz", 681 | "integrity": "sha512-UfnEARfJKI6pbmC1hfFFm+UAcZxeIwTiEcHfqKe/drMsXD/ilnVjF7zgOGpHXyhuvX6jNJK3S8A0hOQjwtFxEw==", 682 | "deprecated": "Package is no longer maintained", 683 | "dependencies": { 684 | "node-forge": "^0.9.0" 685 | }, 686 | "bin": { 687 | "gp12-pem": "build/src/bin/gp12-pem.js" 688 | }, 689 | "engines": { 690 | "node": ">=8.10.0" 691 | } 692 | }, 693 | "node_modules/gtoken": { 694 | "version": "4.1.0", 695 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.0.tgz", 696 | "integrity": "sha512-wqyn2gf5buzEZN4QNmmiiW2i2JkEdZnL7Z/9p44RtZqgt4077m4khRgAYNuu8cBwHWCc6MsP6eDUn/KkF6jFIw==", 697 | "dependencies": { 698 | "gaxios": "^2.0.0", 699 | "google-p12-pem": "^2.0.0", 700 | "jws": "^3.1.5", 701 | "mime": "^2.2.0" 702 | }, 703 | "engines": { 704 | "node": ">=8.10.0" 705 | } 706 | }, 707 | "node_modules/har-schema": { 708 | "version": "2.0.0", 709 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 710 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 711 | "engines": { 712 | "node": ">=4" 713 | } 714 | }, 715 | "node_modules/har-validator": { 716 | "version": "5.1.3", 717 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 718 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 719 | "deprecated": "this library is no longer supported", 720 | "dependencies": { 721 | "ajv": "^6.5.5", 722 | "har-schema": "^2.0.0" 723 | }, 724 | "engines": { 725 | "node": ">=6" 726 | } 727 | }, 728 | "node_modules/has-flag": { 729 | "version": "3.0.0", 730 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 731 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 732 | "engines": { 733 | "node": ">=4" 734 | } 735 | }, 736 | "node_modules/http-proxy-agent": { 737 | "version": "2.1.0", 738 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", 739 | "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", 740 | "dependencies": { 741 | "agent-base": "4", 742 | "debug": "3.1.0" 743 | }, 744 | "engines": { 745 | "node": ">= 4.5.0" 746 | } 747 | }, 748 | "node_modules/http-proxy-agent/node_modules/debug": { 749 | "version": "3.1.0", 750 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 751 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 752 | "dependencies": { 753 | "ms": "2.0.0" 754 | } 755 | }, 756 | "node_modules/http-proxy-agent/node_modules/ms": { 757 | "version": "2.0.0", 758 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 759 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 760 | }, 761 | "node_modules/http-signature": { 762 | "version": "1.2.0", 763 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 764 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 765 | "dependencies": { 766 | "assert-plus": "^1.0.0", 767 | "jsprim": "^1.2.2", 768 | "sshpk": "^1.7.0" 769 | }, 770 | "engines": { 771 | "node": ">=0.8", 772 | "npm": ">=1.3.7" 773 | } 774 | }, 775 | "node_modules/https-proxy-agent": { 776 | "version": "2.2.4", 777 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", 778 | "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", 779 | "dependencies": { 780 | "agent-base": "^4.3.0", 781 | "debug": "^3.1.0" 782 | }, 783 | "engines": { 784 | "node": ">= 4.5.0" 785 | } 786 | }, 787 | "node_modules/iconv-lite": { 788 | "version": "0.5.0", 789 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz", 790 | "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==", 791 | "dependencies": { 792 | "safer-buffer": ">= 2.1.2 < 3" 793 | }, 794 | "engines": { 795 | "node": ">=0.10.0" 796 | } 797 | }, 798 | "node_modules/inherits": { 799 | "version": "2.0.4", 800 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 801 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 802 | }, 803 | "node_modules/is-fullwidth-code-point": { 804 | "version": "2.0.0", 805 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 806 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 807 | "engines": { 808 | "node": ">=4" 809 | } 810 | }, 811 | "node_modules/is-stream-ended": { 812 | "version": "0.1.4", 813 | "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", 814 | "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==" 815 | }, 816 | "node_modules/is-typedarray": { 817 | "version": "1.0.0", 818 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 819 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 820 | }, 821 | "node_modules/isarray": { 822 | "version": "1.0.0", 823 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 824 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 825 | }, 826 | "node_modules/isstream": { 827 | "version": "0.1.2", 828 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 829 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 830 | }, 831 | "node_modules/jsbn": { 832 | "version": "0.1.1", 833 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 834 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 835 | }, 836 | "node_modules/json-bigint": { 837 | "version": "0.3.0", 838 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", 839 | "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", 840 | "dependencies": { 841 | "bignumber.js": "^7.0.0" 842 | } 843 | }, 844 | "node_modules/json-schema": { 845 | "version": "0.2.3", 846 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 847 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 848 | }, 849 | "node_modules/json-schema-traverse": { 850 | "version": "0.4.1", 851 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 852 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 853 | }, 854 | "node_modules/json-stringify-safe": { 855 | "version": "5.0.1", 856 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 857 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 858 | }, 859 | "node_modules/jsprim": { 860 | "version": "1.4.1", 861 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 862 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 863 | "engines": [ 864 | "node >=0.6.0" 865 | ], 866 | "dependencies": { 867 | "assert-plus": "1.0.0", 868 | "extsprintf": "1.3.0", 869 | "json-schema": "0.2.3", 870 | "verror": "1.10.0" 871 | } 872 | }, 873 | "node_modules/jwa": { 874 | "version": "1.4.1", 875 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 876 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 877 | "dependencies": { 878 | "buffer-equal-constant-time": "1.0.1", 879 | "ecdsa-sig-formatter": "1.0.11", 880 | "safe-buffer": "^5.0.1" 881 | } 882 | }, 883 | "node_modules/jws": { 884 | "version": "3.2.2", 885 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 886 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 887 | "dependencies": { 888 | "jwa": "^1.4.1", 889 | "safe-buffer": "^5.0.1" 890 | } 891 | }, 892 | "node_modules/locate-path": { 893 | "version": "3.0.0", 894 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 895 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 896 | "dependencies": { 897 | "p-locate": "^3.0.0", 898 | "path-exists": "^3.0.0" 899 | }, 900 | "engines": { 901 | "node": ">=6" 902 | } 903 | }, 904 | "node_modules/lodash": { 905 | "version": "4.17.21", 906 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 907 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 908 | }, 909 | "node_modules/lodash.at": { 910 | "version": "4.6.0", 911 | "resolved": "https://registry.npmjs.org/lodash.at/-/lodash.at-4.6.0.tgz", 912 | "integrity": "sha1-k83OZk8KGZTqM9181A4jr9EbD/g=", 913 | "deprecated": "This package is deprecated. Use {Array|String}.prototype.at instead." 914 | }, 915 | "node_modules/lodash.camelcase": { 916 | "version": "4.3.0", 917 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 918 | "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" 919 | }, 920 | "node_modules/lodash.has": { 921 | "version": "4.5.2", 922 | "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", 923 | "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" 924 | }, 925 | "node_modules/long": { 926 | "version": "4.0.0", 927 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 928 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 929 | }, 930 | "node_modules/lru-cache": { 931 | "version": "5.1.1", 932 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 933 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 934 | "dependencies": { 935 | "yallist": "^3.0.2" 936 | } 937 | }, 938 | "node_modules/mime": { 939 | "version": "2.4.4", 940 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", 941 | "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", 942 | "bin": { 943 | "mime": "cli.js" 944 | }, 945 | "engines": { 946 | "node": ">=4.0.0" 947 | } 948 | }, 949 | "node_modules/mime-db": { 950 | "version": "1.40.0", 951 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 952 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", 953 | "engines": { 954 | "node": ">= 0.6" 955 | } 956 | }, 957 | "node_modules/mime-types": { 958 | "version": "2.1.24", 959 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 960 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 961 | "dependencies": { 962 | "mime-db": "1.40.0" 963 | }, 964 | "engines": { 965 | "node": ">= 0.6" 966 | } 967 | }, 968 | "node_modules/ms": { 969 | "version": "2.1.2", 970 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 971 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 972 | }, 973 | "node_modules/node-fetch": { 974 | "version": "2.6.7", 975 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 976 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 977 | "dependencies": { 978 | "whatwg-url": "^5.0.0" 979 | }, 980 | "engines": { 981 | "node": "4.x || >=6.0.0" 982 | }, 983 | "peerDependencies": { 984 | "encoding": "^0.1.0" 985 | }, 986 | "peerDependenciesMeta": { 987 | "encoding": { 988 | "optional": true 989 | } 990 | } 991 | }, 992 | "node_modules/node-forge": { 993 | "version": "0.9.1", 994 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz", 995 | "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ==", 996 | "engines": { 997 | "node": ">= 4.5.0" 998 | } 999 | }, 1000 | "node_modules/node-gyp-build": { 1001 | "version": "3.7.0", 1002 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", 1003 | "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", 1004 | "optional": true, 1005 | "bin": { 1006 | "node-gyp-build": "bin.js", 1007 | "node-gyp-build-optional": "optional.js", 1008 | "node-gyp-build-test": "build-test.js" 1009 | } 1010 | }, 1011 | "node_modules/oauth-sign": { 1012 | "version": "0.9.0", 1013 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1014 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1015 | "engines": { 1016 | "node": "*" 1017 | } 1018 | }, 1019 | "node_modules/once": { 1020 | "version": "1.4.0", 1021 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1022 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1023 | "dependencies": { 1024 | "wrappy": "1" 1025 | } 1026 | }, 1027 | "node_modules/p-limit": { 1028 | "version": "2.2.1", 1029 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", 1030 | "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", 1031 | "dependencies": { 1032 | "p-try": "^2.0.0" 1033 | }, 1034 | "engines": { 1035 | "node": ">=6" 1036 | } 1037 | }, 1038 | "node_modules/p-locate": { 1039 | "version": "3.0.0", 1040 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1041 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1042 | "dependencies": { 1043 | "p-limit": "^2.0.0" 1044 | }, 1045 | "engines": { 1046 | "node": ">=6" 1047 | } 1048 | }, 1049 | "node_modules/p-try": { 1050 | "version": "2.2.0", 1051 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1052 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1053 | "engines": { 1054 | "node": ">=6" 1055 | } 1056 | }, 1057 | "node_modules/path-exists": { 1058 | "version": "3.0.0", 1059 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1060 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1061 | "engines": { 1062 | "node": ">=4" 1063 | } 1064 | }, 1065 | "node_modules/performance-now": { 1066 | "version": "2.1.0", 1067 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1068 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1069 | }, 1070 | "node_modules/process-nextick-args": { 1071 | "version": "2.0.1", 1072 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1073 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1074 | }, 1075 | "node_modules/protobufjs": { 1076 | "version": "6.11.3", 1077 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", 1078 | "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", 1079 | "hasInstallScript": true, 1080 | "dependencies": { 1081 | "@protobufjs/aspromise": "^1.1.2", 1082 | "@protobufjs/base64": "^1.1.2", 1083 | "@protobufjs/codegen": "^2.0.4", 1084 | "@protobufjs/eventemitter": "^1.1.0", 1085 | "@protobufjs/fetch": "^1.1.0", 1086 | "@protobufjs/float": "^1.0.2", 1087 | "@protobufjs/inquire": "^1.1.0", 1088 | "@protobufjs/path": "^1.1.2", 1089 | "@protobufjs/pool": "^1.1.0", 1090 | "@protobufjs/utf8": "^1.1.0", 1091 | "@types/long": "^4.0.1", 1092 | "@types/node": ">=13.7.0", 1093 | "long": "^4.0.0" 1094 | }, 1095 | "bin": { 1096 | "pbjs": "bin/pbjs", 1097 | "pbts": "bin/pbts" 1098 | } 1099 | }, 1100 | "node_modules/protobufjs/node_modules/@types/long": { 1101 | "version": "4.0.2", 1102 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", 1103 | "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" 1104 | }, 1105 | "node_modules/protobufjs/node_modules/@types/node": { 1106 | "version": "17.0.38", 1107 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.38.tgz", 1108 | "integrity": "sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g==" 1109 | }, 1110 | "node_modules/psl": { 1111 | "version": "1.4.0", 1112 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", 1113 | "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" 1114 | }, 1115 | "node_modules/pump": { 1116 | "version": "3.0.0", 1117 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1118 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1119 | "dependencies": { 1120 | "end-of-stream": "^1.1.0", 1121 | "once": "^1.3.1" 1122 | } 1123 | }, 1124 | "node_modules/pumpify": { 1125 | "version": "2.0.1", 1126 | "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", 1127 | "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", 1128 | "dependencies": { 1129 | "duplexify": "^4.1.1", 1130 | "inherits": "^2.0.3", 1131 | "pump": "^3.0.0" 1132 | } 1133 | }, 1134 | "node_modules/pumpify/node_modules/duplexify": { 1135 | "version": "4.1.1", 1136 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", 1137 | "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", 1138 | "dependencies": { 1139 | "end-of-stream": "^1.4.1", 1140 | "inherits": "^2.0.3", 1141 | "readable-stream": "^3.1.1", 1142 | "stream-shift": "^1.0.0" 1143 | } 1144 | }, 1145 | "node_modules/pumpify/node_modules/readable-stream": { 1146 | "version": "3.4.0", 1147 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", 1148 | "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", 1149 | "dependencies": { 1150 | "inherits": "^2.0.3", 1151 | "string_decoder": "^1.1.1", 1152 | "util-deprecate": "^1.0.1" 1153 | }, 1154 | "engines": { 1155 | "node": ">= 6" 1156 | } 1157 | }, 1158 | "node_modules/punycode": { 1159 | "version": "2.1.1", 1160 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1161 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1162 | "engines": { 1163 | "node": ">=6" 1164 | } 1165 | }, 1166 | "node_modules/qs": { 1167 | "version": "6.5.3", 1168 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 1169 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 1170 | "engines": { 1171 | "node": ">=0.6" 1172 | } 1173 | }, 1174 | "node_modules/readable-stream": { 1175 | "version": "2.3.6", 1176 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1177 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1178 | "dependencies": { 1179 | "core-util-is": "~1.0.0", 1180 | "inherits": "~2.0.3", 1181 | "isarray": "~1.0.0", 1182 | "process-nextick-args": "~2.0.0", 1183 | "safe-buffer": "~5.1.1", 1184 | "string_decoder": "~1.1.1", 1185 | "util-deprecate": "~1.0.1" 1186 | } 1187 | }, 1188 | "node_modules/request": { 1189 | "version": "2.88.0", 1190 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1191 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1192 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 1193 | "dependencies": { 1194 | "aws-sign2": "~0.7.0", 1195 | "aws4": "^1.8.0", 1196 | "caseless": "~0.12.0", 1197 | "combined-stream": "~1.0.6", 1198 | "extend": "~3.0.2", 1199 | "forever-agent": "~0.6.1", 1200 | "form-data": "~2.3.2", 1201 | "har-validator": "~5.1.0", 1202 | "http-signature": "~1.2.0", 1203 | "is-typedarray": "~1.0.0", 1204 | "isstream": "~0.1.2", 1205 | "json-stringify-safe": "~5.0.1", 1206 | "mime-types": "~2.1.19", 1207 | "oauth-sign": "~0.9.0", 1208 | "performance-now": "^2.1.0", 1209 | "qs": "~6.5.2", 1210 | "safe-buffer": "^5.1.2", 1211 | "tough-cookie": "~2.4.3", 1212 | "tunnel-agent": "^0.6.0", 1213 | "uuid": "^3.3.2" 1214 | }, 1215 | "engines": { 1216 | "node": ">= 4" 1217 | } 1218 | }, 1219 | "node_modules/require-directory": { 1220 | "version": "2.1.1", 1221 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1222 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1223 | "engines": { 1224 | "node": ">=0.10.0" 1225 | } 1226 | }, 1227 | "node_modules/require-main-filename": { 1228 | "version": "2.0.0", 1229 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1230 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" 1231 | }, 1232 | "node_modules/retry-request": { 1233 | "version": "4.1.1", 1234 | "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.1.tgz", 1235 | "integrity": "sha512-BINDzVtLI2BDukjWmjAIRZ0oglnCAkpP2vQjM3jdLhmT62h0xnQgciPwBRDAvHqpkPT2Wo1XuUyLyn6nbGrZQQ==", 1236 | "dependencies": { 1237 | "debug": "^4.1.1", 1238 | "through2": "^3.0.1" 1239 | }, 1240 | "engines": { 1241 | "node": ">=8.10.0" 1242 | } 1243 | }, 1244 | "node_modules/retry-request/node_modules/debug": { 1245 | "version": "4.1.1", 1246 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1247 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1248 | "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", 1249 | "dependencies": { 1250 | "ms": "^2.1.1" 1251 | } 1252 | }, 1253 | "node_modules/safe-buffer": { 1254 | "version": "5.1.2", 1255 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1256 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1257 | }, 1258 | "node_modules/safer-buffer": { 1259 | "version": "2.1.2", 1260 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1261 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1262 | }, 1263 | "node_modules/semver": { 1264 | "version": "6.3.0", 1265 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1266 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1267 | "bin": { 1268 | "semver": "bin/semver.js" 1269 | } 1270 | }, 1271 | "node_modules/set-blocking": { 1272 | "version": "2.0.0", 1273 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1274 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 1275 | }, 1276 | "node_modules/shred": { 1277 | "version": "0.8.10", 1278 | "resolved": "https://registry.npmjs.org/shred/-/shred-0.8.10.tgz", 1279 | "integrity": "sha1-zxz+gPeb9TE9Ltw7kSJ4/RB6hxc=", 1280 | "dependencies": { 1281 | "ax": "0.1.8", 1282 | "cookiejar": "1.3.1", 1283 | "iconv-lite": ">= 0.1.2", 1284 | "sprintf": "0.1.1" 1285 | } 1286 | }, 1287 | "node_modules/sprintf": { 1288 | "version": "0.1.1", 1289 | "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.1.tgz", 1290 | "integrity": "sha1-6JJfyYlOGqaJnpCRx/KhITC3DeU=", 1291 | "deprecated": "The sprintf package is deprecated in favor of sprintf-js.", 1292 | "engines": { 1293 | "node": ">=0.2.4" 1294 | } 1295 | }, 1296 | "node_modules/sshpk": { 1297 | "version": "1.16.1", 1298 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1299 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1300 | "dependencies": { 1301 | "asn1": "~0.2.3", 1302 | "assert-plus": "^1.0.0", 1303 | "bcrypt-pbkdf": "^1.0.0", 1304 | "dashdash": "^1.12.0", 1305 | "ecc-jsbn": "~0.1.1", 1306 | "getpass": "^0.1.1", 1307 | "jsbn": "~0.1.0", 1308 | "safer-buffer": "^2.0.2", 1309 | "tweetnacl": "~0.14.0" 1310 | }, 1311 | "bin": { 1312 | "sshpk-conv": "bin/sshpk-conv", 1313 | "sshpk-sign": "bin/sshpk-sign", 1314 | "sshpk-verify": "bin/sshpk-verify" 1315 | }, 1316 | "engines": { 1317 | "node": ">=0.10.0" 1318 | } 1319 | }, 1320 | "node_modules/stream-events": { 1321 | "version": "1.0.5", 1322 | "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", 1323 | "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", 1324 | "dependencies": { 1325 | "stubs": "^3.0.0" 1326 | } 1327 | }, 1328 | "node_modules/stream-shift": { 1329 | "version": "1.0.0", 1330 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", 1331 | "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" 1332 | }, 1333 | "node_modules/string_decoder": { 1334 | "version": "1.1.1", 1335 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1336 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1337 | "dependencies": { 1338 | "safe-buffer": "~5.1.0" 1339 | } 1340 | }, 1341 | "node_modules/string-width": { 1342 | "version": "3.1.0", 1343 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1344 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1345 | "dependencies": { 1346 | "emoji-regex": "^7.0.1", 1347 | "is-fullwidth-code-point": "^2.0.0", 1348 | "strip-ansi": "^5.1.0" 1349 | }, 1350 | "engines": { 1351 | "node": ">=6" 1352 | } 1353 | }, 1354 | "node_modules/strip-ansi": { 1355 | "version": "5.2.0", 1356 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1357 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1358 | "dependencies": { 1359 | "ansi-regex": "^4.1.0" 1360 | }, 1361 | "engines": { 1362 | "node": ">=6" 1363 | } 1364 | }, 1365 | "node_modules/stubs": { 1366 | "version": "3.0.0", 1367 | "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", 1368 | "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" 1369 | }, 1370 | "node_modules/supports-color": { 1371 | "version": "5.5.0", 1372 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1373 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1374 | "dependencies": { 1375 | "has-flag": "^3.0.0" 1376 | }, 1377 | "engines": { 1378 | "node": ">=4" 1379 | } 1380 | }, 1381 | "node_modules/swagger-client": { 1382 | "version": "2.0.26", 1383 | "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-2.0.26.tgz", 1384 | "integrity": "sha1-c/FQk/be82nzG5ZwxtlkWzMWPk0=", 1385 | "deprecated": "No longer maintained, please upgrade to swagger-client@3.", 1386 | "dependencies": { 1387 | "btoa": "1.1.1", 1388 | "shred": "0.8.10" 1389 | }, 1390 | "engines": { 1391 | "node": ">= 0.6.6" 1392 | } 1393 | }, 1394 | "node_modules/teeny-request": { 1395 | "version": "5.3.0", 1396 | "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-5.3.0.tgz", 1397 | "integrity": "sha512-sN9E3JvEBe2CFqB/jpJpw1erWD1C7MxyYCxogHFCQSyZfkHYcdf4wzVQSw7FZxbwcfnS+FP0W9BS0mp6SEOKjg==", 1398 | "dependencies": { 1399 | "http-proxy-agent": "^2.1.0", 1400 | "https-proxy-agent": "^3.0.0", 1401 | "node-fetch": "^2.2.0", 1402 | "stream-events": "^1.0.5", 1403 | "uuid": "^3.3.2" 1404 | } 1405 | }, 1406 | "node_modules/teeny-request/node_modules/https-proxy-agent": { 1407 | "version": "3.0.1", 1408 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", 1409 | "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", 1410 | "dependencies": { 1411 | "agent-base": "^4.3.0", 1412 | "debug": "^3.1.0" 1413 | }, 1414 | "engines": { 1415 | "node": ">= 4.5.0" 1416 | } 1417 | }, 1418 | "node_modules/through2": { 1419 | "version": "3.0.1", 1420 | "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", 1421 | "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", 1422 | "dependencies": { 1423 | "readable-stream": "2 || 3" 1424 | } 1425 | }, 1426 | "node_modules/tough-cookie": { 1427 | "version": "2.4.3", 1428 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1429 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1430 | "dependencies": { 1431 | "psl": "^1.1.24", 1432 | "punycode": "^1.4.1" 1433 | }, 1434 | "engines": { 1435 | "node": ">=0.8" 1436 | } 1437 | }, 1438 | "node_modules/tough-cookie/node_modules/punycode": { 1439 | "version": "1.4.1", 1440 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1441 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1442 | }, 1443 | "node_modules/tr46": { 1444 | "version": "0.0.3", 1445 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1446 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" 1447 | }, 1448 | "node_modules/tunnel-agent": { 1449 | "version": "0.6.0", 1450 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1451 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1452 | "dependencies": { 1453 | "safe-buffer": "^5.0.1" 1454 | }, 1455 | "engines": { 1456 | "node": "*" 1457 | } 1458 | }, 1459 | "node_modules/tweetnacl": { 1460 | "version": "0.14.5", 1461 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1462 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 1463 | }, 1464 | "node_modules/uri-js": { 1465 | "version": "4.2.2", 1466 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1467 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1468 | "dependencies": { 1469 | "punycode": "^2.1.0" 1470 | } 1471 | }, 1472 | "node_modules/util-deprecate": { 1473 | "version": "1.0.2", 1474 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1475 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1476 | }, 1477 | "node_modules/uuid": { 1478 | "version": "3.3.3", 1479 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 1480 | "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", 1481 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 1482 | "bin": { 1483 | "uuid": "bin/uuid" 1484 | } 1485 | }, 1486 | "node_modules/verror": { 1487 | "version": "1.10.0", 1488 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1489 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1490 | "engines": [ 1491 | "node >=0.6.0" 1492 | ], 1493 | "dependencies": { 1494 | "assert-plus": "^1.0.0", 1495 | "core-util-is": "1.0.2", 1496 | "extsprintf": "^1.2.0" 1497 | } 1498 | }, 1499 | "node_modules/walkdir": { 1500 | "version": "0.4.1", 1501 | "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", 1502 | "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", 1503 | "engines": { 1504 | "node": ">=6.0.0" 1505 | } 1506 | }, 1507 | "node_modules/webidl-conversions": { 1508 | "version": "3.0.1", 1509 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1510 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" 1511 | }, 1512 | "node_modules/whatwg-url": { 1513 | "version": "5.0.0", 1514 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1515 | "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", 1516 | "dependencies": { 1517 | "tr46": "~0.0.3", 1518 | "webidl-conversions": "^3.0.0" 1519 | } 1520 | }, 1521 | "node_modules/which-module": { 1522 | "version": "2.0.0", 1523 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1524 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" 1525 | }, 1526 | "node_modules/wrap-ansi": { 1527 | "version": "5.1.0", 1528 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 1529 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 1530 | "dependencies": { 1531 | "ansi-styles": "^3.2.0", 1532 | "string-width": "^3.0.0", 1533 | "strip-ansi": "^5.0.0" 1534 | }, 1535 | "engines": { 1536 | "node": ">=6" 1537 | } 1538 | }, 1539 | "node_modules/wrappy": { 1540 | "version": "1.0.2", 1541 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1542 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1543 | }, 1544 | "node_modules/ws": { 1545 | "version": "7.4.6", 1546 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", 1547 | "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", 1548 | "engines": { 1549 | "node": ">=8.3.0" 1550 | }, 1551 | "peerDependencies": { 1552 | "bufferutil": "^4.0.1", 1553 | "utf-8-validate": "^5.0.2" 1554 | }, 1555 | "peerDependenciesMeta": { 1556 | "bufferutil": { 1557 | "optional": true 1558 | }, 1559 | "utf-8-validate": { 1560 | "optional": true 1561 | } 1562 | } 1563 | }, 1564 | "node_modules/y18n": { 1565 | "version": "4.0.1", 1566 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 1567 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" 1568 | }, 1569 | "node_modules/yallist": { 1570 | "version": "3.1.1", 1571 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 1572 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 1573 | }, 1574 | "node_modules/yargs": { 1575 | "version": "14.2.0", 1576 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz", 1577 | "integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==", 1578 | "dependencies": { 1579 | "cliui": "^5.0.0", 1580 | "decamelize": "^1.2.0", 1581 | "find-up": "^3.0.0", 1582 | "get-caller-file": "^2.0.1", 1583 | "require-directory": "^2.1.1", 1584 | "require-main-filename": "^2.0.0", 1585 | "set-blocking": "^2.0.0", 1586 | "string-width": "^3.0.0", 1587 | "which-module": "^2.0.0", 1588 | "y18n": "^4.0.0", 1589 | "yargs-parser": "^15.0.0" 1590 | } 1591 | }, 1592 | "node_modules/yargs-parser": { 1593 | "version": "15.0.0", 1594 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz", 1595 | "integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==", 1596 | "dependencies": { 1597 | "camelcase": "^5.0.0", 1598 | "decamelize": "^1.2.0" 1599 | } 1600 | } 1601 | } 1602 | } 1603 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asterisk-external-media", 3 | "version": "0.1.0", 4 | "description": "asterisk-external-media", 5 | "homepage": "https://github.com/asterisk/asterisk-external-media#README.md", 6 | "main": "./lib/ari-transcriber.js", 7 | "bin": { 8 | "ari-transcriber": "./bin/ari-transcriber" 9 | }, 10 | "scripts": { 11 | "start": "./bin/ari-transcriber", 12 | "test": "echo \"Error: no test specified! Configure in package.json\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git://github.com/asterisk/asterisk-external-media" 17 | }, 18 | "keywords": [ 19 | "asterisk", 20 | "asterisk ari", 21 | "asterisk externa -media" 22 | ], 23 | "author": "George Joseph =10" 28 | }, 29 | "dependencies": { 30 | "@google-cloud/speech": "^3.3.1", 31 | "ari-client": "^2.2.0", 32 | "chalk": "^2.4.2", 33 | "datagram-stream": "^1.1.1", 34 | "ws": "^7.4.6", 35 | "yargs": "^14.2.0" 36 | }, 37 | "optionalDependencies": { 38 | "bufferutil": "^4.0.1" 39 | } 40 | } 41 | --------------------------------------------------------------------------------