├── .github
└── FUNDING.yml
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── LICENSE.txt
├── README.md
├── package.json
├── pretest
├── docker-compose.yml
└── ssh
│ ├── Dockerfile
│ ├── authorized_keys
│ └── docker-entrypoint.sh
├── spec
├── connect-hopping-spec.js
├── connect-spec.js
├── connect-ts-spec.ts
├── exec-spec.js
├── fixture.js
├── sftp-spec.js
├── support
│ └── jasmine.json
├── test-hopping-spec.js
├── test.pem
└── util-spec.js
├── src
├── BaseSFTP.ts
├── BaseSSH2Promise.ts
├── index.ts
├── sftp.ts
├── sshConfig.ts
├── sshConnection.ts
├── sshConstants.ts
├── sshUtils.ts
└── tunnelConfig.ts
├── tsconfig.json
└── yarn.lock
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github:
4 | patreon:
5 | open_collective:
6 | ko_fi:
7 | tidelift:
8 | community_bridge:
9 | liberapay:
10 | issuehunt:
11 | otechie:
12 | lfx_crowdfunding:
13 | custom:
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .vscode
3 | spec/fixture.old.json
4 | host.key
5 | test.js
6 | test-spec.js
7 | lib
8 | dist
9 | test
10 | package-lock.json
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 14
4 | services:
5 | - docker
6 | env:
7 | - DOCKER_COMPOSE_VERSION=1.24.1
8 |
9 | before_install:
10 | - sudo rm /usr/local/bin/docker-compose
11 | - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
12 | - chmod +x docker-compose
13 | - sudo mv docker-compose /usr/local/bin
14 | install:
15 | - npm install
16 | - npm run-script build
17 | script:
18 | - cd pretest && docker-compose up -d && cd .. && sleep 10
19 | - npm test
20 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at bajoriasanket@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Sanket Bajoria
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SSH2-Promise 
2 |
3 | [ssh2-promise](https://github.com/sanketbajoria/ssh2-promise) is a powerful promise wrapper around [ssh2](https://www.npmjs.com/package/ssh2) client. It supports all the ssh2 client operation such as connection hopping, exec, spawn, shell, sftp, open tunnel, open socks connection etc... in promisify and async-await way. It helps in caching the sshconnection, to reduce time, during connection hopping. It have reconnect logic, so that, once disconnected, it can retry the sshconnection, automatically.
4 | It has promise wrapper around [sftp](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md) operations too.
5 | This module is written in `Typescript`. It can be used in `Javascript` or in `Typescript` with full type support.
6 |
7 |
We have upgraded to ssh2 v1.1.0. It means minimum Node requirement v10.16.0, if you need support for older version please use ssh2-promise v0.2.0
8 |
9 | Change in sftp api, now ssh.sftp() provide wrapped SFTP session instead of raw sftp session.
10 |
11 | # Installation
12 |
13 | ```javascript
14 | //(Require Node v10.16.0 or newer)
15 | npm install ssh2-promise;
16 |
17 | //for older version (Supports for any version of Node)
18 | npm install ssh2-promise@0.2.0
19 | ```
20 |
21 | # Local Testing
22 | #### Prerequisite to be installed
23 | - docker
24 | - docker-compose
25 |
26 | ```bash
27 | cd pretest
28 | docker-compose up -d
29 | cd ..
30 | yarn test
31 | ```
32 |
33 | # Usage
34 | All examples are shown in promisify and async-await manner.
35 |
36 | #### Require
37 |
38 | ```javascript
39 | //in javascript manner
40 | var SSH2Promise = require('ssh2-promise');
41 |
42 | //or in typescript manner
43 | import SSH2Promise = require('ssh2-promise');
44 |
45 | //or in typescript manner (with esModuleInterop enabled)
46 | import SSH2Promise from 'ssh2-promise';
47 |
48 |
49 | //To import SFTP, SSHConfig, TunnelConfig Type definition, SSHConstants in typescript
50 |
51 | //without esModuleInterop
52 | import SFTP = require('ssh2-promise/lib/sftp')
53 | import SSHConfig = require('ssh2-promise/lib/sshConfig');
54 | import TunnelConfig = require('ssh2-promise/lib/tunnelConfig');
55 | import SSHConstants = require('ssh2-promise/lib/sshConstants');
56 |
57 | //with esModuleInterop
58 | import SFTP from 'ssh2-promise/lib/sftp'
59 | import SSHConfig from 'ssh2-promise/lib/sshConfig';
60 | import TunnelConfig from 'ssh2-promise/lib/tunnelConfig';
61 | import SSHConstants from 'ssh2-promise/lib/sshConstants';
62 | ```
63 |
64 | #### Connect to SSH Server
65 |
66 | Configuration passed to SSH2Promise is aligned to [ssh2](https://www.npmjs.com/package/ssh2) library. For debugging, pass a debug function in configuration, similary how we do for SSH2
67 |
68 | ```javascript
69 | // The config passed to the Client constructor should match the config required by ssh2.
70 | // Extra identity option is provided to directly pass the path of private key file
71 | var sshconfig = {
72 | host: '192.168.1.2',
73 | username: 'ubuntu',
74 | identity: '/here/is/my/key'
75 | }
76 |
77 | var ssh = new SSH2Promise(sshconfig);
78 |
79 | //Promise
80 | ssh.connect().then(() => {
81 | console.log("Connection established")
82 | });
83 |
84 |
85 | //Async Await
86 | (async function(){
87 | await ssh.connect();
88 | console.log("Connection established");
89 | })();
90 |
91 | //Close the ssh connection
92 | //very important otherwise event leaks can happen
93 | ssh.close();
94 |
95 |
96 | ```
97 | #### Connect to SSH Server via hopping
98 |
99 | ```javascript
100 | //SSH server detail used for hopping
101 | var sshconfig1 = {
102 | host: '192.168.1.2',
103 | username: 'ubuntu',
104 | identity: '/here/is/my/key1'
105 | }
106 |
107 | //SSH server detail to be connected
108 | var sshconfig2 = {
109 | host: '192.168.1.3',
110 | username: 'ubuntu',
111 | password: 'mysecret2'
112 | }
113 |
114 | //It will establish connection to sshconfig2 via sshconfig1
115 | //by default it will cache connection,
116 | //to disable caching, pass second parameter as true
117 | //new SSH2Promise([sshconfig1, sshconfig2], true)
118 | var ssh = new SSH2Promise([sshconfig1, sshconfig2]);
119 |
120 | //Promise
121 | ssh.connect().then(() => {
122 | console.log("Connection established")
123 | });
124 |
125 |
126 | //Async Await
127 | (async function(){
128 | await ssh.connect();
129 | console.log("Connection established");
130 | })();
131 |
132 | ```
133 |
134 | #### exec, spawn cmd
135 |
136 | ```javascript
137 | var ssh = new SSH2Promise(sshconfig);
138 |
139 | //Promise
140 | //use exec, if output of command is limited
141 | ssh.exec("whoami").then((data) => {
142 | console.log(data); //ubuntu
143 | });
144 | //use spawn, if you want to stream on output of command
145 | ssh.spawn("tail -f /var/log.txt").then((socket) => {
146 | socket.on('data', () => {
147 | //file content will be available here
148 | })
149 | });
150 |
151 |
152 | //Async Await
153 | //use exec, if output of command is limited
154 | (async function(){
155 | var data = await ssh.exec("whoami");
156 | console.log(data); //ubuntu
157 | })();
158 |
159 | //use spawn, if you want to stream on output of command
160 | (async function(){
161 | var socket = await ssh.spawn("tail -f /var/log.txt");
162 | socket.on('data', () => {
163 | //file content will be available here
164 | })
165 | })();
166 |
167 | ```
168 |
169 | #### sftp, shell cmd
170 |
171 | ```javascript
172 | var ssh = new SSH2Promise(sshconfig);
173 |
174 | //Promise
175 | //Get a sftp session
176 | //see: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md
177 |
178 | //in typescript import sftp type definition
179 | //import SFTP = require('ssh2-promise/lib/sftp')
180 |
181 | var sftp/*:SFTP*/ = ssh.sftp()
182 | sftp.readdir("/").then((data) => {
183 | console.log(data); //file listing
184 | }).catch((err) => {
185 | console.log(err);
186 | })
187 |
188 |
189 | //Get a shell session
190 | ssh.shell().then((socket) => {
191 | socket.on('data', () => {
192 | //shell content will be available here
193 | })
194 | //Can write to socket
195 | socket.write("")
196 | });
197 |
198 |
199 | //Async Await
200 | //Get a sftp session
201 | //see: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md
202 | (async function(){
203 | var sftp = ssh.sftp();
204 | var data = await sftp.readdir("/")
205 | console.log(data); //file listing
206 | })();
207 |
208 | //Get a shell session
209 | (async function(){
210 | var socket = await ssh.shell();
211 | socket.on('data', () => {
212 | //shell content will be available here
213 | })
214 | //Can write to socket
215 | socket.write("")
216 | })();
217 | ```
218 |
219 | #### sftp operation in promise & async await manner
220 |
221 | ```javascript
222 | //in typescript import sftp type definition
223 | //import SFTP = require('ssh2-promise/lib/sftp')
224 | var ssh = new SSH2Promise(sshconfig);
225 | var sftp/*:SFTP*/ = ssh.sftp(); //or new SSH2Promise.SFTP(ssh);
226 |
227 | //We can do all sftp client operation listed in "https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md" in promisify or async await manner.
228 |
229 | //Promise
230 | //Read dir
231 | sftp.readdir("/").then((list) => {
232 | console.log(list); //list of files in directory '/'
233 | });
234 | //Create ReadStream
235 | sftp.createReadStream("/test.sh").then((stream) => {
236 | console.log(stream); //Readable stream, which support data, close events etc..
237 | });
238 | //Get stat
239 | sftp.getStat("/test.sh").then((stat) => {
240 | console.log(stat); //Stat object
241 | });
242 |
243 |
244 | //Async Await
245 | //Read dir
246 | (async function(){
247 | var list = await sftp.readdir("/");
248 | console.log(list); //list of files in directory '/'
249 | })();
250 | //Create ReadStream
251 | (async function(){
252 | var stream = await sftp.createReadStream("/test.sh");
253 | console.log(stream); //Readable stream, which support data, close events etc..
254 | })();
255 | //Get stat
256 | (async function(){
257 | var st = await sftp.getStat("/test.sh");
258 | console.log(stat); //Stat object
259 | })();
260 | ```
261 |
262 | #### tunnel and socks server
263 |
264 | ```javascript
265 | var ssh = new SSH2Promise(sshconfig);
266 |
267 | //Promise
268 | //It will establish the socks connection, one per ssh connection, and return the port
269 | //It is mainly used for reverse tunneling
270 | ssh.getSocksPort().then((port) => {
271 | console.log(port); //Socks port
272 | });
273 |
274 | //Establish a forward tunneling to any resource over above server
275 | ssh.addTunnel({remoteAddr: "www.google.com", remotePort: "80"}).then((tunnel) => {
276 | console.log(tunnel.localPort); //Local port
277 | });
278 |
279 |
280 | //Async Await
281 | //It will establish the socks connection, one per ssh connection, and return the port
282 | //It is mainly used for reverse tunneling
283 | (async function(){
284 | var port = await ssh.getSocksPort();
285 | console.log(port); //Socks port
286 | })();
287 |
288 | //Establish a forward tunneling to any resource over above server
289 | (async function(){
290 | var tunnel = await ssh.addTunnel({remoteAddr: "www.google.com", remotePort: "80"});
291 | console.log(tunnel.localPort); //Local port
292 | })();
293 | ```
294 |
295 | #### x11
296 |
297 | ```javascript
298 | sshconfig.x11 = {srcIP: 'localhost', srcPort: 6000}
299 | //sshconfig.x11 = '/tmp/.X11-unix/X0' //connect to unix socket
300 | var ssh = new SSH2Promise(sshconfig);
301 |
302 | //It will establish the x11 forwarding, if
303 | //x server running locally,
304 | //x forwarding enabled on remote server
305 | //xeyes command is installed on remote server
306 |
307 | //Promise
308 | ssh.x11('xeyes').then(() => {
309 | console.log("success"); //if x server running locally, (x forwarding enabled & xeyes command is installed) on remote server
310 | }, () => {
311 | console.log("error"); //if any success condition is not met
312 | });
313 |
314 | //Async Await
315 | (async function(){
316 | try{
317 | await ssh.x11('xeyes');
318 | console.log("success"); //if x server running locally, (x forwarding enabled & xeyes command is installed) on remote server
319 | }catch(err){
320 | console.log("error"); //if any success condition is not met
321 | }
322 | })();
323 | ```
324 |
325 | #### subsys
326 |
327 | ```javascript
328 | var ssh = new SSH2Promise(sshconfig);
329 |
330 | //It will start subsystem
331 |
332 | //Promise
333 | ssh.subsys('sftp').then((stream) => {
334 | console.log("success"); //sftp system started successfully
335 | });
336 |
337 | //Async Await
338 | (async function(){
339 | var stream = await ssh.subsys('sftp');
340 | console.log("success"); //sftp system started successfully
341 | })();
342 | ```
343 |
344 | # API
345 | `require('ssh2-promise')`
346 | `require('ssh2-promise\lib\sftp')`
347 |
348 | ## SSH2
349 |
350 | #### Events
351 | * **ssh**(< _string_ >status, < _object_ >sshconnection, < _object_ >payload) - Event get generated, when sshconnection status get changed. Various status can be "beforeconnect", "connect", "beforedisconnect", "disconnect"
352 |
353 | * **ssh:< _status_ >**(< _object_ >sshconnection, < _object_ >payload) - Event get generated, when sshconnection status is at particular status. Various status can be "beforeconnect", "connect", "beforedisconnect", "disconnect"
354 |
355 | * **tunnel**(< _string_ >status, < _object_ >sshconnection, < _object_ >payload) - Event get generated, when tunnel status get changed. Various status can be "beforeconnect", "connect", "beforedisconnect", "disconnect"
356 |
357 | * **tunnel:< _status_ >**(< _object_ >sshconnection, < _object_ >payload) - Event get generated, when tunnel status is at particular status. Various status can be "beforeconnect", "connect", "beforedisconnect", "disconnect"
358 |
359 | #### Methods
360 | * **(constructor)**(< _array_ >|< _object_ >sshConfig, < _(Promise)_ >disableCache) - Creates and returns a new SSH2Promise instance. Single or multiple sshconfigs can be passed. sshConfig passed to SSH2Promise is aligned to [ssh2](https://www.npmjs.com/package/ssh2) library. It has few extra options other than ssh2 configuration.
361 | * **host** - _string_ - Hostname or IP address of the server. **Default:** `'localhost'`
362 |
363 | * **port** - _integer_ - Port number of the server. **Default:** `22`
364 |
365 | * **forceIPv4** - _(Promise)_ - Only connect via resolved IPv4 address for `host`. **Default:** `false`
366 |
367 | * **forceIPv6** - _(Promise)_ - Only connect via resolved IPv6 address for `host`. **Default:** `false`
368 |
369 | * **hostHash** - _string_ - 'md5' or 'sha1'. The host's key is hashed using this method and passed to the **hostVerifier** function. **Default:** (none)
370 |
371 | * **hostVerifier** - _function_ - Function with parameters `(hashedKey[, callback])` where `hashedKey` is a string hex hash of the host's key for verification purposes. Return `true` to continue with the handshake or `false` to reject and disconnect, or call `callback()` with `true` or `false` if you need to perform asynchronous verification. **Default:** (auto-accept if `hostVerifier` is not set)
372 |
373 | * **username** - _string_ - Username for authentication. **Default:** (none)
374 |
375 | * **password** - _string_ - Password for password-based user authentication. **Default:** (none)
376 |
377 | * **agent** - _string_ - Path to ssh-agent's UNIX socket for ssh-agent-based user authentication. **Windows users: set to 'pageant' for authenticating with Pageant or (actual) path to a cygwin "UNIX socket."** **Default:** (none)
378 |
379 | * **agentForward** - _(Promise)_ - Set to `true` to use OpenSSH agent forwarding (`auth-agent@openssh.com`) for the life of the connection. `agent` must also be set to use this feature. **Default:** `false`
380 |
381 | * **privateKey** - _mixed_ - _Buffer_ or _string_ that contains a private key for either key-based or hostbased user authentication (OpenSSH format). **Default:** (none)
382 |
383 | * **passphrase** - _string_ - For an encrypted private key, this is the passphrase used to decrypt it. **Default:** (none)
384 |
385 | * **localHostname** - _string_ - Along with **localUsername** and **privateKey**, set this to a non-empty string for hostbased user authentication. **Default:** (none)
386 |
387 | * **localUsername** - _string_ - Along with **localHostname** and **privateKey**, set this to a non-empty string for hostbased user authentication. **Default:** (none)
388 |
389 | * **tryKeyboard** - _(Promise)_ - Try keyboard-interactive user authentication if primary user authentication method fails. If you set this to `true`, you need to handle the `keyboard-interactive` event. **Default:** `false`
390 |
391 | * **keepaliveInterval** - _integer_ - How often (in milliseconds) to send SSH-level keepalive packets to the server (in a similar way as OpenSSH's ServerAliveInterval config option). Set to 0 to disable. **Default:** `0`
392 |
393 | * **keepaliveCountMax** - _integer_ - How many consecutive, unanswered SSH-level keepalive packets that can be sent to the server before disconnection (similar to OpenSSH's ServerAliveCountMax config option). **Default:** `3`
394 |
395 | * **readyTimeout** - _integer_ - How long (in milliseconds) to wait for the SSH handshake to complete. **Default:** `20000`
396 |
397 | * **sock** - _ReadableStream_ - A _ReadableStream_ to use for communicating with the server instead of creating and using a new TCP connection (useful for connection hopping).
398 |
399 | * **strictVendor** - _(Promise)_ - Performs a strict server vendor check before sending vendor-specific requests, etc. (e.g. check for OpenSSH server when using `openssh_noMoreSessions()`) **Default:** `true`
400 |
401 | * **algorithms** - _object_ - This option allows you to explicitly override the default transport layer algorithms used for the connection. The value for each category must either be an array of valid algorithm names to set an exact list (with the most preferable first) or an object containing `append`, `prepend`, and/or `remove` properties that each contain an _array_ of algorithm names or RegExps to match to adjust default lists for each category. Valid keys:
402 |
403 | * **cipher** - _mixed_ - Ciphers.
404 | * Default list (in order from most to least preferable):
405 | * `chacha20-poly1305@openssh.com` (priority of chacha20-poly1305 may vary depending upon CPU and/or optional binding availability)
406 | * `aes128-gcm`
407 | * `aes128-gcm@openssh.com`
408 | * `aes256-gcm`
409 | * `aes256-gcm@openssh.com`
410 | * `aes128-ctr`
411 | * `aes192-ctr`
412 | * `aes256-ctr`
413 | * Other supported names:
414 | * `3des-cbc`
415 | * `aes256-cbc`
416 | * `aes192-cbc`
417 | * `aes128-cbc`
418 | * `arcfour256`
419 | * `arcfour128`
420 | * `arcfour`
421 | * `blowfish-cbc`
422 | * `cast128-cbc`
423 |
424 | * **compress** - _mixed_ - Compression algorithms.
425 | * Default list (in order from most to least preferable):
426 | * `none`
427 | * `zlib@openssh.com`
428 | * `zlib`
429 | * Other supported names:
430 |
431 | * **hmac** - _mixed_ - (H)MAC algorithms.
432 | * Default list (in order from most to least preferable):
433 | * `hmac-sha2-256-etm@openssh.com`
434 | * `hmac-sha2-512-etm@openssh.com`
435 | * `hmac-sha1-etm@openssh.com`
436 | * `hmac-sha2-256`
437 | * `hmac-sha2-512`
438 | * `hmac-sha1`
439 | * Other supported names:
440 | * `hmac-md5`
441 | * `hmac-sha2-256-96`
442 | * `hmac-sha2-512-96`
443 | * `hmac-ripemd160`
444 | * `hmac-sha1-96`
445 | * `hmac-md5-96`
446 |
447 | * **kex** - _mixed_ - Key exchange algorithms.
448 | * Default list (in order from most to least preferable):
449 | * `curve25519-sha256` (node v14.0.0+)
450 | * `curve25519-sha256@libssh.org` (node v14.0.0+)
451 | * `ecdh-sha2-nistp256`
452 | * `ecdh-sha2-nistp384`
453 | * `ecdh-sha2-nistp521`
454 | * `diffie-hellman-group-exchange-sha256`
455 | * `diffie-hellman-group14-sha256`
456 | * `diffie-hellman-group15-sha512`
457 | * `diffie-hellman-group16-sha512`
458 | * `diffie-hellman-group17-sha512`
459 | * `diffie-hellman-group18-sha512`
460 | * Other supported names:
461 | * `diffie-hellman-group-exchange-sha1`
462 | * `diffie-hellman-group14-sha1`
463 | * `diffie-hellman-group1-sha1`
464 |
465 | * **serverHostKey** - _mixed_ - Server host key formats.
466 | * Default list (in order from most to least preferable):
467 | * `ssh-ed25519` (node v12.0.0+)
468 | * `ecdsa-sha2-nistp256`
469 | * `ecdsa-sha2-nistp384`
470 | * `ecdsa-sha2-nistp521`
471 | * `rsa-sha2-512`
472 | * `rsa-sha2-256`
473 | * `ssh-rsa`
474 | * Other supported names:
475 | * `ssh-dss`
476 |
477 | * **compress** - _mixed_ - Set to `true` to enable compression if server supports it, `'force'` to force compression (disconnecting if server does not support it), or `false` to explicitly opt out of compression all of the time. Note: this setting is overridden when explicitly setting a compression algorithm in the `algorithms` configuration option. **Default:** (only use compression if that is only what the server supports)
478 |
479 | * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information.
480 |
481 | * **identity** - to directly pass the path of private key file.
482 |
483 | * **reconnect** - to reconnect automatically, once disconnected. **Default:** `'true'`.
484 |
485 | * **reconnectTries** - Number of reconnect tries. **Default:** `'10'`.
486 |
487 | * **reconnectDelay** - Delay after which reconnect should be done. **Default:** `'5000'`.
488 |
489 | * **hoppingTool** - To hop connection using this tool. **Default:** `'nc'`. Supported Tools are `'nc'`, `'socat'`, `'native'`
490 |
491 | * **x11** - Connect to x11 server in different manner. **Default:** `'localhost:6000'`. Supported Options are {srcIP: 'localhost', srcPort: 6005} or custom unix socket for eg: '/tmp/.X11-unix/X0'
492 |
493 |
494 | * **connect**() - _(Promise)_ - Try to establish a connection. No need to explicitly call connect method. It get called automatically, while doing operation.
495 |
496 | * **exec**(< _string_ >cmd, < _array_ >params, < _objects_ >options) - _(Promise)_ - Execute a cmd, return a result. Options are passed directly to ssh2 exec command.
497 |
498 | * **spawn**(< _string_ >cmd, < _array_ >params, < _objects_ >options) - _(Promise)_ - Spawn a cmd, return a stream. Options are passed directly to ssh2 exec command.
499 |
500 | * **sftp**() - _(SFTP)_ - Get a new sftp session.
501 |
502 | * **subsys**(< _string_ >subsystem) - _(Promise)_ - Invoke a subsystem.
503 |
504 | * **x11**(< _string_ >cmd) - _(Promise)_ - Start a x11 forwarding, by invoking 'cmd' on remote server. It handles error scenario, such as if x11 command not installed on remote server, x11 forwarding not enabled on remote server, & x11 server not running locally, by rejecting it gracefully.
505 |
506 | * **shell**() - _(Promise)_ - Get a shell session.
507 |
508 | * **close**() - _(Promise)_ - Close the sshconnection and associated tunnels.
509 |
510 | * **addTunnel**(< _object_ >tunnelConfig) - _(Promise)_ - Establish a forward tunnel over ssh machine. TunnelConfig has following properties.
511 | * **name** - Unique name. **Default:** `'${remoteAddr}@${remotePort}'`
512 |
513 | * **remoteAddr** - Remote Address to connect.
514 |
515 | * **remotePort** - Remote Port to connect.
516 |
517 | * **localPort** - Local port to bind to. By default, it will bind to a random port, if not passed.
518 |
519 | * **getTunnel**(< _string_ >name) - Get a tunnel by name.
520 |
521 | * **closeTunnel**([< _string_ >name]) - _(Promise)_ - Close a tunnel, if name is passed. Otherwise, will close all the tunnels.
522 |
523 | * **getSocksPort**([< _number_ >localPort]) - _(Promise)_ - Start a socks server. And, return a socks port, for reverse tunneling purpose. localPort is optional. By default, it will bind to a random port, if not passed.
524 |
525 | ## SFTP
526 | It supports all the [sftp](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md) client operations, in promisify way. For detailed explanation of all the operation, please visit [sftp](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md). It has few extra methods `getStat`, `setStat`, `changeTimestamp`, `readFileData`, `writeFileData`, `changeMode`, `changeOwner`.
527 |
528 | #### Methods
529 | * **(constructor)**(< _object_ > ssh2) - Creates and returns a new SFTP instance, which can perform all sftp client operation such readdir, mkdir etc... in promisify way.
530 |
531 | * **fastGet**(< _string_ >remotePath, < _string_ >localPath[, < _object_ >options]) - _(Promise)_ - Downloads a file at `remotePath` to `localPath` using parallel reads for faster throughput. `options` can have the following properties:
532 |
533 | * **concurrency** - _integer_ - Number of concurrent reads **Default:** `64`
534 |
535 | * **chunkSize** - _integer_ - Size of each read in bytes **Default:** `32768`
536 |
537 | * **step** - _function_(< _integer_ >total_transferred, < _integer_ >chunk, < _integer_ >total) - Called every time a part of a file was transferred
538 |
539 | * **fastPut**(< _string_ >localPath, < _string_ >remotePath[, < _object_ >options]) - _(Promise)_ - Uploads a file from `localPath` to `remotePath` using parallel reads for faster throughput. `options` can have the following properties:
540 |
541 | * **concurrency** - _integer_ - Number of concurrent reads **Default:** `64`
542 |
543 | * **chunkSize** - _integer_ - Size of each read in bytes **Default:** `32768`
544 |
545 | * **step** - _function_(< _integer_ >total_transferred, < _integer_ >chunk, < _integer_ >total) - Called every time a part of a file was transferred
546 |
547 | * **mode** - _mixed_ - Integer or string representing the file mode to set for the uploaded file.
548 |
549 | * **createReadStream**(< _string_ >path[, < _object_ >options]) - _(Promise)_ - if resolved successfully, returns a new readable stream for `path`. `options` has the following defaults:
550 |
551 | ```javascript
552 | { flags: 'r',
553 | encoding: null,
554 | handle: null,
555 | mode: 0o666,
556 | autoClose: true
557 | }
558 | ```
559 |
560 | `options` can include `start` and `end` values to read a range of bytes from the file instead of the entire file. Both `start` and `end` are inclusive and start at 0. The `encoding` can be `'utf8'`, `'ascii'`, or `'base64'`.
561 |
562 | If `autoClose` is false, then the file handle won't be closed, even if there's an error. It is your responsiblity to close it and make sure there's no file handle leak. If `autoClose` is set to true (default behavior), on `error` or `end` the file handle will be closed automatically.
563 |
564 | An example to read the last 10 bytes of a file which is 100 bytes long:
565 |
566 | ```javascript
567 | sftp.createReadStream('sample.txt', {start: 90, end: 99});
568 | ```
569 |
570 | * **createWriteStream**(< _string_ >path[, < _object_ >options]) - _(Promise)_ - if resolved successfully, returns a new writable stream for `path`. `options` has the following defaults:
571 |
572 | ```javascript
573 | {
574 | flags: 'w',
575 | encoding: null,
576 | mode: 0o666,
577 | autoClose: true
578 | }
579 | ```
580 |
581 | `options` may also include a `start` option to allow writing data at some position past the beginning of the file. Modifying a file rather than replacing it may require a flags mode of 'r+' rather than the default mode 'w'.
582 |
583 | If 'autoClose' is set to false and you pipe to this stream, this stream will not automatically close after there is no more data upstream -- allowing future pipes and/or manual writes.
584 |
585 | * **open**(< _string_ >filename, < _string_ >flags, [< _mixed_ >attrs_mode]) - _(Promise)_ - Opens a file `filename` with `flags` with optional _ATTRS_ object or file mode `attrs_mode`. `flags` is any of the flags supported by `fs.open` (except sync flag). If promise resolved successfully, then return < _Buffer_ >handle, otherwise < _Error_ >err.
586 |
587 | * **close**(< _Buffer_ >handle) - _(Promise)_ - Closes the resource associated with `handle` given by open() or opendir(). If promise is rejected, then return < _Error_ >err.
588 |
589 | * **readFile**(< _string_ >path, [< _string_|_object_ >encoding]) - _(Promise)_ - Reads file content at given `path`. Default `encoding` is `null`. If promise resolved successfully, then (if encoding is defined, then return < _string_ >content otherwise return < _buffer_ >content), otherwise < _Error_ >err.
590 |
591 | * **writeFile**(< _string_ >path, < _string_ >data, [< _object_ >options]) - _(Promise)_ - Writes `data` at given `path`. `options` can have two properties `encoding` and `flag`, Default encoding is `utf8`, and flag is `w`. If promise is rejected, then return < _Error_ >err.
592 |
593 | * **readFileData**(< _string_ >filename, < _Buffer_ >buffer, < _integer_ >offset, < _integer_ >length, < _integer_ >position) - _(Promise)_ - Reads `length` bytes from the resource associated with `file` starting at `position` and stores the bytes in `buffer` starting at `offset`. If promise resolved successfully, then return Array [< _integer_ >bytesRead, < _Buffer_ >buffer (offset adjusted), < _integer_ >position], otherwise < _Error_ >err.
594 |
595 | * **writeFileData**(< _string_ >filename, < _integer_ >offset, < _integer_ >length, < _integer_ >position) - _(Promise)_ - Writes `length` bytes from `buffer` starting at `offset` to the resource associated with `file` starting at `position`. If promise is rejected, then return < _Error_ >err.
596 |
597 | * **getStat**(< _string_ >filename) - _(Promise)_ - Retrieves attributes for the resource associated with `file`. If promise resolved successfully, then return < _Stats_ >stats, otherwise < _Error_ >err.
598 |
599 | * **setStat**(< _string_ >filename, < _ATTRS_ >attributes) - _(Promise)_ - Sets the attributes defined in `attributes` for the resource associated with `file`. If promise is rejected, then return < _Error_ >err.
600 |
601 | * **changeTimestamp**(< _string_ >filename, < _mixed_ >atime, < _mixed_ >mtime) - _(Promise)_ - Sets the access time and modified time for the resource associated with `file`. `atime` and `mtime` can be Date instances or UNIX timestamps. If promise is rejected, then return < _Error_ >err.
602 |
603 | * **changeOwner**(< _string_ >filename, < _integer_ >uid, < _integer_ >gid) - _(Promise)_ - Sets the owner for the resource associated with `file`. If promise is rejected, then return < _Error_ >err.
604 |
605 | * **changeMode**(< _string_ >filename, < _mixed_ >mode) - _(Promise)_ - Sets the mode for the resource associated with `file`. `mode` can be an integer or a string containing an octal number. If promise is rejected, then return < _Error_ >err.
606 |
607 | * **opendir**(< _string_ >path) - _(Promise)_ - Opens a directory `path`. If promise resolved successfully, then return < _Buffer_ >handle, otherwise < _Error_ >err.
608 |
609 | * **readdir**(< _mixed_ >location) - _(Promise)_ - Retrieves a directory listing. `location` can either be a _Buffer_ containing a valid directory handle from opendir() or a _string_ containing the path to a directory. If promise resolved successfully, then return < _mixed_ >list, otherwise < _Error_ >err. `list` is an _Array_ of `{ filename: 'foo', longname: '....', attrs: {...} }` style objects (attrs is of type _ATTR_). If `location` is a directory handle, this function may need to be called multiple times until `list` is boolean false, which indicates that no more directory entries are available for that directory handle.
610 |
611 | * **unlink**(< _string_ >path) - _(Promise)_ - Removes the file/symlink at `path`. If promise is rejected, then return < _Error_ >err.
612 |
613 | * **rename**(< _string_ >srcPath, < _string_ >destPath) - _(Promise)_ - Renames/moves `srcPath` to `destPath`. If promise is rejected, then return < _Error_ >err.
614 |
615 | * **mkdir**(< _string_ >path, [< _ATTRS_ >attributes, ]) - _(Promise)_ - Creates a new directory `path`. If promise is rejected, then return < _Error_ >err.
616 |
617 | * **rmdir**(< _string_ >path) - _(Promise)_ - Removes the directory at `path`. If promise is rejected, then return < _Error_ >err.
618 |
619 | * **stat**(< _string_ >path) - _(Promise)_ - Retrieves attributes for `path`. If promise resolved successfully, then return < _Stats_ >stats, otherwise < _Error_ >err.
620 |
621 | * **lstat**(< _string_ >path) - _(Promise)_ - Retrieves attributes for `path`. If `path` is a symlink, the link itself is stat'ed instead of the resource it refers to. If promise resolved successfully, then return < _Stats_ >stats, otherwise < _Error_ >err.
622 |
623 | * **setstat**(< _string_ >path, < _ATTRS_ >attributes) - _(Promise)_ - Sets the attributes defined in `attributes` for `path`. If promise is rejected, then return < _Error_ >err.
624 |
625 | * **utimes**(< _string_ >path, < _mixed_ >atime, < _mixed_ >mtime) - _(Promise)_ - Sets the access time and modified time for `path`. `atime` and `mtime` can be Date instances or UNIX timestamps. If promise is rejected, then return < _Error_ >err.
626 |
627 | * **chown**(< _string_ >path, < _integer_ >uid, < _integer_ >gid) - _(Promise)_ - Sets the owner for `path`. If promise is rejected, then return < _Error_ >err.
628 |
629 | * **chmod**(< _string_ >path, < _mixed_ >mode) - _(Promise)_ - Sets the mode for `path`. `mode` can be an integer or a string containing an octal number. If promise is rejected, then return < _Error_ >err.
630 |
631 | * **readlink**(< _string_ >path) - _(Promise)_ - Retrieves the target for a symlink at `path`. If promise resolved successfully, then return < _string_ >target, otherwise < _Error_ >err.
632 |
633 | * **symlink**(< _string_ >targetPath, < _string_ >linkPath) - _(Promise)_ - Creates a symlink at `linkPath` to `targetPath`. If promise is rejected, then return < _Error_ >err.
634 |
635 | * **realpath**(< _string_ >path) - _(Promise)_ - Resolves `path` to an absolute path. If promise resolved successfully, then return < _string_ >absPath, otherwise < _Error_ >err.
636 |
637 | * **ext_openssh_rename**(< _string_ >srcPath, < _string_ >destPath) - _(Promise)_ - **OpenSSH extension** Performs POSIX rename(3) from `srcPath` to `destPath`. If promise is rejected, then return < _Error_ >err.
638 |
639 | * **ext_openssh_statvfs**(< _string_ >path) - _(Promise)_ - **OpenSSH extension** Performs POSIX statvfs(2) on `path`. If promise resolved successfully, then return < _object_ >fsInfo, otherwise < _Error_ >err. `fsInfo` contains the information as found in the [statvfs struct](http://linux.die.net/man/2/statvfs).
640 |
641 | * **ext_openssh_fstatvfs**(< _Buffer_ >handle) - _(Promise)_ - **OpenSSH extension** Performs POSIX fstatvfs(2) on open handle `handle`. If promise resolved successfully, then return < _object_ >fsInfo, otherwise < _Error_ >err. `fsInfo` contains the information as found in the [statvfs struct](http://linux.die.net/man/2/statvfs).
642 |
643 | * **ext_openssh_hardlink**(< _string_ >targetPath, < _string_ >linkPath) - _(Promise)_ - **OpenSSH extension** Performs POSIX link(2) to create a hard link to `targetPath` at `linkPath`. If promise is rejected, then return < _Error_ >err.
644 |
645 | * **ext_openssh_fsync**(< _Buffer_ >handle) - _(Promise)_ - **OpenSSH extension** Performs POSIX fsync(3) on the open handle `handle`. If promise is rejected, then return < _Error_ >err.
646 |
647 | #### ATTRS
648 |
649 | An object with the following valid properties:
650 |
651 | * **mode** - _integer_ - Mode/permissions for the resource.
652 |
653 | * **uid** - _integer_ - User ID of the resource.
654 |
655 | * **gid** - _integer_ - Group ID of the resource.
656 |
657 | * **size** - _integer_ - Resource size in bytes.
658 |
659 | * **atime** - _integer_ - UNIX timestamp of the access time of the resource.
660 |
661 | * **mtime** - _integer_ - UNIX timestamp of the modified time of the resource.
662 |
663 | When supplying an ATTRS object to one of the SFTP methods:
664 |
665 | * `atime` and `mtime` can be either a Date instance or a UNIX timestamp.
666 |
667 | * `mode` can either be an integer or a string containing an octal number.
668 |
669 |
670 | #### Stats
671 |
672 | An object with the same attributes as an ATTRS object with the addition of the following methods:
673 |
674 | * `stats.isDirectory()`
675 |
676 | * `stats.isFile()`
677 |
678 | * `stats.isBlockDevice()`
679 |
680 | * `stats.isCharacterDevice()`
681 |
682 | * `stats.isSymbolicLink()`
683 |
684 | * `stats.isFIFO()`
685 |
686 | * `stats.isSocket()`
687 |
688 |
689 | # LICENSE
690 |
691 | MIT
692 |
693 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ssh2-promise",
3 | "version": "1.0.3",
4 | "description": "Promise wrapper around SSH2 library",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "licenses": [
8 | {
9 | "type": "MIT",
10 | "url": "https://www.opensource.org/licenses/mit-license.php"
11 | }
12 | ],
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/sanketbajoria/ssh2-promise"
16 | },
17 | "scripts": {
18 | "build": "tsc",
19 | "test": "ts-node node_modules/jasmine/bin/jasmine spec/*-spec.*",
20 | "prepare": "npm run build"
21 | },
22 | "keywords": [
23 | "ssh2",
24 | "ssh2 typescript",
25 | "ssh2-promise",
26 | "ssh-promise",
27 | "sftp-promise",
28 | "shell-promise",
29 | "ssh promise",
30 | "ssh tunnel",
31 | "tunnel manager",
32 | "ssh async await",
33 | "tunnel async await",
34 | "cache ssh",
35 | "retry ssh",
36 | "sftp promise",
37 | "sftp async await",
38 | "ssh2 typescript promise",
39 | "tunnel typescript",
40 | "typescript ssh2 async await"
41 | ],
42 | "author": "Sanket Bajoria",
43 | "license": "MIT",
44 | "dependencies": {
45 | "@heroku/socksv5": "^0.0.9",
46 | "ssh2": "^1.10.0"
47 | },
48 | "devDependencies": {
49 | "@types/jasmine": "^2.8.9",
50 | "@types/node": "^16.7.1",
51 | "@types/ssh2": "0.5.52",
52 | "@types/ssh2-streams": "0.1.9",
53 | "gulp": "^3.9.1",
54 | "gulp-typescript": "^3.2.3",
55 | "jasmine": "^2.8.0",
56 | "mock-stdin": "^0.3.1",
57 | "ts-node": "^10.0.0",
58 | "typescript": "^4.3.5"
59 | },
60 | "resolutions": {
61 | "mixin-deep": "^1.3.2",
62 | "set-value": "^4.0.1",
63 | "lodash": "^4.17.21",
64 | "lodash.template": "^4.5.0",
65 | "lodash.merge": "^4.6.2",
66 | "minimist": "^1.2.6",
67 | "kind-of": "^6.0.3",
68 | "minimatch": "^3.0.4",
69 | "glob-parent": "^5.1.2",
70 | "braces": "^2.3.1",
71 | "ini": "^1.3.6"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/pretest/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "2.4"
2 | services:
3 | ssh-with-password:
4 | image: sanketb/alpine-ssh
5 | ports:
6 | - "8331:22"
7 | ssh-with-key:
8 | image: sanketb/alpine-ssh
9 | ports:
10 | - "8332:22"
--------------------------------------------------------------------------------
/pretest/ssh/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:3.9
2 |
3 | ADD docker-entrypoint.sh /usr/local/bin
4 |
5 | RUN sed -i 's/https\:\/\//http\:\/\//g' /etc/apk/repositories \
6 | && apk update \
7 | && apk add --update openssh sudo openssh-server-pam socat \
8 | && sed -ri 's/#UsePAM no/UsePAM yes/g' /etc/ssh/sshd_config \
9 | && sed -ri 's/^#?PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config \
10 | && sed -ri 's/^#?AllowTcpForwarding\s+.*/AllowTcpForwarding yes/' /etc/ssh/sshd_config \
11 | && echo root:root | chpasswd \
12 | && adduser -D sanket \
13 | && echo sanket:sanket | chpasswd \
14 | && mkdir /home/sanket/.ssh \
15 | && echo "sanket ALL=(ALL) ALL" >> /etc/sudoers \
16 | && rm -rf /tmp/* /var/cache/apk/* \
17 | && rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key \
18 | && chmod +x /usr/local/bin/docker-entrypoint.sh
19 |
20 | ADD authorized_keys /home/sanket/.ssh
21 |
22 | EXPOSE 22
23 | ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
24 | CMD ["/usr/sbin/sshd","-D"]
--------------------------------------------------------------------------------
/pretest/ssh/authorized_keys:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAiAlAW5uEkCZBfWeeCI/o+LBYYP4Gd/zs2bG3y6Hvnkvr277QXVPW/LGKv7F4tbLhhq0nzseCfMdRV4bwnH4Cx6l3i/Rh2abSeDa9gcmcq19RGFGNCnXZB6PaBUX/aM6Q85ZR47/MHFQHN/4jT7t3zGv3/iCrJbWWVMd/zMiRAf39cVpq5XVzizkUqMNJKRIIL/cVn08+dEFCCnWi3MisSYkmtIxbrPQ7Z9tBGA3LyZ0tUoy302WOTIaWcF4CLYlUdQ68JEdkd5jbUfWLCnwrqzGeiLcmtvg9Z8lgayxufBJTz9/v2sGbtLPOr40qeU0SblLvpqgv/IgtMNEsq804Yw== rsa-key-20190803
--------------------------------------------------------------------------------
/pretest/ssh/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ ! -f "/etc/ssh/ssh_host_rsa_key" ]; then
4 | # generate fresh rsa key
5 | ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
6 | fi
7 | if [ ! -f "/etc/ssh/ssh_host_dsa_key" ]; then
8 | # generate fresh dsa key
9 | ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa
10 | fi
11 |
12 | #prepare run dir
13 | if [ ! -d "/var/run/sshd" ]; then
14 | mkdir -p /var/run/sshd
15 | fi
16 |
17 | echo "$@"
18 | exec "$@"
--------------------------------------------------------------------------------
/spec/connect-hopping-spec.js:
--------------------------------------------------------------------------------
1 | var SSHTunnel = require("../lib/index");
2 | var SSHConstants = require("../lib/index").Constants;
3 |
4 |
5 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
6 | Promise.prototype.finally = function (cb) {
7 | const res = () => this;
8 | const fin = () => Promise.resolve(cb()).then(res);
9 | return this.then(fin, fin);
10 | };
11 | var fs = require("fs");
12 | var sshConfigs = require('./fixture')//JSON.parse(fs.readFileSync("./spec/fixture.json"));
13 | var util = require('util');
14 |
15 |
16 | describe("connect to dummy server via hopping", function () {
17 | it("should connect to server with hopping with default nc", function (done) {
18 | var sshTunnel = new SSHTunnel(sshConfigs.multiple);
19 | return sshTunnel.connect().then((ssh) => {
20 | expect(ssh).toBeDefined();
21 | }, (error) => {
22 | expect('1').toBe('2');
23 | expect(error).toBeUndefined();
24 | }).finally(() => {
25 | sshTunnel.close();
26 | console.log("closed one")
27 | done();
28 | });
29 | });
30 |
31 | it("should connect to server with hopping with nc", function (done) {
32 | let m = sshConfigs.multiple.slice()
33 | m[0] = Object.assign({hoppingTool:SSHConstants.HOPPINGTOOL.NETCAT}, m[0])
34 | var sshTunnel = new SSHTunnel(m, true);
35 | return sshTunnel.connect().then((ssh) => {
36 | expect(ssh).toBeDefined();
37 | }, (error) => {
38 | expect('1').toBe('2');
39 | expect(error).toBeUndefined();
40 | }).finally(() => {
41 | sshTunnel.close();
42 | console.log("closed one")
43 | done();
44 | });
45 | });
46 |
47 | it("should connect to server with hopping with socat", function (done) {
48 | let m = sshConfigs.multiple.slice()
49 | m[0] = Object.assign({hoppingTool:SSHConstants.HOPPINGTOOL.SOCAT}, m[0])
50 | var sshTunnel = new SSHTunnel(m, true);
51 | return sshTunnel.connect().then((ssh) => {
52 | expect(ssh).toBeDefined();
53 | }, (error) => {
54 | expect('1').toBe('2');
55 | expect(error).toBeUndefined();
56 | }).finally(() => {
57 | sshTunnel.close();
58 | console.log("closed one")
59 | done();
60 | });
61 | });
62 | it("should connect to server with hopping with native", function (done) {
63 | let m = sshConfigs.multiple.slice()
64 | m[0] = Object.assign({hoppingTool:SSHConstants.HOPPINGTOOL.NATIVE}, m[0])
65 | var sshTunnel = new SSHTunnel(m, true);
66 | return sshTunnel.connect().then((ssh) => {
67 | expect(ssh).toBeDefined();
68 | }, (error) => {
69 | expect('1').toBe('2');
70 | expect(error).toBeUndefined();
71 | }).finally(() => {
72 | sshTunnel.close();
73 | console.log("closed one")
74 | done();
75 | });
76 | });
77 | });
--------------------------------------------------------------------------------
/spec/connect-spec.js:
--------------------------------------------------------------------------------
1 | var SSHTunnel = require("../lib/index");
2 | var SSHConstants = require("../lib/index").Constants;
3 |
4 |
5 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
6 | Promise.prototype.finally = function (cb) {
7 | const res = () => this;
8 | const fin = () => Promise.resolve(cb()).then(res);
9 | return this.then(fin, fin);
10 | };
11 | var fs = require("fs");
12 | var sshConfigs = require('./fixture')//JSON.parse(fs.readFileSync("./spec/fixture.json"));
13 | var util = require('util');
14 |
15 |
16 | describe("connect to dummy server", function () {
17 | it("should connect directly to server with password", function (done) {
18 | var sshTunnel = new SSHTunnel(sshConfigs.singleWithPassword);
19 | sshTunnel.connect().then((ssh) => {
20 | expect(ssh).toBeDefined();
21 | }, (error) => {
22 | expect('1').toBe('2');
23 | expect(error).toBeUndefined();
24 | }).finally(() => {
25 | sshTunnel.close();
26 | done();
27 | });
28 | });
29 |
30 | it("should connect directly to server with key", function (done) {
31 | var sshTunnel = new SSHTunnel(sshConfigs.singleWithKey);
32 | sshTunnel.connect().then((ssh) => {
33 | expect(ssh).toBeDefined();
34 | }, (error) => {
35 | expect('1').toBe('2');
36 | expect(error).toBeUndefined();
37 | }).finally(() => {
38 | sshTunnel.close();
39 | done();
40 | });
41 | });
42 |
43 | it("should not connect directly to server, with no password/pem", function (done) {
44 | var c = Object.assign({}, sshConfigs.singleWithPassword);
45 | delete c.password;
46 | var sshTunnel = new SSHTunnel(c);
47 | sshTunnel.connect().then((ssh) => {
48 | expect('1').toBe('2');
49 | expect(ssh).toBeUndefined();
50 | }, (error) => {
51 | expect(error).toBeDefined();
52 | }).finally(() => {
53 | sshTunnel.close();
54 | done();
55 | });
56 | });
57 |
58 | it("should not connect directly to server, with wrong password", function (done) {
59 | var c = Object.assign({}, sshConfigs.singleWithPassword);
60 | c.password = "asfafwerwrwsdfsfd";
61 | var sshTunnel = new SSHTunnel(c);
62 | sshTunnel.connect().then((ssh) => {
63 | expect(ssh).toBeUndefined();
64 | }, (error) => {
65 | expect(error).toBeDefined();
66 | }).finally(() => {
67 | sshTunnel.close();
68 | done();
69 | });
70 | });
71 |
72 | it("should connect with password prompt directly to server", function (done) {
73 | var c = Object.assign({}, sshConfigs.singleWithPassword);
74 | var temp = c.password;
75 | delete c.password;
76 | c.tryKeyboard = true;
77 | var sshTunnel = new SSHTunnel(c);
78 | var stdin = require('mock-stdin').stdin();
79 |
80 | function hook_stdout() {
81 | var old_write = process.stdout.write;
82 | process.stdout.write = (function (write) {
83 | return function (string, encoding, fd) {
84 | write.apply(process.stdout, arguments);
85 | if (string.toString().toLowerCase().indexOf("password") >= 0) {
86 | setTimeout(function () {
87 | stdin.send(temp + "\n", "ascii");
88 | }, 1000);
89 | }
90 | }
91 | })(process.stdout.write)
92 | return function () {
93 | process.stdout.write = old_write;
94 | }
95 | }
96 |
97 | var unhook = hook_stdout()
98 |
99 |
100 | sshTunnel.connect().then((ssh) => {
101 | expect(ssh).toBeDefined();
102 | }, (error) => {
103 | expect('1').toBe('2');
104 | expect(error).toBeUndefined();
105 | }).finally(() => {
106 | sshTunnel.close();
107 | unhook();
108 | stdin.end();
109 | done();
110 | });
111 | });
112 |
113 | it("should connect to server with hopping", function (done) {
114 | var sshTunnel1 = new SSHTunnel(sshConfigs.multiple[0])
115 | var sshTunnel = new SSHTunnel(sshConfigs.multiple);
116 | sshTunnel1.connect().then(() => {
117 | return sshTunnel.connect().then((ssh) => {
118 | expect(ssh).toBeDefined();
119 | }, (error) => {
120 | expect('1').toBe('2');
121 | expect(error).toBeUndefined();
122 | }).finally(() => {
123 | sshTunnel.close();
124 | console.log("closed one")
125 | done();
126 | });
127 | }).finally(() => {
128 | sshTunnel1.close();
129 | done()
130 | })
131 | });
132 |
133 | it("should check the cache and listeners attached to server, after connect and after disconnect", function (done) {
134 | var sshTunnel = new SSHTunnel(sshConfigs.multiple);
135 | sshTunnel.connect().then((ssh) => {
136 | expect(ssh).toBeDefined();
137 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
138 | Object.keys(SSHTunnel.__cache).forEach((k) => {
139 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(1);
140 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(1);
141 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(1);
142 | });
143 | }, (error) => {
144 | expect(error).toBeUndefined();
145 | }).finally(() => {
146 | sshTunnel.close().then(() => {
147 | Object.keys(SSHTunnel.__cache).forEach((k) => {
148 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(0);
149 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(0);
150 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(0);
151 | });
152 | done();
153 | });
154 |
155 | });
156 | });
157 |
158 |
159 | it("should check the cache and listeners attached to server, with multiple tunnels, after connect and after disconnect", function (done) {
160 | var sshTunnel = new SSHTunnel(sshConfigs.multiple);
161 | var sshTunnel2 = new SSHTunnel(sshConfigs.multiple)
162 | sshTunnel.connect().then((ssh) => {
163 | expect(ssh).toBeDefined();
164 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
165 | Object.keys(SSHTunnel.__cache).forEach((k) => {
166 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(1);
167 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(1);
168 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(1);
169 | });
170 | return sshTunnel2.connect();
171 | }, (error) => {
172 | expect(error).toBeUndefined();
173 | }).then((ssh) => {
174 | expect(ssh).toBeDefined();
175 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
176 | Object.keys(SSHTunnel.__cache).forEach((k) => {
177 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(2);
178 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(2);
179 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(2);
180 | });
181 | return sshTunnel.close();
182 | }, (error) => {
183 | expect(error).toBeUndefined();
184 | }).then(() => {
185 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
186 | Object.keys(SSHTunnel.__cache).forEach((k) => {
187 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(1);
188 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(1);
189 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(1);
190 | });
191 | return sshTunnel2.close();
192 | }).finally(() => {
193 | expect(Object.keys(SSHTunnel.__cache).length).toBe(0);
194 | Object.keys(SSHTunnel.__cache).forEach((k) => {
195 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(0);
196 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(0);
197 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(0);
198 | });
199 | done();
200 | });
201 | });
202 |
203 | it("should check the cache and listeners attached to server, with multiple tunnels, after connect and after disconnect", function (done) {
204 |
205 | var sshTunnel = new SSHTunnel(sshConfigs.couchmultiple);
206 | var sshTunnel2 = new SSHTunnel(sshConfigs.couchmultiple)
207 | sshTunnel.connect().then((ssh) => {
208 | expect(ssh).toBeDefined();
209 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
210 | Object.keys(SSHTunnel.__cache).forEach((k) => {
211 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(1);
212 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(1);
213 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(1);
214 | });
215 | return sshTunnel2.connect();
216 | }, (error) => {
217 | expect(error).toBeUndefined();
218 | }).then((ssh) => {
219 | expect(ssh).toBeDefined();
220 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
221 | Object.keys(SSHTunnel.__cache).forEach((k) => {
222 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(2);
223 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(2);
224 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(2);
225 | });
226 | return sshTunnel.close();
227 | }, (error) => {
228 | expect(error).toBeUndefined();
229 | }).then(() => {
230 | expect(Object.keys(SSHTunnel.__cache).length).toBe(2);
231 | Object.keys(SSHTunnel.__cache).forEach((k) => {
232 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(1);
233 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(1);
234 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(1);
235 | });
236 | return sshTunnel2.close();
237 | }).finally(() => {
238 | expect(Object.keys(SSHTunnel.__cache).length).toBe(0);
239 | Object.keys(SSHTunnel.__cache).forEach((k) => {
240 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.SSH)).toBe(0);
241 | expect(SSHTunnel.__cache[k].listenerCount(SSHConstants.CHANNEL.TUNNEL)).toBe(0);
242 | expect(SSHTunnel.__cache[k].listenerCount(`${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`)).toBe(0);
243 | });
244 | done();
245 | });
246 | });
247 |
248 | it("should check the cache and listeners attached to server, with multiple tunnels, after connect and after disconnect", function (done) {
249 |
250 | var sshTunnel = new SSHTunnel(sshConfigs.couchmultiple);
251 | sshTunnel.on("ssh:beforeconnect", (sshConnection, payload) => {
252 | console.log("adsf");
253 | })
254 | sshTunnel.connect().then((ssh) => {
255 |
256 | }).finally(() => {
257 | console.log("finish")
258 | done();
259 | })
260 | });
261 | });
--------------------------------------------------------------------------------
/spec/connect-ts-spec.ts:
--------------------------------------------------------------------------------
1 | import SSHTunnel from '../lib/index'
2 | import SFTP from "../lib/sftp"
3 |
4 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
5 | /* Promise.prototype["finally"] = function (cb) {
6 | const res = () => this;
7 | const fin = () => Promise.resolve(cb()).then(res);
8 | return this.then(fin, fin);
9 | }; */
10 | var fs = require("fs");
11 | var sshConfigs = require('./fixture')//JSON.parse(fs.readFileSync("./spec/fixture.json"));
12 | var util = require('util');
13 |
14 | describe("connect to dummy server", function () {
15 | it("should connect directly to server with password", function (done) {
16 | var sshTunnel = new SSHTunnel(sshConfigs.singleWithPassword);
17 |
18 | sshTunnel.connect().then((ssh: any) => {
19 | expect(ssh).toBeDefined();
20 | sshTunnel.close();
21 | done();
22 | }, (error: any) => {
23 | expect('1').toBe('2');
24 | expect(error).toBeUndefined();
25 | sshTunnel.close();
26 | done();
27 | });
28 | });
29 |
30 | it("read stream", async function (done) {
31 | var sshTunnel = new SSHTunnel(sshConfigs.singleWithKey);
32 | let sftp: SFTP = sshTunnel.sftp()
33 | fs.writeFileSync('./test.txt', "Test module");
34 | try{
35 | await sftp.fastPut('./test.txt', "/home/sanket/test2.txt");
36 | expect(1).toBe(1);
37 | let stream = await sftp.createReadStream("/home/sanket/test2.txt")
38 | expect(stream).toBeDefined();
39 | var buffer = "";
40 | stream.on('data', (data:any) => {
41 | buffer += data.toString();
42 | });
43 | stream.on('error', (err:any) => {
44 | console.log(err);
45 | });
46 | stream.on('close', () => {
47 | console.log("done - " + buffer);
48 | done();
49 | })
50 | }catch(error){
51 | expect('1').toBe('2');
52 | expect(error).toBeUndefined();
53 | done();
54 | }finally{
55 | fs.unlinkSync('./test.txt')
56 | }
57 | });
58 | });
--------------------------------------------------------------------------------
/spec/exec-spec.js:
--------------------------------------------------------------------------------
1 | var SSHTunnel = require("../lib/index");
2 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000;
3 | Promise.prototype.finally = function (cb) {
4 | const res = () => this;
5 | const fin = () => Promise.resolve(cb()).then(res);
6 | return this.then(fin, fin);
7 | };
8 | var fs = require("fs");
9 | var sshConfigs = require('./fixture')//JSON.parse(fs.readFileSync("./spec/fixture.json"));
10 |
11 | describe("exec n spawn cmd", function () {
12 | var sshTunnel;
13 | beforeAll(() => {
14 | sshTunnel = new SSHTunnel(sshConfigs.singleWithKey);
15 | })
16 |
17 | it("exec a command", function (done) {
18 | sshTunnel.exec("whoami").then((username) => {
19 | expect(username.trim()).toEqual("sanket");
20 | }, (error) => {
21 | expect(error).toBeUndefined();
22 | }).finally(() => {
23 | done();
24 | });
25 | });
26 |
27 | it("open sftp session", function (done) {
28 | sshTunnel.rawSFTP().then((sftp) => {
29 | expect(sftp).toBeDefined();
30 | expect(sftp.readdir).toBeDefined();
31 | }, (error) => {
32 | expect(error).toBeUndefined();
33 | }).finally(() => {
34 | done();
35 | });
36 | });
37 |
38 | it("open shell session", function (done) {
39 | sshTunnel.shell().then((socket) => {
40 | expect(socket).toBeDefined();
41 | }, (error) => {
42 | expect(error).toBeUndefined();
43 | }).finally(() => {
44 | done();
45 | });
46 | });
47 |
48 | it("open socks server", function (done) {
49 | sshTunnel.getSocksPort().then((port) => {
50 | expect(port).toBeDefined();
51 | }, (error) => {
52 | expect(error).toBeUndefined();
53 | }).finally(() => {
54 | done();
55 | });
56 | });
57 |
58 | it("open forward tunnel connection", function (done) {
59 | sshTunnel.addTunnel({ remoteAddr: "www.google.com", remotePort: "443" }).then((tunnel) => {
60 | expect(tunnel.localPort).toBeDefined();
61 | }, (error) => {
62 | expect(error).toBeUndefined();
63 | }).finally(() => {
64 | done();
65 | });
66 | });
67 |
68 | it("x11 should not get established", function (done) {
69 | sshTunnel.x11("xeyes").then((data) => {
70 | expect('1').toBe('2');
71 | done()
72 | }, (err) => {
73 | expect(err).toBeDefined();
74 | done();
75 | }).finally(() => {
76 | done();
77 | });
78 | });
79 |
80 | it("subsys should be established", function (done) {
81 | sshTunnel.subsys('sftp').then((stream) => {
82 | expect(stream).toBeDefined();
83 | expect(stream.pipe).toBeDefined();
84 | }, (err) => {
85 | expect('1').toBe('2');
86 | }).finally(() => {
87 | done()
88 | });
89 | });
90 |
91 | it("subsys should throw error", function (done) {
92 | sshTunnel.subsys('dummy').then((stream) => {
93 | expect('1').toBe('2');
94 | }, (err) => {
95 | expect(err).toBeDefined();
96 | }).finally(() => {
97 | done()
98 | });
99 | });
100 |
101 | it("exec a command with error", function (done) {
102 | sshTunnel.exec("mkdir abc && mkdir abc").then(() => {
103 | expect('1').toBe('2');
104 | }, (error) => {
105 | expect(error).toBeDefined();
106 | expect(error).toBe("mkdir: can't create directory 'abc': File exists\n")
107 | }).finally(() => {
108 | done();
109 | });
110 | });
111 |
112 | afterAll(() => {
113 | sshTunnel.close()
114 | })
115 |
116 |
117 | });
--------------------------------------------------------------------------------
/spec/fixture.js:
--------------------------------------------------------------------------------
1 | var base = __dirname;
2 | module.exports = {
3 | "multiple": [{
4 | "username": "sanket",
5 | "host": "localhost",
6 | "password": "sanket",
7 | "port": 8331
8 | }, {
9 | "username": "sanket",
10 | "host": "ssh-with-key",
11 | "identity": base + "/test.pem"
12 | }],
13 | "couchmultiple": [{
14 | "username": "sanket",
15 | "host": "localhost",
16 | "password": "sanket",
17 | "port": 8331
18 | }, {
19 | "username": "sanket",
20 | "host": "ssh-with-key",
21 | "identity": base + "/test.pem"
22 | }],
23 | "singleWithPassword": {
24 | "username": "sanket",
25 | "host": "localhost",
26 | "password": "sanket",
27 | "port": 8331
28 | },
29 | "singleWithKey": {
30 | "username": "sanket",
31 | "host": "localhost",
32 | "port": 8332,
33 | "reconnect": false,
34 | "identity": base + "/test.pem"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/spec/sftp-spec.js:
--------------------------------------------------------------------------------
1 | var SSHTunnel = require("../lib/index");
2 | var fs = require('fs')
3 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
4 | Promise.prototype.finally = function (cb) {
5 | const res = () => this;
6 | const fin = () => Promise.resolve(cb()).then(res);
7 | return this.then(fin, fin);
8 | };
9 | var fs = require("fs");
10 | var sshConfigs = require('./fixture'); //var sshConfigs = JSON.parse(fs.readFileSync("./spec/fixture.json"));
11 | const { Z_STREAM_END } = require("zlib");
12 |
13 |
14 | describe("sftp cmd", function () {
15 | var sshTunnel;
16 | let path = "/home/sanket/sftp"
17 | beforeAll(() => {
18 | sshTunnel = new SSHTunnel(sshConfigs.singleWithKey);
19 | sftp = sshTunnel.sftp();//new SSHTunnel.SFTP(sshTunnel);//sshTunnel.sftp()
20 | });
21 |
22 | beforeEach(async () => {
23 | await sshTunnel.exec("rm", ["-rf", path])
24 | await sshTunnel.exec("mkdir", [path])
25 | })
26 |
27 |
28 |
29 | it("create/delete folder", async () => {
30 | await sftp.mkdir(`${path}/test1`)
31 | expect(await sshTunnel.exec("ls", [path])).toContain("test1");
32 | await sftp.rmdir(`${path}/test1`);
33 | expect(await sshTunnel.exec("ls", [path])).not.toContain("test1");
34 | expect(1).toBe(1);
35 | });
36 |
37 | it("read/write file ", async () => {
38 | await sftp.writeFile(`${path}/dummy`, "testing123");
39 | var content = await sftp.readFile(`${path}/dummy`, "utf8");
40 | expect(content).toBe("testing123");
41 | });
42 |
43 | it("fast get/put file", async () => {
44 | try {
45 | //mock data
46 | fs.writeFileSync('./test.txt', "Test module");
47 |
48 | //fast put
49 | await sftp.fastPut('./test.txt', `${path}/test2.txt`);
50 | let content = await sftp.readFile(`${path}/test2.txt`, "utf8");
51 | expect(content).toBe("Test module");
52 |
53 | //fast get
54 | await sftp.fastGet(`${path}/test2.txt`, './test2.txt');
55 | expect(fs.readFileSync("./test2.txt").toString()).toBe("Test module")
56 | } finally {
57 | fs.unlinkSync('./test.txt')
58 | fs.unlinkSync("./test2.txt");
59 | }
60 | });
61 |
62 | it("read dir", function (done) {
63 | sftp.readdir("/").then((data) => {
64 | expect(data).toBeDefined();
65 | }, (error) => {
66 | expect('1').toBe('2');
67 | expect(error).toBeUndefined();
68 | }).finally(() => {
69 | done();
70 | });
71 | });
72 |
73 | it("write stream", function (done) {
74 | sftp.createWriteStream(`${path}/abc`).then((stream) => {
75 | expect(stream).toBeDefined();
76 | stream.write("dummy");
77 | stream.end("test");
78 | stream.on("finish", async () => {
79 | expect(await sshTunnel.exec("cat", [`${path}/abc`])).toContain("dummytest");
80 | done();
81 | })
82 | stream.on("error", (data) => {
83 | expect('1').toBe('2');
84 | expect(error).toBeUndefined();
85 | done();
86 | })
87 | }, (error) => {
88 | expect('1').toBe('2');
89 | expect(error).toBeUndefined();
90 | console.log(error);
91 | done();
92 | })
93 | });
94 |
95 | it("read stream", async (done) => {
96 | //mock data
97 | await sshTunnel.exec("echo", ['dummytest', '>', `${path}/def`])
98 |
99 | //Test readstream
100 | let stream = await sftp.createReadStream(`${path}/def`)
101 | expect(stream).toBeDefined();
102 | var buffer = "";
103 | stream.on('data', (data) => {
104 | buffer += data.toString();
105 | });
106 | stream.on('error', (err) => {
107 | console.log(err);
108 | done();
109 | });
110 | stream.on('close', () => {
111 | expect(buffer).toContain("dummytest")
112 | done();
113 | })
114 | });
115 |
116 | it("get stats", async () => {
117 | //mock data
118 | await sshTunnel.exec("echo", ['dummytest', '>', `${path}/xyz`])
119 |
120 | //Test stat
121 | let stat = await sftp.getStat(`${path}/xyz`, "r")
122 | expect(stat).toBeDefined();
123 | });
124 |
125 | it("set stats", async () => {
126 | //mock data
127 | await sshTunnel.exec("echo", ['dummytest', '>', `${path}/stat1`])
128 |
129 | //Test set stats
130 | await sftp.setStat(`${path}/stat1`, { mode: 0755 })
131 | expect(1).toBe(1);
132 |
133 | });
134 |
135 | it("update time & access time", async () => {
136 | //mock data
137 | await sshTunnel.exec("echo", ['dummytest', '>', `${path}/testTime`])
138 |
139 | await sftp.changeTimestamp(`${path}/testTime`, new Date().getTime(), new Date().getTime())
140 | expect(1).toBe(1);
141 | });
142 |
143 | it("unable to chown to root", async () => {
144 | //mock data
145 | await sshTunnel.exec("echo", ['dummytest', '>', `${path}/testOwner`])
146 |
147 | //try to change ownership to root
148 | try {
149 | await sftp.changeOwner(`${path}/testOwner`, 0, 0);
150 | expect(1).toBe(2);
151 | } catch (err) {
152 | expect(1).toBe(1);
153 | expect(err.message).toContain("Permission denied")
154 | }
155 | });
156 |
157 | it("rename/move file", async () => {
158 | //mock data
159 | await sshTunnel.exec("echo", ['dummytest', '>', `${path}/renfile`])
160 | expect(await sshTunnel.exec("ls", [path])).toContain("renfile")
161 |
162 | //Test rename/move file
163 | sftp.rename(`${path}/renfile`, `${path}/updatefile`)
164 | expect(await sshTunnel.exec("ls", [path])).not.toContain("renfile")
165 | expect(await sshTunnel.exec("ls", [path])).toContain("updatefile")
166 | });
167 |
168 | afterAll(() => {
169 | sshTunnel.close()
170 | })
171 |
172 | });
--------------------------------------------------------------------------------
/spec/support/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "spec",
3 | "spec_files": [
4 | "**/*[sS]pec.js"
5 | ],
6 | "helpers": [
7 | "helpers/**/*.js"
8 | ],
9 | "stopSpecOnExpectationFailure": false,
10 | "random": false
11 | }
12 |
--------------------------------------------------------------------------------
/spec/test-hopping-spec.js:
--------------------------------------------------------------------------------
1 | var SSHTunnel = require("../lib/index");
2 | var SSHConstants = require("../lib/index").Constants;
3 |
4 |
5 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
6 | Promise.prototype.finally = function (cb) {
7 | const res = () => this;
8 | const fin = () => Promise.resolve(cb()).then(res);
9 | return this.then(fin, fin);
10 | };
11 | var fs = require("fs");
12 | var sshConfigs = require('./fixture')//JSON.parse(fs.readFileSync("./spec/fixture.json"));
13 | var util = require('util');
14 |
15 |
16 | describe("connect to dummy server via hopping", function () {
17 | it("should connect to server with hopping with default nc", function (done) {
18 | var sshTunnel = new SSHTunnel(sshConfigs.multiple);
19 | var sshTunnel1 = new SSHTunnel(sshConfigs.multiple);
20 | return sshTunnel.connect().then((ssh) => {
21 | expect(ssh).toBeDefined();
22 | }, (error) => {
23 | expect('1').toBe('2');
24 | expect(error).toBeUndefined();
25 | }).finally(() => {
26 | return sshTunnel1.connect();
27 | }).finally(() => {
28 | sshTunnel.close();
29 | sshTunnel1.close();
30 | console.log("closed one")
31 | done();
32 | });
33 |
34 | });
35 |
36 | });
--------------------------------------------------------------------------------
/spec/test.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEogIBAAKCAQEAiAlAW5uEkCZBfWeeCI/o+LBYYP4Gd/zs2bG3y6Hvnkvr277Q
3 | XVPW/LGKv7F4tbLhhq0nzseCfMdRV4bwnH4Cx6l3i/Rh2abSeDa9gcmcq19RGFGN
4 | CnXZB6PaBUX/aM6Q85ZR47/MHFQHN/4jT7t3zGv3/iCrJbWWVMd/zMiRAf39cVpq
5 | 5XVzizkUqMNJKRIIL/cVn08+dEFCCnWi3MisSYkmtIxbrPQ7Z9tBGA3LyZ0tUoy3
6 | 02WOTIaWcF4CLYlUdQ68JEdkd5jbUfWLCnwrqzGeiLcmtvg9Z8lgayxufBJTz9/v
7 | 2sGbtLPOr40qeU0SblLvpqgv/IgtMNEsq804YwIBJQKCAQEAgK7OLSRopAiDI5le
8 | I8ZmwbuR3zV7vZw5/lwA4zhRXmN+PpHnsjqNGIxE+oVIq+CQJXNdAd9R66fJfE82
9 | od77tfNVaLa9bQWWqREvzcyNSCm7agf0HqbUN6jVJ5U9tisvK5wIRiQh8UiRNPdR
10 | 1c0Cnsb/WCy9kl+p4X5x+RDAhVao3nl3Ys8jP2XOPEwPZ+og5Qs1Bvd+yM+YCd9h
11 | MwwvMQ3d6PGk3Mif9XNDk10soW595eZIQATgFf17QqIkLEoAYUAm/ndBeBNIYMwY
12 | h3a07pzoOe2ZgLiz/ALe1vngcy2O+o/LHd4A9Yo97c4PEP1zRUL/08CtaPI5Er3Y
13 | 9vsfZQKBgQDMlyt+p5L8fV8FvIly4T4G7bla5rgwL9Lv4pk9rcImjzj6rqslVgPq
14 | eWDG+cKeb6ejbQaq0yZScNX0pqyllyxyYGQSuc2jbRAigJyP4HfQeIJzC4dpMKOl
15 | UTr2GBzvF0XpTJEcoUtwxpL2/96cwJBge0uziiZ9I9ulUsjv7ovuXwKBgQCqOCOL
16 | SnU0iQC4jznjQGAnoJD3sTmlfsYQg9L+bhbmIA5QD5/udNpmAPH/ezHSSOciD75+
17 | yzLD/vUfe/ADJbbhrdvfR4ant3um0WtHoiB3WwH7enZkZKdHiHzAlF8dFuy2G1e6
18 | rCxkbjbt/W5R6JrRsR9+H2WN0CF+u5dQD+6sfQKBgQCPxCxm1p6jll5yu9Y1DPsn
19 | dp3s2XqCudJ/De8kbEM9sMBBc9I16WqJFwW8QM3yywAtpo8QQVkzAy6QPcVtcSYm
20 | 2/NLbc7F3e+pis7hpKc4jAij3paBRMYFd1ndXQ1pvVO4slgh9M06fbNhdYesa6O5
21 | a2WgwfGIXmL+jTNA0SQPSQKBgFwCq23jDuv3B08BT7kb4PLTVUeeEVKJtyuFhs64
22 | DGC3Ya68VnMOuz4OWUvT45RDFScrGtzA3SusaNK/iKfBW++cP3+cSMlcQta2Y4Cq
23 | qcP5147aaYJf67f2v/lk9SR7GCsVsuFx0s6Aw77p2sR9u3hEEQXndSoPo2cZSt8r
24 | NOedAoGAOyn5329hpCan50eBJZWKerhkf9+on933VaON6H5i+bGoJ6/2z12AzNMt
25 | b0RYWBT15LWyXWLHdC7CHmt4IMFNGislg3QuyePT/QFJq+4xyLGmS3JiotViln/6
26 | Yfgv+mhiIZoo65slFVpXwyEAoEwPC7CwkrOfuxMgXDyk8bsWUUs=
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/spec/util-spec.js:
--------------------------------------------------------------------------------
1 | var SSHUtils = require("../lib/index").Utils;
2 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
3 | Promise.prototype.finally = function(cb) {
4 | const res = () => this;
5 | const fin = () => Promise.resolve(cb()).then(res);
6 | return this.then(fin, fin);
7 | };
8 |
9 |
10 | describe("utils", function () {
11 |
12 | it("resolve deferred promise, with success", function (done) {
13 | var deferred = SSHUtils.createDeferredPromise();
14 | deferred.promise.then((data) => {
15 | expect(data).toBe("success");
16 | }, (error) => {
17 | expect(error).toBeUndefined();
18 | }).finally(done);
19 | deferred.resolve("success");
20 | });
21 |
22 | it("reject deferred promise, with error", function (done) {
23 | var deferred = SSHUtils.createDeferredPromise();
24 | deferred.promise.then((data) => {
25 | expect(data).toBeUndefined();
26 | }, (error) => {
27 | expect(error).toBe("error");
28 | }).finally(done);
29 | deferred.reject("error");
30 | });
31 |
32 |
33 |
34 | });
--------------------------------------------------------------------------------
/src/BaseSFTP.ts:
--------------------------------------------------------------------------------
1 | import * as stream from "stream";
2 | import { EventEmitter } from 'events';
3 | import { InputAttributes, Stats, ReadStreamOptions, WriteStreamOptions, TransferOptions } from 'ssh2-streams';
4 |
5 | export default abstract class BaseSFTP extends EventEmitter {
6 |
7 | /**
8 | * (Client-only)
9 | * Returns a new readable stream for `path`.
10 | *
11 | * Returns `Promise`
12 | */
13 | abstract createReadStream(path: string, options?: ReadStreamOptions): Promise;
14 |
15 | /**
16 | * (Client-only)
17 | * Returns a new writable stream for `path`.
18 | *
19 | * Returns `Promise`
20 | */
21 | abstract createWriteStream(path: string, options?: WriteStreamOptions): Promise;
22 |
23 | /**
24 | * (Client-only)
25 | * Downloads a file at `remotePath` to `localPath` using parallel reads for faster throughput.
26 | *
27 | * Returns `Promise`
28 | */
29 | fastGet(remotePath: string, localPath: string, options?: TransferOptions): Promise {
30 | return Promise.reject(false);
31 | }
32 |
33 | /**
34 | * (Client-only)
35 | * Uploads a file from `localPath` to `remotePath` using parallel reads for faster throughput.
36 | *
37 | * Returns `Promise`
38 | */
39 | fastPut(localPath: string, remotePath: string, options?: TransferOptions): Promise {
40 | return Promise.reject(false);
41 | }
42 |
43 | /**
44 | * (Client-only)
45 | * Opens a file `filename` for `mode` with optional `attributes`.
46 | *
47 | * Returns `Promise`
48 | */
49 | open(filename: string, mode: string, attributes?: InputAttributes): Promise {
50 | return Promise.reject(false);
51 | }
52 |
53 | /**
54 | * (Client-only)
55 | * Closes the resource associated with `handle` given by `open()` or `opendir()`.
56 | *
57 | * Returns `Promise`
58 | */
59 | close(handle: Buffer): Promise {
60 | return Promise.reject(false);
61 | }
62 |
63 | /**
64 | * (Client-only)
65 | * Reads `length` bytes from the resource associated with `handle` starting at `position`
66 | * and stores the bytes in `buffer` starting at `offset`.
67 | *
68 | * Returns `Promise>`
69 | */
70 | read(handle: Buffer, buffer: Buffer, offset: number, length: number, position: number): Promise> {
71 | return Promise.reject(false);
72 | }
73 |
74 | /**
75 | * (Client-only)
76 | * Reads length bytes from the resource associated with file starting at position and stores the bytes in buffer starting at
77 | * offset. If promise resolved successfully, then return Array [< integer >bytesRead, < Buffer >buffer
78 | * (offset adjusted), < integer >position], otherwise < Error >err.
79 | *
80 | * Returns `Promise>`
81 | */
82 | readFileData(filename: string, buffer: Buffer, offset: number, length: number, position: number): Promise> {
83 | return Promise.reject(false);
84 | }
85 |
86 | /**
87 | * (Client-only)
88 | * Reads file content at given path. Default encoding is null.
89 | *
90 | * Returns `Promise`
91 | */
92 | readFile(filename: string, encoding?: string|any): Promise {
93 | return Promise.reject(false);
94 | }
95 |
96 | /**
97 | * (Client-only)
98 | * Writes length bytes from buffer starting at offset to the resource associated with file starting at position.
99 | *
100 | * Returns `Promise`
101 | */
102 | write(handle: Buffer, buffer: Buffer, offset: number, length: number, position: number): Promise {
103 | return Promise.reject(false);
104 | }
105 |
106 | /**
107 | * (Client-only)
108 | * Writes length bytes from buffer starting at offset to the resource associated with file starting at position.
109 | *
110 | * Returns `Promise`
111 | */
112 | writeFileData(filename: string, buffer: Buffer, offset: number, length: number, position: number): Promise {
113 | return Promise.reject(false);
114 | }
115 |
116 | /**
117 | * Writes data at given path. options can have two properties encoding and flag, Default encoding is utf8, and flag is w.
118 | *
119 | * Returns `Promise`
120 | */
121 | writeFile(filename: string, data: string, options: any): Promise {
122 | return Promise.reject(false);
123 | }
124 |
125 | /**
126 | * (Client-only)
127 | * Retrieves attributes for the resource associated with `handle`.
128 | *
129 | * Returns `Promise`
130 | */
131 | fstat(handle: Buffer): Promise {
132 | return Promise.reject(false);
133 | }
134 |
135 | /**
136 | * (Client-only)
137 | * Retrieves attributes for the resource associated with `file`. If promise resolved successfully, then return < Stats >stats, * otherwise < Error >err.
138 | *
139 | * Returns `Promise`
140 | */
141 | getStat(filename: string): Promise {
142 | return Promise.reject(false);
143 | }
144 |
145 | /**
146 | * (Client-only)
147 | * Sets the attributes defined in `attributes` for the resource associated with `handle`.
148 | *
149 | * Returns `Promise`
150 | */
151 | fsetstat(handle: Buffer, attributes: InputAttributes): Promise {
152 | return Promise.reject(false);
153 | }
154 |
155 | /**
156 | * (Client-only)
157 | * Sets the attributes defined in `attributes` for the resource associated with `file`.
158 | *
159 | * Returns `Promise`
160 | */
161 | setStat(filename: string, attributes: InputAttributes): Promise {
162 | return Promise.reject(false);
163 | }
164 |
165 | /**
166 | * (Client-only)
167 | * Sets the access time and modified time for the resource associated with `handle`.
168 | *
169 | * Returns `Promise`
170 | */
171 | futimes(handle: Buffer, atime: number | Date, mtime: number | Date): Promise {
172 | return Promise.reject(false);
173 | }
174 |
175 | /**
176 | * (Client-only)
177 | * Sets the access time and modified time for the resource associated with `file`.
178 | *
179 | * Returns `Promise`
180 | */
181 | changeTimestamp(filename: string, atime: number | Date, mtime: number | Date): Promise {
182 | return Promise.reject(false);
183 | }
184 |
185 | /**
186 | * (Client-only)
187 | * Sets the owner for the resource associated with `handle`.
188 | *
189 | * Returns `Promise`
190 | */
191 | fchown(handle: Buffer, uid: number, gid: number): Promise {
192 | return Promise.reject(false);
193 | }
194 |
195 | /**
196 | * (Client-only)
197 | * Sets the owner for the resource associated with `file`.
198 | *
199 | * Returns `Promise`
200 | */
201 | changeOwner(filename: string, uid: number, gid: number): Promise {
202 | return Promise.reject(false);
203 | }
204 |
205 | /**
206 | * (Client-only)
207 | * Sets the mode for the resource associated with `handle`.
208 | *
209 | * Returns `Promise`
210 | */
211 | fchmod(handle: Buffer, mode: number | string): Promise {
212 | return Promise.reject(false);
213 | }
214 |
215 | /**
216 | * (Client-only)
217 | * Sets the mode for the resource associated with `file`.
218 | *
219 | * Returns `Promise`
220 | */
221 | changeMode(filename: string, mode: number | string): Promise {
222 | return Promise.reject(false);
223 | }
224 |
225 | /**
226 | * (Client-only)
227 | * Opens a directory `path`.
228 | *
229 | * Returns `Promise`
230 | */
231 | opendir(path: string): Promise {
232 | return Promise.reject(false);
233 | }
234 |
235 | /**
236 | * (Client-only)
237 | * Retrieves a directory listing.
238 | *
239 | * Returns `Promise`
240 | */
241 | readdir(location: string | Buffer): Promise {
242 | return Promise.reject(false);
243 | }
244 |
245 | /**
246 | * (Client-only)
247 | * Removes the file/symlink at `path`.
248 | *
249 | * Returns `Promise`
250 | */
251 | unlink(path: string): Promise {
252 | return Promise.reject(false);
253 | }
254 |
255 | /**
256 | * (Client-only)
257 | * Renames/moves `srcPath` to `destPath`.
258 | *
259 | * Returns `Promise`
260 | */
261 | rename(srcPath: string, destPath: string): Promise {
262 | return Promise.reject(false);
263 | }
264 |
265 | /**
266 | * (Client-only)
267 | * Creates a new directory `path`.
268 | *
269 | * Returns `Promise`
270 | */
271 | mkdir(path: string, attributes?: InputAttributes): Promise {
272 | return Promise.reject(false);
273 | }
274 |
275 | /**
276 | * (Client-only)
277 | * Removes the directory at `path`.
278 | *
279 | * Returns `Promise`
280 | */
281 | rmdir(path: string): Promise {
282 | return Promise.reject(false);
283 | }
284 |
285 | /**
286 | * (Client-only)
287 | * Retrieves attributes for `path`.
288 | *
289 | * Returns `Promise`
290 | */
291 | stat(path: string): Promise {
292 | return Promise.reject(false);
293 | }
294 |
295 | /**
296 | * (Client-only)
297 | * Retrieves attributes for `path`. If `path` is a symlink, the link itself is stat'ed
298 | * instead of the resource it refers to.
299 | *
300 | * Returns `Promise`
301 | */
302 | lstat(path: string): Promise {
303 | return Promise.reject(false);
304 | }
305 | /**
306 | * (Client-only)
307 | * Sets the attributes defined in `attributes` for `path`.
308 | *
309 | * Returns `Promise`
310 | */
311 | setstat(path: string, attributes: InputAttributes): Promise {
312 | return Promise.reject(false);
313 | }
314 |
315 | /**
316 | * (Client-only)
317 | * Sets the access time and modified time for `path`.
318 | *
319 | * Returns `Promise`
320 | */
321 | utimes(path: string, atime: number | Date, mtime: number | Date): Promise {
322 | return Promise.reject(false);
323 | }
324 |
325 | /**
326 | * (Client-only)
327 | * Sets the owner for `path`.
328 | *
329 | * Returns `Promise`
330 | */
331 | chown(path: string, uid: number, gid: number): Promise {
332 | return Promise.reject(false);
333 | }
334 |
335 | /**
336 | * (Client-only)
337 | * Sets the mode for `path`.
338 | *
339 | * Returns `Promise`
340 | */
341 | chmod(path: string, mode: number | string): Promise {
342 | return Promise.reject(false);
343 | }
344 |
345 | /**
346 | * (Client-only)
347 | * Retrieves the target for a symlink at `path`.
348 | *
349 | * Returns `Promise`
350 | */
351 | readlink(path: string): Promise {
352 | return Promise.reject(false);
353 | }
354 | /**
355 | * (Client-only)
356 | * Creates a symlink at `linkPath` to `targetPath`.
357 | *
358 | * Returns `Promise`
359 | */
360 | symlink(targetPath: string, linkPath: string): Promise {
361 | return Promise.reject(false);
362 | }
363 |
364 | /**
365 | * (Client-only)
366 | * Resolves `path` to an absolute path.
367 | *
368 | * Returns `Promise`
369 | */
370 | realpath(path: string): Promise {
371 | return Promise.reject(false);
372 | }
373 |
374 | /**
375 | * (Client-only, OpenSSH extension)
376 | * Performs POSIX rename(3) from `srcPath` to `destPath`.
377 | *
378 | * Returns `Promise`
379 | */
380 | ext_openssh_rename(srcPath: string, destPath: string): Promise {
381 | return Promise.reject(false);
382 | }
383 |
384 | /**
385 | * (Client-only, OpenSSH extension)
386 | * Performs POSIX statvfs(2) on `path`.
387 | *
388 | * Returns `Promise`
389 | */
390 | ext_openssh_statvfs(path: string): Promise {
391 | return Promise.reject(false);
392 | }
393 |
394 | /**
395 | * (Client-only, OpenSSH extension)
396 | * Performs POSIX fstatvfs(2) on open handle `handle`.
397 | *
398 | * Returns `Promise`
399 | */
400 | ext_openssh_fstatvfs(handle: Buffer): Promise {
401 | return Promise.reject(false);
402 | }
403 | /**
404 | * (Client-only, OpenSSH extension)
405 | * Performs POSIX link(2) to create a hard link to `targetPath` at `linkPath`.
406 | *
407 | * Returns `Promise`
408 | */
409 | ext_openssh_hardlink(targetPath: string, linkPath: string): Promise {
410 | return Promise.reject(false);
411 | }
412 | /**
413 | * (Client-only, OpenSSH extension)
414 | * Performs POSIX fsync(3) on the open handle `handle`.
415 | *
416 | * Returns `Promise`
417 | */
418 | ext_openssh_fsync(handle: Buffer): Promise {
419 | return Promise.reject(false);
420 | }
421 |
422 | }
--------------------------------------------------------------------------------
/src/BaseSSH2Promise.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from 'events';
2 | import TunnelConfig from './tunnelConfig';
3 |
4 | export default abstract class BaseSSH2Promise extends EventEmitter {
5 |
6 |
7 | /**
8 | * Execute a cmd
9 | * @param cmd
10 | * @param params
11 | * @param options
12 | */
13 | exec(cmd:string, params?:Array, options?:any): Promise {
14 | return Promise.reject(false);
15 | }
16 |
17 | /**
18 | * Spawn a cmd
19 | * @param cmd
20 | * @param params
21 | * @param options
22 | */
23 | spawn(cmd:string, params?:Array, options?:any): Promise {
24 | return Promise.reject(false);
25 | }
26 |
27 | /**
28 | * Get shell socket
29 | */
30 | shell(options?:any): Promise {
31 | return Promise.reject(false);
32 | }
33 |
34 | /**
35 | * Get a subsys
36 | */
37 | subsys(cmd:string): Promise {
38 | return Promise.reject(false);
39 | }
40 |
41 | /**
42 | * Get a X11 port
43 | */
44 | x11(cmd:string): Promise {
45 | return Promise.reject(false);
46 | }
47 |
48 | /**
49 | * Get a Socks Port
50 | */
51 | getSocksPort(localPort:number): Promise {
52 | return Promise.reject(false);
53 | }
54 |
55 | /**
56 | * Get existing tunnel by name
57 | */
58 | getTunnel(name:string):any {
59 |
60 | }
61 |
62 | /**
63 | * Add new tunnel if not exist
64 | */
65 | addTunnel(tunnelConfig: TunnelConfig): Promise {
66 | return Promise.reject(false);
67 | }
68 |
69 | /**
70 | * Close the tunnel
71 | */
72 | closeTunnel(name?:string): Promise {
73 | return Promise.reject(false);
74 | }
75 |
76 | }
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | SFTPWrapper
3 | } from 'ssh2';
4 | import BaseSSH2Promise from './BaseSSH2Promise';
5 | import SFTP from './sftp';
6 | import SSHConfig from "./sshConfig";
7 | import SSHConnection from './sshConnection';
8 | import SSHConstants from './sshConstants';
9 | import SSHUtils from './sshUtils';
10 |
11 | function isRegistered(sshConnection: SSHConnection, sshTunnel: SSH2Promise) {
12 | return sshTunnel.deregister.filter((i) => {
13 | return i.sshConnection.config.uniqueId === sshConnection.config.uniqueId;
14 | }).length > 0;
15 | }
16 |
17 | function register(sshConnection: SSHConnection, sshTunnel: SSH2Promise, isLast: boolean) {
18 | var events = [SSHConstants.CHANNEL.SSH, SSHConstants.CHANNEL.TUNNEL];
19 | sshConnection.__sshTunnels = sshConnection.__sshTunnels || [];
20 | sshConnection.__sshTunnels.push(sshTunnel);
21 |
22 | var cbs = events.map((event) => {
23 | var cb = (function () {
24 | this.emit.apply(this, arguments);
25 | }).bind(sshTunnel, event);
26 | sshConnection.on(event, cb);
27 | return cb;
28 | });
29 |
30 |
31 | var disconnectEvent = `${SSHConstants.CHANNEL.SSH}:${SSHConstants.STATUS.DISCONNECT}`;
32 | var disconnectCb = () => {
33 | var del;
34 | for (var i = 0; i < sshTunnel.config.length; i++) {
35 | if (sshTunnel.config[i].uniqueId === sshConnection.config.uniqueId) {
36 | del = true;
37 | }
38 | if (del && SSH2Promise.__cache[sshTunnel.config[i].uniqueId]) {
39 | SSH2Promise.__cache[sshTunnel.config[i].uniqueId].close();
40 | delete SSH2Promise.__cache[sshTunnel.config[i].uniqueId];
41 | }
42 | }
43 | };
44 | events.push(disconnectEvent);
45 | cbs.push(disconnectCb);
46 | sshConnection.on(disconnectEvent, disconnectCb);
47 |
48 | return {
49 | sshConnection: sshConnection,
50 | events: events,
51 | close: function () {
52 | var idx = sshConnection.__sshTunnels.indexOf(sshTunnel);
53 | sshConnection.__sshTunnels.splice(idx, 1);
54 | if (sshConnection.__sshTunnels.length > 0) {
55 | events.forEach((event, idx) => {
56 | sshConnection.removeListener(event, cbs[idx]);
57 | });
58 | return Promise.resolve();
59 | } else {
60 | if(sshConnection.config.sock){
61 | (sshConnection.config.sock as any).destroy();
62 | }
63 | return sshConnection.close().then(() => {
64 | events.forEach((event, idx) => {
65 | sshConnection.removeListener(event, cbs[idx]);
66 | });
67 | });
68 | }
69 | }
70 | }
71 | }
72 |
73 | var methods = ['exec', 'spawn', {'rawSFTP':'sftp'}, 'shell', 'subsys', 'x11', 'getSocksPort', 'getTunnel', 'addTunnel', 'closeTunnel']
74 |
75 | var defaultOptions = {
76 | reconnect: true,
77 | port: 22,
78 | reconnectTries: 10,
79 | reconnectDelay: 5000
80 | };
81 |
82 |
83 | class SSH2Promise extends BaseSSH2Promise {
84 |
85 | /**
86 | * For caching SSH Connection
87 | */
88 | static __cache: any = {};
89 | static SSH = SSHConnection;
90 | static Utils = SSHUtils;
91 | static SFTP = SFTP;
92 | static Constants = SSHConstants;
93 |
94 | rawSFTP: () => Promise;
95 | config: Array;
96 | deregister: Array;
97 | disableCache: boolean;
98 |
99 | constructor(options: Array | SSHConfig, disableCache?: boolean) {
100 | super();
101 | options = Array.isArray(options) ? options : [options];
102 | this.config = options.map((o: any) => {
103 | o = Object.assign({}, defaultOptions, o);
104 | o.uniqueId = o.uniqueId || `${o.username}@${o.host}:${o.port}`;
105 | return o;
106 | });
107 | this.deregister = [];
108 | this.disableCache = disableCache || false;
109 | methods.forEach((m: any) => {
110 | var k = typeof m == "string"?m:Object.keys(m)[0];
111 | (this as any)[k] = function () {
112 | var params = arguments;
113 | return this.connect().then((sshConnection: any) => {
114 | return sshConnection[typeof m == "string"?m:m[k]].apply(sshConnection, params);
115 | });
116 | }.bind(this);
117 | });
118 | }
119 |
120 | /**
121 | * Get SFTP session, with promise and async/await
122 | */
123 | sftp(): SFTP {
124 | return new SFTP(this);
125 | }
126 |
127 | emit(event: string | symbol, ...args: any[]): boolean {
128 | var config = SSHUtils.peek(this.config);
129 | if (config.debug) {
130 | config.debug(arguments);
131 | }
132 | return super.emit.apply(this, arguments);
133 | }
134 |
135 | /**
136 | * Get SSH if existing from cache otherwise create new one
137 | * @param {*} sshConfig
138 | */
139 | getSSHConnection(sshConfig: any, isLast: boolean) {
140 | var ret;
141 | if (this.disableCache) {
142 | ret = new SSHConnection(sshConfig);
143 | } else {
144 | if (sshConfig && !SSH2Promise.__cache[sshConfig.uniqueId]) {
145 | ret = SSH2Promise.__cache[sshConfig.uniqueId] = new SSHConnection(sshConfig);
146 | }
147 | ret = SSH2Promise.__cache[sshConfig.uniqueId];
148 | }
149 | if (!isRegistered(ret, this)) {
150 | this.deregister.push(register(ret, this, isLast));
151 | }
152 | return ret.connect().then((ssh: SSHConnection) => {
153 | ssh.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.CONNECT);
154 | return ssh;
155 | });
156 | }
157 |
158 | /**
159 | * Connect SSH connection, via single or multiple hopping connection
160 | * @param {*} Single/Array of sshConfigs
161 | */
162 | connect() {
163 | var lastSSH;
164 | for (var i = 0; i < this.config.length; i++) {
165 | ((sshConfig:SSHConfig, isLast:boolean) => {
166 | if (!lastSSH) {
167 | lastSSH = this.getSSHConnection(sshConfig, isLast);
168 | } else {
169 | lastSSH = lastSSH.then((ssh: SSHConnection) => {
170 | if(ssh.config.hoppingTool === SSHConstants.HOPPINGTOOL.SOCAT){
171 | return SSHUtils.checkStreamError(ssh.spawn(`socat - TCP:${sshConfig.host}:${sshConfig.port}`));
172 | }else if(ssh.config.hoppingTool === SSHConstants.HOPPINGTOOL.NATIVE){
173 | return ssh.forwardOut('127.0.0.1', SSHUtils.getRandomPort(), sshConfig.host, sshConfig.port);
174 | }else {
175 | return SSHUtils.checkStreamError(ssh.spawn(`nc ${sshConfig.host} ${sshConfig.port}`));
176 | }
177 | }).then((stream: any) => {
178 | sshConfig.sock = stream;
179 | return this.getSSHConnection(sshConfig, isLast);
180 | });
181 | }
182 | })(this.config[i], i == this.config.length - 1);
183 | }
184 | return lastSSH;
185 | }
186 |
187 | /**
188 | * Close SSH Connection
189 | */
190 | close() {
191 | return Promise.all(this.deregister.map(f => f.close()));
192 | }
193 |
194 | }
195 |
196 | export = SSH2Promise;
197 |
--------------------------------------------------------------------------------
/src/sftp.ts:
--------------------------------------------------------------------------------
1 | import { ReadStreamOptions, WriteStreamOptions } from 'ssh2-streams';
2 | import BaseSFTP from './BaseSFTP';
3 | import SSH2Promise from './index';
4 |
5 | var stringFlagMap = ['r', 'r+', 'w', 'wx', 'xw', 'w+', 'wx+', 'xw+', 'a', 'ax', 'xa', 'a+', 'ax+', 'xa+'];
6 |
7 | var methods = ["fastGet", "fastPut", "open", "close", "readFile", "writeFile", "read", "write", "fstat", "fsetstat", "futimes", "fchown", "fchmod", "opendir", "readdir", "unlink", "rename", "mkdir", "rmdir", "stat", "lstat", "setstat", "utimes", "chown", "chmod", "readlink", "symlink", "realpath", "ext_openssh_rename", "ext_openssh_statvfs", "ext_openssh_fstatvfs", "ext_openssh_hardlink", "ext_openssh_fsync"];
8 |
9 | var enhanceMethods: any = {"readFileData": "read", "writeFileData": "write", "getStat": "fstat", "setStat": "fsetstat", "changeTimestamp": "futimes", "changeOwner": "fchown", "changeMode": "fchmod"};
10 |
11 | class SFTP extends BaseSFTP {
12 |
13 | ssh:SSH2Promise;
14 |
15 | constructor(ssh:SSH2Promise) {
16 | super();
17 | this.ssh = ssh;
18 | methods.forEach((m:string) => {
19 | (this as any)[m] = function () {
20 | var params = [...arguments];
21 | return new Promise((resolve, reject) => {
22 | params.push(function (err:Error, ...results:any) {
23 | if (err)
24 | return reject(err);
25 | return (results && results.length==1)?resolve(results[0]):resolve(results);
26 | });
27 | this.ssh.rawSFTP().then((sftp:any) => {
28 | sftp[m].apply(sftp, params);
29 | }).catch((err:any) => reject(err));
30 | });
31 | }.bind(this);
32 | });
33 |
34 | Object.keys(enhanceMethods).forEach((m) => {
35 | (this as any)[m] = function () {
36 | var params = [...arguments];
37 | var path = params[0];
38 | var flag = "r+";
39 | if(params[1] && stringFlagMap.indexOf(params[1]) >= 0){
40 | flag = params[1];
41 | params = params.slice(2);
42 | }else{
43 | params = params.slice(1);
44 | }
45 | return this.open(path, flag).then((handle:any) => {
46 | return this[enhanceMethods[m]].apply(this, [handle].concat(params)).then((data:any) => {
47 | this.close(handle);
48 | return data;
49 | }, (err:any) => {
50 | this.close(handle);
51 | return Promise.reject(err);
52 | })
53 | });
54 | }
55 | });
56 | }
57 |
58 | createReadStream(path: string, options?: ReadStreamOptions) {
59 | var params = [...arguments];
60 | return this.ssh.rawSFTP().then((sftp:any) => {
61 | return sftp.createReadStream.apply(sftp, params);
62 | });
63 | }
64 |
65 | createWriteStream(path: string, options?: WriteStreamOptions) {
66 | var params = [...arguments];
67 | return this.ssh.rawSFTP().then((sftp:any) => {
68 | return sftp.createWriteStream.apply(sftp, params);
69 | });
70 | }
71 | }
72 |
73 | export = SFTP
74 |
--------------------------------------------------------------------------------
/src/sshConfig.ts:
--------------------------------------------------------------------------------
1 |
2 | import {ConnectConfig, X11Details} from 'ssh2';
3 | import { PathLike } from 'fs';
4 | interface SSHConfig extends ConnectConfig {
5 | /** Optional Unique ID attached to ssh connection. */
6 | uniqueId?: string;
7 | /** Automatic retry to connect, after disconnect. Default true */
8 | reconnect?: boolean;
9 | /** Number of reconnect retry, after disconnect. Default 10 */
10 | reconnectTries?: number;
11 | /** Delay after which reconnect should be done. Default 5000ms */
12 | reconnectDelay?: number;
13 | /** Path to private key */
14 | identity?: PathLike;
15 | /** To hop multiple connection using this tool. Default nc. Supported Value are nc, socat, native */
16 | hoppingTool?: string;
17 |
18 | /** x11 details can srcIP or srcPort, or unix socket string */
19 | x11?: string | X11Details
20 |
21 | }
22 | export = SSHConfig
--------------------------------------------------------------------------------
/src/sshConnection.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from 'events';
2 | import * as net from 'net';
3 | import * as fs from 'fs';
4 | import SSHConstants from './sshConstants';
5 | import SSHUtils, { Deferred } from './sshUtils';
6 | import SSH2Promise from './index';
7 | import TunnelConfig from './tunnelConfig';
8 | import {
9 | Client, ClientChannel, ClientErrorExtensions, ExecOptions, SFTPWrapper, ShellOptions,
10 | } from 'ssh2';
11 | import { Server } from "net";
12 | import SSHConfig from './sshConfig'
13 |
14 | const socks = require('@heroku/socksv5');
15 |
16 |
17 | const defaultOptions: Partial = {
18 | reconnect: true,
19 | port: 22,
20 | reconnectTries: 10,
21 | reconnectDelay: 5000
22 | };
23 |
24 | export default class SSHConnection extends EventEmitter {
25 |
26 | __sshTunnels: Array;
27 |
28 | config: SSHConfig;
29 |
30 | private activeTunnels:{[index:string]: TunnelConfig & {server: Server}} = {};
31 |
32 | private __$connectPromise: Promise = null;
33 |
34 | private __retries: number = 0;
35 |
36 | private __err: Error & ClientErrorExtensions & { code?: string } = null;
37 |
38 | private __sftp: Promise = null;
39 |
40 | private __x11: Deferred = null;
41 |
42 | private sshConnection: Client = null;
43 |
44 | constructor(options: SSHConfig) {
45 | super();
46 | this.config = Object.assign({}, defaultOptions, options);
47 | this.config.uniqueId = this.config.uniqueId || `${this.config.username}@${this.config.host}`;
48 | }
49 |
50 | /**
51 | * Emit message on this channel
52 | * @param {*} channel
53 | * @param {*} status
54 | * @param {*} payload
55 | */
56 | emit(channel: string, status: string, payload?: any): boolean {
57 | super.emit(channel, status, this, payload);
58 | return super.emit(`${channel}:${status}`, this, payload);
59 | }
60 |
61 |
62 | /**
63 | * Get shell socket
64 | */
65 | shell(options: ShellOptions = {}): Promise {
66 | return this.connect().then(() => {
67 | return new Promise((resolve, reject) => {
68 | this.sshConnection.shell(options, (err, stream) => err ? reject(err) : resolve(stream));
69 | });
70 | })
71 | }
72 |
73 | /**
74 | * Get a sftp session
75 | */
76 | sftp(createNew: boolean): Promise {
77 | return this.connect().then(() => {
78 | if (createNew || !this.__sftp) {
79 | this.__sftp = new Promise((resolve, reject) => {
80 | this.sshConnection.sftp((err, sftp) => err ? reject(err) : resolve(sftp));
81 | });
82 | }
83 | return this.__sftp;
84 | });
85 | }
86 |
87 | /**
88 | * Get a subsys
89 | */
90 | subsys(cmd: string): Promise {
91 | return this.connect().then(() => {
92 | return new Promise((resolve, reject) => {
93 | this.sshConnection.subsys(cmd, (err, stream) => err ? reject(err) : resolve(stream));
94 | });
95 | });
96 | }
97 |
98 | /**
99 | * Spawn a command
100 | */
101 | spawn(cmd: string, params?: Array, options: ExecOptions = {}): Promise {
102 | cmd += (Array.isArray(params) ? (" " + params.join(" ")) : "");
103 | return this.connect().then(() => {
104 | return new Promise((resolve, reject) => {
105 | this.sshConnection.exec(cmd, options, (err, stream) => {
106 | if (err)
107 | return reject(err);
108 |
109 | stream.on('close', function () {
110 | //console.log(`Closed stream - ${cmd}`);
111 | }).on('finish', function () {
112 | //console.log(`Closed stream - ${cmd}`);
113 | })/* .stderr.on('data', function (data) {
114 | reject(data.toString());
115 | }); */
116 | resolve(stream)
117 | });
118 | });
119 | });
120 | }
121 |
122 | /**
123 | * Exec a command
124 | */
125 | exec(cmd: string, params?: Array, options: ExecOptions = {}): Promise {
126 | cmd += (Array.isArray(params) ? (" " + params.join(" ")) : "");
127 | return this.connect().then(() => {
128 | return new Promise((resolve, reject) => {
129 | this.sshConnection.exec(cmd, options, (err, stream) => {
130 | if (err)
131 | return reject(err);
132 | let buffer = "";
133 | let errBuffer = "";
134 | stream.on('close', function () {
135 | return errBuffer?reject(errBuffer):resolve(buffer);
136 | }).on('data', function (data: Buffer|string) {
137 | buffer += data.toString();
138 | }).stderr.on('data', function (data: Buffer|string) {
139 | errBuffer += data.toString();
140 | });
141 | })
142 | })
143 | })
144 | }
145 |
146 | /**
147 | * Forward out
148 | */
149 | forwardOut(srcIP:string, srcPort:number, destIP:string, destPort:number): Promise {
150 | return this.connect().then(() => {
151 | return new Promise((resolve, reject) => {
152 | this.sshConnection.forwardOut(srcIP, srcPort, destIP, destPort, (err, stream) => {
153 | if (err)
154 | return reject(err);
155 | resolve(stream)
156 | })
157 | })
158 | })
159 | }
160 |
161 | /**
162 | * Get a Socks Port
163 | */
164 | getSocksPort(localPort: number): Promise {
165 | return this.addTunnel({ name: "__socksServer", socks: true, localPort: localPort }).then((tunnel) => {
166 | return tunnel.localPort;
167 | });
168 | }
169 |
170 | /**
171 | * Get a X11 port
172 | */
173 | x11(cmd: string): Promise {
174 | return this.spawn(cmd, null, { x11: true }).then((stream) => {
175 | this.__x11 = SSHUtils.createDeferredPromise();
176 | var code = 0;
177 | stream.on('finish', (err: Error & ClientErrorExtensions) => {
178 | if (code !== 0) {
179 | this.__x11.reject("X11 forwading not enabled on server");
180 | this.emit(SSHConstants.CHANNEL.X11, SSHConstants.STATUS.DISCONNECT, {err: err, msg: "X11 forwading not enabled on server"});
181 | }
182 | }).on('exit', (exitcode:number) => {
183 | code = exitcode;
184 | });
185 | this.__x11.promise.catch(() => {
186 | stream.close();
187 | });
188 | return this.__x11.promise;
189 | });
190 | }
191 |
192 | /**
193 | * Close SSH Connection
194 | */
195 | close(): Promise {
196 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.BEFOREDISCONNECT);
197 | return this.closeTunnel().then(() => {
198 | if (this.sshConnection){
199 | this.sshConnection.end();
200 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.DISCONNECT);
201 | }
202 | });
203 | }
204 |
205 | /**
206 | * Connect the SSH Connection
207 | */
208 | connect(c?: SSHConfig): Promise {
209 | this.config = Object.assign(this.config, c);
210 | ++this.__retries;
211 |
212 | if (this.__$connectPromise != null)
213 | return this.__$connectPromise;
214 |
215 | this.__$connectPromise = new Promise((resolve, reject) => {
216 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.BEFORECONNECT);
217 | if (!this.config || typeof this.config === 'function' || !(this.config.host || this.config.sock) || !this.config.username) {
218 | reject("Invalid SSH connection configuration host/username can't be empty");
219 | this.__$connectPromise = null;
220 | return;
221 | }
222 |
223 | if (this.config.tryKeyboard && !this.config.password && typeof this.config !== 'undefined') {
224 | delete this.config.password;
225 | }
226 |
227 | if (this.config.identity) {
228 | if (fs.existsSync(this.config.identity)) {
229 | this.config.privateKey = fs.readFileSync(this.config.identity);
230 | }
231 | delete this.config.identity;
232 | }
233 |
234 | //Start ssh server connection
235 | this.sshConnection = new Client();
236 | this.sshConnection.on('keyboard-interactive', (name, instructions, lang, prompts, finish) => {
237 | prompts.forEach((prompt) => {
238 | SSHUtils.prompt(prompt.prompt, (password) => {
239 | finish([password]);
240 | })
241 | });
242 | }).on('ready', (err: Error & ClientErrorExtensions) => {
243 | if (err) {
244 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.DISCONNECT, { err: err });
245 | this.__$connectPromise = null;
246 | return reject(err);
247 | }
248 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.CONNECT);
249 | this.__retries = 0;
250 | this.__err = null;
251 | resolve(this);
252 | }).on('x11', (info: any, accept: any) => {
253 | var xserversock = new net.Socket();
254 | xserversock.on('connect', () => {
255 | var xclientsock = accept();
256 | xclientsock.pipe(xserversock).pipe(xclientsock);
257 | this.__x11.resolve();
258 | this.emit(SSHConstants.CHANNEL.X11, SSHConstants.STATUS.CONNECT);
259 | }).on('error', (err) => {
260 | this.__x11.reject("X Server not running locally.");
261 | this.emit(SSHConstants.CHANNEL.X11, SSHConstants.STATUS.DISCONNECT, {err: err, msg: "X Server not running locally."})
262 | });
263 | // connects to localhost:0.0
264 | if(this.config.x11){
265 | if(typeof this.config.x11 === 'string'){
266 | xserversock.connect(this.config.x11)
267 | }else{
268 | xserversock.connect(this.config.x11.srcPort, this.config.x11.srcIP)
269 | }
270 | }else{
271 | xserversock.connect(6000, 'localhost');
272 | }
273 |
274 | }).on('error', (err) => {
275 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.DISCONNECT, {err: err});
276 | this.__err = err;
277 | //reject(err);
278 | //this.__$connectPromise = null;
279 | }).on('close', () => {
280 | this.emit(SSHConstants.CHANNEL.SSH, SSHConstants.STATUS.DISCONNECT, {err: this.__err});
281 | if (this.config.reconnect && this.__retries <= this.config.reconnectTries && this.__err != null && this.__err.level != "client-authentication" && this.__err.code != 'ENOTFOUND') {
282 | setTimeout(() => {
283 | this.__$connectPromise = null;
284 | resolve(this.connect());
285 | }, this.config.reconnectDelay);
286 | }else{
287 | reject(this.__err);
288 | }
289 | }).connect(this.config);
290 | });
291 | return this.__$connectPromise;
292 | }
293 |
294 | /**
295 | * Get existing tunnel by name
296 | */
297 | getTunnel(name: string) {
298 | return this.activeTunnels[name];
299 | }
300 |
301 | /**
302 | * Add new tunnel if not exist
303 | */
304 | addTunnel(tunnelConfig: TunnelConfig): Promise {
305 | tunnelConfig.name = tunnelConfig.name || `${tunnelConfig.remoteAddr}@${tunnelConfig.remotePort}`;
306 | this.emit(SSHConstants.CHANNEL.TUNNEL, SSHConstants.STATUS.BEFORECONNECT, {tunnelConfig: tunnelConfig});
307 | if (this.getTunnel(tunnelConfig.name)) {
308 | this.emit(SSHConstants.CHANNEL.TUNNEL, SSHConstants.STATUS.CONNECT, {tunnelConfig: tunnelConfig});
309 | return Promise.resolve(this.getTunnel(tunnelConfig.name))
310 | } else {
311 | return new Promise((resolve, reject) => {
312 | var server: any;
313 | if (tunnelConfig.socks) {
314 | server = socks.createServer((info:any, accept:Function, deny:Function) => {
315 | this.connect().then(() => {
316 | this.sshConnection.forwardOut(info.srcAddr,
317 | info.srcPort,
318 | info.dstAddr,
319 | info.dstPort,
320 | (err, stream) => {
321 | if (err) {
322 | this.emit(SSHConstants.CHANNEL.TUNNEL, SSHConstants.STATUS.DISCONNECT, {tunnelConfig: tunnelConfig, err: err});
323 | return deny();
324 | }
325 | const clientSocket = accept(true);
326 | if (clientSocket) {
327 | stream.pipe(clientSocket).pipe(stream).on('close', () => {
328 | stream.end();
329 | });
330 | } else if (stream) {
331 | stream.end();
332 | }
333 | });
334 | });
335 | }).useAuth(socks.auth.None());
336 | } else {
337 | server = net.createServer()
338 | .on('connection', (socket) => {
339 | this.connect().then(() => {
340 | this.sshConnection.forwardOut('', 0, tunnelConfig.remoteAddr, tunnelConfig.remotePort, (err, stream) => {
341 | if (err) {
342 | this.emit(SSHConstants.CHANNEL.TUNNEL, SSHConstants.STATUS.DISCONNECT, {tunnelConfig: tunnelConfig, err: err});
343 | return;
344 | }
345 | stream.pipe(socket).pipe(stream).on('close', () => {
346 | stream.end();
347 | });
348 | });
349 | });
350 | });
351 | }
352 |
353 | tunnelConfig.localPort = tunnelConfig.localPort || 0;
354 | server.on('listening', () => {
355 | tunnelConfig.localPort = server.address().port;
356 | this.activeTunnels[tunnelConfig.name] = Object.assign({}, { server: server }, tunnelConfig);
357 | this.emit(SSHConstants.CHANNEL.TUNNEL, SSHConstants.STATUS.CONNECT, {tunnelConfig: tunnelConfig});
358 | resolve(this.activeTunnels[tunnelConfig.name]);
359 | }).on('error', (err: any) => {
360 | this.emit(SSHConstants.CHANNEL.TUNNEL, SSHConstants.STATUS.DISCONNECT, {tunnelConfig: tunnelConfig, err: err});
361 | server.close();
362 | reject(err);
363 | delete this.activeTunnels[tunnelConfig.name];
364 | }).listen(tunnelConfig.localPort);
365 |
366 | });
367 | }
368 | }
369 |
370 | /**
371 | * Close the tunnel
372 | */
373 | closeTunnel(name?: string): Promise {
374 | if (name && this.activeTunnels[name]) {
375 | return new Promise((resolve) => {
376 | var tunnel = this.activeTunnels[name];
377 | this.emit(
378 | SSHConstants.CHANNEL.TUNNEL,
379 | SSHConstants.STATUS.BEFOREDISCONNECT,
380 | { tunnelConfig: tunnel }
381 | );
382 | tunnel.server.close(() => {
383 | this.emit(
384 | SSHConstants.CHANNEL.TUNNEL,
385 | SSHConstants.STATUS.DISCONNECT,
386 | { tunnelConfig: this.activeTunnels[name] }
387 | );
388 | delete this.activeTunnels[name];
389 | resolve();
390 | });
391 | });
392 | } else if (!name) {
393 | var tunnels = Object.keys(this.activeTunnels).map((key) => this.closeTunnel(key));
394 | return Promise.all(tunnels).then(() => {});
395 | }
396 | }
397 |
398 | }
399 |
--------------------------------------------------------------------------------
/src/sshConstants.ts:
--------------------------------------------------------------------------------
1 | let Constants = {
2 | "CHANNEL": {
3 | SSH: "ssh",
4 | TUNNEL: "tunnel",
5 | X11: "x11"
6 | },
7 | "STATUS": {
8 | BEFORECONNECT: "beforeconnect",
9 | CONNECT: "connect",
10 | BEFOREDISCONNECT: "beforedisconnect",
11 | DISCONNECT: "disconnect"
12 | },
13 | "HOPPINGTOOL": {
14 | NETCAT: 'nc',
15 | SOCAT: 'socat',
16 | NATIVE: 'native'
17 | }
18 | }
19 |
20 | export = Constants
--------------------------------------------------------------------------------
/src/sshUtils.ts:
--------------------------------------------------------------------------------
1 | var readline = require('readline');
2 | var Writable = require('stream').Writable;
3 |
4 | var mutableStdout = new Writable({
5 | write: function(chunk:any, encoding:any, callback:Function) {
6 | if (!this.muted)
7 | process.stdout.write(chunk, encoding);
8 | callback();
9 | }
10 | });
11 | mutableStdout.muted = false;
12 |
13 | export interface Deferred {
14 | resolve: Function;
15 | reject: Function;
16 | promise: Promise;
17 | }
18 |
19 | export default {
20 | /**
21 | * Peek the array
22 | */
23 | peek: function(arr: Array) {
24 | return arr[arr.length - 1]
25 | },
26 | /**
27 | * End pty socket session by sending kill signal
28 | * @param {*} socket
29 | */
30 | endSocket: function(socket: any) {
31 | if(socket){
32 | if(socket.writable){
33 | socket.end('\x03');
34 | socket.signal('INT');
35 | socket.signal('KILL');
36 | }
37 | socket.close();
38 | }
39 | },
40 | /**
41 | * Prompt for asking anything
42 | */
43 | prompt: function(question: string, cb: (password: string) => void) {
44 | var rl = readline.createInterface({
45 | input: process.stdin,
46 | output: mutableStdout,
47 | terminal: true
48 | });
49 | rl.question(question, function(password: string) {
50 | cb(password);
51 | rl.close();
52 | });
53 | mutableStdout.muted = true;
54 | },
55 |
56 | /**
57 | * Create a Deferred promise
58 | */
59 | createDeferredPromise: function() {
60 | var __resolve, __reject;
61 | var __promise = new Promise((resolve, reject) => {
62 | __resolve = resolve;
63 | __reject = reject;
64 | })
65 | return {
66 | promise: __promise,
67 | resolve: __resolve,
68 | reject: __reject
69 | } as Deferred;
70 | },
71 | getRandomPort(){
72 | return this.randomNumber(49152, 60999);
73 | },
74 | randomNumber(min:number, max:number) {
75 | min = Math.ceil(min);
76 | max = Math.floor(max);
77 | return Math.floor(Math.random() * (max - min + 1)) + min;
78 | },
79 | async checkStreamError(stream: any, timeout?: number) {
80 | stream = await stream;
81 | return new Promise((resolve, reject) => {
82 | stream.stderr.on('data', function (data: any) {
83 | reject(data.toString());
84 | });
85 | setTimeout(() => { resolve(stream) }, timeout || 500);
86 | })
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/tunnelConfig.ts:
--------------------------------------------------------------------------------
1 | interface TunnelConfig {
2 | /** Remote Address to connect */
3 | remoteAddr?: string;
4 | /** Local port to bind to. By default, it will bind to a random port, if not passed */
5 | localPort?: number;
6 | /** Remote Port to connect */
7 | remotePort?: number;
8 | socks?: boolean;
9 | /** Unique name */
10 | name?: string;
11 | }
12 | export = TunnelConfig
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "ES6",
5 | "noImplicitAny": true,
6 | "moduleResolution": "node",
7 | "outDir": "./lib",
8 | "declaration": true,
9 | "baseUrl": ".",
10 | "paths": {
11 | "*": [
12 | "node_modules/*"
13 | ]
14 | },
15 | "esModuleInterop": true
16 | },
17 | "include": [
18 | "src/**/*.ts"
19 | ],
20 | "exclude": [
21 | "node_modules"
22 | ]
23 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@heroku/socksv5@^0.0.9":
6 | version "0.0.9"
7 | resolved "https://registry.npmjs.org/@heroku/socksv5/-/socksv5-0.0.9.tgz"
8 | integrity sha1-ejkFkhE2smZpeaD4a7TwYvZX95M=
9 | dependencies:
10 | ip-address "^5.8.8"
11 |
12 | "@tsconfig/node10@^1.0.7":
13 | version "1.0.8"
14 | resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz"
15 | integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==
16 |
17 | "@tsconfig/node12@^1.0.7":
18 | version "1.0.9"
19 | resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz"
20 | integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==
21 |
22 | "@tsconfig/node14@^1.0.0":
23 | version "1.0.1"
24 | resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz"
25 | integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==
26 |
27 | "@tsconfig/node16@^1.0.1":
28 | version "1.0.1"
29 | resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz"
30 | integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==
31 |
32 | "@types/jasmine@^2.8.9":
33 | version "2.8.17"
34 | resolved "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.17.tgz"
35 | integrity sha512-lXmY2lBjE38ASvP7ah38yZwXCdc7DTCKhHqx4J3WGNiVzp134U0BD9VKdL5x9q9AAfhnpJeQr4owL6ZOXhOpfA==
36 |
37 | "@types/node@*", "@types/node@^16.7.1":
38 | version "16.7.1"
39 | resolved "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz"
40 | integrity sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==
41 |
42 | "@types/ssh2-streams@*":
43 | version "0.1.8"
44 | resolved "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.8.tgz"
45 | integrity sha512-I7gixRPUvVIyJuCEvnmhr3KvA2dC0639kKswqD4H5b4/FOcnPtNU+qWLiXdKIqqX9twUvi5j0U1mwKE5CUsrfA==
46 | dependencies:
47 | "@types/node" "*"
48 |
49 | "@types/ssh2-streams@0.1.9":
50 | version "0.1.9"
51 | resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.9.tgz#8ca51b26f08750a780f82ee75ff18d7160c07a87"
52 | integrity sha512-I2J9jKqfmvXLR5GomDiCoHrEJ58hAOmFrekfFqmCFd+A6gaEStvWnPykoWUwld1PNg4G5ag1LwdA+Lz1doRJqg==
53 | dependencies:
54 | "@types/node" "*"
55 |
56 | "@types/ssh2@0.5.52":
57 | version "0.5.52"
58 | resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.52.tgz#9dbd8084e2a976e551d5e5e70b978ed8b5965741"
59 | integrity sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==
60 | dependencies:
61 | "@types/node" "*"
62 | "@types/ssh2-streams" "*"
63 |
64 | ansi-gray@^0.1.1:
65 | version "0.1.1"
66 | resolved "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz"
67 | integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE=
68 | dependencies:
69 | ansi-wrap "0.1.0"
70 |
71 | ansi-regex@^2.0.0:
72 | version "2.1.1"
73 | resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz"
74 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
75 |
76 | ansi-styles@^2.2.1:
77 | version "2.2.1"
78 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
79 | integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
80 |
81 | ansi-wrap@0.1.0:
82 | version "0.1.0"
83 | resolved "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz"
84 | integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768=
85 |
86 | archy@^1.0.0:
87 | version "1.0.0"
88 | resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz"
89 | integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=
90 |
91 | arg@^4.1.0:
92 | version "4.1.3"
93 | resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz"
94 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
95 |
96 | arr-diff@^2.0.0:
97 | version "2.0.0"
98 | resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz"
99 | integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
100 | dependencies:
101 | arr-flatten "^1.0.1"
102 |
103 | arr-diff@^4.0.0:
104 | version "4.0.0"
105 | resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz"
106 | integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
107 |
108 | arr-flatten@^1.0.1, arr-flatten@^1.1.0:
109 | version "1.1.0"
110 | resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz"
111 | integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
112 |
113 | arr-union@^3.1.0:
114 | version "3.1.0"
115 | resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz"
116 | integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
117 |
118 | array-differ@^1.0.0:
119 | version "1.0.0"
120 | resolved "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz"
121 | integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=
122 |
123 | array-each@^1.0.1:
124 | version "1.0.1"
125 | resolved "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz"
126 | integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8=
127 |
128 | array-slice@^1.0.0:
129 | version "1.1.0"
130 | resolved "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz"
131 | integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==
132 |
133 | array-uniq@^1.0.2:
134 | version "1.0.3"
135 | resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz"
136 | integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
137 |
138 | array-unique@^0.2.1:
139 | version "0.2.1"
140 | resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz"
141 | integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
142 |
143 | array-unique@^0.3.2:
144 | version "0.3.2"
145 | resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz"
146 | integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
147 |
148 | asn1@^0.2.4:
149 | version "0.2.4"
150 | resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz"
151 | integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
152 | dependencies:
153 | safer-buffer "~2.1.0"
154 |
155 | assign-symbols@^1.0.0:
156 | version "1.0.0"
157 | resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz"
158 | integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
159 |
160 | atob@^2.1.2:
161 | version "2.1.2"
162 | resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz"
163 | integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
164 |
165 | balanced-match@^1.0.0:
166 | version "1.0.2"
167 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
168 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
169 |
170 | base@^0.11.1:
171 | version "0.11.2"
172 | resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz"
173 | integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
174 | dependencies:
175 | cache-base "^1.0.1"
176 | class-utils "^0.3.5"
177 | component-emitter "^1.2.1"
178 | define-property "^1.0.0"
179 | isobject "^3.0.1"
180 | mixin-deep "^1.2.0"
181 | pascalcase "^0.1.1"
182 |
183 | bcrypt-pbkdf@^1.0.2:
184 | version "1.0.2"
185 | resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz"
186 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
187 | dependencies:
188 | tweetnacl "^0.14.3"
189 |
190 | beeper@^1.0.0:
191 | version "1.1.1"
192 | resolved "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz"
193 | integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=
194 |
195 | brace-expansion@^1.1.7:
196 | version "1.1.11"
197 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
198 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
199 | dependencies:
200 | balanced-match "^1.0.0"
201 | concat-map "0.0.1"
202 |
203 | braces@^1.8.2, braces@^2.3.1:
204 | version "2.3.2"
205 | resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz"
206 | integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
207 | dependencies:
208 | arr-flatten "^1.1.0"
209 | array-unique "^0.3.2"
210 | extend-shallow "^2.0.1"
211 | fill-range "^4.0.0"
212 | isobject "^3.0.1"
213 | repeat-element "^1.1.2"
214 | snapdragon "^0.8.1"
215 | snapdragon-node "^2.0.1"
216 | split-string "^3.0.2"
217 | to-regex "^3.0.1"
218 |
219 | buffer-from@^1.0.0:
220 | version "1.1.1"
221 | resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz"
222 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
223 |
224 | buildcheck@0.0.3:
225 | version "0.0.3"
226 | resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.3.tgz#70451897a95d80f7807e68fc412eb2e7e35ff4d5"
227 | integrity sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==
228 |
229 | cache-base@^1.0.1:
230 | version "1.0.1"
231 | resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz"
232 | integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
233 | dependencies:
234 | collection-visit "^1.0.0"
235 | component-emitter "^1.2.1"
236 | get-value "^2.0.6"
237 | has-value "^1.0.0"
238 | isobject "^3.0.1"
239 | set-value "^2.0.0"
240 | to-object-path "^0.3.0"
241 | union-value "^1.0.0"
242 | unset-value "^1.0.0"
243 |
244 | chalk@^1.0.0:
245 | version "1.1.3"
246 | resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"
247 | integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
248 | dependencies:
249 | ansi-styles "^2.2.1"
250 | escape-string-regexp "^1.0.2"
251 | has-ansi "^2.0.0"
252 | strip-ansi "^3.0.0"
253 | supports-color "^2.0.0"
254 |
255 | class-utils@^0.3.5:
256 | version "0.3.6"
257 | resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz"
258 | integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
259 | dependencies:
260 | arr-union "^3.1.0"
261 | define-property "^0.2.5"
262 | isobject "^3.0.0"
263 | static-extend "^0.1.1"
264 |
265 | clone-stats@^0.0.1:
266 | version "0.0.1"
267 | resolved "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz"
268 | integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=
269 |
270 | clone@^0.2.0:
271 | version "0.2.0"
272 | resolved "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz"
273 | integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=
274 |
275 | clone@^1.0.0, clone@^1.0.2:
276 | version "1.0.4"
277 | resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz"
278 | integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
279 |
280 | collection-visit@^1.0.0:
281 | version "1.0.0"
282 | resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz"
283 | integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
284 | dependencies:
285 | map-visit "^1.0.0"
286 | object-visit "^1.0.0"
287 |
288 | color-support@^1.1.3:
289 | version "1.1.3"
290 | resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz"
291 | integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
292 |
293 | component-emitter@^1.2.1:
294 | version "1.3.0"
295 | resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz"
296 | integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
297 |
298 | concat-map@0.0.1:
299 | version "0.0.1"
300 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
301 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
302 |
303 | convert-source-map@^1.1.1:
304 | version "1.8.0"
305 | resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz"
306 | integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
307 | dependencies:
308 | safe-buffer "~5.1.1"
309 |
310 | copy-descriptor@^0.1.0:
311 | version "0.1.1"
312 | resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz"
313 | integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
314 |
315 | core-util-is@~1.0.0:
316 | version "1.0.2"
317 | resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
318 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
319 |
320 | cpu-features@~0.0.4:
321 | version "0.0.4"
322 | resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.4.tgz#0023475bb4f4c525869c162e4108099e35bf19d8"
323 | integrity sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==
324 | dependencies:
325 | buildcheck "0.0.3"
326 | nan "^2.15.0"
327 |
328 | create-require@^1.1.0:
329 | version "1.1.1"
330 | resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz"
331 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
332 |
333 | dateformat@^2.0.0:
334 | version "2.2.0"
335 | resolved "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz"
336 | integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=
337 |
338 | debug@^2.2.0, debug@^2.3.3:
339 | version "2.6.9"
340 | resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
341 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
342 | dependencies:
343 | ms "2.0.0"
344 |
345 | decode-uri-component@^0.2.0:
346 | version "0.2.0"
347 | resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz"
348 | integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
349 |
350 | defaults@^1.0.0:
351 | version "1.0.3"
352 | resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz"
353 | integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
354 | dependencies:
355 | clone "^1.0.2"
356 |
357 | define-property@^0.2.5:
358 | version "0.2.5"
359 | resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz"
360 | integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
361 | dependencies:
362 | is-descriptor "^0.1.0"
363 |
364 | define-property@^1.0.0:
365 | version "1.0.0"
366 | resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz"
367 | integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
368 | dependencies:
369 | is-descriptor "^1.0.0"
370 |
371 | define-property@^2.0.2:
372 | version "2.0.2"
373 | resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz"
374 | integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
375 | dependencies:
376 | is-descriptor "^1.0.2"
377 | isobject "^3.0.1"
378 |
379 | deprecated@^0.0.1:
380 | version "0.0.1"
381 | resolved "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz"
382 | integrity sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=
383 |
384 | detect-file@^1.0.0:
385 | version "1.0.0"
386 | resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz"
387 | integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
388 |
389 | diff@^4.0.1:
390 | version "4.0.2"
391 | resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz"
392 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
393 |
394 | duplexer2@0.0.2:
395 | version "0.0.2"
396 | resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz"
397 | integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=
398 | dependencies:
399 | readable-stream "~1.1.9"
400 |
401 | duplexify@^3.2.0:
402 | version "3.7.1"
403 | resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz"
404 | integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
405 | dependencies:
406 | end-of-stream "^1.0.0"
407 | inherits "^2.0.1"
408 | readable-stream "^2.0.0"
409 | stream-shift "^1.0.0"
410 |
411 | end-of-stream@^1.0.0:
412 | version "1.4.4"
413 | resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz"
414 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
415 | dependencies:
416 | once "^1.4.0"
417 |
418 | end-of-stream@~0.1.5:
419 | version "0.1.5"
420 | resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz"
421 | integrity sha1-jhdyBsPICDfYVjLouTWd/osvbq8=
422 | dependencies:
423 | once "~1.3.0"
424 |
425 | escape-string-regexp@^1.0.2:
426 | version "1.0.5"
427 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
428 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
429 |
430 | exit@^0.1.2:
431 | version "0.1.2"
432 | resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz"
433 | integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
434 |
435 | expand-brackets@^0.1.4:
436 | version "0.1.5"
437 | resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz"
438 | integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
439 | dependencies:
440 | is-posix-bracket "^0.1.0"
441 |
442 | expand-brackets@^2.1.4:
443 | version "2.1.4"
444 | resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz"
445 | integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
446 | dependencies:
447 | debug "^2.3.3"
448 | define-property "^0.2.5"
449 | extend-shallow "^2.0.1"
450 | posix-character-classes "^0.1.0"
451 | regex-not "^1.0.0"
452 | snapdragon "^0.8.1"
453 | to-regex "^3.0.1"
454 |
455 | expand-tilde@^2.0.0, expand-tilde@^2.0.2:
456 | version "2.0.2"
457 | resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz"
458 | integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
459 | dependencies:
460 | homedir-polyfill "^1.0.1"
461 |
462 | extend-shallow@^2.0.1:
463 | version "2.0.1"
464 | resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz"
465 | integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
466 | dependencies:
467 | is-extendable "^0.1.0"
468 |
469 | extend-shallow@^3.0.0, extend-shallow@^3.0.2:
470 | version "3.0.2"
471 | resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz"
472 | integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
473 | dependencies:
474 | assign-symbols "^1.0.0"
475 | is-extendable "^1.0.1"
476 |
477 | extend@^3.0.0:
478 | version "3.0.2"
479 | resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz"
480 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
481 |
482 | extglob@^0.3.1:
483 | version "0.3.2"
484 | resolved "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz"
485 | integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
486 | dependencies:
487 | is-extglob "^1.0.0"
488 |
489 | extglob@^2.0.4:
490 | version "2.0.4"
491 | resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz"
492 | integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
493 | dependencies:
494 | array-unique "^0.3.2"
495 | define-property "^1.0.0"
496 | expand-brackets "^2.1.4"
497 | extend-shallow "^2.0.1"
498 | fragment-cache "^0.2.1"
499 | regex-not "^1.0.0"
500 | snapdragon "^0.8.1"
501 | to-regex "^3.0.1"
502 |
503 | fancy-log@^1.1.0:
504 | version "1.3.3"
505 | resolved "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz"
506 | integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==
507 | dependencies:
508 | ansi-gray "^0.1.1"
509 | color-support "^1.1.3"
510 | parse-node-version "^1.0.0"
511 | time-stamp "^1.0.0"
512 |
513 | filename-regex@^2.0.0:
514 | version "2.0.1"
515 | resolved "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz"
516 | integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
517 |
518 | fill-range@^4.0.0:
519 | version "4.0.0"
520 | resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz"
521 | integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
522 | dependencies:
523 | extend-shallow "^2.0.1"
524 | is-number "^3.0.0"
525 | repeat-string "^1.6.1"
526 | to-regex-range "^2.1.0"
527 |
528 | find-index@^0.1.1:
529 | version "0.1.1"
530 | resolved "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz"
531 | integrity sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=
532 |
533 | findup-sync@^2.0.0:
534 | version "2.0.0"
535 | resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz"
536 | integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
537 | dependencies:
538 | detect-file "^1.0.0"
539 | is-glob "^3.1.0"
540 | micromatch "^3.0.4"
541 | resolve-dir "^1.0.1"
542 |
543 | fined@^1.0.1:
544 | version "1.2.0"
545 | resolved "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz"
546 | integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==
547 | dependencies:
548 | expand-tilde "^2.0.2"
549 | is-plain-object "^2.0.3"
550 | object.defaults "^1.1.0"
551 | object.pick "^1.2.0"
552 | parse-filepath "^1.0.1"
553 |
554 | first-chunk-stream@^1.0.0:
555 | version "1.0.0"
556 | resolved "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz"
557 | integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=
558 |
559 | flagged-respawn@^1.0.0:
560 | version "1.0.1"
561 | resolved "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz"
562 | integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==
563 |
564 | for-in@^1.0.1, for-in@^1.0.2:
565 | version "1.0.2"
566 | resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz"
567 | integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
568 |
569 | for-own@^0.1.4:
570 | version "0.1.5"
571 | resolved "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz"
572 | integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
573 | dependencies:
574 | for-in "^1.0.1"
575 |
576 | for-own@^1.0.0:
577 | version "1.0.0"
578 | resolved "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz"
579 | integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=
580 | dependencies:
581 | for-in "^1.0.1"
582 |
583 | fragment-cache@^0.2.1:
584 | version "0.2.1"
585 | resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz"
586 | integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
587 | dependencies:
588 | map-cache "^0.2.2"
589 |
590 | fs.realpath@^1.0.0:
591 | version "1.0.0"
592 | resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
593 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
594 |
595 | function-bind@^1.1.1:
596 | version "1.1.1"
597 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
598 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
599 |
600 | gaze@^0.5.1:
601 | version "0.5.2"
602 | resolved "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz"
603 | integrity sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=
604 | dependencies:
605 | globule "~0.1.0"
606 |
607 | get-value@^2.0.3, get-value@^2.0.6:
608 | version "2.0.6"
609 | resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz"
610 | integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
611 |
612 | glob-base@^0.3.0:
613 | version "0.3.0"
614 | resolved "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz"
615 | integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
616 | dependencies:
617 | glob-parent "^2.0.0"
618 | is-glob "^2.0.0"
619 |
620 | glob-parent@^2.0.0, glob-parent@^3.0.0, glob-parent@^5.1.2:
621 | version "5.1.2"
622 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
623 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
624 | dependencies:
625 | is-glob "^4.0.1"
626 |
627 | glob-stream@^3.1.5:
628 | version "3.1.18"
629 | resolved "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz"
630 | integrity sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=
631 | dependencies:
632 | glob "^4.3.1"
633 | glob2base "^0.0.12"
634 | minimatch "^2.0.1"
635 | ordered-read-streams "^0.1.0"
636 | through2 "^0.6.1"
637 | unique-stream "^1.0.0"
638 |
639 | glob-stream@^5.3.2:
640 | version "5.3.5"
641 | resolved "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz"
642 | integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=
643 | dependencies:
644 | extend "^3.0.0"
645 | glob "^5.0.3"
646 | glob-parent "^3.0.0"
647 | micromatch "^2.3.7"
648 | ordered-read-streams "^0.3.0"
649 | through2 "^0.6.0"
650 | to-absolute-glob "^0.1.1"
651 | unique-stream "^2.0.2"
652 |
653 | glob-watcher@^0.0.6:
654 | version "0.0.6"
655 | resolved "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz"
656 | integrity sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=
657 | dependencies:
658 | gaze "^0.5.1"
659 |
660 | glob2base@^0.0.12:
661 | version "0.0.12"
662 | resolved "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz"
663 | integrity sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=
664 | dependencies:
665 | find-index "^0.1.1"
666 |
667 | glob@^4.3.1:
668 | version "4.5.3"
669 | resolved "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz"
670 | integrity sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=
671 | dependencies:
672 | inflight "^1.0.4"
673 | inherits "2"
674 | minimatch "^2.0.1"
675 | once "^1.3.0"
676 |
677 | glob@^5.0.3:
678 | version "5.0.15"
679 | resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz"
680 | integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
681 | dependencies:
682 | inflight "^1.0.4"
683 | inherits "2"
684 | minimatch "2 || 3"
685 | once "^1.3.0"
686 | path-is-absolute "^1.0.0"
687 |
688 | glob@^7.0.6:
689 | version "7.1.7"
690 | resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz"
691 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
692 | dependencies:
693 | fs.realpath "^1.0.0"
694 | inflight "^1.0.4"
695 | inherits "2"
696 | minimatch "^3.0.4"
697 | once "^1.3.0"
698 | path-is-absolute "^1.0.0"
699 |
700 | glob@~3.1.21:
701 | version "3.1.21"
702 | resolved "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz"
703 | integrity sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=
704 | dependencies:
705 | graceful-fs "~1.2.0"
706 | inherits "1"
707 | minimatch "~0.2.11"
708 |
709 | global-modules@^1.0.0:
710 | version "1.0.0"
711 | resolved "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz"
712 | integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
713 | dependencies:
714 | global-prefix "^1.0.1"
715 | is-windows "^1.0.1"
716 | resolve-dir "^1.0.0"
717 |
718 | global-prefix@^1.0.1:
719 | version "1.0.2"
720 | resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz"
721 | integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
722 | dependencies:
723 | expand-tilde "^2.0.2"
724 | homedir-polyfill "^1.0.1"
725 | ini "^1.3.4"
726 | is-windows "^1.0.1"
727 | which "^1.2.14"
728 |
729 | globule@~0.1.0:
730 | version "0.1.0"
731 | resolved "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz"
732 | integrity sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=
733 | dependencies:
734 | glob "~3.1.21"
735 | lodash "~1.0.1"
736 | minimatch "~0.2.11"
737 |
738 | glogg@^1.0.0:
739 | version "1.0.2"
740 | resolved "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz"
741 | integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==
742 | dependencies:
743 | sparkles "^1.0.0"
744 |
745 | graceful-fs@^3.0.0:
746 | version "3.0.12"
747 | resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz"
748 | integrity sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==
749 | dependencies:
750 | natives "^1.1.3"
751 |
752 | graceful-fs@^4.0.0, graceful-fs@^4.1.2:
753 | version "4.2.6"
754 | resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz"
755 | integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
756 |
757 | graceful-fs@~1.2.0:
758 | version "1.2.3"
759 | resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz"
760 | integrity sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=
761 |
762 | gulp-sourcemaps@1.6.0:
763 | version "1.6.0"
764 | resolved "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz"
765 | integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=
766 | dependencies:
767 | convert-source-map "^1.1.1"
768 | graceful-fs "^4.1.2"
769 | strip-bom "^2.0.0"
770 | through2 "^2.0.0"
771 | vinyl "^1.0.0"
772 |
773 | gulp-typescript@^3.2.3:
774 | version "3.2.4"
775 | resolved "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.4.tgz"
776 | integrity sha512-bZosNvbUGzFA4bjjWoUPyjU5vfgJSzlYKkU0Jutbsrj+td8yvtqxethhqfzB9MwyamaUODIuidj5gIytZ523Bw==
777 | dependencies:
778 | gulp-util "~3.0.7"
779 | source-map "~0.5.3"
780 | through2 "~2.0.1"
781 | vinyl-fs "~2.4.3"
782 |
783 | gulp-util@^3.0.0, gulp-util@~3.0.7:
784 | version "3.0.8"
785 | resolved "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz"
786 | integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08=
787 | dependencies:
788 | array-differ "^1.0.0"
789 | array-uniq "^1.0.2"
790 | beeper "^1.0.0"
791 | chalk "^1.0.0"
792 | dateformat "^2.0.0"
793 | fancy-log "^1.1.0"
794 | gulplog "^1.0.0"
795 | has-gulplog "^0.1.0"
796 | lodash._reescape "^3.0.0"
797 | lodash._reevaluate "^3.0.0"
798 | lodash._reinterpolate "^3.0.0"
799 | lodash.template "^3.0.0"
800 | minimist "^1.1.0"
801 | multipipe "^0.1.2"
802 | object-assign "^3.0.0"
803 | replace-ext "0.0.1"
804 | through2 "^2.0.0"
805 | vinyl "^0.5.0"
806 |
807 | gulp@^3.9.1:
808 | version "3.9.1"
809 | resolved "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz"
810 | integrity sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=
811 | dependencies:
812 | archy "^1.0.0"
813 | chalk "^1.0.0"
814 | deprecated "^0.0.1"
815 | gulp-util "^3.0.0"
816 | interpret "^1.0.0"
817 | liftoff "^2.1.0"
818 | minimist "^1.1.0"
819 | orchestrator "^0.3.0"
820 | pretty-hrtime "^1.0.0"
821 | semver "^4.1.0"
822 | tildify "^1.0.0"
823 | v8flags "^2.0.2"
824 | vinyl-fs "^0.3.0"
825 |
826 | gulplog@^1.0.0:
827 | version "1.0.0"
828 | resolved "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz"
829 | integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U=
830 | dependencies:
831 | glogg "^1.0.0"
832 |
833 | has-ansi@^2.0.0:
834 | version "2.0.0"
835 | resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz"
836 | integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
837 | dependencies:
838 | ansi-regex "^2.0.0"
839 |
840 | has-gulplog@^0.1.0:
841 | version "0.1.0"
842 | resolved "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz"
843 | integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=
844 | dependencies:
845 | sparkles "^1.0.0"
846 |
847 | has-value@^0.3.1:
848 | version "0.3.1"
849 | resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz"
850 | integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
851 | dependencies:
852 | get-value "^2.0.3"
853 | has-values "^0.1.4"
854 | isobject "^2.0.0"
855 |
856 | has-value@^1.0.0:
857 | version "1.0.0"
858 | resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz"
859 | integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
860 | dependencies:
861 | get-value "^2.0.6"
862 | has-values "^1.0.0"
863 | isobject "^3.0.0"
864 |
865 | has-values@^0.1.4:
866 | version "0.1.4"
867 | resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz"
868 | integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
869 |
870 | has-values@^1.0.0:
871 | version "1.0.0"
872 | resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz"
873 | integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
874 | dependencies:
875 | is-number "^3.0.0"
876 | kind-of "^4.0.0"
877 |
878 | has@^1.0.3:
879 | version "1.0.3"
880 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz"
881 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
882 | dependencies:
883 | function-bind "^1.1.1"
884 |
885 | homedir-polyfill@^1.0.1:
886 | version "1.0.3"
887 | resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz"
888 | integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
889 | dependencies:
890 | parse-passwd "^1.0.0"
891 |
892 | inflight@^1.0.4:
893 | version "1.0.6"
894 | resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
895 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
896 | dependencies:
897 | once "^1.3.0"
898 | wrappy "1"
899 |
900 | inherits@1:
901 | version "1.0.2"
902 | resolved "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz"
903 | integrity sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=
904 |
905 | inherits@2, inherits@^2.0.1, inherits@~2.0.1, inherits@~2.0.3:
906 | version "2.0.4"
907 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
908 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
909 |
910 | ini@^1.3.4, ini@^1.3.6:
911 | version "1.3.8"
912 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
913 | integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
914 |
915 | interpret@^1.0.0:
916 | version "1.4.0"
917 | resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz"
918 | integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
919 |
920 | ip-address@^5.8.8:
921 | version "5.9.4"
922 | resolved "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz"
923 | integrity sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==
924 | dependencies:
925 | jsbn "1.1.0"
926 | lodash "^4.17.15"
927 | sprintf-js "1.1.2"
928 |
929 | is-absolute@^1.0.0:
930 | version "1.0.0"
931 | resolved "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz"
932 | integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==
933 | dependencies:
934 | is-relative "^1.0.0"
935 | is-windows "^1.0.1"
936 |
937 | is-accessor-descriptor@^0.1.6:
938 | version "0.1.6"
939 | resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz"
940 | integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
941 | dependencies:
942 | kind-of "^3.0.2"
943 |
944 | is-accessor-descriptor@^1.0.0:
945 | version "1.0.0"
946 | resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz"
947 | integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
948 | dependencies:
949 | kind-of "^6.0.0"
950 |
951 | is-core-module@^2.2.0:
952 | version "2.4.0"
953 | resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz"
954 | integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
955 | dependencies:
956 | has "^1.0.3"
957 |
958 | is-data-descriptor@^0.1.4:
959 | version "0.1.4"
960 | resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz"
961 | integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
962 | dependencies:
963 | kind-of "^3.0.2"
964 |
965 | is-data-descriptor@^1.0.0:
966 | version "1.0.0"
967 | resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz"
968 | integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
969 | dependencies:
970 | kind-of "^6.0.0"
971 |
972 | is-descriptor@^0.1.0:
973 | version "0.1.6"
974 | resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz"
975 | integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
976 | dependencies:
977 | is-accessor-descriptor "^0.1.6"
978 | is-data-descriptor "^0.1.4"
979 | kind-of "^5.0.0"
980 |
981 | is-descriptor@^1.0.0, is-descriptor@^1.0.2:
982 | version "1.0.2"
983 | resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz"
984 | integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
985 | dependencies:
986 | is-accessor-descriptor "^1.0.0"
987 | is-data-descriptor "^1.0.0"
988 | kind-of "^6.0.2"
989 |
990 | is-dotfile@^1.0.0:
991 | version "1.0.3"
992 | resolved "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz"
993 | integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
994 |
995 | is-equal-shallow@^0.1.3:
996 | version "0.1.3"
997 | resolved "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz"
998 | integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
999 | dependencies:
1000 | is-primitive "^2.0.0"
1001 |
1002 | is-extendable@^0.1.0, is-extendable@^0.1.1:
1003 | version "0.1.1"
1004 | resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz"
1005 | integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
1006 |
1007 | is-extendable@^1.0.1:
1008 | version "1.0.1"
1009 | resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz"
1010 | integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
1011 | dependencies:
1012 | is-plain-object "^2.0.4"
1013 |
1014 | is-extglob@^1.0.0:
1015 | version "1.0.0"
1016 | resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz"
1017 | integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
1018 |
1019 | is-extglob@^2.1.0, is-extglob@^2.1.1:
1020 | version "2.1.1"
1021 | resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
1022 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
1023 |
1024 | is-glob@^2.0.0, is-glob@^2.0.1:
1025 | version "2.0.1"
1026 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz"
1027 | integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
1028 | dependencies:
1029 | is-extglob "^1.0.0"
1030 |
1031 | is-glob@^3.1.0:
1032 | version "3.1.0"
1033 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz"
1034 | integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
1035 | dependencies:
1036 | is-extglob "^2.1.0"
1037 |
1038 | is-glob@^4.0.1:
1039 | version "4.0.1"
1040 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz"
1041 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
1042 | dependencies:
1043 | is-extglob "^2.1.1"
1044 |
1045 | is-number@^3.0.0:
1046 | version "3.0.0"
1047 | resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz"
1048 | integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
1049 | dependencies:
1050 | kind-of "^3.0.2"
1051 |
1052 | is-plain-object@^2.0.3, is-plain-object@^2.0.4:
1053 | version "2.0.4"
1054 | resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz"
1055 | integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
1056 | dependencies:
1057 | isobject "^3.0.1"
1058 |
1059 | is-posix-bracket@^0.1.0:
1060 | version "0.1.1"
1061 | resolved "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz"
1062 | integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
1063 |
1064 | is-primitive@^2.0.0:
1065 | version "2.0.0"
1066 | resolved "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz"
1067 | integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
1068 |
1069 | is-primitive@^3.0.1:
1070 | version "3.0.1"
1071 | resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-3.0.1.tgz#98c4db1abff185485a657fc2905052b940524d05"
1072 | integrity sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==
1073 |
1074 | is-relative@^1.0.0:
1075 | version "1.0.0"
1076 | resolved "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz"
1077 | integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
1078 | dependencies:
1079 | is-unc-path "^1.0.0"
1080 |
1081 | is-stream@^1.0.1:
1082 | version "1.1.0"
1083 | resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz"
1084 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
1085 |
1086 | is-unc-path@^1.0.0:
1087 | version "1.0.0"
1088 | resolved "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz"
1089 | integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
1090 | dependencies:
1091 | unc-path-regex "^0.1.2"
1092 |
1093 | is-utf8@^0.2.0:
1094 | version "0.2.1"
1095 | resolved "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz"
1096 | integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
1097 |
1098 | is-valid-glob@^0.3.0:
1099 | version "0.3.0"
1100 | resolved "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz"
1101 | integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=
1102 |
1103 | is-windows@^1.0.1, is-windows@^1.0.2:
1104 | version "1.0.2"
1105 | resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz"
1106 | integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
1107 |
1108 | isarray@0.0.1:
1109 | version "0.0.1"
1110 | resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
1111 | integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
1112 |
1113 | isarray@1.0.0, isarray@~1.0.0:
1114 | version "1.0.0"
1115 | resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
1116 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
1117 |
1118 | isexe@^2.0.0:
1119 | version "2.0.0"
1120 | resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
1121 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
1122 |
1123 | isobject@^2.0.0:
1124 | version "2.1.0"
1125 | resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz"
1126 | integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
1127 | dependencies:
1128 | isarray "1.0.0"
1129 |
1130 | isobject@^3.0.0, isobject@^3.0.1:
1131 | version "3.0.1"
1132 | resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz"
1133 | integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
1134 |
1135 | jasmine-core@~2.99.0:
1136 | version "2.99.1"
1137 | resolved "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz"
1138 | integrity sha1-5kAN8ea1bhMLYcS80JPap/boyhU=
1139 |
1140 | jasmine@^2.8.0:
1141 | version "2.99.0"
1142 | resolved "https://registry.npmjs.org/jasmine/-/jasmine-2.99.0.tgz"
1143 | integrity sha1-jKctEC5jm4Z8ZImFbg4YqceqQrc=
1144 | dependencies:
1145 | exit "^0.1.2"
1146 | glob "^7.0.6"
1147 | jasmine-core "~2.99.0"
1148 |
1149 | jsbn@1.1.0:
1150 | version "1.1.0"
1151 | resolved "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz"
1152 | integrity sha1-sBMHyym2GKHtJux56RH4A8TaAEA=
1153 |
1154 | json-stable-stringify-without-jsonify@^1.0.1:
1155 | version "1.0.1"
1156 | resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz"
1157 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
1158 |
1159 | kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0, kind-of@^4.0.0, kind-of@^5.0.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
1160 | version "6.0.3"
1161 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
1162 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
1163 |
1164 | lazystream@^1.0.0:
1165 | version "1.0.0"
1166 | resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz"
1167 | integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
1168 | dependencies:
1169 | readable-stream "^2.0.5"
1170 |
1171 | liftoff@^2.1.0:
1172 | version "2.5.0"
1173 | resolved "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz"
1174 | integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=
1175 | dependencies:
1176 | extend "^3.0.0"
1177 | findup-sync "^2.0.0"
1178 | fined "^1.0.1"
1179 | flagged-respawn "^1.0.0"
1180 | is-plain-object "^2.0.4"
1181 | object.map "^1.0.0"
1182 | rechoir "^0.6.2"
1183 | resolve "^1.1.7"
1184 |
1185 | lodash._reescape@^3.0.0:
1186 | version "3.0.0"
1187 | resolved "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz"
1188 | integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=
1189 |
1190 | lodash._reevaluate@^3.0.0:
1191 | version "3.0.0"
1192 | resolved "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz"
1193 | integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=
1194 |
1195 | lodash._reinterpolate@^3.0.0:
1196 | version "3.0.0"
1197 | resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz"
1198 | integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
1199 |
1200 | lodash.isequal@^4.0.0:
1201 | version "4.5.0"
1202 | resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
1203 | integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
1204 |
1205 | lodash.merge@^4.6.2:
1206 | version "4.6.2"
1207 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
1208 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
1209 |
1210 | lodash.template@^3.0.0, lodash.template@^4.5.0:
1211 | version "4.5.0"
1212 | resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
1213 | integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
1214 | dependencies:
1215 | lodash._reinterpolate "^3.0.0"
1216 | lodash.templatesettings "^4.0.0"
1217 |
1218 | lodash.templatesettings@^4.0.0:
1219 | version "4.2.0"
1220 | resolved "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz"
1221 | integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
1222 | dependencies:
1223 | lodash._reinterpolate "^3.0.0"
1224 |
1225 | lodash@^4.17.15, lodash@^4.17.21, lodash@~1.0.1:
1226 | version "4.17.21"
1227 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
1228 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
1229 |
1230 | make-error@^1.1.1:
1231 | version "1.3.6"
1232 | resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz"
1233 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
1234 |
1235 | make-iterator@^1.0.0:
1236 | version "1.0.1"
1237 | resolved "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz"
1238 | integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==
1239 | dependencies:
1240 | kind-of "^6.0.2"
1241 |
1242 | map-cache@^0.2.0, map-cache@^0.2.2:
1243 | version "0.2.2"
1244 | resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz"
1245 | integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
1246 |
1247 | map-visit@^1.0.0:
1248 | version "1.0.0"
1249 | resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz"
1250 | integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
1251 | dependencies:
1252 | object-visit "^1.0.0"
1253 |
1254 | merge-stream@^1.0.0:
1255 | version "1.0.1"
1256 | resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz"
1257 | integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
1258 | dependencies:
1259 | readable-stream "^2.0.1"
1260 |
1261 | micromatch@^2.3.7:
1262 | version "2.3.11"
1263 | resolved "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz"
1264 | integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
1265 | dependencies:
1266 | arr-diff "^2.0.0"
1267 | array-unique "^0.2.1"
1268 | braces "^1.8.2"
1269 | expand-brackets "^0.1.4"
1270 | extglob "^0.3.1"
1271 | filename-regex "^2.0.0"
1272 | is-extglob "^1.0.0"
1273 | is-glob "^2.0.1"
1274 | kind-of "^3.0.2"
1275 | normalize-path "^2.0.1"
1276 | object.omit "^2.0.0"
1277 | parse-glob "^3.0.4"
1278 | regex-cache "^0.4.2"
1279 |
1280 | micromatch@^3.0.4:
1281 | version "3.1.10"
1282 | resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz"
1283 | integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
1284 | dependencies:
1285 | arr-diff "^4.0.0"
1286 | array-unique "^0.3.2"
1287 | braces "^2.3.1"
1288 | define-property "^2.0.2"
1289 | extend-shallow "^3.0.2"
1290 | extglob "^2.0.4"
1291 | fragment-cache "^0.2.1"
1292 | kind-of "^6.0.2"
1293 | nanomatch "^1.2.9"
1294 | object.pick "^1.3.0"
1295 | regex-not "^1.0.0"
1296 | snapdragon "^0.8.1"
1297 | to-regex "^3.0.2"
1298 |
1299 | "minimatch@2 || 3", minimatch@^2.0.1, minimatch@^3.0.4, minimatch@~0.2.11:
1300 | version "3.0.4"
1301 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz"
1302 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
1303 | dependencies:
1304 | brace-expansion "^1.1.7"
1305 |
1306 | minimist@^1.1.0, minimist@^1.2.5, minimist@^1.2.6:
1307 | version "1.2.6"
1308 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
1309 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
1310 |
1311 | mixin-deep@^1.2.0, mixin-deep@^1.3.2:
1312 | version "1.3.2"
1313 | resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
1314 | integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
1315 | dependencies:
1316 | for-in "^1.0.2"
1317 | is-extendable "^1.0.1"
1318 |
1319 | mkdirp@^0.5.0:
1320 | version "0.5.5"
1321 | resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz"
1322 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
1323 | dependencies:
1324 | minimist "^1.2.5"
1325 |
1326 | mock-stdin@^0.3.1:
1327 | version "0.3.1"
1328 | resolved "https://registry.npmjs.org/mock-stdin/-/mock-stdin-0.3.1.tgz"
1329 | integrity sha1-xlfZZC2QeGQ1xkyl6Zu9TQm9fdM=
1330 |
1331 | ms@2.0.0:
1332 | version "2.0.0"
1333 | resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
1334 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
1335 |
1336 | multipipe@^0.1.2:
1337 | version "0.1.2"
1338 | resolved "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz"
1339 | integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=
1340 | dependencies:
1341 | duplexer2 "0.0.2"
1342 |
1343 | nan@^2.15.0:
1344 | version "2.15.0"
1345 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
1346 | integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
1347 |
1348 | nanomatch@^1.2.9:
1349 | version "1.2.13"
1350 | resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz"
1351 | integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
1352 | dependencies:
1353 | arr-diff "^4.0.0"
1354 | array-unique "^0.3.2"
1355 | define-property "^2.0.2"
1356 | extend-shallow "^3.0.2"
1357 | fragment-cache "^0.2.1"
1358 | is-windows "^1.0.2"
1359 | kind-of "^6.0.2"
1360 | object.pick "^1.3.0"
1361 | regex-not "^1.0.0"
1362 | snapdragon "^0.8.1"
1363 | to-regex "^3.0.1"
1364 |
1365 | natives@^1.1.3:
1366 | version "1.1.6"
1367 | resolved "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz"
1368 | integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==
1369 |
1370 | normalize-path@^2.0.1:
1371 | version "2.1.1"
1372 | resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz"
1373 | integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
1374 | dependencies:
1375 | remove-trailing-separator "^1.0.1"
1376 |
1377 | object-assign@^3.0.0:
1378 | version "3.0.0"
1379 | resolved "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz"
1380 | integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=
1381 |
1382 | object-assign@^4.0.0:
1383 | version "4.1.1"
1384 | resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
1385 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
1386 |
1387 | object-copy@^0.1.0:
1388 | version "0.1.0"
1389 | resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz"
1390 | integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
1391 | dependencies:
1392 | copy-descriptor "^0.1.0"
1393 | define-property "^0.2.5"
1394 | kind-of "^3.0.3"
1395 |
1396 | object-visit@^1.0.0:
1397 | version "1.0.1"
1398 | resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz"
1399 | integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
1400 | dependencies:
1401 | isobject "^3.0.0"
1402 |
1403 | object.defaults@^1.1.0:
1404 | version "1.1.0"
1405 | resolved "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz"
1406 | integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=
1407 | dependencies:
1408 | array-each "^1.0.1"
1409 | array-slice "^1.0.0"
1410 | for-own "^1.0.0"
1411 | isobject "^3.0.0"
1412 |
1413 | object.map@^1.0.0:
1414 | version "1.0.1"
1415 | resolved "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz"
1416 | integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=
1417 | dependencies:
1418 | for-own "^1.0.0"
1419 | make-iterator "^1.0.0"
1420 |
1421 | object.omit@^2.0.0:
1422 | version "2.0.1"
1423 | resolved "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz"
1424 | integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
1425 | dependencies:
1426 | for-own "^0.1.4"
1427 | is-extendable "^0.1.1"
1428 |
1429 | object.pick@^1.2.0, object.pick@^1.3.0:
1430 | version "1.3.0"
1431 | resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz"
1432 | integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
1433 | dependencies:
1434 | isobject "^3.0.1"
1435 |
1436 | once@^1.3.0, once@^1.4.0:
1437 | version "1.4.0"
1438 | resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
1439 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
1440 | dependencies:
1441 | wrappy "1"
1442 |
1443 | once@~1.3.0:
1444 | version "1.3.3"
1445 | resolved "https://registry.npmjs.org/once/-/once-1.3.3.tgz"
1446 | integrity sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=
1447 | dependencies:
1448 | wrappy "1"
1449 |
1450 | orchestrator@^0.3.0:
1451 | version "0.3.8"
1452 | resolved "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz"
1453 | integrity sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=
1454 | dependencies:
1455 | end-of-stream "~0.1.5"
1456 | sequencify "~0.0.7"
1457 | stream-consume "~0.1.0"
1458 |
1459 | ordered-read-streams@^0.1.0:
1460 | version "0.1.0"
1461 | resolved "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz"
1462 | integrity sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=
1463 |
1464 | ordered-read-streams@^0.3.0:
1465 | version "0.3.0"
1466 | resolved "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz"
1467 | integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s=
1468 | dependencies:
1469 | is-stream "^1.0.1"
1470 | readable-stream "^2.0.1"
1471 |
1472 | os-homedir@^1.0.0:
1473 | version "1.0.2"
1474 | resolved "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz"
1475 | integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
1476 |
1477 | parse-filepath@^1.0.1:
1478 | version "1.0.2"
1479 | resolved "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz"
1480 | integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=
1481 | dependencies:
1482 | is-absolute "^1.0.0"
1483 | map-cache "^0.2.0"
1484 | path-root "^0.1.1"
1485 |
1486 | parse-glob@^3.0.4:
1487 | version "3.0.4"
1488 | resolved "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz"
1489 | integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
1490 | dependencies:
1491 | glob-base "^0.3.0"
1492 | is-dotfile "^1.0.0"
1493 | is-extglob "^1.0.0"
1494 | is-glob "^2.0.0"
1495 |
1496 | parse-node-version@^1.0.0:
1497 | version "1.0.1"
1498 | resolved "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz"
1499 | integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==
1500 |
1501 | parse-passwd@^1.0.0:
1502 | version "1.0.0"
1503 | resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz"
1504 | integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
1505 |
1506 | pascalcase@^0.1.1:
1507 | version "0.1.1"
1508 | resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz"
1509 | integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
1510 |
1511 | path-is-absolute@^1.0.0:
1512 | version "1.0.1"
1513 | resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
1514 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
1515 |
1516 | path-parse@^1.0.6:
1517 | version "1.0.7"
1518 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
1519 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
1520 |
1521 | path-root-regex@^0.1.0:
1522 | version "0.1.2"
1523 | resolved "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz"
1524 | integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=
1525 |
1526 | path-root@^0.1.1:
1527 | version "0.1.1"
1528 | resolved "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz"
1529 | integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=
1530 | dependencies:
1531 | path-root-regex "^0.1.0"
1532 |
1533 | posix-character-classes@^0.1.0:
1534 | version "0.1.1"
1535 | resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz"
1536 | integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
1537 |
1538 | pretty-hrtime@^1.0.0:
1539 | version "1.0.3"
1540 | resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz"
1541 | integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
1542 |
1543 | process-nextick-args@~2.0.0:
1544 | version "2.0.1"
1545 | resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
1546 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
1547 |
1548 | "readable-stream@>=1.0.33-1 <1.1.0-0":
1549 | version "1.0.34"
1550 | resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz"
1551 | integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
1552 | dependencies:
1553 | core-util-is "~1.0.0"
1554 | inherits "~2.0.1"
1555 | isarray "0.0.1"
1556 | string_decoder "~0.10.x"
1557 |
1558 | readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@~2.3.6:
1559 | version "2.3.7"
1560 | resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz"
1561 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
1562 | dependencies:
1563 | core-util-is "~1.0.0"
1564 | inherits "~2.0.3"
1565 | isarray "~1.0.0"
1566 | process-nextick-args "~2.0.0"
1567 | safe-buffer "~5.1.1"
1568 | string_decoder "~1.1.1"
1569 | util-deprecate "~1.0.1"
1570 |
1571 | readable-stream@~1.1.9:
1572 | version "1.1.14"
1573 | resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz"
1574 | integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
1575 | dependencies:
1576 | core-util-is "~1.0.0"
1577 | inherits "~2.0.1"
1578 | isarray "0.0.1"
1579 | string_decoder "~0.10.x"
1580 |
1581 | rechoir@^0.6.2:
1582 | version "0.6.2"
1583 | resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz"
1584 | integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
1585 | dependencies:
1586 | resolve "^1.1.6"
1587 |
1588 | regex-cache@^0.4.2:
1589 | version "0.4.4"
1590 | resolved "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz"
1591 | integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
1592 | dependencies:
1593 | is-equal-shallow "^0.1.3"
1594 |
1595 | regex-not@^1.0.0, regex-not@^1.0.2:
1596 | version "1.0.2"
1597 | resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz"
1598 | integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
1599 | dependencies:
1600 | extend-shallow "^3.0.2"
1601 | safe-regex "^1.1.0"
1602 |
1603 | remove-trailing-separator@^1.0.1:
1604 | version "1.1.0"
1605 | resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz"
1606 | integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
1607 |
1608 | repeat-element@^1.1.2:
1609 | version "1.1.4"
1610 | resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz"
1611 | integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
1612 |
1613 | repeat-string@^1.6.1:
1614 | version "1.6.1"
1615 | resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz"
1616 | integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
1617 |
1618 | replace-ext@0.0.1:
1619 | version "0.0.1"
1620 | resolved "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz"
1621 | integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=
1622 |
1623 | resolve-dir@^1.0.0, resolve-dir@^1.0.1:
1624 | version "1.0.1"
1625 | resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz"
1626 | integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
1627 | dependencies:
1628 | expand-tilde "^2.0.0"
1629 | global-modules "^1.0.0"
1630 |
1631 | resolve-url@^0.2.1:
1632 | version "0.2.1"
1633 | resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz"
1634 | integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
1635 |
1636 | resolve@^1.1.6, resolve@^1.1.7:
1637 | version "1.20.0"
1638 | resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz"
1639 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
1640 | dependencies:
1641 | is-core-module "^2.2.0"
1642 | path-parse "^1.0.6"
1643 |
1644 | ret@~0.1.10:
1645 | version "0.1.15"
1646 | resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz"
1647 | integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
1648 |
1649 | safe-buffer@~5.1.0, safe-buffer@~5.1.1:
1650 | version "5.1.2"
1651 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz"
1652 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
1653 |
1654 | safe-regex@^1.1.0:
1655 | version "1.1.0"
1656 | resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz"
1657 | integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
1658 | dependencies:
1659 | ret "~0.1.10"
1660 |
1661 | safer-buffer@~2.1.0:
1662 | version "2.1.2"
1663 | resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
1664 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
1665 |
1666 | semver@^4.1.0:
1667 | version "4.3.6"
1668 | resolved "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz"
1669 | integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=
1670 |
1671 | sequencify@~0.0.7:
1672 | version "0.0.7"
1673 | resolved "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz"
1674 | integrity sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=
1675 |
1676 | set-value@^2.0.0, set-value@^2.0.1, set-value@^4.0.1:
1677 | version "4.1.0"
1678 | resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.1.0.tgz#aa433662d87081b75ad88a4743bd450f044e7d09"
1679 | integrity sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==
1680 | dependencies:
1681 | is-plain-object "^2.0.4"
1682 | is-primitive "^3.0.1"
1683 |
1684 | snapdragon-node@^2.0.1:
1685 | version "2.1.1"
1686 | resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz"
1687 | integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
1688 | dependencies:
1689 | define-property "^1.0.0"
1690 | isobject "^3.0.0"
1691 | snapdragon-util "^3.0.1"
1692 |
1693 | snapdragon-util@^3.0.1:
1694 | version "3.0.1"
1695 | resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz"
1696 | integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
1697 | dependencies:
1698 | kind-of "^3.2.0"
1699 |
1700 | snapdragon@^0.8.1:
1701 | version "0.8.2"
1702 | resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz"
1703 | integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
1704 | dependencies:
1705 | base "^0.11.1"
1706 | debug "^2.2.0"
1707 | define-property "^0.2.5"
1708 | extend-shallow "^2.0.1"
1709 | map-cache "^0.2.2"
1710 | source-map "^0.5.6"
1711 | source-map-resolve "^0.5.0"
1712 | use "^3.1.0"
1713 |
1714 | source-map-resolve@^0.5.0:
1715 | version "0.5.3"
1716 | resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz"
1717 | integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
1718 | dependencies:
1719 | atob "^2.1.2"
1720 | decode-uri-component "^0.2.0"
1721 | resolve-url "^0.2.1"
1722 | source-map-url "^0.4.0"
1723 | urix "^0.1.0"
1724 |
1725 | source-map-support@^0.5.17:
1726 | version "0.5.19"
1727 | resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz"
1728 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
1729 | dependencies:
1730 | buffer-from "^1.0.0"
1731 | source-map "^0.6.0"
1732 |
1733 | source-map-url@^0.4.0:
1734 | version "0.4.1"
1735 | resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz"
1736 | integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
1737 |
1738 | source-map@^0.5.6, source-map@~0.5.3:
1739 | version "0.5.7"
1740 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
1741 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
1742 |
1743 | source-map@^0.6.0:
1744 | version "0.6.1"
1745 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
1746 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
1747 |
1748 | sparkles@^1.0.0:
1749 | version "1.0.1"
1750 | resolved "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz"
1751 | integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==
1752 |
1753 | split-string@^3.0.2:
1754 | version "3.1.0"
1755 | resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz"
1756 | integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
1757 | dependencies:
1758 | extend-shallow "^3.0.0"
1759 |
1760 | sprintf-js@1.1.2:
1761 | version "1.1.2"
1762 | resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz"
1763 | integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
1764 |
1765 | ssh2@^1.10.0:
1766 | version "1.10.0"
1767 | resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.10.0.tgz#e05d870dfc8e83bc918a2ffb3dcbd4d523472dee"
1768 | integrity sha512-OnKAAmf4j8wCRrXXZv3Tp5lCZkLJZtgZbn45ELiShCg27djDQ3XFGvIzuGsIsf4hdHslP+VdhA9BhUQdTdfd9w==
1769 | dependencies:
1770 | asn1 "^0.2.4"
1771 | bcrypt-pbkdf "^1.0.2"
1772 | optionalDependencies:
1773 | cpu-features "~0.0.4"
1774 | nan "^2.15.0"
1775 |
1776 | static-extend@^0.1.1:
1777 | version "0.1.2"
1778 | resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz"
1779 | integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
1780 | dependencies:
1781 | define-property "^0.2.5"
1782 | object-copy "^0.1.0"
1783 |
1784 | stream-consume@~0.1.0:
1785 | version "0.1.1"
1786 | resolved "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz"
1787 | integrity sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==
1788 |
1789 | stream-shift@^1.0.0:
1790 | version "1.0.1"
1791 | resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz"
1792 | integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
1793 |
1794 | string_decoder@~0.10.x:
1795 | version "0.10.31"
1796 | resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
1797 | integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
1798 |
1799 | string_decoder@~1.1.1:
1800 | version "1.1.1"
1801 | resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
1802 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
1803 | dependencies:
1804 | safe-buffer "~5.1.0"
1805 |
1806 | strip-ansi@^3.0.0:
1807 | version "3.0.1"
1808 | resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
1809 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
1810 | dependencies:
1811 | ansi-regex "^2.0.0"
1812 |
1813 | strip-bom-stream@^1.0.0:
1814 | version "1.0.0"
1815 | resolved "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz"
1816 | integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=
1817 | dependencies:
1818 | first-chunk-stream "^1.0.0"
1819 | strip-bom "^2.0.0"
1820 |
1821 | strip-bom@^1.0.0:
1822 | version "1.0.0"
1823 | resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz"
1824 | integrity sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=
1825 | dependencies:
1826 | first-chunk-stream "^1.0.0"
1827 | is-utf8 "^0.2.0"
1828 |
1829 | strip-bom@^2.0.0:
1830 | version "2.0.0"
1831 | resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz"
1832 | integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
1833 | dependencies:
1834 | is-utf8 "^0.2.0"
1835 |
1836 | supports-color@^2.0.0:
1837 | version "2.0.0"
1838 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
1839 | integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
1840 |
1841 | through2-filter@^2.0.0:
1842 | version "2.0.0"
1843 | resolved "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz"
1844 | integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=
1845 | dependencies:
1846 | through2 "~2.0.0"
1847 | xtend "~4.0.0"
1848 |
1849 | through2-filter@^3.0.0:
1850 | version "3.0.0"
1851 | resolved "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz"
1852 | integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==
1853 | dependencies:
1854 | through2 "~2.0.0"
1855 | xtend "~4.0.0"
1856 |
1857 | through2@^0.6.0, through2@^0.6.1:
1858 | version "0.6.5"
1859 | resolved "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz"
1860 | integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=
1861 | dependencies:
1862 | readable-stream ">=1.0.33-1 <1.1.0-0"
1863 | xtend ">=4.0.0 <4.1.0-0"
1864 |
1865 | through2@^2.0.0, through2@~2.0.0, through2@~2.0.1:
1866 | version "2.0.5"
1867 | resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz"
1868 | integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
1869 | dependencies:
1870 | readable-stream "~2.3.6"
1871 | xtend "~4.0.1"
1872 |
1873 | tildify@^1.0.0:
1874 | version "1.2.0"
1875 | resolved "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz"
1876 | integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=
1877 | dependencies:
1878 | os-homedir "^1.0.0"
1879 |
1880 | time-stamp@^1.0.0:
1881 | version "1.1.0"
1882 | resolved "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz"
1883 | integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=
1884 |
1885 | to-absolute-glob@^0.1.1:
1886 | version "0.1.1"
1887 | resolved "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz"
1888 | integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38=
1889 | dependencies:
1890 | extend-shallow "^2.0.1"
1891 |
1892 | to-object-path@^0.3.0:
1893 | version "0.3.0"
1894 | resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz"
1895 | integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
1896 | dependencies:
1897 | kind-of "^3.0.2"
1898 |
1899 | to-regex-range@^2.1.0:
1900 | version "2.1.1"
1901 | resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz"
1902 | integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
1903 | dependencies:
1904 | is-number "^3.0.0"
1905 | repeat-string "^1.6.1"
1906 |
1907 | to-regex@^3.0.1, to-regex@^3.0.2:
1908 | version "3.0.2"
1909 | resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz"
1910 | integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
1911 | dependencies:
1912 | define-property "^2.0.2"
1913 | extend-shallow "^3.0.2"
1914 | regex-not "^1.0.2"
1915 | safe-regex "^1.1.0"
1916 |
1917 | ts-node@^10.0.0:
1918 | version "10.0.0"
1919 | resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz"
1920 | integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==
1921 | dependencies:
1922 | "@tsconfig/node10" "^1.0.7"
1923 | "@tsconfig/node12" "^1.0.7"
1924 | "@tsconfig/node14" "^1.0.0"
1925 | "@tsconfig/node16" "^1.0.1"
1926 | arg "^4.1.0"
1927 | create-require "^1.1.0"
1928 | diff "^4.0.1"
1929 | make-error "^1.1.1"
1930 | source-map-support "^0.5.17"
1931 | yn "3.1.1"
1932 |
1933 | tweetnacl@^0.14.3:
1934 | version "0.14.5"
1935 | resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz"
1936 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
1937 |
1938 | typescript@^4.3.5:
1939 | version "4.3.5"
1940 | resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz"
1941 | integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
1942 |
1943 | unc-path-regex@^0.1.2:
1944 | version "0.1.2"
1945 | resolved "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz"
1946 | integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
1947 |
1948 | union-value@^1.0.0:
1949 | version "1.0.1"
1950 | resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz"
1951 | integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
1952 | dependencies:
1953 | arr-union "^3.1.0"
1954 | get-value "^2.0.6"
1955 | is-extendable "^0.1.1"
1956 | set-value "^2.0.1"
1957 |
1958 | unique-stream@^1.0.0:
1959 | version "1.0.0"
1960 | resolved "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz"
1961 | integrity sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=
1962 |
1963 | unique-stream@^2.0.2:
1964 | version "2.3.1"
1965 | resolved "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz"
1966 | integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==
1967 | dependencies:
1968 | json-stable-stringify-without-jsonify "^1.0.1"
1969 | through2-filter "^3.0.0"
1970 |
1971 | unset-value@^1.0.0:
1972 | version "1.0.0"
1973 | resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz"
1974 | integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
1975 | dependencies:
1976 | has-value "^0.3.1"
1977 | isobject "^3.0.0"
1978 |
1979 | urix@^0.1.0:
1980 | version "0.1.0"
1981 | resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz"
1982 | integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
1983 |
1984 | use@^3.1.0:
1985 | version "3.1.1"
1986 | resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz"
1987 | integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
1988 |
1989 | user-home@^1.1.1:
1990 | version "1.1.1"
1991 | resolved "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz"
1992 | integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA=
1993 |
1994 | util-deprecate@~1.0.1:
1995 | version "1.0.2"
1996 | resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
1997 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
1998 |
1999 | v8flags@^2.0.2:
2000 | version "2.1.1"
2001 | resolved "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz"
2002 | integrity sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=
2003 | dependencies:
2004 | user-home "^1.1.1"
2005 |
2006 | vali-date@^1.0.0:
2007 | version "1.0.0"
2008 | resolved "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz"
2009 | integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=
2010 |
2011 | vinyl-fs@^0.3.0:
2012 | version "0.3.14"
2013 | resolved "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz"
2014 | integrity sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=
2015 | dependencies:
2016 | defaults "^1.0.0"
2017 | glob-stream "^3.1.5"
2018 | glob-watcher "^0.0.6"
2019 | graceful-fs "^3.0.0"
2020 | mkdirp "^0.5.0"
2021 | strip-bom "^1.0.0"
2022 | through2 "^0.6.1"
2023 | vinyl "^0.4.0"
2024 |
2025 | vinyl-fs@~2.4.3:
2026 | version "2.4.4"
2027 | resolved "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz"
2028 | integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=
2029 | dependencies:
2030 | duplexify "^3.2.0"
2031 | glob-stream "^5.3.2"
2032 | graceful-fs "^4.0.0"
2033 | gulp-sourcemaps "1.6.0"
2034 | is-valid-glob "^0.3.0"
2035 | lazystream "^1.0.0"
2036 | lodash.isequal "^4.0.0"
2037 | merge-stream "^1.0.0"
2038 | mkdirp "^0.5.0"
2039 | object-assign "^4.0.0"
2040 | readable-stream "^2.0.4"
2041 | strip-bom "^2.0.0"
2042 | strip-bom-stream "^1.0.0"
2043 | through2 "^2.0.0"
2044 | through2-filter "^2.0.0"
2045 | vali-date "^1.0.0"
2046 | vinyl "^1.0.0"
2047 |
2048 | vinyl@^0.4.0:
2049 | version "0.4.6"
2050 | resolved "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz"
2051 | integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc=
2052 | dependencies:
2053 | clone "^0.2.0"
2054 | clone-stats "^0.0.1"
2055 |
2056 | vinyl@^0.5.0:
2057 | version "0.5.3"
2058 | resolved "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz"
2059 | integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=
2060 | dependencies:
2061 | clone "^1.0.0"
2062 | clone-stats "^0.0.1"
2063 | replace-ext "0.0.1"
2064 |
2065 | vinyl@^1.0.0:
2066 | version "1.2.0"
2067 | resolved "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz"
2068 | integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=
2069 | dependencies:
2070 | clone "^1.0.0"
2071 | clone-stats "^0.0.1"
2072 | replace-ext "0.0.1"
2073 |
2074 | which@^1.2.14:
2075 | version "1.3.1"
2076 | resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz"
2077 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
2078 | dependencies:
2079 | isexe "^2.0.0"
2080 |
2081 | wrappy@1:
2082 | version "1.0.2"
2083 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
2084 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
2085 |
2086 | "xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1:
2087 | version "4.0.2"
2088 | resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz"
2089 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
2090 |
2091 | yn@3.1.1:
2092 | version "3.1.1"
2093 | resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz"
2094 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
2095 |
--------------------------------------------------------------------------------