diff --git a/.changelogrc b/.changelogrc index 14a1a6896..10c054b31 100644 --- a/.changelogrc +++ b/.changelogrc @@ -2,10 +2,10 @@ "app_name": "", "logo": "", "intro": "", - "branch" : "master", + "branch" : "development", "repo_url": "https://github.com/Unitech/pm2", - "version_name" : "2.10.4", - "tag": "2.10.3", + "version_name" : "3.0.1", + "tag": "3.0.0", "file": "currentTagChangelog.md", "template": "changelogTemplate.md", "sections": [ @@ -19,7 +19,7 @@ }, { "title": "Features", - "grep": "^feat" + "grep": "^feature" }, { "title": "Documentation", diff --git a/.drone.yml b/.drone.yml index 89a44e2de..b79617d70 100644 --- a/.drone.yml +++ b/.drone.yml @@ -14,7 +14,7 @@ pipeline: - ./packager/publish_deb_rpm.sh secrets: ['packagecloud_token'] when: - event: tag + event: tag build_apk: group: build image: keymetrics/alpine-pm2-builder:latest @@ -22,4 +22,4 @@ pipeline: - AWS_REPO_BUCKET=alpine-apk.pm2.io secrets: ['apk_rsa_priv_key', 'apk_rsa_pub_key', 'aws_access_key_id', 'aws_secret_access_key'] when: - event: tag + event: tag diff --git a/.editorconfig b/.editorconfig index 510e1a442..ad4dc394f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,22 +10,6 @@ insert_final_newline = true indent_style = space indent_size = 2 -# JavaScript -[*.js] -indent_style = space -indent_size = 2 - -# YAML -[*.yml] -indent_style = space -indent_size = 3 - -# JSON -[*.json] -indent_style = space -indent_size = 2 - -# SHELL -[*.sh] -indent_style = space -indent_size = 2 +# Makefile +[Makefile] +indent_style = tab diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 549bfe759..cbc7115c2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -12,11 +12,11 @@ We 'd like to keep our master branch as clean as possible, please avoid PRs on m ## Fire an issue -When you got an issue by using pm2, you will fire an issue on [github](https://github.com/Unitech/pm2). We'll be glad to help or to fix it but the more data you give the most fast it would be resolved. +When you got an issue by using pm2, you will fire an issue on [github](https://github.com/Unitech/pm2). We'll be glad to help or to fix it but the more data you give the most fast it would be resolved. Please try following these rules it will make the task easier for you and for us: #### 1. Search through issues if it hasn't been resolved yet -#### 2. Make sure that you provide following informations: +#### 2. Make sure that you provide following informations: - pm2 version `pm2 --version` - nodejs version `node --version` - operating system @@ -27,7 +27,7 @@ Please try following these rules it will make the task easier for you and for us - How may I reproduce this? (this isn't easy in some cases) - Are you using a cluster module? Are you trying to catch SIGTERM signals? With `code` if possible. -#### 4. Think global +#### 4. Think global If your issue is too specific we might not be able to help and stackoverflow might be a better place to seak for an answer #### 5. Be clear and format issues with [markdown](http://daringfireball.net/projects/markdown/) @@ -37,4 +37,4 @@ Note that we might understand english, german and french but english is prefered ```DEBUG=pm2:* PM2_DEBUG=true ./bin/pm2 --no-daemon start my-buggy-thing.js``` -If your issue is flagged as `need data` be sure that there won't be any upgrade unless we can have enough data to reproduce. +If your issue is flagged as `need data` be sure that there won't be any upgrade unless we can have enough data to reproduce. diff --git a/.gitignore b/.gitignore index e65767451..9f426d89e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ package-lock.json currentTagChangelog.md joblog-X test/fixtures/path-check*.txt +yarn.lock diff --git a/.npmignore b/.npmignore index cec874728..b162e7155 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,7 @@ test apps doc -pres +/pres *.log *.pid examples diff --git a/CHANGELOG.md b/CHANGELOG.md index fbd96fd2c..8f0adf063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,466 @@ +## 3.0.1 ( Mon Jul 23 2018 14:13:35 GMT+0200 (CEST) ) + + +## Bug Fixes + - allow to set a name via pm2 link + ([ebffb609](https://github.com/Unitech/pm2/commit/ebffb609cf4da195c72ee67d8341c63b78f0654e)) + - disable network monitoring as long as ampq not supported + ([ae1547bf](https://github.com/Unitech/pm2/commit/ae1547bfa9505b2d13e30df39ce614eee29463b0)) + - display error message from pm2-deploy + ([9171b810](https://github.com/Unitech/pm2/commit/9171b81024641c3e104f3eeb2e2c6eb852dbe7f4)) + - protect geteuid/getegid from being called on windows #3793 + ([0495bd8e](https://github.com/Unitech/pm2/commit/0495bd8e4ffaeb1db729b35fa569696145d79c5f)) + - put message module at the right level + ([56f5e047](https://github.com/Unitech/pm2/commit/56f5e04787da29e8b582bf4fa8325f72404a2fbe)) + - do not ignore child pres folder + ([10ee9987](https://github.com/Unitech/pm2/commit/10ee99876d75679723e1e8522da07413a618e48c)) + - let->var + ([89e2a125](https://github.com/Unitech/pm2/commit/89e2a125c22aee27014c279c86d1d9e0a0df0235)) + - method renaming + ([f3faa3d8](https://github.com/Unitech/pm2/commit/f3faa3d846d1e895232743dd619f5ecb15fdf7ad)) + - path + ([4f980550](https://github.com/Unitech/pm2/commit/4f9805508d2c1c575aabc4abbab25728f1c6a28a)) + - #3791 mitigate pidusage errores + ([88551b8c](https://github.com/Unitech/pm2/commit/88551b8cfe8bf8dd330d582e71b808faadfaf161)) + - pm2 plus + ([9bc34e56](https://github.com/Unitech/pm2/commit/9bc34e56b7ad66cbc6efbd26d4017f1e1813a720)) + - #3764 + ([3a582b42](https://github.com/Unitech/pm2/commit/3a582b42f9cca57779b99964c95a2cd0516efa11)) + - drop coffee-script (installed via pm2 install coffeescript) + ([76ceb2fd](https://github.com/Unitech/pm2/commit/76ceb2fd52a2e5acbf03deacc3fa8a120a197023)) + - restore no_interaction for pm2-dev + ([902e5a5a](https://github.com/Unitech/pm2/commit/902e5a5a1225d2072ab6337aa067caf9c6a7cca4)) + - option -w doesn't work + ([165a05c8](https://github.com/Unitech/pm2/commit/165a05c854f9b3dd1418b988c954d333f81ba88f)) + - retab shell script to use space for indent consistency + ([e3b4327d](https://github.com/Unitech/pm2/commit/e3b4327d9a6120c5ad589734ca926d3b49a8b706)) + - set Makefile indent to tab instead of common space + ([4db0ae01](https://github.com/Unitech/pm2/commit/4db0ae011c161cbfca9e250da40deff9fdc36069)) + - set yaml file indent to 2 spaces instead of 3 + ([e4ecb0b2](https://github.com/Unitech/pm2/commit/e4ecb0b29dbcc4c6ca2d67b6bdc7da4c0a5d17a5)) + - remove trailing spaces + ([5c115983](https://github.com/Unitech/pm2/commit/5c1159832680231bff5da79f1c91caf32ce3b5e0)) + - fixes #3735 + ([0548cb82](https://github.com/Unitech/pm2/commit/0548cb82aa1193a5725ca22e1babfc38db2e3b77)) + + + + +## Hot Fixes + - fix #3767, do not consider as a command if space and slash are found + ([d15a12ce](https://github.com/Unitech/pm2/commit/d15a12ceae8b0c9c27625180ae002178b0bfe5d0)) + - fix #3767, do not consider as a command if space and slash are found + ([f8ec1503](https://github.com/Unitech/pm2/commit/f8ec1503c3e92bc0dec10d395ac682b116e2914e)) + + + + +## Features + - add inspector for node 10 and heap snapshot + ([dc61bca6](https://github.com/Unitech/pm2/commit/dc61bca66828c16cf6fd04a6f749f127da697cec)) + - pm2 plus xx yy now generates a name with hostname-UID + ([fcf75e2c](https://github.com/Unitech/pm2/commit/fcf75e2cc321791273f6afe86c07fd147c6e8414)) + - #3757 --only='app1,app2' + ([bea98330](https://github.com/Unitech/pm2/commit/bea983306c4736d3a2b1090f2708b7b29c44ed03)) + - pm2 plus cli + ([1da6edde](https://github.com/Unitech/pm2/commit/1da6edde80e3029d99084992ec1a4ada7b2cc279)) + - reload all apps after connection to pm2 plus + ([35a1ed2a](https://github.com/Unitech/pm2/commit/35a1ed2a1328a859a7797ec8e22024d171599d86)) + - ask to install module after connection with KM + ([68e87b39](https://github.com/Unitech/pm2/commit/68e87b39ae2b57e9fbb0b0abde68112c839f05ee)) + - with pm2 plus command ask to install modules + ([28c61716](https://github.com/Unitech/pm2/commit/28c61716ee5e8f2402205e4b06ed7ee0a942a3cc)) + + + + +## Test + - test with development packages + ([d361c840](https://github.com/Unitech/pm2/commit/d361c8405db47969bd68c7b1058a54f38e8e0e52)) + + + + +## Chore + - clean old snapshot method + ([d064750b](https://github.com/Unitech/pm2/commit/d064750be0d437945efdcd6a5ce4e56547b1bce6)) + - update version to 3.0.1 + ([efbcb021](https://github.com/Unitech/pm2/commit/efbcb02180ae38dd930e43282113dbcb24288eab)) + - bump to 3.0.1 + ([fb8357e3](https://github.com/Unitech/pm2/commit/fb8357e32f9f015e5b6e7ed8ef150f59de382c6d)) + - new ascii logo + refactor pm2 plus command + ([8692a1da](https://github.com/Unitech/pm2/commit/8692a1daf7b4b7dfb8a4d6ec3363ac0cc62203a8)) + - change motd.update + alias register to pm2 plus + ([cdc4a767](https://github.com/Unitech/pm2/commit/cdc4a767d5f1ff5873d0466b471daa3006608604)) + - btn + ([319fa0dc](https://github.com/Unitech/pm2/commit/319fa0dcbea331a88a9888c207368e52665309ce)) + - README button + ([1c6fb68c](https://github.com/Unitech/pm2/commit/1c6fb68c758d76cf81e53c43c2423ecd742265e5)) + - remove duplicate configs in .editorconfig + ([86ad52b8](https://github.com/Unitech/pm2/commit/86ad52b837e23a7ec92705d21a152394c244571f)) + + + + +## Branchs merged + - Merge branch 'development' into uid-gen + ([5324c878](https://github.com/Unitech/pm2/commit/5324c878fd0d37e068bc25c8e37f19f73bfebf30)) + - Merge branch 'master' into development + ([7d04f638](https://github.com/Unitech/pm2/commit/7d04f63835845e92d32d6ad7ffab166a2954302f)) + + + + +## Pull requests merged + - Merge pull request #3811 from Unitech/memory_inspector + ([62018044](https://github.com/Unitech/pm2/commit/62018044d7a1ef7fd0b37fe3082da4bf05989de0)) + - Merge pull request #3801 from vkotovv/grammar-fixes + ([9bb37a66](https://github.com/Unitech/pm2/commit/9bb37a662a91369caaa5a1a43751541e41970a51)) + - Merge pull request #3799 from Unitech/refactor-agent + ([bcc4fea8](https://github.com/Unitech/pm2/commit/bcc4fea80885ce941e11b17936aab6582660fc7f)) + - Merge pull request #3787 from Unitech/multi-only + ([ea5d74a8](https://github.com/Unitech/pm2/commit/ea5d74a87f6911b238634419665c716bc877be10)) + - Merge pull request #3788 from Unitech/uid-gen + ([f70444f3](https://github.com/Unitech/pm2/commit/f70444f39b7cc8fe05faf57dac1b46fc15a2053c)) + - Merge pull request #3784 from Unitech/pm2-plus-cli + ([e8c13c37](https://github.com/Unitech/pm2/commit/e8c13c374dfeabf42f75af50b838adb7ac4a50aa)) + - Merge pull request #3780 from Unitech/plus_modules + ([466d2701](https://github.com/Unitech/pm2/commit/466d2701ca48d0c4b8466d6867135e43b22deeb5)) + - Merge pull request #3768 from Unitech/spaces + ([0477354b](https://github.com/Unitech/pm2/commit/0477354b502aef612012e833bd47ce1940da1a0b)) + - Merge pull request #3771 from chinesedfan/patch-2 + ([8de987a6](https://github.com/Unitech/pm2/commit/8de987a604679774ec39e7d5a1a905556524c53d)) + - Merge pull request #3762 from shaharmor/issue-3441 + ([429e455d](https://github.com/Unitech/pm2/commit/429e455db96d2a56448a11b7602333324c9bf433)) + - Merge pull request #3761 from PeterDaveHello/fix-sh-indent-style + ([24cddc25](https://github.com/Unitech/pm2/commit/24cddc257734beebb33ee5abac5a4107a5d86093)) + - Merge pull request #3737 from morugu/add-node-env-output + ([6628f163](https://github.com/Unitech/pm2/commit/6628f1637497771bbc5c4f0ba0e9423c63660e0e)) + - Merge pull request #3743 from vivex/master + ([06872c25](https://github.com/Unitech/pm2/commit/06872c2520f73bcabb6198a96c4dafb46706c9e9)) + - Merge pull request #3748 from JimiC/support_nvm4win + ([2dac235b](https://github.com/Unitech/pm2/commit/2dac235bc8956d170fee2341517739d3781048d7)) + - Merge pull request #3752 from PeterDaveHello/upstart.tpl + ([d4e66e3a](https://github.com/Unitech/pm2/commit/d4e66e3a9d954ab5c15d5bc35910cdfb71ba8321)) + - Merge pull request #3753 from PeterDaveHello/fix-editorconfig + ([d1478680](https://github.com/Unitech/pm2/commit/d1478680325822c206afbcb197a9a732318f6d64)) + - Merge pull request #3754 from PeterDaveHello/remove-trailing-space + ([b660f03e](https://github.com/Unitech/pm2/commit/b660f03eba71bb80a1a3d313be4525160727921f)) + + + + + + +## 3.0.0 ( Wed Jun 20 2018 11:06:21 GMT+0200 (CEST) ) + + +## Breaking changes + - merge_logs is now activated by default if not in cluster mode. Logs will not be suffixed by the pm_id if only one app is started + ([ae02adf6](https://github.com/Unitech/pm2/commit/ae02adf63f70ceb3bf101be968996ca68d9ce277)) + - Drop support for node 0.12 + - Drop gracefulReload command + - Remove Interactor from PM2 source code + - Replace pmx with [pm2-io-apm](https://github.com/keymetrics/pm2-io-apm) + + +## Bug Fixes + - return the configuration and allow custom conf to override default values + ([37dc7de1](https://github.com/Unitech/pm2/commit/37dc7de11e930aa4fce6a485e892f11ee714acd6)) + - add use strict for node 4 compatibility + ([ba2ee3b1](https://github.com/Unitech/pm2/commit/ba2ee3b1ea9aa5fa665e706b3d49a205eac44d53)) + - #3605 fix parameters definition, don't use camelcase for properties + ([c8616276](https://github.com/Unitech/pm2/commit/c8616276e4e08b4d90a742e219372e775bb81098)) + - #3695 change version check method in order to make it work with alpha/beta versions + ([052d6c55](https://github.com/Unitech/pm2/commit/052d6c55df0e941e1dd11430bbcbcaa34061a06e)) + - deprecated warning on isbinaryfile + ([db09275f](https://github.com/Unitech/pm2/commit/db09275f8e353e257c89e12fed754236b15cee74)) + - #3688 test adaptation + pm2 serve --port option + ([f0249684](https://github.com/Unitech/pm2/commit/f0249684bcbfdb75749a516f447c8e8d32020709)) + - startup script issue 18.04 #3645 + ([ff1a7f31](https://github.com/Unitech/pm2/commit/ff1a7f315bfee38eb9fd9cdd63efcc0d971585f8)) + - that this - uncache node_modules + ([294038d7](https://github.com/Unitech/pm2/commit/294038d76272a915e3addc67d3694717a9f7d704)) + - verify default conf variable via package.json on public module + ([157b106d](https://github.com/Unitech/pm2/commit/157b106df78af1d28d37bbea069b926de4dceca5)) + - bug because of const + ([56f05a90](https://github.com/Unitech/pm2/commit/56f05a900b03fb0c8dd635aede666c7d2f213271)) + - do not run two pm2 para cmds + ([3274132b](https://github.com/Unitech/pm2/commit/3274132b866ba5c93d5786e755acbada922f5f1e)) + - version + ([3ec178e5](https://github.com/Unitech/pm2/commit/3ec178e577e79730aae02c913301cd905ea8ce52)) + - re-enable agent tests + ([e6febcd7](https://github.com/Unitech/pm2/commit/e6febcd70dd0f1e68b74df8563d3046ee3b32b89)) + - test/display summary + ([b075e6d0](https://github.com/Unitech/pm2/commit/b075e6d09b09ff371adf045dc5079bb8ef82f1cf)) + - skip interactor tests + ([36c4d6bc](https://github.com/Unitech/pm2/commit/36c4d6bca7445b46afc1236dc8ab4b8bf921148b)) + - remove unused tests + ([234c6314](https://github.com/Unitech/pm2/commit/234c63143e723a508796bc1d323c7241979bf4c2)) + - add missing libraries in travis + ([88fbb845](https://github.com/Unitech/pm2/commit/88fbb84597cee7029ce33f5b7e20e45f5a815b4b)) + - remove unused variable when trying to use tracing + ([3aeeba02](https://github.com/Unitech/pm2/commit/3aeeba02f628bf4f19e8d5b93657fd94a6ef0ec7)) + - remove useless tests from .sh + ([e0be81c8](https://github.com/Unitech/pm2/commit/e0be81c86c7defb5e7a271edd5cc37f960c6aa69)) + - conflict + ([e13f39c9](https://github.com/Unitech/pm2/commit/e13f39c90b6a5e803c59c5424332520564703f5c)) + - fix bug with interpreter args + ([b26efa0d](https://github.com/Unitech/pm2/commit/b26efa0d4cd72cf04762df7b7d2eaddc4f4117d2)) + - improve error message if action has failed + ([d9f44f17](https://github.com/Unitech/pm2/commit/d9f44f170f115c2d6dfb6a7fe71dc31bd7fb66fb)) + - use polyfill module for copySync with node 4.x + ([bc07f43b](https://github.com/Unitech/pm2/commit/bc07f43b115066f6077606df8f59379777f2a917)) + - improve error message if action has failed + ([dacc6542](https://github.com/Unitech/pm2/commit/dacc654207cbe494af0d12a3f9f27c3b16541802)) + - solve empty list when no process and try to update pm2 + ([89511846](https://github.com/Unitech/pm2/commit/8951184688c720ded5b4b46bd5b393c3793f9b03)) + - #3485 fix issue when there is empty dump file + ([f2523f6a](https://github.com/Unitech/pm2/commit/f2523f6a6b9d8b61ba6ace7b89a0353bee76360b)) + - #3456 use homedir() instead of process.env.HOME, make module installation work on windows + ([1e001732](https://github.com/Unitech/pm2/commit/1e0017325fc8cf658263fb4e02c7bf8912f422b3)) + + + + +## Features + - add support for openbsd rc.d init scripts + ([fdeb0c32](https://github.com/Unitech/pm2/commit/fdeb0c327afd91b113b214c4c4de187848f9f1cb)) + - add kill_retry_time argument + ([b2cc0031](https://github.com/Unitech/pm2/commit/b2cc003114b44f1a9a31876ee4a2f4cb91e210b3)) + + - **bin/pm2** + - improve usage + ([2c310084](https://github.com/Unitech/pm2/commit/2c310084453dd7b1546957e59b1fc7ef964d425b)) + + + + +## Refactor + - use @pm2/js-api for login/register on pm2.io via CLI + ([cb6521ac](https://github.com/Unitech/pm2/commit/cb6521ac32f4737c42fc97fef972960bfe16c829)) + - keymetrics examples + ([109b331d](https://github.com/Unitech/pm2/commit/109b331ddf37e061d1890ef952f4cd167ce53f64)) + - faster cli with less require + ([ee5e6a06](https://github.com/Unitech/pm2/commit/ee5e6a06cbf93f2d1fa7fa022d6bdcad55a39695)) + - replace fs-extra with node calls + ([4576b4c9](https://github.com/Unitech/pm2/commit/4576b4c97bc685c9d774018d6b29c918abd7cb8d)) + - centralize SECRET/PUBLIC/MACHINE_NAME + change some wordings + ([d0a2a30e](https://github.com/Unitech/pm2/commit/d0a2a30e4110496b178199fb33e026d6402dd00d)) + - remove test deported to keymetrics-agent + ([299a52a2](https://github.com/Unitech/pm2/commit/299a52a253d70edcde23cbd7e0c201d492984df4)) + - parallel test v1 + ([08612de5](https://github.com/Unitech/pm2/commit/08612de5b7893a004ae33ed77fcb2ee3ff7b2251)) + - e2e test rewrite + ([2b9ffd4e](https://github.com/Unitech/pm2/commit/2b9ffd4eb493f1ff32c979e3811f4f1fedfae97d)) + - drop gracefullreload + ([bb57c76d](https://github.com/Unitech/pm2/commit/bb57c76d4191343925013d4353299092d80732c9)) + - add node 4.x support + ([d322dd00](https://github.com/Unitech/pm2/commit/d322dd00de0f527224c027b4fec5e86f12fd69ed)) + - create alias method instead of modify prototype + ([6d8f0dfa](https://github.com/Unitech/pm2/commit/6d8f0dfae8106deb2fee0a7ae15b6ca9802a066d)) + - change safety var to const + ([047aa494](https://github.com/Unitech/pm2/commit/047aa494d5c4dd4342915766b54d673db0d5cdf1)) + - drop some 0.x patch + ([0cab8880](https://github.com/Unitech/pm2/commit/0cab8880ffa362cf27ab7d7b6a64d6b478dce7cd)) + - remove prototype from API and create method + ([9552bd61](https://github.com/Unitech/pm2/commit/9552bd61b72692beb620a91765ad440cdf6abefe)) + - transform API into class + ([e3831f95](https://github.com/Unitech/pm2/commit/e3831f95c8d71f98e8840da37f7e883727eccd59)) + - name tests well + ([c3ccc651](https://github.com/Unitech/pm2/commit/c3ccc651d09ed7291090f516637b75bda99ff71c)) + - refactor e2e one line parallel + ([93802711](https://github.com/Unitech/pm2/commit/938027117cdb2f300ee772ab27f008cbe22a4b19)) + - e2e rename + ([8a7db95a](https://github.com/Unitech/pm2/commit/8a7db95aabc8437f292af0316cec81ab80ec41f5)) + - change params + ([282186f2](https://github.com/Unitech/pm2/commit/282186f24b19b010999f7c7c49750935ef19c190)) + - parallelize bash test + ([d4b4375e](https://github.com/Unitech/pm2/commit/d4b4375e16fe7ac463b252702da662d3a21bf8b4)) + + + + +## Test + - adapt test to new api + ([7a275e27](https://github.com/Unitech/pm2/commit/7a275e279ea01b1239e9dd8b9cf8e088e407b96d)) + - refactor before/after + ([b85ca3ca](https://github.com/Unitech/pm2/commit/b85ca3caa3c68e18f7ce6954cc85e90a9d33efef)) + - 3 concurrent jobs + ([472aba34](https://github.com/Unitech/pm2/commit/472aba3499ff2d9d0eb834e819410026b1a44503)) + - move test + ([9c973324](https://github.com/Unitech/pm2/commit/9c9733246dbe6afff1b488bc3ba3b6fea3877ea5)) + - move test + ([952b7631](https://github.com/Unitech/pm2/commit/952b7631d19e1074ea73cc7a67bbaefe20950603)) + - fix test with km_link + ([23fd8ecf](https://github.com/Unitech/pm2/commit/23fd8ecfea9b2bf61359f62a8e6e1a582c3b0d6e)) + + + + +## Chore + - shorten ecosystem file + ([992a0452](https://github.com/Unitech/pm2/commit/992a045227aed559e708ac4e6bb3f54beabe48e0)) + - change motd wording + ([aa183ba1](https://github.com/Unitech/pm2/commit/aa183ba19d88777d82619aa40499c2661d67879e)) + - merge master in development + ([0e4453d9](https://github.com/Unitech/pm2/commit/0e4453d9cc789aa08ee778ff400572337e90d2e3)) + - keymetrics -> pm2 + ([2c8170c2](https://github.com/Unitech/pm2/commit/2c8170c25e231eb8827bb0944b76c2f4b041d84e)) + - upgrade all modules + keymetrics-agent -> pm2/agent + increase version enabling v8-compile-cache + ([53ca18c1](https://github.com/Unitech/pm2/commit/53ca18c12868ab177b60a4edff2ccaa8127e301f)) + - pm2.io -> @pm2/io + ([ae098962](https://github.com/Unitech/pm2/commit/ae098962df35eee7f482dc0a514fd29a02a5f4ad)) + - right names as pm2 maintainers + ([e8cd7131](https://github.com/Unitech/pm2/commit/e8cd7131a6b9c9d497a2079bcbfc03770a753a06)) + - add changelog generation into contributing.md + ([d77bfbc3](https://github.com/Unitech/pm2/commit/d77bfbc3c8929851ee19ea604b2a6481d03771e3)) + - cache node_modules + ([81627e94](https://github.com/Unitech/pm2/commit/81627e94c72efa1f4d726e20bbf67f0bbd5c116f)) + - clone last 5 commits + ([dad38ed1](https://github.com/Unitech/pm2/commit/dad38ed1bae849147f66e44186cd71c4b9cb022d)) + - delete old stagnating pmx inside test + ([36834c2c](https://github.com/Unitech/pm2/commit/36834c2c00d496e04c38abaca30202eb650015c4)) + - pmx -> pm2.io + ([adcbebc3](https://github.com/Unitech/pm2/commit/adcbebc3f6419cd97c5ea99f3c3a6789585bda66)) + - updgrade pmx-2 + ([eeeb2988](https://github.com/Unitech/pm2/commit/eeeb2988f8886e405aea107db3b888fc1fc929f8)) + - disable legacy test + ([13723bd9](https://github.com/Unitech/pm2/commit/13723bd938d0e6fb1cbf35f15eabe91c52d87b58)) + - remove test for pmx alert system + ([c43414a6](https://github.com/Unitech/pm2/commit/c43414a63438d724b8099eb531ec72bab23b8ca2)) + - sync from master + ([3424ee27](https://github.com/Unitech/pm2/commit/3424ee27870feaf62fdf4509cce9015f8b1a8a2e)) + - add unique id for each process + ([85a5ee0f](https://github.com/Unitech/pm2/commit/85a5ee0f1fd16da9635fb4b16ddcd8d53aca8224)) + - use npm install for CI as yarn has issue with npm + ([52902186](https://github.com/Unitech/pm2/commit/5290218626af815f6cae8173bc78d21881a4dda8)) + - remove unused dependency + ([830fc15f](https://github.com/Unitech/pm2/commit/830fc15fad1aee95e65b2681482b03369f1f97d7)) + - upgrade PM2 to 3.0 + ([4bc2eb4c](https://github.com/Unitech/pm2/commit/4bc2eb4c9a8179b9ae38438e98ce7650a91b64db)) + - remove unused console.log + ([33db5084](https://github.com/Unitech/pm2/commit/33db5084814ae7940c90b7f933f9514d28008b78)) + - wording on error message + ([c251c8c9](https://github.com/Unitech/pm2/commit/c251c8c97e6f18aae584cac6b7f3c83cf4f2de9c)) + - revert PR #3496 + ([aae1d55e](https://github.com/Unitech/pm2/commit/aae1d55e410c4dcfbbca83eaabbdf1a65d55f3aa)) + - fix issue with snapshot command + remove command forceGc + ([97fd1010](https://github.com/Unitech/pm2/commit/97fd1010d005e59f2411042fa95891f9717fa8b7)) + - wording on error message + ([5f78ecbf](https://github.com/Unitech/pm2/commit/5f78ecbf90f9f46a7feb2a169968e86b0ecac91e)) + - drop 0.12 test on travis + ([beb6e487](https://github.com/Unitech/pm2/commit/beb6e48787c39c66569141d0fd8d090736114d23)) + - downgrade promptly + ([074a7a40](https://github.com/Unitech/pm2/commit/074a7a407a31b4d88442f5834d253d62f4e543b8)) + - remove coffee and livescript dependencies + ([13d6565c](https://github.com/Unitech/pm2/commit/13d6565c72e3596d05f87bfc8be15d3ee45fb279)) + - upgrade module version and engine version + ([84796956](https://github.com/Unitech/pm2/commit/84796956347ca638750fe89cb5545e2a90a0f2c2)) + + + + +## Branchs merged + - Merge branch 'development' into chore/dev-cache-node-modules + ([146c4e11](https://github.com/Unitech/pm2/commit/146c4e113c88e8ade17c7558c8e14cf523a3b2d6)) + - Merge branch 'development' of https://github.com/Unitech/pm2 into new-agent + ([3514e7fa](https://github.com/Unitech/pm2/commit/3514e7fac624bb83b4cc22651ebc05385f9c284d)) + - Merge branch 'development' into master + ([f5668331](https://github.com/Unitech/pm2/commit/f5668331dbe7346304258317a3b84450f421ed03)) + - Merge branch 'development' into new-usage-cli + ([4ae27694](https://github.com/Unitech/pm2/commit/4ae27694e34c4bc6ed389566d71fc5ec48b69652)) + - Merge branch 'Eywek-improv/agent' into new-agent + ([3e259dd1](https://github.com/Unitech/pm2/commit/3e259dd1d6bb96ea41897c49f3a84557c00c7dad)) + - Merge branch 'ecosystem-documentation' of github.com:rmonnier/pm2 into ecosystem-documentation + ([98348955](https://github.com/Unitech/pm2/commit/98348955a6eb3a9cd524b991bd1dd6ed03d2c857)) + - Merge branch 'development' into ecosystem-documentation + ([40157784](https://github.com/Unitech/pm2/commit/40157784a63bcb0e744d4ed56f6c687e28379fdd)) + - Merge branch 'inspect_mode' of github.com:Unitech/pm2 into inspect_mode + ([7e1494c7](https://github.com/Unitech/pm2/commit/7e1494c7f7971aaf1f4d00d2ee691c3c41775001)) + - Merge branch 'development' of github.com:Unitech/pm2 into development + ([48f81a8b](https://github.com/Unitech/pm2/commit/48f81a8b2f6f0db39edd86083fb369b74845c387)) + - Merge branch 'development' into master + ([47e54109](https://github.com/Unitech/pm2/commit/47e5410987ab3d824a34c062d70c24ab686e57db)) + - Merge branch 'development' into module_install_windows + ([7b82fb91](https://github.com/Unitech/pm2/commit/7b82fb916ed453c1c263bae43c962f6a5294d810)) + - Merge branch 'development' into module_install_windows + ([80b0495f](https://github.com/Unitech/pm2/commit/80b0495f63d1224b850af4b14cdeb055e3fef50b)) + + + + +## Pull requests merged + - Merge pull request #3726 from soyuka/fix-list + ([0255c5a6](https://github.com/Unitech/pm2/commit/0255c5a6ab1b8a8f609d2183d998695b8c42838d)) + - Merge pull request #3725 from soyuka/fix-list + ([a39eb4f8](https://github.com/Unitech/pm2/commit/a39eb4f806e87565f53758a19f0ee289b6489b67)) + - Merge pull request #3718 from AaronM04/openbsd-init-script + ([85458261](https://github.com/Unitech/pm2/commit/85458261d2673c609cb252d64ad4dfbaa466d848)) + - Merge pull request #3721 from Unitech/io_conf + ([70ec1f81](https://github.com/Unitech/pm2/commit/70ec1f81eae089f75e82723fde7b0b3926d0a9bc)) + - Merge pull request #3716 from Unitech/io_conf + ([0bc000b9](https://github.com/Unitech/pm2/commit/0bc000b9aae7dd37b456bc2d4fbc9eb4a9f047ef)) + - Merge pull request #3714 from Unitech/definition + ([d8cff0de](https://github.com/Unitech/pm2/commit/d8cff0dec5160a620d1512ff56726c073368d1a4)) + - Merge pull request #3700 from Unitech/report_error + ([4b2cad40](https://github.com/Unitech/pm2/commit/4b2cad407b76994e978074a2a3825fe70656304d)) + - Merge pull request #3670 from Unitech/changelog + ([4bcbcce1](https://github.com/Unitech/pm2/commit/4bcbcce16ced596f6ca2bab2b77d608a174a7c1a)) + - Merge pull request #3662 from DanielRuf/chore/dev-cache-node-modules + ([540590ee](https://github.com/Unitech/pm2/commit/540590ee056b44eed3b688a7b0b16ca78ec82cd9)) + - Merge pull request #3663 from DanielRuf/chore/dev-clone-last-5-commits + ([bdf95fc9](https://github.com/Unitech/pm2/commit/bdf95fc997f9ab2995b23668f25f11b6e98b5c47)) + - Merge pull request #3584 from ngtmuzi/development + ([33984b64](https://github.com/Unitech/pm2/commit/33984b64a2969ca4a3a5913f0f7da0242b6c5ec1)) + - Merge pull request #3500 from Unitech/test-parallel + ([da56c7af](https://github.com/Unitech/pm2/commit/da56c7aff18d3a38b3ad068b22cd75b290bac9d0)) + - Merge pull request #3539 from KimSeongIl/master + ([1325704d](https://github.com/Unitech/pm2/commit/1325704d95d324e56b0ebc86aed8137e0d0aa450)) + - Merge pull request #3556 from N-Nagorny/logs-smart-app-name-cutting + ([bfddf4fd](https://github.com/Unitech/pm2/commit/bfddf4fdef5ec293119d850cc2532ac5d6490ae3)) + - Merge pull request #3553 from Unitech/fix_tracing_not_working + ([9d51fe08](https://github.com/Unitech/pm2/commit/9d51fe0819182339f3a6a4aee7ea603ea3f4dd76)) + - Merge pull request #3549 from Eywek/new-agent + ([2f04027b](https://github.com/Unitech/pm2/commit/2f04027b536094d192b399677b3a113102f06b8e)) + - Merge pull request #3548 from rmonnier/start-ecosystem-default + ([55412f26](https://github.com/Unitech/pm2/commit/55412f263250395de0085144932cfe06b8c7180d)) + - Merge pull request #3546 from soyuka/improve-monitor-perf + ([e4e29233](https://github.com/Unitech/pm2/commit/e4e29233f99db36462a6e8f48eb8ebd3d2fd9fa5)) + - Merge pull request #3534 from rmonnier/new-usage-cli + ([5dfba8a4](https://github.com/Unitech/pm2/commit/5dfba8a4491f0bb83f2879915f0c4b164be2552c)) + - Merge pull request #3542 from rmonnier/default-start-ecosystem + ([c65595f4](https://github.com/Unitech/pm2/commit/c65595f4a70659e1e0d753e6c28a1fcedf45a91a)) + - Merge pull request #3545 from rmonnier/default-ecosystem + ([b3718656](https://github.com/Unitech/pm2/commit/b3718656f630aa54880343d9742534a2a508daec)) + - Merge pull request #3543 from rmonnier/ecosystem-documentation + ([a60580a1](https://github.com/Unitech/pm2/commit/a60580a12b4a0066c8df6620317fbc8bf599b0b6)) + - Merge pull request #3541 from soyuka/development + ([67e7a015](https://github.com/Unitech/pm2/commit/67e7a015cabaa7b08206a3b1bf9c0399af88f76b)) + - Merge pull request #3511 from Unitech/inspect_mode + ([75fb87f8](https://github.com/Unitech/pm2/commit/75fb87f8a1c46a6db8e974b421e857175e69b535)) + - Merge pull request #3517 from Unitech/polyfill_fs_copy_node4 + ([524f5494](https://github.com/Unitech/pm2/commit/524f54948de5080632d43bb512038d7bd7271619)) + - Merge pull request #3516 from Unitech/drop_unused_feature + ([9436f11a](https://github.com/Unitech/pm2/commit/9436f11aeecfc07e77aa9d6b108df4478b43402e)) + - Merge pull request #3510 from Unitech/dump_refacto + ([674e4469](https://github.com/Unitech/pm2/commit/674e4469554e6a765bb3d57a3c083e6ab53b20cc)) + - Merge pull request #3501 from Unitech/refactor_api + ([9f2c4ca4](https://github.com/Unitech/pm2/commit/9f2c4ca4c9eadf6c7730e3889c72e908cd2d8f5d)) + - Merge pull request #3496 from rmonnier/master + ([829cc303](https://github.com/Unitech/pm2/commit/829cc3032b2d61e20f7a2e7d1d819c0ddc0845e8)) + - Merge pull request #3484 from Unitech/pull_by_name + ([24d29404](https://github.com/Unitech/pm2/commit/24d294049008a0d01b2bc407b9b2b880d5843fbd)) + - Merge pull request #3482 from Unitech/mjs_support + ([ebe7b048](https://github.com/Unitech/pm2/commit/ebe7b0487218557858aaa98527360eca1776b140)) + - Merge pull request #3495 from Unitech/module_install_windows + ([e9c625d3](https://github.com/Unitech/pm2/commit/e9c625d3088c71eef4237ecd866b806957c61815)) + - Merge pull request #3507 from cheapsteak/patch-1 + ([a49287d6](https://github.com/Unitech/pm2/commit/a49287d6a1d22b39270e2d05dee2a17c0ed55797)) + + + + ## 2.10.4 ( Thu May 17 2018 14:32:40 GMT+0200 (CEST) ) @@ -611,7 +1074,7 @@ pm2.destroy(cb) // Close and delete all pm2 related files of this session - keymetrics linking after pm2 update is done once all apps are started - pm2 list processes are now sorted by name instead id - #2248 livescript support added in development mode -- The client/server file called Satan.js does not exists anymore. It has been replaced by the file combo ./lib/Client.js and ./lib/Daemon.js +- The client/server file called Satan.js does not exist anymore. It has been replaced by the file combo ./lib/Client.js and ./lib/Daemon.js - PM2 --no-daemon is better now ### Breaking change diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21dda9d79..e786fb8b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -111,8 +111,8 @@ npm install git-changelog -g ### usage -Edit .changelogrc -Change "version_name" to the next version to release (example 1.1.2). +Edit .changelogrc +Change "version_name" to the next version to release (example 1.1.2). Change "tag" to the latest existing tag (example 1.1.1). Run the following command into pm2 directory diff --git a/README.md b/README.md index 445b4e9c6..f7c07a6e9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- + pm2 logo
@@ -9,12 +9,12 @@ Runtime Edition

- + npm version - - NPM Downloads + + npm version @@ -38,10 +38,10 @@ $ pm2 start app.js PM2 is constantly assailed by [more than 1800 tests](https://travis-ci.org/Unitech/pm2). -Official website: [http://pm2.keymetrics.io/](http://pm2.keymetrics.io/) +Official website: [https://pm2.io/doc/](https://pm2.io/doc/) Works on Linux (stable) & macOS (stable) & Windows (stable). -All Node.js versions are supported starting Node.js 0.12. +All Node.js versions are supported starting Node.js 4.X. [![NPM](https://nodei.co/npm/pm2.png?downloads=true&downloadRank=true)](https://nodei.co/npm/pm2/) @@ -63,36 +63,33 @@ $ pm2 start app.js Your app is now daemonized, monitored and kept alive forever. -[More about Process Management](http://pm2.keymetrics.io/docs/usage/process-management/) +[More about Process Management](https://pm2.io/doc/en/runtime/guide/process-management/?utm_source=github) ### Container Support -With the drop-in replacement command for `node`, called `pm2-runtime`, run your Node.js application in a proper production environment. -There is also an [officialy supported Docker image](https://hub.docker.com/r/keymetrics/pm2/). - +With the drop-in replacement command for `node`, called `pm2-runtime`, run your Node.js application in a hardened production environment. Using it is seamless: ``` -FROM keymetrics/pm2:latest-alpine -[...] +RUN npm install pm2 -g CMD [ "pm2-runtime", "npm", "--", "start" ] ``` -[Read More about the dedicated integration](http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/) +[Read More about the dedicated integration](https://pm2.io/doc/en/runtime/integration/docker/?utm_source=github) -### Managing a Process +### Managing Applications Once applications are started you can manage them easily: ![Process listing](https://github.com/unitech/pm2/raw/master/pres/pm2-list.png) -To list all running processes: +To list all running applications: ```bash $ pm2 list ``` -Managing processes is straightforward: +Managing apps is straightforward: ```bash $ pm2 stop @@ -100,21 +97,21 @@ $ pm2 restart $ pm2 delete ``` -To have more details on a specific process: +To have more details on a specific application: ```bash $ pm2 describe ``` -To monitor logs, custom metrics, process information: +To monitor logs, custom metrics, application information: ```bash $ pm2 monit ``` -[More about Process Management](http://pm2.keymetrics.io/docs/usage/process-management/) +[More about Application Management](https://pm2.io/doc/en/runtime/guide/process-management/?utm_source=github) -### Cluster Mode: Node.js Load Balancing & Hot Reload +### Cluster Mode: Node.js Load Balancing & Zero Downtime Reload The Cluster mode is a special mode when starting a Node.js application, it starts multiple processes and load-balance HTTP/TCP/UDP queries between them. This increase overall performance (by a factor of x10 on 16 cores machines) and reliability (faster socket re-balancing in case of unhandled errors). @@ -126,7 +123,7 @@ $ pm2 start api.js -i `` can be `'max'`, `-1` (all cpu minus 1) or a specified number of instances to start. -**Hot Reload** +**Zero Downtime Reload** Hot Reload allows to update an application without any downtime: @@ -150,182 +147,141 @@ Monitor all processes launched straight from the command line: $ pm2 monit ``` -### Monitor PM2 and Applications with our SaaS - -Once you deploy your application in production, you can monitor, debug and profile it externally with our [SaaS Monitoring](https://keymetrics.io). +### Log Management -To start monitoring applications from the terminal: +To consult logs just type the command: ```bash -$ pm2 register +$ pm2 logs ``` -[More about PM2 Monitoring](http://docs.keymetrics.io/) - -### Expose Custom Metrics - -To get more insights on how your application behave, plug custom metrics inside your code and monitor them with the `pm2 monit` command: +Standard, Raw, JSON and formated output are available. -In your project install [pmx](https://github.com/keymetrics/pmx): +Examples: ```bash -$ npm install pmx --save +$ pm2 logs APP-NAME # Display APP-NAME logs +$ pm2 logs --json # JSON output +$ pm2 logs --format # Formated output + +$ pm2 flush # Flush all logs +$ pm2 reloadLogs # Reload all logs ``` -Then plug a custom metric: +[More about log management](https://pm2.io/doc/en/runtime/guide/log-management/?utm_source=github) -```javascript -var Probe = require('pmx').probe(); +### Startup Hooks Generation -var counter = 1; +PM2 can generates and configure a Startup Script to keep PM2 and your processes alive at every server restart. -var metric = Probe.metric({ - name : 'Counter', - value : function() { - return counter; - } -}); +Init Systems Supported: **systemd**, **upstart**, **launchd**, **rc.d** -setInterval(function() { - counter++; -}, 1000); +```bash +# Generate Startup Script +$ pm2 startup + +# Freeze your process list across server restart +$ pm2 save + +# Remove Startup Script +$ pm2 unstartup ``` -Then to see the metric type from in the terminal: +[More about Startup Hooks](https://pm2.io/doc/en/runtime/guide/startup-hook/?utm_source=github) + +### Updating PM2 ```bash -$ pm2 monitor +# Install latest PM2 version +$ npm install pm2@latest -g +# Save process list, exit old PM2 & restore all processes +$ pm2 update ``` -Metric, Counter, Histogram and Meters are [available](http://pm2.keymetrics.io/docs/usage/process-metrics/) - -### Log facilities +*PM2 updates are seamless* -![Monit](https://github.com/unitech/pm2/raw/master/pres/pm2-logs.png) +## Ready to Scale? Go further with PM2 Plus! -Displaying logs of a specified process or all processes, in real time is easy: +
+
+
+
+ PM2 plus logo + +
+
+PM2
+ Plus Edition +

+
```bash -$ pm2 logs ['all'|app_name|app_id] [--json] [--format] [--raw] +$ pm2 plus ``` -Standard, Raw, JSON and formated output are available. +Once you scale you need to make sure that your application is running properly, without bugs, performance issues and without downtimes. -Examples: +That's why we created PM2 Plus. It's a set of advanced features for both hardening the PM2 Runtime and monitoring applications in production. -```bash -$ pm2 logs APP-NAME # Display APP-NAME logs -$ pm2 logs --json # JSON output -$ pm2 logs --format # Formated output +With PM2 Plus you get: +- A Real-time Monitoring Web Interface +- Smart Exception Reporting +- Production Profiling for Memory and CPU +- PM2 Runtime High Availability Fallback -$ pm2 flush # Flush all logs -$ pm2 reloadLogs # Reload all logs -``` +And much more like realtime logs, custom metrics, remote actions... -[More about log management](http://pm2.keymetrics.io/docs/usage/log-management/) +You can also create account via the app: [here](https://app.pm2.io/) -### Startup script generation +### PM2 Plus Features -PM2 can generates and configure a startup script to keep PM2 and your processes alive at every server restart. +**Visual Memory Snapshots**: -Supports init systems like: **systemd** (Ubuntu 16, CentOS, Arch), **upstart** (Ubuntu 14/12), **launchd** (MacOSx, Darwin), **rc.d** (FreeBSD). +![https://raw.githubusercontent.com/Unitech/pm2/master/pres/memory-profiling.png](https://raw.githubusercontent.com/Unitech/pm2/master/pres/memory-profiling.png) -```bash -# Auto detect init system + generate and setup PM2 boot at server startup -$ pm2 startup +**CPU FlameGraphs**: -# Manually specify the startup system -# Can be: systemd, upstart, launchd, rcd -$ pm2 startup [platform] +![https://raw.githubusercontent.com/Unitech/pm2/master/pres/flamegraph.png](https://raw.githubusercontent.com/Unitech/pm2/master/pres/flamegraph.png) -# Disable and remove PM2 boot at server startup -$ pm2 unstartup -``` +**Multi Server Overview**: -To save/freeze a process list on reboot: +![https://raw.githubusercontent.com/Unitech/pm2/master/pres/pm2-ls-multi.png](https://raw.githubusercontent.com/Unitech/pm2/master/pres/pm2-ls-multi.png) -```bash -$ pm2 save -``` +
+ +
-[More about startup scripts](http://pm2.keymetrics.io/docs/usage/startup/) +### PM2 Plus: Expose Custom Metrics -### Commands Cheatsheet +To get more insights on how your application behave, plug custom metrics inside your code and monitor them with the `pm2 monit` command: + +In your project install [pm2-io-pm](https://github.com/keymetrics/pm2-io-apm): ```bash -# General -$ npm install pm2 -g # Install PM2 -$ pm2 start app.js # Start, Daemonize and auto-restart application (Node) -$ pm2 start app.py # Start, Daemonize and auto-restart application (Python) -$ pm2 start npm -- start # Start, Daemonize and auto-restart Node application - -# Cluster Mode (Node.js only) -$ pm2 start app.js -i 4 # Start 4 instances of application in cluster mode - # it will load balance network queries to each app -$ pm2 reload all # Zero Second Downtime Reload -$ pm2 scale [app-name] 10 # Scale Cluster app to 10 process - -# Process Monitoring -$ pm2 list # List all processes started with PM2 -$ pm2 list --sort= # Sort all processes started with PM2 -$ pm2 monit # Display memory and cpu usage of each app -$ pm2 show [app-name] # Show all information about application - -# Log management -$ pm2 logs # Display logs of all apps -$ pm2 logs [app-name] # Display logs for a specific app -$ pm2 logs --json # Logs in JSON format -$ pm2 flush -$ pm2 reloadLogs - -# Process State Management -$ pm2 start app.js --name="api" # Start application and name it "api" -$ pm2 start app.js -- -a 34 # Start app and pass option "-a 34" as argument -$ pm2 start app.js --watch # Restart application on file change -$ pm2 start script.sh # Start bash script -$ pm2 start app.json # Start all applications declared in app.json -$ pm2 reset [app-name] # Reset all counters -$ pm2 stop all # Stop all apps -$ pm2 stop 0 # Stop process with id 0 -$ pm2 restart all # Restart all apps -$ pm2 delete all # Kill and delete all apps -$ pm2 delete 0 # Delete app with id 0 - -# Startup/Boot management -$ pm2 startup # Detect init system, generate and configure pm2 boot on startup -$ pm2 save # Save current process list -$ pm2 resurrect # Restore previously saved processes -$ pm2 unstartup # Disable and remove startup system - -$ pm2 update # Save processes, kill PM2 and restore processes -$ pm2 init # Generate a sample js configuration file - -# Deployment -$ pm2 deploy app.json prod setup # Setup "prod" remote server -$ pm2 deploy app.json prod # Update "prod" remote server -$ pm2 deploy app.json prod revert 2 # Revert "prod" remote server by 2 - -# Module system -$ pm2 module:generate [name] # Generate sample module with name [name] -$ pm2 install pm2-logrotate # Install module (here a log rotation system) -$ pm2 uninstall pm2-logrotate # Uninstall module -$ pm2 publish # Increment version, git push and npm publish +$ npm install @pm2/io --save ``` -Also check out the [example folder](https://github.com/Unitech/pm2/tree/master/examples) to discover all features. +Then plug a custom metric: -## Updating PM2 +```javascript +const io = require('@pm2/io'); -```bash -# Install latest PM2 version -$ npm install pm2@latest -g -# Save process list, exit old PM2 & restore all processes -$ pm2 update -``` +let counter = 1; -*PM2 updates are seamless* +const latency = io.metric({ + name : 'Counter', + value : function() { + return counter; + } +}); + +setInterval(() => { + counter++; +}, 1000); -## Module system +``` + +### PM2 Plus: Module system PM2 embeds a simple and powerful module system. Installing a module is straightforward: @@ -335,33 +291,8 @@ $ pm2 install Here are some PM2 compatible modules (standalone Node.js applications managed by PM2): -[**pm2-logrotate**](https://github.com/pm2-hive/pm2-logrotate) auto rotate logs of PM2 and applications managed
-[**pm2-webshell**](https://github.com/pm2-hive/pm2-webshell) expose a fully capable terminal in browsers
-[**pm2-server-monit**](https://github.com/pm2-hive/pm2-server-monit) monitor your server health
- -[Writing your own module](http://pm2.keymetrics.io/docs/advanced/pm2-module-system/) - -## Keymetrics monitoring - -[![Keymetrics Dashboard](https://keymetrics.io/assets/images/application-demo.png)](https://app.keymetrics.io/#/register) - -If you manage your NodeJS app with PM2, Keymetrics makes it easy to monitor and manage apps across servers. -Feel free to try it: - -[Discover the monitoring dashboard for PM2](https://app.keymetrics.io/#/register) - -Thanks in advance and we hope that you like PM2! - -## More about PM2 - -- [Application Declaration via JS files](http://pm2.keymetrics.io/docs/usage/application-declaration/) -- [Watch & Restart](http://pm2.keymetrics.io/docs/usage/watch-and-restart/) -- [PM2 API](http://pm2.keymetrics.io/docs/usage/pm2-api/) -- [Deployment workflow](http://pm2.keymetrics.io/docs/usage/deployment/) -- [PM2 on Heroku/Azure/App Engine](http://pm2.keymetrics.io/docs/usage/use-pm2-with-cloud-providers/) -- [PM2 auto completion](http://pm2.keymetrics.io/docs/usage/auto-completion/) -- [Using PM2 in ElasticBeanStalk](http://pm2.keymetrics.io/docs/tutorials/use-pm2-with-aws-elastic-beanstalk/) -- [PM2 Tutorial Series](https://futurestud.io/tutorials/pm2-utility-overview-installation) +[**pm2-logrotate**](https://www.npmjs.com/package/pm2-logrotate) automatically rotate logs and limit logs size
+[**pm2-server-monit**](https://www.npmjs.com/package/pm2-server-monit) monitor the current server with more than 20+ metrics and 8 actions
## CHANGELOG @@ -374,6 +305,6 @@ Thanks in advance and we hope that you like PM2! ## License PM2 is made available under the terms of the GNU Affero General Public License 3.0 (AGPL 3.0). -We can deliver other licenses, for more informations [contact sales](mailto:sales@keymetrics.io). +For other licenses [contact us](mailto:contact@keymetrics.io). [![GA](https://ga-beacon.appspot.com/UA-51734350-7/pm2/readme?pixel&useReferer)](https://github.com/igrigorik/ga-beacon) diff --git a/bin/pm2 b/bin/pm2 index c81ad5aef..d7826ef15 100755 --- a/bin/pm2 +++ b/bin/pm2 @@ -8,16 +8,16 @@ if (semver.satisfies(process.versions.node, '>= 6.0.0')) process.env.PM2_USAGE = 'CLI'; -var cst = require('../constants.js'); +var cst = require('../constants.js'); -var commander = require('commander'); -var chalk = require('chalk'); -var async = require('async'); +var commander = require('commander'); +var chalk = require('chalk'); +var forEachLimit = require('async/forEachLimit'); -var debug = require('debug')('pm2:cli'); -var PM2 = require('../lib/API.js'); -var pkg = require('../package.json'); -var tabtab = require('../lib/completion.js'); +var debug = require('debug')('pm2:cli'); +var PM2 = require('../lib/API.js'); +var pkg = require('../package.json'); +var tabtab = require('../lib/completion.js'); // Early detection of silent to avoid printing motd if (process.argv.indexOf('--silent') > -1 || @@ -198,7 +198,7 @@ if (_arr.indexOf('--no-daemon') > -1) { // Start daemon if it does not exist // // Function checks if --no-daemon option is present, - // and starts daemon in the same process if it does not exists + // and starts daemon in the same process if it does not exist // console.log('pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)'); @@ -296,7 +296,7 @@ commander.command('start [name|file|ecosystem|id...]') if (cmd.length === 0) { cmd = [cst.APP_CONF_DEFAULT_FILE]; } - async.forEachLimit(cmd, 1, function(script, next) { + forEachLimit(cmd, 1, function(script, next) { pm2.start(script, commander, next); }, function(err) { pm2.speedList(err ? 1 : 0); @@ -347,7 +347,7 @@ commander.command('stop ') .option('--watch', 'Stop watching folder for changes') .description('stop a process') .action(function(param) { - async.forEachLimit(param, 1, function(script, next) { + forEachLimit(param, 1, function(script, next) { pm2.stop(script, next); }, function(err) { pm2.speedList(err ? 1 : 0); @@ -363,7 +363,7 @@ commander.command('restart ') .action(function(param) { // Commander.js patch param = patchCommanderArg(param); - async.forEachLimit(param, 1, function(script, next) { + forEachLimit(param, 1, function(script, next) { pm2.restart(script, commander, next); }, function(err) { pm2.speedList(err ? 1 : 0); @@ -434,7 +434,7 @@ commander.command('delete ') pm2.delete(param, 'pipe'); }); } else - async.forEachLimit(name, 1, function(script, next) { + forEachLimit(name, 1, function(script, next) { pm2.delete(script,'', next); }, function(err) { pm2.speedList(err ? 1 : 0); @@ -563,14 +563,13 @@ commander.command('report') }); // -// Keymetrics CLI integratio +// PM2 I/O // commander.command('link [secret] [public] [name]') - .alias('interact') .option('--info-node [url]', 'set url info node') .option('--ws', 'websocket mode') .description('link with the pm2 monitoring dashboard') - .action(pm2._pre_interact.bind(pm2)); + .action(pm2.linkManagement.bind(pm2)); commander.command('unlink') .description('unlink with the pm2 monitoring dashboard') @@ -596,16 +595,75 @@ commander.command('open') pm2.openDashboard(); }); -commander.command('register') - .description('register on pm2 monitoring') - .action(function(name) { - pm2.registerToKM(); +function connect(type, sec, pub, name, _opts) { + var opts = { + infoNode: _opts.infoNode, + discrete: _opts.discrete, + installAll: _opts.installAll, + public: pub, + secret: sec, + name: name, + type: type, + ws: true + } + + if (sec == 'link' || sec == 'relink' || (sec == null && pub == null && pm2.gl_is_km_linked)) { + return pm2.linkManagement(null, null, null, opts, function(err, dt) { + pm2.speedList() + }) + } + + if (sec == 'delete') { + return pm2.linkManagement('delete', null, null, opts, function(err, dt) { + pm2.clearSetup(opts, function() { + console.log(cst.PM2_IO_MSG + 'Agent disabled, modules removed, monitoring disabled'); + setTimeout(function() { + pm2.speedList() + }, 300) + }) + }) + } + + if (opts.public && opts.secret) + return pm2.linkManagement(opts.secret, opts.public, opts.name, opts, function(err, dt) { + pm2.minimumSetup(opts, function() { + console.log(cst.PM2_IO_MSG + 'Remote dashboard: https://app.pm2.io/#/r/' + dt.public_key); + pm2.speedList() + }) + }) + + pm2.register(opts); +} + +commander.command('enterprise [secret] [public] [name]') + .option('--info-node [url]', 'set url info node for on-premise pm2 plus') + .option('-d --discrete', 'silent mode') + .option('-a --install-all', 'install all modules (force yes)') + .description('enable pm2 enterprise') + .action(function(sec, pub, name, _opts) { + connect('enterprise', sec, pub, name, _opts) + }) + +commander.command('plus [secret] [public] [name]') + .alias('register') + .option('--info-node [url]', 'set url info node for on-premise pm2 plus') + .option('-d --discrete', 'silent mode') + .option('-a --install-all', 'install all modules (force yes)') + .description('enable pm2 plus') + .action(function(sec, pub, name, _opts) { + connect('plus', sec, pub, name, _opts) }); commander.command('login') - .description('use login to link with the pm2 monitoring dashboard') + .description('Login to pm2 plus') .action(function(name) { - pm2.loginToKM(); + connect('plus', null, null, null, {}) + }); + +commander.command('logout') + .description('Logout from pm2 plus') + .action(function(name) { + connect('plus', 'delete', null, null, {}) }); // @@ -804,12 +862,20 @@ commander.command('dashboard') // // Flushing command // + +commander.command('flush [api]') +.description('flush logs') +.action(function(api) { + pm2.flush(api); +}); + +/* old version commander.command('flush') .description('flush logs') .action(failOnUnknown(function() { pm2.flush(); })); - +*/ // // Reload all logs // diff --git a/changelogTemplate.md b/changelogTemplate.md index b82e71d2c..2d515ec67 100644 --- a/changelogTemplate.md +++ b/changelogTemplate.md @@ -1,8 +1,8 @@ <% if(logo) { %>pm2 logo <% } %> <% if(logo) { %># <%= title %> <% } %> -<% if(intro) { %><%= '\n' %><%= intro %><%= '\n' %><% } %> +<% if(intro) { %><%= '\n' %><%= intro %><%= '\n' %><% } %> <% if(version && (version.name || version.number)) { %>##<% if(version.name){%> <%= version.name %><% } %> <% if(version.date){ %>( <%= version.date %> )<% } %><%= '\n' %><% } %> -<% _.forEach(sections, function(section){ +<% _.forEach(sections, function(section){ if(section.commitsCount > 0) { %> ## <%= section.title %> <% _.forEach(section.commits, function(commit){ %> - <%= printCommit(commit, true) %><% }) %> diff --git a/constants.js b/constants.js index 3bbcb07cb..68a5d0298 100644 --- a/constants.js +++ b/constants.js @@ -25,6 +25,9 @@ var csts = { PREFIX_MSG_WARNING : chalk.yellow('[PM2][WARN] '), PREFIX_MSG_SUCCESS : chalk.cyan('[PM2] '), + PM2_IO_MSG : chalk.cyan('[PM2 I/O] '), + PM2_IO_MSG_ERR : chalk.red('[PM2 I/O] '), + TEMPLATE_FOLDER : p.join(__dirname, 'lib/templates'), APP_CONF_DEFAULT_FILE : 'ecosystem.config.js', @@ -60,8 +63,8 @@ var csts = { KEYMETRICS_ROOT_URL : process.env.KEYMETRICS_NODE || process.env.ROOT_URL || process.env.INFO_NODE || 'root.keymetrics.io', - KEYMETRICS_BANNER : '../lib/motd', - KEYMETRICS_UPDATE : '../lib/motd.update', + PM2_BANNER : '../lib/motd', + PM2_UPDATE : '../lib/API/pm2-plus/pres/motd.update', DEFAULT_MODULE_JSON : 'package.json', REMOTE_PORT_TCP : isNaN(parseInt(process.env.KEYMETRICS_PUSH_PORT)) ? 80 : parseInt(process.env.KEYMETRICS_PUSH_PORT), @@ -92,7 +95,7 @@ var csts = { WORKER_INTERVAL : process.env.PM2_WORKER_INTERVAL || 30000, KILL_TIMEOUT : process.env.PM2_KILL_TIMEOUT || 1600, PM2_PROGRAMMATIC : typeof(process.env.pm_id) !== 'undefined' || process.env.PM2_PROGRAMMATIC, - PM2_LOG_DATE_FORMAT : process.env.PM2_LOG_DATE_FORMAT !== undefined ? process.env.PM2_LOG_DATE_FORMAT : 'YYYY-MM-DD HH:mm:ss' + PM2_LOG_DATE_FORMAT : process.env.PM2_LOG_DATE_FORMAT !== undefined ? process.env.PM2_LOG_DATE_FORMAT : 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' }; diff --git a/examples/misc-examples/apps/killfast.json b/examples/misc-examples/apps/killfast.json index fbb8b0a98..f6fc13288 100644 --- a/examples/misc-examples/apps/killfast.json +++ b/examples/misc-examples/apps/killfast.json @@ -1,6 +1,6 @@ { "min_uptime" : "100", - "max_restarts" : "400", + "max_restarts" : "400", "name" : "auto-kill", "script" : "./examples/killfast.js" } diff --git a/examples/misc-examples/exit.js b/examples/misc-examples/exit.js index 23fb97f15..d32974ee1 100644 --- a/examples/misc-examples/exit.js +++ b/examples/misc-examples/exit.js @@ -1,5 +1,5 @@ -// process.on('exit', function() { +// process.on('exit', function() { // console.log('About to exit.'); // }); diff --git a/examples/sourcemap-auto-resolve/API.js b/examples/sourcemap-auto-resolve/API.js index 544138794..4ce93f39c 100644 --- a/examples/sourcemap-auto-resolve/API.js +++ b/examples/sourcemap-auto-resolve/API.js @@ -7,7 +7,8 @@ var commander = require('commander'); var fs = require('fs'); var path = require('path'); -var async = require('async'); +var eachLimit = require('async/eachLimit'); +var series = require('async/series'); var debug = require('debug')('pm2:cli'); var util = require('util'); var chalk = require('chalk'); @@ -317,7 +318,7 @@ API.prototype.reset = function(process_name, cb) { var that = this; function processIds(ids, cb) { - async.eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next) { + eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next) { that.Client.executeRemote('resetMetaProcessId', id, function(err, res) { if (err) console.error(err); Common.printOut(conf.PREFIX_MSG + 'Resetting meta for process id %d', id); @@ -777,7 +778,7 @@ API.prototype._startScript = function(script, opts, cb) { }); } - async.series([ + series([ restartExistingProcessName, restartExistingProcessId, restartExistingProcessPath @@ -916,7 +917,7 @@ API.prototype._startJson = function(file, opts, action, pipe, cb) { * Auto detect application already started * and act on them depending on action */ - async.eachLimit(Object.keys(proc_list), conf.CONCURRENT_ACTIONS, function(proc_name, next) { + eachLimit(Object.keys(proc_list), conf.CONCURRENT_ACTIONS, function(proc_name, next) { // Skip app name (--only option) if (apps_name.indexOf(proc_name) == -1) return next(); @@ -981,7 +982,7 @@ API.prototype._startJson = function(file, opts, action, pipe, cb) { } }); - async.eachLimit(apps_to_start, conf.CONCURRENT_ACTIONS, function(app, next) { + eachLimit(apps_to_start, conf.CONCURRENT_ACTIONS, function(app, next) { if (opts.cwd) app.cwd = opts.cwd; if (opts.force_name) @@ -1096,7 +1097,7 @@ API.prototype.actionFromJson = function(action, file, opts, jsonVia, cb) { if ((appConf = Common.verifyConfs(appConf)) instanceof Error) return cb ? cb(appConf) : that.exitCli(conf.ERROR_EXIT); - async.eachLimit(appConf, conf.CONCURRENT_ACTIONS, function(proc, next1) { + eachLimit(appConf, conf.CONCURRENT_ACTIONS, function(proc, next1) { var name = ''; var new_env; @@ -1120,7 +1121,7 @@ API.prototype.actionFromJson = function(action, file, opts, jsonVia, cb) { } if (!ids) return next1(); - async.eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next2) { + eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next2) { var opts = {}; //stopProcessId could accept options to? @@ -1212,7 +1213,7 @@ API.prototype._operate = function(action_name, process_name, envs, cb) { if (action_name == 'deleteProcessId') concurrent_actions = 10; - async.eachLimit(ids, concurrent_actions, function(id, next) { + eachLimit(ids, concurrent_actions, function(id, next) { var opts; // These functions need extra param to be passed diff --git a/examples/start-a-binary/ls b/examples/start-a-binary/ls index 6dd19be88..edd6db318 100755 Binary files a/examples/start-a-binary/ls and b/examples/start-a-binary/ls differ diff --git a/lib/API.js b/lib/API.js index 14b8594f1..ba25e4093 100644 --- a/lib/API.js +++ b/lib/API.js @@ -8,7 +8,8 @@ const commander = require('commander'); const fs = require('fs'); const path = require('path'); -const async = require('async'); +const eachLimit = require('async/eachLimit'); +const series = require('async/series'); const debug = require('debug')('pm2:cli'); const util = require('util'); const chalk = require('chalk'); @@ -126,9 +127,25 @@ class API { if (this.secret_key && process.env.NODE_ENV == 'local_test') that.gl_is_km_linked = true; - KMDaemon.getInteractInfo(this._conf, function (i_err, interact) { - that.gl_interact_infos = interact; - }); + KMDaemon.ping(this._conf, function(err, result) { + if (!err && result === true) { + fs.readFile(conf.INTERACTION_CONF, (err, _conf) => { + if (!err) { + try { + that.gl_interact_infos = JSON.parse(_conf.toString()) + } catch(e) { + var json5 = require('./tools/json5.js') + try { + that.gl_interact_infos = json5.parse(_conf.toString()) + } catch(e) { + console.error(e) + that.gl_interact_infos = null + } + } + } + }) + } + }) this.gl_retry = 0; } @@ -322,7 +339,7 @@ class API { var that = this; function processIds(ids, cb) { - async.eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next) { + eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next) { that.Client.executeRemote('resetMetaProcessId', id, function(err, res) { if (err) console.error(err); Common.printOut(conf.PREFIX_MSG + 'Resetting meta for process id %d', id); @@ -376,7 +393,7 @@ class API { that.getVersion(function(err, new_version) { // If not linked to PM2 plus, and update PM2 to latest, display motd.update if (!that.gl_is_km_linked && !err && (pkg.version != new_version)) { - var dt = fs.readFileSync(path.join(__dirname, that._conf.KEYMETRICS_UPDATE)); + var dt = fs.readFileSync(path.join(__dirname, that._conf.PM2_UPDATE)); console.log(dt.toString()); } @@ -390,7 +407,6 @@ class API { Common.printOut(chalk.blue.bold('>>>>>>>>>> PM2 updated')); Modularizer.launchAll(that, function() { KMDaemon.launchAndInteract(that._conf, null, function(err, data, interactor_proc) { - // Interactor error can be skipped here return cb ? cb(null, {success:true}) : that.speedList(); }); }); @@ -568,7 +584,7 @@ class API { return false; } - return cb ? cb(null, list) : that.speedList(); + return cb ? cb(null, list) : that.speedList(null, list); }); } @@ -580,20 +596,27 @@ class API { killDaemon (cb) { var that = this; - var semver = require('semver'); - Common.printOut(conf.PREFIX_MSG + 'Stopping PM2...'); - that.Client.executeRemote('notifyKillPM2', {}, function() {}); + Common.printOut(conf.PREFIX_MSG + '[-] Stopping Modules'); that.killAllModules(function() { + Common.printOut(conf.PREFIX_MSG + '[v] Modules Stopped'); + + Common.printOut(conf.PREFIX_MSG + '[-] Stopping all Applications'); that._operate('deleteProcessId', 'all', function(err, list) { - Common.printOut(conf.PREFIX_MSG + 'All processes have been stopped and deleted'); + Common.printOut(conf.PREFIX_MSG + '[v] All Applications Stopped'); process.env.PM2_SILENT = 'false'; - that.killInteract(function(err, data) { + Common.printOut(conf.PREFIX_MSG + '[-] Stopping Agent'); + that.killAgent(function(err, data) { + //if (err) console.error(err) + Common.printOut(conf.PREFIX_MSG + '[v] Agent Stopped'); + + Common.printOut(conf.PREFIX_MSG + '[-] Stopping PM2 Daemon'); that.Client.killDaemon(function(err, res) { if (err) Common.printError(err); - Common.printOut(conf.PREFIX_MSG + 'PM2 stopped'); + Common.printOut(conf.PREFIX_MSG + '[-] PM2 Daemon Stopped'); + return cb ? cb(err, res) : that.exitCli(conf.SUCCESS_EXIT); }); }); @@ -659,7 +682,7 @@ class API { /** * If -w option, write configuration to configuration.json file */ - if (appConf.write) { + if (app_conf.write) { var dst_path = path.join(process.env.PWD || process.cwd(), app_conf.name + '-pm2.json'); Common.printOut(conf.PREFIX_MSG + 'Writing configuration to', chalk.blue(dst_path)); // pretty JSON @@ -786,7 +809,7 @@ class API { }); } - async.series([ + series([ restartExistingProcessName, restartExistingProcessId, restartExistingProcessPath @@ -875,9 +898,14 @@ class API { // Here we pick only the field we want from the CLI when starting a JSON appConf.forEach(function(app) { + if (!app.env) { app.env = {}; } + app.env.io = app.io; // --only - if (opts.only && opts.only != app.name) - return false; + if (opts.only) { + var apps = opts.only.split(/,| /) + if (apps.indexOf(app.name) == -1) + return false + } // --watch if (!app.watch && opts.watch && opts.watch === true) app.watch = true; @@ -917,7 +945,8 @@ class API { * Auto detect application already started * and act on them depending on action */ - async.eachLimit(Object.keys(proc_list), conf.CONCURRENT_ACTIONS, function(proc_name, next) { + + eachLimit(Object.keys(proc_list), conf.CONCURRENT_ACTIONS, function(proc_name, next) { // Skip app name (--only option) if (apps_name.indexOf(proc_name) == -1) @@ -983,7 +1012,7 @@ class API { } }); - async.eachLimit(apps_to_start, conf.CONCURRENT_ACTIONS, function(app, next) { + eachLimit(apps_to_start, conf.CONCURRENT_ACTIONS, function(app, next) { if (opts.cwd) app.cwd = opts.cwd; if (opts.force_name) @@ -1098,7 +1127,7 @@ class API { if ((appConf = Common.verifyConfs(appConf)) instanceof Error) return cb ? cb(appConf) : that.exitCli(conf.ERROR_EXIT); - async.eachLimit(appConf, conf.CONCURRENT_ACTIONS, function(proc, next1) { + eachLimit(appConf, conf.CONCURRENT_ACTIONS, function(proc, next1) { var name = ''; var new_env; @@ -1122,7 +1151,7 @@ class API { } if (!ids) return next1(); - async.eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next2) { + eachLimit(ids, conf.CONCURRENT_ACTIONS, function(id, next2) { var opts = {}; //stopProcessId could accept options to? @@ -1214,7 +1243,7 @@ class API { if (action_name == 'deleteProcessId') concurrent_actions = 10; - async.eachLimit(ids, concurrent_actions, function(id, next) { + eachLimit(ids, concurrent_actions, function(id, next) { var opts; // These functions need extra param to be passed @@ -1472,16 +1501,22 @@ class API { * @method speedList * @return */ - speedList (code) { + speedList (code, list) { var that = this; // Do nothing if PM2 called programmatically and not called from CLI (also in exitCli) if (conf.PM2_PROGRAMMATIC && process.env.PM2_USAGE != 'CLI') return false; - that.Client.executeRemote('getMonitorData', {}, function(err, list) { + if (list) { + return doList(null, list) + } + + that.Client.executeRemote('getMonitorData', {}, doList); + + function doList(err, list) { if (err) { - if (gl_retry == 0) { - gl_retry += 1; + if (that.gl_retry == 0) { + that.gl_retry += 1; return setTimeout(that.speedList.bind(that), 1400); } console.error('Error retrieving process list: %s.\nA process seems to be on infinite loop, retry in 5 seconds',err); @@ -1494,10 +1529,14 @@ class API { UX.miniDisplay(list); else if (!commander.silent) { if (that.gl_interact_infos) { - Common.printOut('%s Agent Online | Access: %s | Server: %s', + Common.printOut('%s PM2+ activated | Web: %s | Server: %s | Conn: %s', chalk.green.bold('⇆'), chalk.bold('https://app.pm2.io/#/r/' + that.gl_interact_infos.public_key), - chalk.bold(that.gl_interact_infos.machine_name)); + chalk.bold(that.gl_interact_infos.machine_name), + that.gl_interact_infos.agent_transport_websocket === 'true' ? 'Websocket' : 'Axon'); + if (that.gl_interact_infos.info_node != 'https://root.keymetrics.io') { + Common.printOut(`PM2+ on-premise link: ${that.gl_interact_infos.info_node}`) + } } UX.dispAsTable(list, commander); Common.printOut(chalk.white.italic(' Use `pm2 show ` to get more details about an app')); @@ -1515,7 +1554,7 @@ class API { else { return that.exitCli(code ? code : conf.SUCCESS_EXIT); } - }); + } } /** @@ -1647,10 +1686,14 @@ class API { ////////////////////////// require('./API/Extra.js')(API); -require('./API/Interaction.js')(API); require('./API/Deploy.js')(API); require('./API/Modules/Modules.js')(API); -require('./API/PM2/PM2IO.js')(API); + +require('./API/pm2-plus/link.js')(API); +require('./API/pm2-plus/process-selector.js')(API); +require('./API/pm2-plus/helpers.js')(API); +require('./API/pm2-plus/PM2IO.js')(API); + require('./API/Configuration.js')(API); require('./API/Version.js')(API); require('./API/Startup.js')(API); diff --git a/lib/API/CliUx.js b/lib/API/CliUx.js index a25f72e01..6030f51fd 100644 --- a/lib/API/CliUx.js +++ b/lib/API/CliUx.js @@ -8,7 +8,6 @@ var p = require('path'); var chalk = require('chalk'); var Common = require('../Common'); var Spinner = require('./Spinner.js'); -var os = require('os'); var UX = module.exports = {}; /** @@ -103,6 +102,7 @@ UX.describeTable = function(process) { { 'exec mode' : pm2_env.exec_mode }, { 'node.js version' : pm2_env.node_version }, + { 'node env': pm2_env.env.NODE_ENV }, { 'watch & reload' : pm2_env.watch ? chalk.green.bold('✔') : '✘' }, { 'unstable restarts' : pm2_env.unstable_restarts }, { 'created at' : created_at } @@ -269,14 +269,10 @@ UX.dispAsTable = function(list, commander) { if (l.pm2_env.axm_options) { var deep_monitored = l.pm2_env.axm_options.tracing_enabled || false; if (deep_monitored == true) { - key = key + ' ' + chalk.green('⏱'); + key = chalk.green('✚') + ' ' + key; } } - if (typeof l.pm2_env._km_monitored === 'boolean' && l.pm2_env._km_monitored === false) { - key = chalk.bold.red('◉') + ' ' + key; - } - if (l.pm2_env.pmx_module == true) { // pm2 ls for Modules obj[key] = []; diff --git a/lib/API/Configuration.js b/lib/API/Configuration.js index 321a295e4..1c8549f5a 100644 --- a/lib/API/Configuration.js +++ b/lib/API/Configuration.js @@ -3,10 +3,7 @@ var Common = require('../Common.js'); var cst = require('../../constants.js'); var UX = require('./CliUx'); var chalk = require('chalk'); -var async = require('async'); var Configuration = require('../Configuration.js'); -//@todo double check that imported methods works -var InteractorDaemonizer = require('@pm2/agent/src/InteractorClient'); module.exports = function(CLI) { diff --git a/lib/API/Containerizer.js b/lib/API/Containerizer.js index 686edfd1d..6a8ffe414 100644 --- a/lib/API/Containerizer.js +++ b/lib/API/Containerizer.js @@ -226,7 +226,7 @@ module.exports = function(CLI) { fs.stat(docker_filepath, function(err, stat) { if (err) { - // Dockerfile does not exists, generate one + // Dockerfile does not exist, generate one // console.log(chalk.blue.bold('Generating new Dockerfile')); if (opts.force == true) { return resolve(generateDockerfile(docker_filepath, main_script, { diff --git a/lib/API/Dashboard.js b/lib/API/Dashboard.js index 85c37a7f6..4b78b31ef 100644 --- a/lib/API/Dashboard.js +++ b/lib/API/Dashboard.js @@ -7,7 +7,6 @@ var os = require('os'); var p = require('path'); var blessed = require('blessed'); -var fs = require('fs'); var debug = require('debug')('pm2:monit'); var sprintf = require('sprintf-js').sprintf; diff --git a/lib/API/Deploy.js b/lib/API/Deploy.js index 7cc7845ac..7dcc0c84e 100644 --- a/lib/API/Deploy.js +++ b/lib/API/Deploy.js @@ -105,6 +105,7 @@ module.exports = function(CLI) { require('pm2-deploy').deployForEnv(json_conf.deploy, env, args, function(err, data) { if (err) { Common.printError('Deploy failed'); + Common.printError(err.message || err); return cb ? cb(err) : that.exitCli(cst.ERROR_EXIT); } Common.printOut('--> Success'); diff --git a/lib/API/Extra.js b/lib/API/Extra.js index bca1da253..147bc521d 100644 --- a/lib/API/Extra.js +++ b/lib/API/Extra.js @@ -9,7 +9,6 @@ var cst = require('../../constants.js'); var Common = require('../Common.js'); var UX = require('./CliUx'); var chalk = require('chalk'); -var async = require('async'); var path = require('path'); var fs = require('fs'); var fmt = require('../tools/fmt.js'); @@ -63,13 +62,13 @@ module.exports = function(CLI) { fmt.title(chalk.bold.blue('CLI')); fmt.field('local pm2', pkg.version); fmt.field('node version', process.versions.node); - fmt.field('node path', process.env['_']); + fmt.field('node path', process.env['_'] || 'not found'); fmt.field('argv', process.argv); fmt.field('argv0', process.argv0); fmt.field('user', process.env.USER || process.env.LNAME || process.env.USERNAME); - if (process.geteuid) + if (cst.IS_WINDOWS === false && process.geteuid) fmt.field('uid', process.geteuid()); - if (process.getegid) + if (cst.IS_WINDOWS === false && process.getegid) fmt.field('gid', process.getegid()); var os = require('os'); diff --git a/lib/API/Interaction.js b/lib/API/Interaction.js deleted file mode 100644 index 621dbf27e..000000000 --- a/lib/API/Interaction.js +++ /dev/null @@ -1,184 +0,0 @@ - -var cst = require('../../constants.js'); -var Common = require('../Common.js'); -var UX = require('./CliUx'); -var chalk = require('chalk'); -var async = require('async'); -var path = require('path'); -var fs = require('fs'); -var KMDaemon = require('@pm2/agent/src/InteractorClient'); -var pkg = require('../../package.json') - -module.exports = function(CLI) { - - var installServerMonit = function(CLI, cb) { - if (process.env.NO_SERVER_MONIT || - process.env.NODE_ENV == 'test' || - cst.IS_WINDOWS == true) - return cb(); - - CLI.Client.executeRemote('getMonitorData', {}, function(err, list) { - var installed = list.some(function(app) { - return app.name == 'pm2-server-monit'; - }); - if (installed == false) - CLI.install('pm2-server-monit', cb); - else cb(); - }) - }; - - /** - * Launch interactor - * For programmatic interaction - * http://pm2.keymetrics.io/docs/usage/use-pm2-with-cloud-providers/ - * @method interact - * @param {string} secret_key - * @param {string} public_key - * @param {string} machine_name - */ - CLI.prototype.interact = function(secret_key, public_key, machine_name, cb) { - var that = this; - - if (typeof(machine_name) == 'function') { - cb = machine_name; - machine_name = null; - } - KMDaemon.launchAndInteract(that._conf, { - secret_key : secret_key || null, - public_key : public_key || null, - machine_name : machine_name || null, - pm2_version: pkg.version - }, function(err, dt) { - if (err) { - return cb ? cb(err) : that.exitCli(cst.ERROR_EXIT); - } - return cb ? cb(null, dt) : that.exitCli(cst.SUCCESS_EXIT); - }); - }; - - /** - * Aliases - */ - CLI.prototype.link = CLI.prototype.interact; - - CLI.prototype.unlink = function(cb) { - this._pre_interact('delete', cb); - }; - - CLI.prototype.interactInfos = function(cb) { - KMDaemon.getInteractInfo(this._conf, function(err, data) { - if (err) - return cb(Common.retErr(err)); - return cb(null, data); - }); - }; - - // - // Interact - // - CLI.prototype._pre_interact = function(cmd, public_key, machine, opts) { - var that = this; - - if (cmd == 'stop' || cmd == 'kill') { - console.log(chalk.cyan('[PM2 agent]') + ' Stopping agent...'); - that.killInteract(function() { - console.log(chalk.cyan('[PM2 agent]') + ' Stopped'); - return process.exit(cst.SUCCESS_EXIT); - }); - return false; - } - - if (cmd == 'info') { - console.log(chalk.cyan('[PM2 agent]') + ' Getting agent information...'); - that.interactInfos(function(err, infos) { - if (err) { - console.error(err.message); - return that.exitCli(cst.ERROR_EXIT); - } - console.log(infos); - return that.exitCli(cst.SUCCESS_EXIT); - }); - return false; - } - - if (cmd == 'delete') { - that.killInteract(function() { - try { - fs.unlinkSync(cst.INTERACTION_CONF); - } catch(e) { - console.log(chalk.cyan('[PM2 agent]') + ' No interaction config file found'); - return process.exit(cst.SUCCESS_EXIT); - } - console.log(chalk.cyan('[PM2 agent]') + ' Agent interaction ended'); - return process.exit(cst.SUCCESS_EXIT); - }); - return false; - } - - if (cmd == 'start' || cmd == 'restart') { - KMDaemon.launchAndInteract(that._conf, { - public_key : null, - secret_key : null, - machine_name : null, - info_node : null, - pm2_version: pkg.version - }, function(err, dt) { - if (err) { - Common.printError(err); - return that.exitCli(cst.ERROR_EXIT); - } - return that.exitCli(cst.SUCCESS_EXIT); - }); - } - - if (cmd && !public_key) { - console.error(chalk.cyan('[PM2 agent]') + ' Command [%s] unknown or missing public key', cmd); - return process.exit(cst.ERROR_EXIT); - } - - var infos; - - if (!cmd) { - infos = null; - } - else - infos = { - public_key : public_key, - secret_key : cmd, - machine_name : machine, - info_node : opts.infoNode || null, - pm2_version: pkg.version - } - - if (opts.ws === true && infos) { - infos.agent_transport_axon = false - infos.agent_transport_websocket = true - process.env.AGENT_TRANSPORT_AXON = false - process.env.AGENT_TRANSPORT_WEBSOCKET = true - } - else if (infos) { - infos.agent_transport_axon = true - infos.agent_transport_websocket = false - process.env.AGENT_TRANSPORT_AXON = true - process.env.AGENT_TRANSPORT_WEBSOCKET = false - } - - KMDaemon.launchAndInteract(that._conf, infos, function(err, dt) { - if (err) - return that.exitCli(cst.ERROR_EXIT); - return that.exitCli(cst.SUCCESS_EXIT); - }); - }; - - /** - * Kill interactor - * @method killInteract - */ - CLI.prototype.killInteract = function(cb) { - var that = this; - KMDaemon.killInteractorDaemon(that._conf, function(err) { - return cb ? cb(Common.retErr('Interactor not launched')) : that.exitCli(cst.SUCCESS_EXIT); - }); - }; - -}; diff --git a/lib/API/Log.js b/lib/API/Log.js index 37ad02974..6b9d5de41 100644 --- a/lib/API/Log.js +++ b/lib/API/Log.js @@ -6,7 +6,7 @@ var fs = require('fs'), util = require('util'), chalk = require('chalk'), - async = require('async'), + forEachLimit = require('async/forEachLimit'), moment = require('moment'); var Log = module.exports = {}; @@ -48,7 +48,7 @@ Log.tail = function(apps_list, lines, raw, callback) { (fs.existsSync(b.path) ? fs.statSync(b.path).mtime.valueOf() : 0); }); - async.forEachLimit(apps_list, 1, function(app, next) { + forEachLimit(apps_list, 1, function(app, next) { if (!fs.existsSync(app.path || '')) return next(); @@ -95,6 +95,8 @@ Log.stream = function(Client, id, raw, timestamp, exclusive) { } }); + var min_padding = 3 + bus.on('log:*', function(type, packet) { if (id !== 'all' && packet.process.name != id @@ -124,12 +126,15 @@ Log.stream = function(Client, id, raw, timestamp, exclusive) { var name = packet.process.pm_id + '|' + packet.process.name; + if (name.length > min_padding) + min_padding = name.length + 1 + if (type === 'out') - process.stdout.write(chalk.green(pad(DEFAULT_PADDING, name) + ' | ')); + process.stdout.write(chalk.green(pad(' '.repeat(min_padding), name) + ' | ')); else if (type === 'err') - process.stdout.write(chalk.red(pad(DEFAULT_PADDING, name) + ' | ')); + process.stdout.write(chalk.red(pad(' '.repeat(min_padding), name) + ' | ')); else if (!raw && (id === 'all' || id === 'PM2')) - process.stdout.write(chalk.blue(pad(DEFAULT_PADDING, 'PM2') + ' | ')); + process.stdout.write(chalk.blue(pad(' '.repeat(min_padding), 'PM2') + ' | ')); process.stdout.write(util.format(line) + '\n'); }); }); @@ -148,6 +153,8 @@ Log.devStream = function(Client, id, raw, timestamp, exclusive) { }); }, 1000); + var min_padding = 3 + bus.on('log:*', function(type, packet) { if (id !== 'all' && packet.process.name != id @@ -182,12 +189,15 @@ Log.devStream = function(Client, id, raw, timestamp, exclusive) { var name = packet.process.name + '-' + packet.process.pm_id; + if (name.length > min_padding) + min_padding = name.length + 1 + if (type === 'out') - process.stdout.write(chalk.green(pad(DEFAULT_PADDING, name) + ' | ')); + process.stdout.write(chalk.green(pad(' '.repeat(min_padding), name) + ' | ')); else if (type === 'err') - process.stdout.write(chalk.red(pad(DEFAULT_PADDING, name) + ' | ')); + process.stdout.write(chalk.red(pad(' '.repeat(min_padding), name) + ' | ')); else if (!raw && (id === 'all' || id === 'PM2')) - process.stdout.write(chalk.blue(pad(DEFAULT_PADDING, 'PM2') + ' | ')); + process.stdout.write(chalk.blue(pad(' '.repeat(min_padding), 'PM2') + ' | ')); process.stdout.write(util.format(line) + '\n'); }); }); diff --git a/lib/API/LogManagement.js b/lib/API/LogManagement.js index 47fa06d17..6be1ea14d 100644 --- a/lib/API/LogManagement.js +++ b/lib/API/LogManagement.js @@ -15,9 +15,8 @@ module.exports = function(CLI) { * @method flush * @return */ - CLI.prototype.flush = function(cb) { + CLI.prototype.flush = function(api, cb) { var that = this; - Common.printOut(cst.PREFIX_MSG + 'Flushing ' + cst.PM2_LOG_FILE_PATH); fs.closeSync(fs.openSync(cst.PM2_LOG_FILE_PATH, 'w')); @@ -31,13 +30,27 @@ module.exports = function(CLI) { Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path); Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path); - if (l.pm2_env.pm_log_path) { - Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path); - fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w')); + if(typeof api == 'undefined') + { + if (l.pm2_env.pm_log_path) { + Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path); + fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w')); + } + fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w')); + fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w')); } + else + { + if (l.pm2_env.pm_log_path && l.pm2_env.pm_log_path.lastIndexOf('/') < l.pm2_env.pm_log_path.lastIndexOf(api)) { + Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path); + fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w')); + } - fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w')); - fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w')); + if(l.pm2_env.pm_out_log_path.lastIndexOf('/') < l.pm2_env.pm_out_log_path.lastIndexOf(api)) + fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w')); + if(l.pm2_env.pm_err_log_path.lastIndexOf('/') < l.pm2_env.pm_err_log_path.lastIndexOf(api)) + fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w')); + } }); Common.printOut(cst.PREFIX_MSG + 'Logs flushed'); return cb ? cb(null, list) : that.exitCli(cst.SUCCESS_EXIT); diff --git a/lib/API/Modules/Modularizer.js b/lib/API/Modules/Modularizer.js index 900afc1e5..71f612f8a 100644 --- a/lib/API/Modules/Modularizer.js +++ b/lib/API/Modules/Modularizer.js @@ -6,7 +6,9 @@ var path = require('path'); var fs = require('fs'); var os = require('os'); -var async = require('async'); +var parallel = require('async/parallel'); +var eachLimit = require('async/eachLimit'); +var forEachLimit = require('async/forEachLimit'); var p = path; var readline = require('readline'); var spawn = require('child_process').spawn; @@ -20,7 +22,7 @@ var Modularizer = module.exports = {}; var MODULE_CONF_PREFIX = 'module-db-v2'; -var KNOWN_MODULES = { +var INTERNAL_MODULES = { 'deep-monitoring': { dependencies: [{name: 'v8-profiler-node8'}, {name: 'gc-stats'}, {name: 'event-loop-inspector'}] }, @@ -68,7 +70,7 @@ Modularizer.install = function (CLI, moduleName, opts, cb) { return cb(Common.retErr(e)); } - Modularizer.installMultipleModules(config.dependencies, cb); + Modularizer.installMultipleInternalModules(config.dependencies, cb); return; } @@ -76,11 +78,11 @@ Modularizer.install = function (CLI, moduleName, opts, cb) { var canonicModuleName = Utility.getCanonicModuleName(moduleName); - if (KNOWN_MODULES.hasOwnProperty(moduleName)) { - var currentModule = KNOWN_MODULES[moduleName]; + if (INTERNAL_MODULES.hasOwnProperty(moduleName)) { + var currentModule = INTERNAL_MODULES[moduleName]; if (currentModule && currentModule.hasOwnProperty('dependencies')) { - Modularizer.installMultipleModules(currentModule.dependencies, cb); + Modularizer.installMultipleInternalModules(currentModule.dependencies, cb); } else { installModuleByName(currentModule, cb); } @@ -109,7 +111,7 @@ Modularizer.install = function (CLI, moduleName, opts, cb) { }); }; -Modularizer.installMultipleModules = function (modules, cb) { +Modularizer.installMultipleInternalModules = function (modules, cb) { var functionList = []; for (var i = 0; i < modules.length; i++) { functionList.push((function (index) { @@ -126,7 +128,7 @@ Modularizer.installMultipleModules = function (modules, cb) { })(i)); } - async.parallel(functionList, function (err, results) { + parallel(functionList, function (err, results) { for (var i = 0; i < results.length; i++) { var display = results[i].module.message || results[i].module.name; if (results[i].err) { @@ -137,7 +139,7 @@ Modularizer.installMultipleModules = function (modules, cb) { } } - cb(err); + if(cb) cb(err); }); }; @@ -267,7 +269,7 @@ Modularizer.launchModules = function(CLI, cb) { if (!modules) return cb(); - async.eachLimit(Object.keys(modules), 1, function(module_name, next) { + eachLimit(Object.keys(modules), 1, function(module_name, next) { Common.printOut(cst.PREFIX_MSG_MOD + 'Starting module ' + module_name); var install_path = path.join(cst.DEFAULT_MODULE_PATH, module_name); @@ -335,9 +337,9 @@ function startModule(CLI, opts, cb) { CLI.start(package_json, opts, function(err, data) { if (err) return cb(err); - Common.printOut(cst.PREFIX_MSG_MOD + 'Monitoring module behavior for potential issue (5secs...)'); - if (opts.safe) { + Common.printOut(cst.PREFIX_MSG_MOD + 'Monitoring module behavior for potential issue (5secs...)'); + var time = typeof(opts.safe) == 'boolean' ? 3000 : parseInt(opts.safe); return setTimeout(function() { CLI.describe(package_json.name, function(err, apps) { @@ -366,7 +368,7 @@ Modularizer.uninstall = function(CLI, module_name, cb) { if (!modules) return cb(); - return async.forEachLimit(Object.keys(modules), 1, function(module_name, next) { + return forEachLimit(Object.keys(modules), 1, function(module_name, next) { uninstallModule(CLI, { module_name : module_name, deep_uninstall : true @@ -436,7 +438,7 @@ var Rollback = { // Delete failing module require('shelljs').rm('-r', module_path); // Restore working version - require('shelljs').cp('-r', backup_path, module_path); + require('shelljs').cp('-r', backup_path, cst.DEFAULT_MODULE_PATH); var proc_path = path.join(module_path, 'node_modules', canonic_module_name); var package_json_path = path.join(proc_path, 'package.json'); diff --git a/lib/API/Modules/Modularizerv1.js b/lib/API/Modules/Modularizerv1.js index ad63a5609..f95f69f80 100644 --- a/lib/API/Modules/Modularizerv1.js +++ b/lib/API/Modules/Modularizerv1.js @@ -5,7 +5,7 @@ */ var path = require('path'); var fs = require('fs'); -var async = require('async'); +var eachLimit = require('async/eachLimit'); var p = path; var spawn = require('child_process').spawn; var chalk = require('chalk'); @@ -72,7 +72,7 @@ Modularizer.launchModules = function(CLI, cb) { if (!modules) return cb(); - async.eachLimit(Object.keys(modules), 1, function(module, next) { + eachLimit(Object.keys(modules), 1, function(module, next) { var pmod = p.join(module_folder, module, cst.DEFAULT_MODULE_JSON); Common.printOut(cst.PREFIX_MSG_MOD + 'Starting module ' + module); diff --git a/lib/API/Modules/Modules.js b/lib/API/Modules/Modules.js index 3d9f6f2a3..7b97c9ced 100644 --- a/lib/API/Modules/Modules.js +++ b/lib/API/Modules/Modules.js @@ -5,19 +5,11 @@ * **************************/ -var cst = require('../../../constants.js'); -var Common = require('../../Common.js'); -var UX = require('../CliUx'); -var chalk = require('chalk'); -var async = require('async'); - -var path = require('path'); -var fs = require('fs'); -var p = path; -var Configuration = require('../../Configuration.js'); -var Utility = require('../../Utility.js'); - -var MODULE_CONF_PREFIX = 'module-db'; +var cst = require('../../../constants.js'); +var Common = require('../../Common.js'); +var UX = require('../CliUx'); +var chalk = require('chalk'); +var forEachLimit = require('async/forEachLimit'); var Modularizer = require('./Modularizer.js'); var ModularizerV1 = require('./Modularizerv1.js'); @@ -154,7 +146,7 @@ module.exports = function(CLI) { var that = this; this.Client.getAllModulesId(function(err, modules_id) { - async.forEachLimit(modules_id, 1, function(id, next) { + forEachLimit(modules_id, 1, function(id, next) { that._operate('deleteProcessId', id, next); }, function() { return cb ? cb() : false; diff --git a/lib/API/Monit.js b/lib/API/Monit.js index 9d86c27ca..71a69e6a5 100644 --- a/lib/API/Monit.js +++ b/lib/API/Monit.js @@ -116,7 +116,7 @@ Monit.refresh = function(processes) { //this is to avoid a print issue when the process is restarted for example //we might also check for the pid but restarted|restarting will be rendered bad if(this.bars[proc.pm_id] && proc.pm2_env.status !== this.bars[proc.pm_id].status) { - debug('bars for %s does not exists', proc.pm_id); + debug('bars for %s does not exist', proc.pm_id); this.addProcesses(processes); break; } diff --git a/lib/API/PM2/PM2IO.js b/lib/API/PM2/PM2IO.js deleted file mode 100644 index 090480713..000000000 --- a/lib/API/PM2/PM2IO.js +++ /dev/null @@ -1,245 +0,0 @@ -'use strict' - -var cst = require('../../../constants.js'); -var Common = require('../../Common.js'); -var KMDaemon = require('@pm2/agent/src/InteractorClient'); - -const chalk = require('chalk'); -const async = require('async'); -const path = require('path'); -const fs = require('fs'); -const Table = require('cli-table-redemption'); -const open = require('../../tools/open.js'); -const pkg = require('../../../package.json') -const IOAPI = require('@pm2/js-api') - - -// const CustomStrategy = require('./custom_auth') -// const strategy = new CustomStrategy({ -// client_id: '7412235273' -// }) - -const CLIAuth = require('./CliAuth') - -const CLIAuthStrategy = new CLIAuth({ - client_id: '938758711' -}) - -const io = new IOAPI().use(CLIAuthStrategy) - -module.exports = function(CLI) { - - CLI.prototype.openDashboard = function() { - KMDaemon.getInteractInfo(this._conf, (err, data) => { - if (err) { - Common.printError(chalk.bold.white('Agent if offline, type `$ pm2 register` to log in')); - return this.exitCli(cst.ERROR_EXIT); - } - Common.printOut(chalk.bold('Opening Dashboard in Browser...')); - open('https://app.pm2.io/#/r/' + data.public_key); - setTimeout(_ => { - this.exitCli(); - }, 200); - }); - }; - - CLI.prototype.loginToKM = function() { - var promptly = require('promptly') - printMotd(); - - return CLIAuthStrategy._retrieveTokens((err, tokens) => { - if (err) { - console.error(`Oups, a error happened : ${err}`) - process.exit(1) - } - - // query both the user and all bucket - Promise.all([ io.user.retrieve(), io.bucket.retrieveAll() ]) - .then(results => { - let user = results[0].data - let buckets = results[1].data - - if (buckets.length > 1) { - var table = new Table({ - style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}, - head : ['Bucket name', 'Plan type'] - }); - - buckets.forEach(function(bucket) { - table.push([bucket.name, bucket.credits.offer_type]); - }); - - console.log(table.toString()); - - (function retryInsertion() { - promptly.prompt('Type the bucket you want to link to: ', function(err, bucket_name) { - var target_bucket = null; - - buckets.some(function(bucket) { - if (bucket.name == bucket_name) { - target_bucket = bucket; - return true; - } - }); - - if (target_bucket == null) - return retryInsertion(); - linkOpenExit(target_bucket); - }); - })(); - } - else { - var target_bucket = buckets[0]; - linkOpenExit(target_bucket) - } - }).catch(err => { - console.error(chalk.bold.red(`Oups, a error happened : ${err}`)) - return process.exit(1) - }) - }) - }; - - CLI.prototype.registerToKM = function() { - var promptly = require('promptly'); - - promptly.confirm(chalk.bold('Do you have a pm2.io account? (y/n)'), (err, answer) => { - if (answer == true) { - return this.loginToKM(); - } - CLIAuthStrategy.registerViaCLI((err, data) => { - console.log('[-] Creating Bucket...') - - io.bucket.create({ - name: 'Node.JS Monitoring' - }).then(res => { - const bucket = res.data.bucket - console.log(chalk.bold.green('[+] Bucket created!')) - linkOpenExit(bucket) - }) - }) - }); - } - - CLI.prototype.logoutToKM = function () { - CLIAuthStrategy._retrieveTokens(_ => { - io.auth.logout() - .then(res => { - console.log(`- Logout successful`) - return process.exit(0) - }).catch(err => { - console.error(`Oups, a error happened : ${err.message}`) - return process.exit(1) - }) - }) - } - - CLI.prototype.connectToPM2IO = function() { - io.bucket.create({ - name: 'Node.JS Monitoring' - }).then(res => { - const bucket = res.data.bucket - console.log(`Succesfully created a bucket !`) - console.log(`To start using it, you should push data with : - pm2 link ${bucket.secret_id} ${bucket.public_id} - `) - console.log(`You can also access our dedicated UI by going here : - https://app.pm2.io/#/r/${bucket.public_id} - `) - - KMDaemon.launchAndInteract(cst, { - public_key : bucket.public_id, - secret_key : bucket.secret_id - }, function(err, dt) { - open(`https://app.pm2.io/#/r/${bucket.public_id}`); - setTimeout(_ => { - return process.exit(0) - }, 200) - }); - - }) - } - - /** - * Monitor Selectively Processes (auto filter in interaction) - * @param String state 'monitor' or 'unmonitor' - * @param String target - * @param Function cb callback - */ - CLI.prototype.monitorState = function(state, target, cb) { - var that = this; - - if (process.env.NODE_ENV !== 'test') { - try { - fs.statSync(this._conf.INTERACTION_CONF); - } catch(e) { - printMotd(); - return this.registerToKM(); - } - } - - if (!target) { - Common.printError(cst.PREFIX_MSG_ERR + 'Please specify an '); - return cb ? cb(new Error('argument missing')) : that.exitCli(cst.ERROR_EXIT); - } - - function monitor (pm_id, cb) { - // State can be monitor or unmonitor - that.Client.executeRemote(state, pm_id, cb); - } - if (target === 'all') { - that.Client.getAllProcessId(function (err, procs) { - if (err) { - Common.printError(err); - return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT); - } - async.forEachLimit(procs, 1, monitor, function (err, res) { - return typeof cb === 'function' ? cb(err, res) : that.speedList(); - }); - }); - } else if (!Number.isInteger(parseInt(target))) { - this.Client.getProcessIdByName(target, true, function (err, procs) { - if (err) { - Common.printError(err); - return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT); - } - async.forEachLimit(procs, 1, monitor, function (err, res) { - return typeof cb === 'function' ? cb(err, res) : that.speedList(); - }); - }); - } else { - monitor(parseInt(target), function (err, res) { - return typeof cb === 'function' ? cb(err, res) : that.speedList(); - }); - } - }; - - - function linkOpenExit(target_bucket) { - console.log('[-] Linking local PM2 to newly created bucket...') - KMDaemon.launchAndInteract(cst, { - public_key : target_bucket.public_id, - secret_key : target_bucket.secret_id, - pm2_version: pkg.version - }, function(err, dt) { - console.log(chalk.bold.green('[+] Local PM2 Connected!')) - - console.log('[-] Opening Monitoring Interface in Browser...') - - setTimeout(function() { - open('https://app.pm2.io/#/r/' + target_bucket.public_id); - console.log(chalk.bold.green('[+] Opened! Exiting now.')) - setTimeout(function() { - process.exit(cst.SUCCESS_EXIT); - }, 100); - }, 1000) - }); - } - - /** - * Private Functions - */ - function printMotd() { - var dt = fs.readFileSync(path.join(__dirname, 'motd')); - console.log(dt.toString()); - } -}; diff --git a/lib/API/PM2/motd b/lib/API/PM2/motd deleted file mode 100644 index 9d44fc761..000000000 --- a/lib/API/PM2/motd +++ /dev/null @@ -1,13 +0,0 @@ - - 88888888ba 88b d88 ad888888b, 88 ,ad8888ba, - 88 "8b 888b d888 d8" "88 88 d8"' `"8b - 88 ,8P 88`8b d8'88 a8P 88 d8' `8b - 88aaaaaa8P' 88 `8b d8' 88 ,d8P" 88 88 88 - 88""""""' 88 `8b d8' 88 a8P" 88 88 88 - 88 88 `8b d8' 88 a8P' 88 Y8, ,8P - 88 88 `888' 88 d8" 888 88 Y8a. .a8P - 88 88 `8' 88 88888888888 888 88 `"Y8888Y"' - - https://pm2.io/ - - Add Control and Monitoring to Your Node.js Apps diff --git a/lib/API/Startup.js b/lib/API/Startup.js index d35cd05cf..64c17aa43 100644 --- a/lib/API/Startup.js +++ b/lib/API/Startup.js @@ -3,15 +3,14 @@ * Use of this source code is governed by a license that * can be found in the LICENSE file. */ -var debug = require('debug')('pm2:cli:startup'); -var chalk = require('chalk'); -var path = require('path'); -var fs = require('fs'); -var async = require('async'); -var exec = require('child_process').exec; -var Common = require('../Common.js'); -var cst = require('../../constants.js'); -var spawn = require('child_process').spawn; +var chalk = require('chalk'); +var path = require('path'); +var fs = require('fs'); +var forEachLimit = require('async/forEachLimit'); +var eachLimit = require('async/eachLimit'); +var exec = require('child_process').exec; +var Common = require('../Common.js'); +var cst = require('../../constants.js'); module.exports = function(CLI) { /** @@ -41,7 +40,8 @@ module.exports = function(CLI) { 'chkconfig' : 'systemv', 'rc-update' : 'openrc', 'launchctl' : 'launchd', - 'sysrc' : 'rcd' + 'sysrc' : 'rcd', + 'rcctl' : 'rcd-openbsd', }; var init_systems = Object.keys(hash_map); @@ -136,7 +136,7 @@ module.exports = function(CLI) { case 'launchd': var destination = path.join(process.env.HOME, 'Library/LaunchAgents/' + launchd_service_name + '.plist'); commands = [ - 'launchctl remove com.' + launchd_service_name, + 'launchctl remove ' + launchd_service_name, 'rm ' + destination ]; break; @@ -147,6 +147,16 @@ module.exports = function(CLI) { 'sysrc -x ' + service_name + '_enable', 'rm /usr/local/etc/rc.d/' + service_name ]; + break; + case 'rcd-openbsd': + service_name = (opts.serviceName || 'pm2_' + user); + var destination = path.join('/etc/rc.d', service_name); + commands = [ + 'rcctl stop ' + service_name, + 'rcctl disable ' + service_name, + 'rm ' + destination + ]; + break; }; require('shelljs').exec(commands.join('&& '), function(code, stdout, stderr) { @@ -270,6 +280,17 @@ module.exports = function(CLI) { 'sysrc ' + service_name + '_enable=YES' ]; break; + case 'openbsd': + case 'rcd-openbsd': + template = getTemplate('rcd-openbsd'); + service_name = (opts.serviceName || 'pm2_' + user); + destination = path.join('/etc/rc.d/', service_name); + commands = [ + 'chmod 755 ' + destination, + 'rcctl enable ' + service_name, + 'rcctl start ' + service_name + ]; + break; case 'openrc': template = getTemplate('openrc'); service_name = openrc_service_name; @@ -311,7 +332,7 @@ module.exports = function(CLI) { Common.printOut(cst.PREFIX_MSG + 'Making script booting at startup...'); - async.forEachLimit(commands, 1, function(command, next) { + forEachLimit(commands, 1, function(command, next) { Common.printOut(cst.PREFIX_MSG + '[-] Executing: %s...', chalk.bold(command)); require('shelljs').exec(command, function(code, stdout, stderr) { if (code === 0) { @@ -531,7 +552,7 @@ module.exports = function(CLI) { return Object.keys(current).indexOf(i) < 0; }) - async.eachLimit(processes, cst.CONCURRENT_ACTIONS, function(app, next) { + eachLimit(processes, cst.CONCURRENT_ACTIONS, function(app, next) { if (tostart.indexOf(app.name) == -1) return next(); that.Client.executeRemote('prepare', app, function(err, dt) { diff --git a/lib/API/Version.js b/lib/API/Version.js index aefe9352b..fbb7fa409 100644 --- a/lib/API/Version.js +++ b/lib/API/Version.js @@ -1,9 +1,9 @@ -var cst = require('../../constants.js'); -var Common = require('../Common.js'); -var fs = require('fs'); -var async = require('async'); -var child = require('child_process'); +var cst = require('../../constants.js'); +var Common = require('../Common.js'); +var fs = require('fs'); +var eachSeries = require('async/eachSeries'); +var child = require('child_process'); var printError = Common.printError; var printOut = Common.printOut; @@ -274,7 +274,7 @@ module.exports = function(CLI) { var execCommands = function(repo_path, command_list, cb) { var stdout = ''; - async.eachSeries(command_list, function(command, callback) { + eachSeries(command_list, function(command, callback) { stdout += '\n' + command; exec('cd '+repo_path+';'+command, function(code, output) { @@ -315,7 +315,7 @@ module.exports = function(CLI) { } if (data && data.apps) { - async.eachSeries(data.apps, function(item, callb) { + eachSeries(data.apps, function(item, callb) { if (item.name && item.name === proc_name) { if (item.post_update && typeof(item.post_update) === 'object') { if (item.exec_timeout) @@ -342,7 +342,7 @@ module.exports = function(CLI) { }); }; - async.eachSeries(['ecosystem.json', 'process.json', 'package.json'], searchForCommands, + eachSeries(['ecosystem.json', 'process.json', 'package.json'], searchForCommands, function(final) { return cb(final ? final : []); }); diff --git a/lib/API/pm2-plus/PM2IO.js b/lib/API/pm2-plus/PM2IO.js new file mode 100644 index 000000000..2dc88e846 --- /dev/null +++ b/lib/API/pm2-plus/PM2IO.js @@ -0,0 +1,181 @@ +'use strict' + +var cst = require('../../../constants.js'); +const chalk = require('chalk'); +const path = require('path'); +const fs = require('fs'); +const Table = require('cli-table-redemption'); +const pkg = require('../../../package.json') +const IOAPI = require('@pm2/js-api') +const promptly = require('promptly') + +var CLIAuthStrategy +var io + +module.exports = function(CLI) { + + function initializeConnection() { + // const CustomStrategy = require('./custom_auth') + // const strategy = new CustomStrategy({ + // client_id: '7412235273' + // }) + + const CLIAuth = require('./auth-strategies/CliAuth') + CLIAuthStrategy = new CLIAuth({ + client_id: '938758711' + }) + + io = new IOAPI().use(CLIAuthStrategy) + } + + /** + * CLI LOGIN + */ + CLI.prototype.login = function(cb) { + var self = this + + initializeConnection() + + return CLIAuthStrategy._retrieveTokens((err, tokens) => { + if (err) { + console.error(cst.PM2_IO_MSG_ERR + `Error: ${err}`) + process.exit(1) + } + + // query both the user and all bucket + Promise.all([ io.user.retrieve(), io.bucket.retrieveAll() ]) + .then(results => { + let user = results[0].data + let buckets = results[1].data + + var table = new Table({ + style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}, + head : ['Bucket name', 'Plan type'] + }); + + buckets.forEach(function(bucket) { + table.push([bucket.name, bucket.credits.offer_type]); + }); + + console.log(table.toString()); + + (function retryInsertion() { + promptly.prompt('Type the bucket you want to link to: ', function(err, bucket_name) { + var target_bucket = null; + + buckets.some(function(bucket) { + if (bucket.name == bucket_name) { + target_bucket = bucket; + return true; + } + }); + + if (target_bucket == null) { + return retryInsertion(); + } + + var connection_info = { + public_key: target_bucket.public_id, + secret_key: target_bucket.secret_id, + pm2_version: pkg.version + } + + return self.link(connection_info, function(err, endpoints) { + cb(err, target_bucket) + }); + }); + })(); + }).catch(err => { + console.error(cst.PM2_IO_MSG_ERR + `Error: ${err}`) + return process.exit(1) + }) + }) + }; + + /** + * CLI REGISTER + */ + CLI.prototype.register = function(opts) { + const self = this + + initializeConnection() + printMotd(); + + function finalize(bucket) { + if (bucket.type === 'enterprise') + opts.type = 'enterprise' + else if (bucket._payment.offer_type.indexOf('pro') > -1) + opts.type = 'plus' + + self.minimumSetup(opts, () => { + console.log() + console.log(chalk.green('[+] PM2 Plus has been successfully enabled!')) + + console.log(cst.PM2_IO_MSG + 'Access to the remote dashboard: https://app.pm2.io/#/r/' + bucket.public_id); + + self.speedList() + setTimeout(function() { + console.log(chalk.bold.green('[+] Exiting now.')) + process.exit(cst.SUCCESS_EXIT); + }, 200) + }) + } + + promptly.confirm(chalk.bold('Do you have a pm2.io account? (y/n)'), (err, answer) => { + + // Login + if (answer == true) { + return self.login((err, bucket) => { + if (err) { + console.error(err) + return process.exit(1) + } + + self.gl_is_km_linked = true + finalize(bucket) + }); + } + + // Register + CLIAuthStrategy.registerViaCLI((err, data) => { + console.log('[-] Creating Bucket...') + + io.bucket.create({ + name: 'Node.JS Monitoring' + }).then(res => { + const bucket = res.data.bucket + console.log(chalk.bold.green('[+] Bucket created!')) + self.link(bucket, () => { + finalize(bucket) + }) + }) + }) + }); + } + + /** + * CLI LOGOUT + */ + CLI.prototype.logout = function () { + initializeConnection() + + CLIAuthStrategy._retrieveTokens(_ => { + io.auth.logout() + .then(res => { + console.log(`- Logout successful`) + return process.exit(0) + }).catch(err => { + console.error(`Oups, a error happened : ${err.message}`) + return process.exit(1) + }) + }) + } + + /** + * Private Functions + */ + function printMotd() { + var dt = fs.readFileSync(path.join(__dirname, './pres/motd')); + console.log(dt.toString()); + } +}; diff --git a/lib/API/PM2/CliAuth.js b/lib/API/pm2-plus/auth-strategies/CliAuth.js similarity index 98% rename from lib/API/PM2/CliAuth.js rename to lib/API/pm2-plus/auth-strategies/CliAuth.js index 17e74d8b6..ccaa9e151 100644 --- a/lib/API/PM2/CliAuth.js +++ b/lib/API/pm2-plus/auth-strategies/CliAuth.js @@ -8,12 +8,12 @@ const http = require('http') const fs = require('fs') const url = require('url') const exec = require('child_process').exec -const async = require('async') +const tryEach = require('async/tryEach') const path = require('path') const os = require('os') const needle = require('needle'); const chalk = require('chalk') -const cst = require('../../../constants.js'); +const cst = require('../../../../constants.js'); module.exports = class CustomStrategy extends AuthStrategy { // the client will try to call this but we handle this part ourselves @@ -60,7 +60,7 @@ module.exports = class CustomStrategy extends AuthStrategy { const km = this.km const cb = this.callback - async.tryEach([ + tryEach([ // try to find the token via the environement (next) => { if (!process.env.KM_TOKEN) { diff --git a/lib/API/PM2/WebAuth.js b/lib/API/pm2-plus/auth-strategies/WebAuth.js similarity index 96% rename from lib/API/PM2/WebAuth.js rename to lib/API/pm2-plus/auth-strategies/WebAuth.js index 49a526316..493d04324 100644 --- a/lib/API/PM2/WebAuth.js +++ b/lib/API/pm2-plus/auth-strategies/WebAuth.js @@ -1,17 +1,14 @@ 'use strict' -const cst = require('../../../constants.js'); +const cst = require('../../../../constants.js'); const AuthStrategy = require('@pm2/js-api/src/auth_strategies/strategy') const http = require('http') const fs = require('fs') const url = require('url') const exec = require('child_process').exec -const async = require('async') -const path = require('path') -const os = require('os') -const needle = require('needle'); +const tryEach = require('async/tryEach') module.exports = class CustomStrategy extends AuthStrategy { // the client will try to call this but we handle this part ourselves @@ -56,7 +53,7 @@ module.exports = class CustomStrategy extends AuthStrategy { refresh_token: refresh }) } - async.tryEach([ + tryEach([ // try to find the token via the environement (next) => { if (!process.env.KM_TOKEN) { diff --git a/lib/API/pm2-plus/helpers.js b/lib/API/pm2-plus/helpers.js new file mode 100644 index 000000000..3e1e22f93 --- /dev/null +++ b/lib/API/pm2-plus/helpers.js @@ -0,0 +1,105 @@ + +var cst = require('../../../constants.js'); +var Common = require('../../Common.js'); + +const chalk = require('chalk'); +const forEach = require('async/forEach'); +const open = require('../../tools/open.js'); +const semver = require('semver'); +const Modularizer = require('../Modules/Modularizer.js'); + +function processesAreAlreadyMonitored(CLI, cb) { + CLI.Client.executeRemote('getMonitorData', {}, function(err, list) { + if (err) return cb(false); + var l = list.filter(l => l.pm2_env.km_link == true) + var l2 = list.filter(l => l.name == 'pm2-server-monit') + + return cb(l.length > 0 && l2.length > 0 ? true : false) + }) +} + +module.exports = function(CLI) { + CLI.prototype.openDashboard = function() { + if (!this.gl_interact_infos) { + Common.printError(chalk.bold.white('Agent if offline, type `$ pm2 plus` to log in')); + return this.exitCli(cst.ERROR_EXIT); + } + + var uri = `https://app.pm2.io/#/r/${this.gl_interact_infos.public_key}` + console.log(cst.PM2_IO_MSG + `Opening ${uri}`) + open(uri); + setTimeout(_ => { + this.exitCli(); + }, 200); + }; + + CLI.prototype.clearSetup = function (opts, cb) { + const modules = ['pm2-logrotate', 'pm2-server-monit', 'event-loop-inspector'] + this.gl_is_km_linked = false + + if (semver.satisfies(process.version, '< 10.0.0')) { + modules.push('v8-profiler-node8') + } + + forEach(modules, (_module, next) => { + Modularizer.uninstall(this, _module, () => { + next() + }); + }, (err) => { + this.reload('all', () => { + return cb() + }) + }) + } + + /** + * Install required package and enable flags for current running processes + */ + CLI.prototype.minimumSetup = function (opts, cb) { + var self = this; + this.gl_is_km_linked = true + + function install(cb) { + var modules = [] + + if (opts.type === 'enterprise' || opts.type === 'plus') { + modules = ['pm2-logrotate', 'pm2-server-monit', 'event-loop-inspector'] + if (semver.satisfies(process.version, '< 8.0.0')) { + modules.push('v8-profiler-node8') + } + if (opts.type === 'enterprise') { + modules.push('deep-metrics') + } + } + + forEach(modules, (_module, next) => { + Modularizer.install(self, _module, {}, () => { + next() + }); + }, (err) => { + self.reload('all', () => { + return cb() + }) + }) + } + + processesAreAlreadyMonitored(self, (already_monitored) => { + if (already_monitored) { + console.log(cst.PM2_IO_MSG + `PM2 ${opts.type} bundle already installed`); + return cb() + } + + if (opts.installAll) + return install(cb) + + // promptly.confirm(chalk.bold('Install all pm2 plus dependencies ? (y/n)'), (err, answer) => { + // if (!err && answer === true) + return install(cb) + // self.reload('all', () => { + // return cb() + // }) + // }); + }) + } + +} diff --git a/lib/API/pm2-plus/link.js b/lib/API/pm2-plus/link.js new file mode 100644 index 000000000..9b04389e6 --- /dev/null +++ b/lib/API/pm2-plus/link.js @@ -0,0 +1,140 @@ + +var cst = require('../../../constants.js'); +var Common = require('../../Common.js'); +var chalk = require('chalk'); +var fs = require('fs'); +var KMDaemon = require('@pm2/agent/src/InteractorClient'); +var pkg = require('../../../package.json') + +module.exports = function(CLI) { + + CLI.prototype.linkManagement = function(cmd, public_key, machine, opts, cb) { + var that = this; + + // pm2 link stop || kill + if (cmd == 'stop' || cmd == 'kill') { + that.gl_is_km_linked = false + console.log(cst.PM2_IO_MSG + 'Stopping agent...'); + + return that.killAgent(function(err) { + if (err) { + Common.printError(err); + return process.exit(cst.ERROR_EXIT); + } + console.log(cst.PM2_IO_MSG + 'Stopped'); + + that.reload('all', () => { + return process.exit(cst.SUCCESS_EXIT); + }) + }); + } + + // pm2 link info + if (cmd == 'info') { + console.log(cst.PM2_IO_MSG + 'Getting agent information...'); + that.agentInfos(function(err, infos) { + if (err) { + console.error(cst.PM2_IO_MSG_ERR + err.message); + return that.exitCli(cst.ERROR_EXIT); + } + console.log(infos); + return that.exitCli(cst.SUCCESS_EXIT); + }); + return false; + } + + // pm2 link delete + if (cmd == 'delete') { + that.gl_is_km_linked = false + console.log(cst.PM2_IO_MSG + 'Permanently disable agent...'); + that.killAgent(function(err) { + try { + fs.unlinkSync(cst.INTERACTION_CONF); + } catch(e) { + console.log(cst.PM2_IO_MSG + 'No interaction config file found'); + return process.exit(cst.SUCCESS_EXIT); + } + console.log(cst.PM2_IO_MSG + 'Agent interaction ended'); + if (!cb) + return process.exit(cst.SUCCESS_EXIT); + return cb() + }); + return false; + } + + if (cmd && !public_key) { + console.error(cst.PM2_IO_MSG + 'Command [%s] unknown or missing public key', cmd); + return process.exit(cst.ERROR_EXIT); + } + + // pm2 link xxx yyy + var infos; + + if (!cmd) { + infos = null; + } + else + infos = { + public_key : public_key, + secret_key : cmd, + machine_name : machine, + info_node : opts.infoNode || null, + pm2_version: pkg.version + } + + if (opts.ws === true && infos) { + infos.agent_transport_axon = false + infos.agent_transport_websocket = true + process.env.AGENT_TRANSPORT_AXON = false + process.env.AGENT_TRANSPORT_WEBSOCKET = true + } + else if (infos) { + infos.agent_transport_axon = true + infos.agent_transport_websocket = false + process.env.AGENT_TRANSPORT_AXON = true + process.env.AGENT_TRANSPORT_WEBSOCKET = false + } + + that.link(infos, cb) + }; + + CLI.prototype.link = function(infos, cb) { + var that = this; + + if (infos && !infos.machine_name) + infos.machine_name = require('os').hostname() + '-' + require('crypto').randomBytes(2).toString('hex') + + KMDaemon.launchAndInteract(cst, infos, function(err, dt) { + if (err) { + Common.printError(cst.PM2_IO_MSG + 'Run `$ pm2 plus` to connect') + return that.exitCli(cst.ERROR_EXIT); + } + console.log(chalk.bold.green('[+] PM2+ activated!')) + if (!cb) { + return that.exitCli(cst.SUCCESS_EXIT); + } + return cb(null, dt) + }); + }; + + CLI.prototype.agentInfos = function(cb) { + KMDaemon.getInteractInfo(this._conf, function(err, data) { + if (err) + return cb(Common.retErr(err)); + return cb(null, data); + }); + }; + + CLI.prototype.killAgent = function(cb) { + var that = this; + KMDaemon.killInteractorDaemon(that._conf, function(err) { + if (err) + return cb ? cb(Common.retErr(err)) : that.exitCli(cst.SUCCESS_EXIT); + return cb ? cb(null) : that.exitCli(cst.SUCCESS_EXIT); + }); + }; + + CLI.prototype.unlink = function(cb) { + this.linkManagement('delete', cb); + }; +}; diff --git a/lib/API/pm2-plus/pres/motd b/lib/API/pm2-plus/pres/motd new file mode 100644 index 000000000..091287164 --- /dev/null +++ b/lib/API/pm2-plus/pres/motd @@ -0,0 +1,16 @@ + + ██████╗ ███╗ ███╗██████╗ ██╗ ██╗ ██████╗ + ██╔══██╗████╗ ████║╚════██╗ ██║ ██╔╝██╔═══██╗ + ██████╔╝██╔████╔██║ █████╔╝ ██║ ██╔╝ ██║ ██║ + ██╔═══╝ ██║╚██╔╝██║██╔═══╝ ██║ ██╔╝ ██║ ██║ + ██║ ██║ ╚═╝ ██║███████╗ ██║██╔╝ ╚██████╔╝ + ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝╚═╝ ╚═════╝ + + https://pm2.io/ + + Harden your Node.js Production Environment + + - Real-time Monitoring Web Interface + - Pro Active Alerting System + - Production Profiling for Memory and CPU + - PM2 Runtime High Availability Fallback diff --git a/lib/API/pm2-plus/pres/motd.update b/lib/API/pm2-plus/pres/motd.update new file mode 100644 index 000000000..a4ee45ce4 --- /dev/null +++ b/lib/API/pm2-plus/pres/motd.update @@ -0,0 +1,26 @@ + + ------------- + + + ██████╗ ███╗ ███╗██████╗ ██╗ ██╗ ██████╗ + ██╔══██╗████╗ ████║╚════██╗ ██║ ██╔╝██╔═══██╗ + ██████╔╝██╔████╔██║ █████╔╝ ██║ ██╔╝ ██║ ██║ + ██╔═══╝ ██║╚██╔╝██║██╔═══╝ ██║ ██╔╝ ██║ ██║ + ██║ ██║ ╚═╝ ██║███████╗ ██║██╔╝ ╚██████╔╝ + ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝╚═╝ ╚═════╝ + + https://pm2.io/ + + Harden your Node.js Production Environment + + - Real-time Monitoring Web Interface + - Pro Active Alerting System + - Production Profiling for Memory and CPU + - PM2 Runtime High Availability Fallback + + + Start using it by typing: + + $ pm2 plus + + ------------- diff --git a/lib/API/pm2-plus/process-selector.js b/lib/API/pm2-plus/process-selector.js new file mode 100644 index 000000000..805c86213 --- /dev/null +++ b/lib/API/pm2-plus/process-selector.js @@ -0,0 +1,60 @@ +const fs = require('fs'); +const forEachLimit = require('async/forEachLimit'); + +var cst = require('../../../constants.js'); +var Common = require('../../Common.js'); + +module.exports = function(CLI) { + /** + * Monitor Selectively Processes (auto filter in interaction) + * @param String state 'monitor' or 'unmonitor' + * @param String target + * @param Function cb callback + */ + CLI.prototype.monitorState = function(state, target, cb) { + var that = this; + + if (process.env.NODE_ENV !== 'test') { + try { + fs.statSync(this._conf.INTERACTION_CONF); + } catch(e) { + return this.register({}); + } + } + + if (!target) { + Common.printError(cst.PREFIX_MSG_ERR + 'Please specify an '); + return cb ? cb(new Error('argument missing')) : that.exitCli(cst.ERROR_EXIT); + } + + function monitor (pm_id, cb) { + // State can be monitor or unmonitor + that.Client.executeRemote(state, pm_id, cb); + } + if (target === 'all') { + that.Client.getAllProcessId(function (err, procs) { + if (err) { + Common.printError(err); + return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT); + } + forEachLimit(procs, 1, monitor, function (err, res) { + return typeof cb === 'function' ? cb(err, res) : that.speedList(); + }); + }); + } else if (!Number.isInteger(parseInt(target))) { + this.Client.getProcessIdByName(target, true, function (err, procs) { + if (err) { + Common.printError(err); + return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT); + } + forEachLimit(procs, 1, monitor, function (err, res) { + return typeof cb === 'function' ? cb(err, res) : that.speedList(); + }); + }); + } else { + monitor(parseInt(target), function (err, res) { + return typeof cb === 'function' ? cb(err, res) : that.speedList(); + }); + } + }; +} diff --git a/lib/API/schema.json b/lib/API/schema.json index 063ffcdda..94ef70e03 100644 --- a/lib/API/schema.json +++ b/lib/API/schema.json @@ -304,5 +304,9 @@ }, "write": { "type": "boolean" + }, + "io": { + "type": "object", + "docDescription": "Specify apm values and configuration" } } diff --git a/lib/Client.js b/lib/Client.js index 6edb18f77..e7c598ffc 100644 --- a/lib/Client.js +++ b/lib/Client.js @@ -8,12 +8,12 @@ var debug = require('debug')('pm2:client'); var Common = require('./Common.js'); var KMDaemon = require('@pm2/agent/src/InteractorClient'); var rpc = require('pm2-axon-rpc'); -var async = require('async'); +var forEach = require('async/forEach'); var axon = require('pm2-axon'); var util = require('util'); var fs = require('fs'); var path = require('path'); -var pkg = require('../package.json') +var pkg = require('../package.json'); function noop() {} @@ -26,7 +26,7 @@ var Client = module.exports = function(opts) { this.conf = opts.conf; } - this.daemon_mode = typeof(opts.daemon_mode) == 'undefined' ? true : opts.daemon_mode; + this.daemon_mode = typeof(opts.daemon_mode) === 'undefined' ? true : opts.daemon_mode; this.pm2_home = this.conf.PM2_ROOT_PATH; this.secret_key = opts.secret_key; this.public_key = opts.public_key; @@ -40,7 +40,7 @@ var Client = module.exports = function(opts) { debug('Using PUB file %s', this.conf.DAEMON_PUB_PORT); this.rpc_socket_file = this.conf.DAEMON_RPC_PORT; this.pub_socket_file = this.conf.DAEMON_PUB_PORT; -} +}; // @breaking change (noDaemonMode has been drop) // @todo ret err @@ -48,7 +48,7 @@ Client.prototype.start = function(cb) { var that = this; this.pingDaemon(function(daemonAlive) { - if (daemonAlive == true) + if (daemonAlive === true) return that.launchRPC(function(err, meta) { return cb(null, { daemon_mode : that.conf.daemon_mode, @@ -62,7 +62,7 @@ Client.prototype.start = function(cb) { /** * No Daemon mode */ - if (that.daemon_mode == false) { + if (that.daemon_mode === false) { var Daemon = require('./Daemon.js'); var daemon = new Daemon({ @@ -168,7 +168,7 @@ Client.prototype.initFileStructure = function (opts) { } if (!process.env.PM2_PROGRAMMATIC && !fs.existsSync(path.join(opts.PM2_HOME, 'touch'))) { - var dt = fs.readFileSync(path.join(__dirname, opts.KEYMETRICS_BANNER)); + var dt = fs.readFileSync(path.join(__dirname, opts.PM2_BANNER)); console.log(dt.toString()); try { fs.writeFileSync(path.join(opts.PM2_HOME, 'touch'), Date.now()); @@ -181,7 +181,7 @@ Client.prototype.initFileStructure = function (opts) { Client.prototype.close = function(cb) { var that = this; - async.forEach([ + forEach([ that.disconnectRPC.bind(that), that.disconnectBus.bind(that) ], function(fn, next) { @@ -271,6 +271,9 @@ Client.prototype.launchDaemon = function(opts, cb) { if (opts && opts.interactor == false) return cb(null, child); + if (process.env.PM2_NO_INTERACTION == 'true') + return cb(null, child); + /** * Here the Keymetrics agent is launched automaticcaly if * it has been already configured before (via pm2 link) @@ -310,7 +313,7 @@ Client.prototype.pingDaemon = function pingDaemon(cb) { }); client.sock.once('error', function(e) { - if (e.code == 'EACCES') { + if (e.code === 'EACCES') { fs.stat(that.conf.DAEMON_RPC_PORT, function(e, stats) { if (stats.uid === 0) { console.error(that.conf.PREFIX_MSG_ERR + 'Permission denied, to give access to current user:'); @@ -342,6 +345,7 @@ Client.prototype.pingDaemon = function pingDaemon(cb) { * This method wait to be connected to the Daemon * Once he's connected it trigger the command parsing (on ./bin/pm2 file, at the end) * @method launchRPC + * @params {function} [cb] * @return */ Client.prototype.launchRPC = function launchRPC(cb) { @@ -350,22 +354,25 @@ Client.prototype.launchRPC = function launchRPC(cb) { var req = axon.socket('req'); this.client = new rpc.Client(req); - this.client.sock.once('connect', function() { - // Avoid keeping the event loop busy if no more items running - // if (req && req.socks && req.socks[0] && req.socks[0].unref && - // self.conf.PM2_PROGRAMMATIC) - // req.socks[0].unref(); + var connectHandler = function() { + self.client.sock.removeListener('error', errorHandler); debug('RPC Connected to Daemon'); - //process.emit('satan:client:ready'); - setTimeout(function() { - return cb ? cb(null) : false; - }, 4); - }); + if (cb) { + setTimeout(function() { + cb(null); + }, 4); + } + }; - this.client.sock.on('error', function(e) { - return cb(e); - }); + var errorHandler = function(e) { + self.client.sock.removeListener('connect', connectHandler); + if (cb) { + return cb(e); + } + }; + this.client.sock.once('connect', connectHandler); + this.client.sock.once('error', errorHandler); this.client_sock = req.connect(this.rpc_socket_file); }; @@ -384,8 +391,8 @@ Client.prototype.disconnectRPC = function disconnectRPC(cb) { }); } - if (this.client_sock.connected == false || - this.client_sock.closing == true) { + if (this.client_sock.connected === false || + this.client_sock.closing === true) { this.client = null; return process.nextTick(function() { cb(new Error('RPC already being closed')); @@ -413,7 +420,7 @@ Client.prototype.disconnectRPC = function disconnectRPC(cb) { } catch(e) { debug('Error while disconnecting RPC PM2', e.stack || e); return cb(e); - }; + } return false; }; @@ -439,8 +446,8 @@ Client.prototype.disconnectBus = function disconnectBus(cb) { }); } - if (this.sub_sock.connected == false || - this.sub_sock.closing == true) { + if (this.sub_sock.connected === false || + this.sub_sock.closing === true) { that.sub = null; return process.nextTick(function() { cb(new Error('SUB connection is already being closed')); @@ -515,7 +522,9 @@ Client.prototype.executeRemote = function executeRemote(method, app_conf, fn) { console.error(error); return process.exit(0); } - return self.client.call(method, app_conf, fn); + if (self.client) { + return self.client.call(method, app_conf, fn); + } }); return false; } diff --git a/lib/Common.js b/lib/Common.js index 35b133898..8ddaa57ce 100644 --- a/lib/Common.js +++ b/lib/Common.js @@ -12,7 +12,6 @@ var fs = require('fs'); var path = require('path'); var os = require('os'); var util = require('util'); -var async = require('async'); var chalk = require('chalk'); var fclone = require('fclone'); var semver = require('semver'); @@ -144,7 +143,7 @@ Common.prepareAppConf = function(opts, app) { app.pm_exec_path = path.resolve(cwd, app.script); - // If script does not exists after resolution + // If script does not exist after resolution if (!fs.existsSync(app.pm_exec_path)) { var ckd; // Try resolve command available in $PATH @@ -221,7 +220,7 @@ Common.prepareAppConf = function(opts, app) { var dir = path.dirname(path.resolve(cwd, af)); if (!fs.existsSync(dir)) { - Common.printError(cst.PREFIX_MSG_WARNING + 'Folder does not exists: ' + dir); + Common.printError(cst.PREFIX_MSG_WARNING + 'Folder does not exist: ' + dir); Common.printOut(cst.PREFIX_MSG + 'Creating folder: ' + dir); require('mkdirp')(dir, function(err) { if (!err) return; @@ -343,29 +342,42 @@ var resolveNodeInterpreter = function(app) { Common.printError(cst.PREFIX_MSG_WARNING + chalk.bold.yellow('Choosing the Node.js version in cluster mode is not supported')); return false; } - if (!process.env.NVM_DIR) { + + var nvm_path = cst.IS_WINDOWS ? process.env.NVM_HOME : process.env.NVM_DIR; + if (!nvm_path) { Common.printError(cst.PREFIX_MSG_ERR + chalk.red('NVM is not available in PATH')); Common.printError(cst.PREFIX_MSG_ERR + chalk.red('Fallback to node in PATH')); - Common.printOut(cst.PREFIX_MSG_ERR + chalk.bold('Install NVM:\n$ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash')); + var msg = cst.IS_WINDOWS + ? 'https://github.com/coreybutler/nvm-windows/releases/' + : '$ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash'; + Common.printOut(cst.PREFIX_MSG_ERR + chalk.bold('Install NVM:\n' + msg)); } else { var node_version = app.exec_interpreter.split('@')[1]; - var nvm_node_path; - - if (semver.satisfies(node_version, '>= 0.12.0')) - nvm_node_path = path.join(process.env.NVM_DIR, '/versions/node/v' + node_version + '/bin/node'); - else - nvm_node_path = path.join(process.env.NVM_DIR, '/v' + node_version + '/bin/node'); + var path_to_node = cst.IS_WINDOWS + ? '/v' + node_version + '/node.exe' + : semver.satisfies(node_version, '>= 0.12.0') + ? '/versions/node/v' + node_version + '/bin/node' + : '/v' + node_version + '/bin/node'; + var nvm_node_path = path.join(nvm_path, path_to_node); try { fs.accessSync(nvm_node_path); } catch(e) { Common.printOut(cst.PREFIX_MSG + 'Installing Node v%s', node_version); - var nvm_bin = path.join(process.env.NVM_DIR, 'nvm.sh'); - var nvm_cmd = '. ' + nvm_bin + ' ; nvm install ' + node_version; + var nvm_bin = path.join(nvm_path, 'nvm.' + (cst.IS_WINDOWS ? 'exe' : 'sh')); + var nvm_cmd = cst.IS_WINDOWS + ? nvm_bin + ' install ' + node_version + : '. ' + nvm_bin + ' ; nvm install ' + node_version; Common.printOut(cst.PREFIX_MSG + 'Executing: %s', nvm_cmd); require('shelljs').exec(nvm_cmd); + + // in order to support both arch, nvm for Windows renames 'node.exe' to: + // 'node32.exe' for x32 arch + // 'node64.exe' for x64 arch + if (cst.IS_WINDOWS) + nvm_node_path = nvm_node_path.replace(/node/, 'node' + process.arch.slice(1)) } Common.printOut(cst.PREFIX_MSG + chalk.green.bold('Setting Node to v%s (path=%s)'), @@ -599,7 +611,8 @@ Common.verifyConfs = function(appConfs){ // If command is like pm2 start "python xx.py --ok" // Then automatically start the script with bash -c and set a name eq to command - if (app.script && app.script.indexOf(' ') > -1) { + + if (app.script && app.script.indexOf(' ') > -1 && app.script === path.basename(app.script)) { var _script = app.script; if (require('shelljs').which('bash')) app.script = 'bash'; diff --git a/lib/Configuration.js b/lib/Configuration.js index c68557a73..5bea8cbb9 100644 --- a/lib/Configuration.js +++ b/lib/Configuration.js @@ -9,7 +9,7 @@ var Configuration = module.exports = {}; var fs = require('fs'); var Common = require('./Common'); -var async = require('async'); +var eachSeries = require('async/eachSeries'); var cst = require('../constants.js'); function splitKey(key) { @@ -238,7 +238,7 @@ Configuration.multiset = function(serial, cb) { while (serial.length > 0) arrays.push(serial.splice(0, 2)); - async.eachSeries(arrays, function(el, next) { + eachSeries(arrays, function(el, next) { Configuration.set(el[0], el[1], next); }, cb); }; diff --git a/lib/Daemon.js b/lib/Daemon.js index 95eee01b8..f7ae6ba87 100644 --- a/lib/Daemon.js +++ b/lib/Daemon.js @@ -14,8 +14,9 @@ var Utility = require('./Utility.js'); var util = require('util'); var fs = require('fs'); var God = require('./God'); -var async = require('async'); +var eachLimit = require('async/eachLimit'); var fmt = require('./tools/fmt.js'); +var semver = require('semver'); var Daemon = module.exports = function(opts) { if (!opts) opts = {}; @@ -153,7 +154,7 @@ Daemon.prototype.innerStart = function(cb) { var profiler; try { - profiler = require('v8-profiler-node8'); + profiler = semver.satisfies(process.version, '>= 10.0.0') ? require('inspector') : null; } catch(e) { profiler = null; } @@ -163,18 +164,31 @@ Daemon.prototype.innerStart = function(cb) { */ function snapshotPM2(msg, cb) { if (profiler == null) { - console.log('v8-profiler is not available'); - return cb(new Error('v8-profiler is not available')); + console.log('Heap snapshot is not available (node 10+)'); + return cb(new Error('Heap snapshot is not available (node 10+)')); } - var snapshot1 = profiler.takeSnapshot(); - var path = require('path'); - snapshot1.export(function(error, result) { - fs.writeFile(msg.pwd, result, function() { - snapshot1.delete(); + const session = new profiler.Session() + session.connect() + session.post('HeapProfiler.enable') + + const chunks = [] + session.on('HeapProfiler.addHeapSnapshotChunk', (data) => { + chunks.push(data.params.chunk) + }) + + session.post('HeapProfiler.takeHeapSnapshot', { + reportProgress: false + }, (err, data) => { + if (err) return cb(err) + + fs.writeFile(msg.pwd, chunks.join(''), function() { + session.post('Profiler.disable') + session.disconnect() + return cb(null, {file : msg.pwd}); }); - }); + }) } function startProfilingPM2(msg, cb) { @@ -328,7 +342,7 @@ Daemon.prototype.gracefullExit = function() { var processes = God.getFormatedProcesses(); - async.eachLimit(processes, 1, function(proc, next) { + eachLimit(processes, 1, function(proc, next) { console.log('Deleting process %s', proc.pm2_env.pm_id); God.deleteProcessId(proc.pm2_env.pm_id, function() { return next(); diff --git a/lib/God.js b/lib/God.js index 2067ec312..42c73c806 100644 --- a/lib/God.js +++ b/lib/God.js @@ -20,12 +20,11 @@ var numCPUs = require('os').cpus() ? require('os').cpus().length : 1; var path = require('path'); var EventEmitter2 = require('eventemitter2').EventEmitter2; var fs = require('fs'); -var pidusage = require('pidusage'); var vizion = require('vizion'); var debug = require('debug')('pm2:god'); var Utility = require('./Utility'); var cst = require('../constants.js'); -var async = require('async'); +var timesLimit = require('async/timesLimit'); /** * Override cluster module configuration @@ -325,30 +324,45 @@ God.handleExit = function handleExit(clu, exit_code, kill_signal) { var min_uptime = typeof(proc.pm2_env.min_uptime) !== 'undefined' ? proc.pm2_env.min_uptime : 1000; var max_restarts = typeof(proc.pm2_env.max_restarts) !== 'undefined' ? proc.pm2_env.max_restarts : 16; + + //Only if process restart in repiting restart count ++ if process not run minimal uptime + if ((Date.now() - proc.pm2_env.pm_uptime) < min_uptime) { + // Increment unstable restart + proc.pm2_env.repiting_reset += 1; + } else { + proc.pm2_env.repiting_reset = 0; + } + + + + //On boot if ((Date.now() - proc.pm2_env.created_at) < (min_uptime * max_restarts)) { if ((Date.now() - proc.pm2_env.pm_uptime) < min_uptime) { // Increment unstable restart proc.pm2_env.unstable_restarts += 1; + } else { + proc.pm2_env.repiting_reset = 0; } + } - if (proc.pm2_env.unstable_restarts >= max_restarts) { - // Too many unstable restart in less than 15 seconds - // Set the process as 'ERRORED' - // And stop restarting it - proc.pm2_env.status = cst.ERRORED_STATUS; - proc.process.pid = 0; - console.log('Script %s had too many unstable restarts (%d). Stopped. %j', - proc.pm2_env.pm_exec_path, - proc.pm2_env.unstable_restarts, - proc.pm2_env.status); + if (proc.pm2_env.unstable_restarts >= max_restarts || proc.pm2_env.repiting_reset>= max_restarts) { + // Too many unstable restart in less than 15 seconds + // Set the process as 'ERRORED' + // And stop restarting it + proc.pm2_env.status = cst.ERRORED_STATUS; + proc.process.pid = 0; - God.notify('restart overlimit', proc); + console.log('Script %s had too many unstable restarts (%d). Stopped. %j', + proc.pm2_env.pm_exec_path, + proc.pm2_env.unstable_restarts, + proc.pm2_env.status); - proc.pm2_env.unstable_restarts = 0; - proc.pm2_env.created_at = null; - overlimit = true; - } + God.notify('restart overlimit', proc); + + proc.pm2_env.unstable_restarts = 0; + proc.pm2_env.created_at = null; + overlimit = true; } if (typeof(exit_code) !== 'undefined') proc.pm2_env.exit_code = exit_code; @@ -407,7 +421,7 @@ God.prepare = function prepare (env, cb) { env.instances = 1; } - async.timesLimit(env.instances, 1, function (n, next) { + timesLimit(env.instances, 1, function (n, next) { env.vizion_running = false; if (env.env && env.env.vizion_running) { env.env.vizion_running = false; diff --git a/lib/God/ActionMethods.js b/lib/God/ActionMethods.js index 836655712..c9272f645 100644 --- a/lib/God/ActionMethods.js +++ b/lib/God/ActionMethods.js @@ -13,7 +13,7 @@ var fs = require('fs'); var path = require('path'); -var async = require('async'); +var eachLimit = require('async/eachLimit'); var os = require('os'); var p = path; var cst = require('../../constants.js'); @@ -22,7 +22,6 @@ var pidusage = require('pidusage'); var util = require('util'); var debug = require('debug')('pm2:ActionMethod'); var Utility = require('../Utility'); -var semver = require('semver'); /** * Description @@ -63,6 +62,26 @@ module.exports = function(God) { if (err) { console.error('Error caught while calling pidusage'); console.error(err); + + return cb(null, processes.map(function(pro) { + pro['monit'] = { + memory : 0, + cpu : 0 + }; + return pro + })) + } + + if (!statistics) { + console.error('Statistics is not defined!') + + return cb(null, processes.map(function(pro) { + pro['monit'] = { + memory : 0, + cpu : 0 + }; + return pro + })) } processes = processes.map(function(pro) { @@ -89,7 +108,7 @@ module.exports = function(God) { pro['monit'] = { memory: stat.memory, - cpu: stat.cpu + cpu: Math.round(stat.cpu * 10) / 10 }; return pro; @@ -355,6 +374,7 @@ module.exports = function(God) { God.clusters_db[id].pm2_env.created_at = Utility.getDate(); God.clusters_db[id].pm2_env.unstable_restarts = 0; God.clusters_db[id].pm2_env.restart_time = 0; + God.clusters_db[id].pm2_env.repiting_reset = 0; return cb(null, God.getFormatedProcesses()); }; @@ -442,7 +462,7 @@ module.exports = function(God) { if (processes && processes.length === 0) return cb(God.logAndGenerateError('Unknown process'), {}); - async.eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { + eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { if (God.pm2_being_killed) return next('[Watch] PM2 is being killed, stopping restart procedure...'); if (proc.pm2_env.status === cst.ONLINE_STATUS) @@ -451,7 +471,7 @@ module.exports = function(God) { && proc.pm2_env.status !== cst.LAUNCHING_STATUS) return God.startProcessId(proc.pm2_env.pm_id, next); else - return next("[Watch] Process name %s is being stopped so I won't restart it", name); + return next(util.format('[Watch] Process name %s is being stopped so I won\'t restart it', name)); }, function(err) { if (err) return cb(God.logAndGenerateError(err)); return cb(null, God.getFormatedProcesses()); @@ -500,7 +520,7 @@ module.exports = function(God) { if (processes && processes.length === 0) return cb(God.logAndGenerateError('Unknown process name'), {}); - async.eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { + eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { if (proc.pm2_env.status == cst.ONLINE_STATUS || proc.pm2_env.status == cst.LAUNCHING_STATUS) { try { process.kill(proc.process.pid, signal); @@ -835,12 +855,12 @@ module.exports = function(God) { var report = { pm2_version : pkg.version, node_version : 'N/A', - node_path : process.env['_'], + node_path : process.env['_'] || 'not found', argv0 : process.argv0, argv : process.argv, user : process.env.USER, - uid : process.geteuid ? process.geteuid() : 'N/A', - gid : process.getegid ? process.getegid() : 'N/A', + uid : (cst.IS_WINDOWS === false && process.geteuid) ? process.geteuid() : 'N/A', + gid : (cst.IS_WINDOWS === false && process.getegid) ? process.getegid() : 'N/A', env : process.env, managed_apps : Object.keys(God.clusters_db).length, started_at : God.started_at diff --git a/lib/God/ClusterMode.js b/lib/God/ClusterMode.js index 3a1185a33..677f08708 100644 --- a/lib/God/ClusterMode.js +++ b/lib/God/ClusterMode.js @@ -11,7 +11,6 @@ * @project PM2 */ var cluster = require('cluster'); -var cst = require('../../constants.js'); var Utility = require('../Utility.js'); var pkg = require('../../package.json'); diff --git a/lib/God/ForkMode.js b/lib/God/ForkMode.js index d5ac57bcb..1bddafb12 100644 --- a/lib/God/ForkMode.js +++ b/lib/God/ForkMode.js @@ -12,7 +12,6 @@ */ var log = require('debug')('pm2:fork_mode'); var fs = require('fs'); -var cst = require('../../constants.js'); var moment = require('moment'); var Utility = require('../Utility.js'); var path = require('path'); diff --git a/lib/God/Methods.js b/lib/God/Methods.js index 60fc31be3..73e0c589c 100644 --- a/lib/God/Methods.js +++ b/lib/God/Methods.js @@ -11,10 +11,8 @@ * @project PM2 */ var p = require('path'); -var Utility = require('../Utility'); var treekill = require('../TreeKill'); var cst = require('../../constants.js'); -var debug = require('debug')('pm2:methods'); /** * Description diff --git a/lib/God/Reload.js b/lib/God/Reload.js index 5472f3b4e..2966eee5f 100644 --- a/lib/God/Reload.js +++ b/lib/God/Reload.js @@ -11,7 +11,6 @@ * @project PM2 */ -var async = require('async'); var cst = require('../../constants.js'); var Utility = require('../Utility.js'); diff --git a/lib/ProcessUtils.js b/lib/ProcessUtils.js index 0cc84f3ba..cdca79d43 100644 --- a/lib/ProcessUtils.js +++ b/lib/ProcessUtils.js @@ -1,16 +1,40 @@ +'use strict' + module.exports = { injectModules: function() { if (process.env.pmx !== 'false') { const pmx = require('@pm2/io'); - pmx.init({ - transactions: (process.env.trace === 'true' || process.env.deep_monitoring === 'true') || false, - http: process.env.km_link === 'true' || false, - v8: process.env.v8 === 'true' || process.env.deep_monitoring === 'true' || false, - event_loop_dump: process.env.event_loop_inspector === 'true' || process.env.deep_monitoring === 'true' || false, - deep_metrics: process.env.deep_monitoring === 'true' || false - }); - - if(require('semver').satisfies(process.versions.node, '>= 8.0.0')) { + + let conf = {}; + + if (process.env.io) { + const io = JSON.parse(process.env.io); + conf = io.conf ? io.conf : conf; + } + + var activate = process.env.km_link == 'true' || process.env.deep_monitoring === 'true' || false; + + // transaction: { + // tracing: activate + // }, + + let defaultConf = { + metrics: { + deepMetrics: activate, + v8: activate + }, + actions: { + eventLoopDump: activate, + profilingCpu: activate, + profilingHeap: activate + } + }; + + const mergedConf = Object.assign(defaultConf, conf); + + pmx.init(mergedConf); + + if (activate && require('semver').satisfies(process.versions.node, '>= 8.0.0')) { var url = ''; pmx.action('internal:inspect', function(reply) { const inspector = require('inspector'); diff --git a/lib/Satan.js b/lib/Satan.js index a6c77c264..887719945 100644 --- a/lib/Satan.js +++ b/lib/Satan.js @@ -23,7 +23,7 @@ var fs = require('fs'); var p = require('path'); var Utility = require('./Utility.js'); var domain = require('domain'); -var async = require('async'); +var eachLimit = require('async/eachLimit'); /** * Export @@ -96,7 +96,7 @@ Satan.processStateHandler = function(God) { var processes = God.getFormatedProcesses(); - async.eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { + eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { console.log('Deleting process %s', proc.pm2_env.pm_id); God.deleteProcessId(proc.pm2_env.pm_id, function() { return next(); diff --git a/lib/Utility.js b/lib/Utility.js index f172dc81d..b3be4e196 100644 --- a/lib/Utility.js +++ b/lib/Utility.js @@ -8,13 +8,12 @@ * Common Utilities ONLY USED IN ->DAEMON<- */ -var fclone = require('fclone'); -var fs = require('fs'); -var path = require('path'); -var cst = require('../constants.js'); -var async = require('async'); -var util = require('util'); -var url = require('url'); +var fclone = require('fclone'); +var fs = require('fs'); +var cst = require('../constants.js'); +var waterfall = require('async/waterfall'); +var util = require('util'); +var url = require('url'); var Utility = module.exports = { getDate : function() { @@ -176,7 +175,7 @@ var Utility = module.exports = { return createWS(types.splice(0, 1)); })(types.splice(0, 1)); - async.waterfall(flows, callback); + waterfall(flows, callback); }, /** diff --git a/lib/Watcher.js b/lib/Watcher.js index 1397d9308..2b09b6934 100644 --- a/lib/Watcher.js +++ b/lib/Watcher.js @@ -4,7 +4,6 @@ * can be found in the LICENSE file. */ var chokidar = require('chokidar'); -var p = require('path'); var util = require('util'); var log = require('debug')('pm2:watch'); diff --git a/lib/Worker.js b/lib/Worker.js index 1a6cf7c8d..60f9597ca 100644 --- a/lib/Worker.js +++ b/lib/Worker.js @@ -3,11 +3,11 @@ * Use of this source code is governed by a license that * can be found in the LICENSE file. */ -var vizion = require('vizion'); -var cst = require('../constants.js'); -var async = require('async'); -var debug = require('debug')('pm2:worker'); -var domain = require('domain'); +var vizion = require('vizion'); +var cst = require('../constants.js'); +var eachLimit = require('async/eachLimit'); +var debug = require('debug')('pm2:worker'); +var domain = require('domain'); module.exports = function(God) { var timer = null; @@ -104,7 +104,7 @@ module.exports = function(God) { return console.error(err); } - async.eachLimit(data, 1, function(proc_key, next) { + eachLimit(data, 1, function(proc_key, next) { if (!proc_key || !proc_key.pm2_env || proc_key.pm2_env.pm_id === undefined) diff --git a/lib/binaries/DevCLI.js b/lib/binaries/DevCLI.js index f06c8c0c9..02f986d9b 100644 --- a/lib/binaries/DevCLI.js +++ b/lib/binaries/DevCLI.js @@ -7,14 +7,10 @@ process.env.PM2_DISCRETE_MODE = true; var commander = require('commander'); -var debug = require('debug')('pm2:cli'); var PM2 = require('../..'); var Log = require('../API/Log'); var cst = require('../../constants.js'); var pkg = require('../../package.json'); -var platform = require('os').platform(); -var moment = require('moment'); -var Common = require('../Common'); var chalk = require('chalk'); var path = require('path'); var fmt = require('../tools/fmt.js'); diff --git a/lib/binaries/Runtime.js b/lib/binaries/Runtime.js index 0ad94aeef..5c24d32e8 100644 --- a/lib/binaries/Runtime.js +++ b/lib/binaries/Runtime.js @@ -3,7 +3,6 @@ var commander = require('commander'); -var debug = require('debug')('pm2:cli'); var PM2 = require('../..'); var Log = require('../../lib/API/Log'); var cst = require('../../constants.js'); diff --git a/lib/binaries/Runtime4Docker.js b/lib/binaries/Runtime4Docker.js index 837daa4b3..3bc84b8f7 100644 --- a/lib/binaries/Runtime4Docker.js +++ b/lib/binaries/Runtime4Docker.js @@ -4,7 +4,6 @@ * Specialized PM2 CLI for Containers */ var commander = require('commander'); -var debug = require('debug')('pm2:cli'); var PM2 = require('../..'); var Log = require('../../lib/API/Log'); var cst = require('../../constants.js'); @@ -115,7 +114,7 @@ var Runtime = { if (err) return cb(err); if (obj && obj.length == 0) - return cb(new Error('Failed to start application')) + return cb(new Error(`0 application started (no apps to run on ${cmd})`)) if (commander.web) { var port = commander.web === true ? cst.WEB_PORT : commander.web; diff --git a/lib/completion.js b/lib/completion.js index 82ade219a..38495bec6 100644 --- a/lib/completion.js +++ b/lib/completion.js @@ -4,8 +4,7 @@ * can be found in the LICENSE file. */ var fs = require('fs'), - pth = require('path'), - exec = require('child_process').exec; + pth = require('path'); // hacked from node-tabtab 0.0.4 https://github.com/mklabs/node-tabtab.git // Itself based on npm completion by @isaac @@ -53,7 +52,7 @@ exports.complete = function complete(name, completer, cb) { // Really, one should not be tossing away EPIPE errors, or any // errors, so casually. But, without this, `. <(npm completion)` // can never ever work on OS X. - // -- isaacs + // -- isaacs // https://github.com/isaacs/npm/blob/master/lib/completion.js#L162 if (er.errno === "EPIPE") er = null cb(er, null, content); diff --git a/lib/motd.update b/lib/motd.update deleted file mode 100644 index 7ea0e9b63..000000000 --- a/lib/motd.update +++ /dev/null @@ -1,18 +0,0 @@ - - ------------- - __ __ __ _ - / //_/__ __ ______ ___ ___ / /______(_)_________ - / ,< / _ \/ / / / __ `__ \/ _ \/ __/ ___/ / ___/ ___/ - / /| / __/ /_/ / / / / / / __/ /_/ / / / /__(__ ) - /_/ |_\___/\__, /_/ /_/ /_/\___/\__/_/ /_/\___/____/ - /____/ - - Start monitoring your Node.js application today - - $ pm2 monitor - - To know more about the PM2 monitoring solution: - - https://keymetrics.io/ - - ------------- diff --git a/lib/templates/init-scripts/rcd-openbsd.tpl b/lib/templates/init-scripts/rcd-openbsd.tpl new file mode 100644 index 000000000..590a995e1 --- /dev/null +++ b/lib/templates/init-scripts/rcd-openbsd.tpl @@ -0,0 +1,41 @@ +#!/bin/sh +# +# from /usr/ports/infrastructure/templates/rc.template + +daemon="/usr/local/bin/pm2" +#daemon_flags= +#daemon_rtable=0 +#daemon_timeout="30" +daemon_user="%USER%" + +. /etc/rc.d/rc.subr + +pexp="node: PM2.*God Daemon.*" +#rc_bg= # (undefined) +#rc_reload= # (undefined) +#rc_usercheck=YES + +#rc_pre() { +#} + +rc_start() { + ${rcexec} "${daemon} ${daemon_flags} resurrect" +} + +#rc_check() { +# pgrep -T "${daemon_rtable}" -q -xf "${pexp}" +#} + +rc_reload() { + ${rcexec} "${daemon} reload all" + #pkill -HUP -T "${daemon_rtable}" -xf "${pexp}" +} + +#rc_stop() { +# pkill -T "${daemon_rtable}" -xf "${pexp}" +#} + +#rc_post() { +#} + +rc_cmd $1 diff --git a/lib/templates/init-scripts/upstart.tpl b/lib/templates/init-scripts/upstart.tpl index 2bd728789..eba124bb3 100644 --- a/lib/templates/init-scripts/upstart.tpl +++ b/lib/templates/init-scripts/upstart.tpl @@ -24,7 +24,7 @@ MAX_OPEN_FILES= # overwrite settings from default file if [ -f "$DEFAULT" ]; then - . "$DEFAULT" + . "$DEFAULT" fi # set maximum open files if set @@ -33,7 +33,8 @@ if [ -n "$MAX_OPEN_FILES" ]; then fi get_user_shell() { - local shell=$(getent passwd ${1:-`whoami`} | cut -d: -f7 | sed -e 's/[[:space:]]*$//') + local shell + shell=$(getent passwd "${1:-$(whoami)}" | cut -d: -f7 | sed -e 's/[[:space:]]*$//') if [[ $shell == *"/sbin/nologin" ]] || [[ $shell == "/bin/false" ]] || [[ -z "$shell" ]]; then @@ -44,8 +45,9 @@ get_user_shell() { } super() { - local shell=$(get_user_shell $USER) - su - $USER -s $shell -c "PATH=$PATH; PM2_HOME=$PM2_HOME $*" + local shell + shell=$(get_user_shell $USER) + su - "$USER" -s "$shell" -c "PATH=$PATH; PM2_HOME=$PM2_HOME $*" } start() { diff --git a/lib/tools/isbinaryfile.js b/lib/tools/isbinaryfile.js index 7b0135d08..23b51f2c6 100644 --- a/lib/tools/isbinaryfile.js +++ b/lib/tools/isbinaryfile.js @@ -4,7 +4,6 @@ * can be found in the LICENSE file. */ var fs = require('fs'); -var path = require("path"); var max_bytes = 512; module.exports = function(bytes, size) { diff --git a/lib/tools/xdg-open b/lib/tools/xdg-open index 9be7f32f6..2b7a8ed94 100755 --- a/lib/tools/xdg-open +++ b/lib/tools/xdg-open @@ -311,7 +311,7 @@ check_vendor_prefix() check_output_file() { # if the file exists, check if it is writeable - # if it does not exists, check if we are allowed to write on the directory + # if it does not exist, check if we are allowed to write on the directory if [ -e "$1" ]; then if [ ! -w "$1" ]; then exit_failure_file_permission_write "no permission to write to file '$1'" @@ -415,7 +415,7 @@ detectDE() DE=gnome; ;; LXDE|Lubuntu) - DE=lxde; + DE=lxde; ;; MATE) DE=mate; @@ -428,7 +428,7 @@ detectDE() if [ x"$DE" = x"" ]; then # fallback to uname output for other platforms - case "$(uname 2>/dev/null)" in + case "$(uname 2>/dev/null)" in Darwin) DE=darwin; ;; diff --git a/package.json b/package.json index 243a8988c..814a32441 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pm2", "preferGlobal": true, - "version": "3.0.0-alpha1", + "version": "3.0.1", "engines": { "node": ">=4.0.0" }, @@ -158,13 +158,13 @@ "pm2-runtime": "./bin/pm2-runtime" }, "dependencies": { - "@pm2/agent": "latest", - "@pm2/io": "latest", - "@pm2/js-api": "latest", - "async": "^2.6", + "@pm2/agent": "^0.5.11", + "@pm2/io": "~2.1.0", + "@pm2/js-api": "^0.5.15", + "async": "^2.6.1", "blessed": "^0.1.81", "chalk": "^2.4.1", - "chokidar": "^2.0.3", + "chokidar": "^2.0.4", "cli-table-redemption": "^1.0.0", "commander": "2.15.1", "cron": "^1.3", @@ -172,25 +172,25 @@ "eventemitter2": "5.0.1", "fclone": "1.0.11", "mkdirp": "0.5.1", - "moment": "^2.22", - "needle": "^2.2.0", + "moment": "^2.22.2", + "needle": "^2.2.1", "nssocket": "0.6.0", - "pidusage": "^2.0.6", - "pm2-axon": "3.1.0", + "pidusage": "^2.0.14", + "pm2-axon": "3.3.0", "pm2-axon-rpc": "^0.5.1", "pm2-deploy": "^0.3.9", "pm2-multimeter": "^0.1.2", - "promptly": "2.2.0", + "promptly": "^2", "semver": "^5.5", "shelljs": "~0.8.2", - "source-map-support": "^0.5", + "source-map-support": "^0.5.6", "sprintf-js": "1.1.1", "v8-compile-cache": "^2.0.0", - "vizion": "~0.2.0", + "vizion": "2.0.2", "yamljs": "^0.3.0" }, "devDependencies": { - "mocha": "^3.5", + "mocha": "^5.2.0", "should": "^13" }, "optionalDependencies": { diff --git a/packager/debian/postinst b/packager/debian/postinst index e37fd104f..9a6a7834c 100755 --- a/packager/debian/postinst +++ b/packager/debian/postinst @@ -3,13 +3,13 @@ set -e adduser --quiet --system \ - --group --home /etc/pm2 \ - --gecos "PM2 Process Manager" pm2 + --group --home /etc/pm2 \ + --gecos "PM2 Process Manager" pm2 if hash systemctl 2> /dev/null; then { - systemctl enable "pm2.service" && \ - systemctl start "pm2.service" + systemctl enable "pm2.service" && \ + systemctl start "pm2.service" } || echo "pm2 could not be registered or started" elif hash service 2> /dev/null; then service "pm2" start || echo "pm2 could not be registered or started" diff --git a/packager/debian/prerm b/packager/debian/prerm index d9deb2446..3f94737a5 100755 --- a/packager/debian/prerm +++ b/packager/debian/prerm @@ -2,8 +2,8 @@ if hash systemctl 2> /dev/null; then systemctl disable "pm2.service" && \ - systemctl stop "pm2.service" || \ - echo "pm2 wasn't even running!" + systemctl stop "pm2.service" || \ + echo "pm2 wasn't even running!" elif hash service 2> /dev/null; then service "pm2" stop || echo "pm2 wasn't even running!" else diff --git a/packager/rhel/postinst b/packager/rhel/postinst index ed22be211..db38cb414 100755 --- a/packager/rhel/postinst +++ b/packager/rhel/postinst @@ -5,15 +5,15 @@ set -e mkdir -p /etc/pm2 adduser --system \ - --home-dir /etc/pm2 \ - --comment "PM2 Process Manager" pm2 + --home-dir /etc/pm2 \ + --comment "PM2 Process Manager" pm2 chown -R pm2:pm2 /etc/pm2 if hash systemctl 2> /dev/null; then { - systemctl enable "pm2.service" && \ - systemctl start "pm2.service" + systemctl enable "pm2.service" && \ + systemctl start "pm2.service" } || echo "pm2 could not be registered or started" elif hash service 2> /dev/null; then service "pm2" start || echo "pm2 could not be registered or started" diff --git a/packager/rhel/prerm b/packager/rhel/prerm index d9deb2446..3f94737a5 100755 --- a/packager/rhel/prerm +++ b/packager/rhel/prerm @@ -2,8 +2,8 @@ if hash systemctl 2> /dev/null; then systemctl disable "pm2.service" && \ - systemctl stop "pm2.service" || \ - echo "pm2 wasn't even running!" + systemctl stop "pm2.service" || \ + echo "pm2 wasn't even running!" elif hash service 2> /dev/null; then service "pm2" stop || echo "pm2 wasn't even running!" else diff --git a/packager/setup.deb.sh b/packager/setup.deb.sh index 5d78d6127..272d641b2 100755 --- a/packager/setup.deb.sh +++ b/packager/setup.deb.sh @@ -4,7 +4,7 @@ REPOSITORY_OWNER="Keymetrics" show_banner () { - echo + echo echo "__/\\\\\\\\\\\\\\\\\\\\\\\\\\____/\\\\\\\\____________/\\\\\\\\____/\\\\\\\\\\\\\\\\\\_____" echo " _\\/\\\\\\/////////\\\\\\_\\/\\\\\\\\\\\\________/\\\\\\\\\\\\__/\\\\\\///////\\\\\\___" echo " _\\/\\\\\\_______\\/\\\\\\_\\/\\\\\\//\\\\\\____/\\\\\\//\\\\\\_\\///______\\//\\\\\\__" @@ -33,15 +33,15 @@ gpg_check () { echo "Checking for gpg..." if command -v gpg > /dev/null; then - echo "Detected gpg..." + echo "Detected gpg..." else - echo "Installing gnupg for GPG verification..." - apt-get install -y gnupg - if [ "$?" -ne "0" ]; then - echo "Unable to install GPG! Your base system has a problem; please check your default OS's package repositories because GPG should work." - echo "Repository installation aborted." - exit 1 - fi + echo "Installing gnupg for GPG verification..." + apt-get install -y gnupg + if [ "$?" -ne "0" ]; then + echo "Unable to install GPG! Your base system has a problem; please check your default OS's package repositories because GPG should work." + echo "Repository installation aborted." + exit 1 + fi fi } @@ -49,24 +49,24 @@ curl_check () { echo "Checking for curl..." if command -v curl > /dev/null; then - echo "Detected curl..." + echo "Detected curl..." else - echo "Installing curl..." - apt-get install -q -y curl - if [ "$?" -ne "0" ]; then - echo "Unable to install curl! Your base system has a problem; please check your default OS's package repositories because curl should work." - echo "Repository installation aborted." - exit 1 - fi + echo "Installing curl..." + apt-get install -q -y curl + if [ "$?" -ne "0" ]; then + echo "Unable to install curl! Your base system has a problem; please check your default OS's package repositories because curl should work." + echo "Repository installation aborted." + exit 1 + fi fi } install_debian_keyring () { if [ "${os}" = "debian" ]; then - echo "Installing debian-archive-keyring which is needed for installing " - echo "apt-transport-https on many Debian systems." - apt-get install -y debian-archive-keyring &> /dev/null + echo "Installing debian-archive-keyring which is needed for installing " + echo "apt-transport-https on many Debian systems." + apt-get install -y debian-archive-keyring &> /dev/null fi } @@ -74,44 +74,44 @@ install_debian_keyring () detect_os () { if [[ ( -z "${os}" ) && ( -z "${dist}" ) ]]; then - # some systems dont have lsb-release yet have the lsb_release binary and - # vice-versa - if [ -e /etc/lsb-release ]; then - . /etc/lsb-release - - if [ "${ID}" = "raspbian" ]; then - os=${ID} - dist=`cut --delimiter='.' -f1 /etc/debian_version` - else - os=${DISTRIB_ID} - dist=${DISTRIB_CODENAME} - - if [ -z "$dist" ]; then - dist=${DISTRIB_RELEASE} - fi - fi - - elif [ `which lsb_release 2>/dev/null` ]; then - dist=`lsb_release -c | cut -f2` - os=`lsb_release -i | cut -f2 | awk '{ print tolower($1) }'` - - elif [ -e /etc/debian_version ]; then - # some Debians have jessie/sid in their /etc/debian_version - # while others have '6.0.7' - os=`cat /etc/issue | head -1 | awk '{ print tolower($1) }'` - if grep -q '/' /etc/debian_version; then - dist=`cut --delimiter='/' -f1 /etc/debian_version` - else - dist=`cut --delimiter='.' -f1 /etc/debian_version` - fi - - else - unknown_os - fi + # some systems dont have lsb-release yet have the lsb_release binary and + # vice-versa + if [ -e /etc/lsb-release ]; then + . /etc/lsb-release + + if [ "${ID}" = "raspbian" ]; then + os=${ID} + dist=`cut --delimiter='.' -f1 /etc/debian_version` + else + os=${DISTRIB_ID} + dist=${DISTRIB_CODENAME} + + if [ -z "$dist" ]; then + dist=${DISTRIB_RELEASE} + fi + fi + + elif [ `which lsb_release 2>/dev/null` ]; then + dist=`lsb_release -c | cut -f2` + os=`lsb_release -i | cut -f2 | awk '{ print tolower($1) }'` + + elif [ -e /etc/debian_version ]; then + # some Debians have jessie/sid in their /etc/debian_version + # while others have '6.0.7' + os=`cat /etc/issue | head -1 | awk '{ print tolower($1) }'` + if grep -q '/' /etc/debian_version; then + dist=`cut --delimiter='/' -f1 /etc/debian_version` + else + dist=`cut --delimiter='.' -f1 /etc/debian_version` + fi + + else + unknown_os + fi fi if [ -z "$dist" ]; then - unknown_os + unknown_os fi # remove whitespace from OS and dist name @@ -164,31 +164,31 @@ main () curl_exit_code=$? if [ "$curl_exit_code" = "22" ]; then - echo "This script is unable to download the repository definition." - echo - [ -e $apt_source_path ] && rm $apt_source_path - unknown_os + echo "This script is unable to download the repository definition." + echo + [ -e $apt_source_path ] && rm $apt_source_path + unknown_os elif [ "$curl_exit_code" = "35" -o "$curl_exit_code" = "60" ]; then - echo "curl is unable to connect to packagecloud.io over TLS when running: " - echo " curl ${apt_config_url}" - echo "This is usually due to one of two things:" - echo - echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)" - echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version" - echo - echo "Contact support@packagecloud.io with information about your system for help." - [ -e $apt_source_path ] && rm $apt_source_path - exit 1 + echo "curl is unable to connect to packagecloud.io over TLS when running: " + echo " curl ${apt_config_url}" + echo "This is usually due to one of two things:" + echo + echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)" + echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version" + echo + echo "Contact support@packagecloud.io with information about your system for help." + [ -e $apt_source_path ] && rm $apt_source_path + exit 1 elif [ "$curl_exit_code" -gt "0" ]; then - echo - echo "Unable to run: " - echo " curl ${apt_config_url}" - echo - echo "Double check your curl installation and try again." - [ -e $apt_source_path ] && rm $apt_source_path - exit 1 + echo + echo "Unable to run: " + echo " curl ${apt_config_url}" + echo + echo "Double check your curl installation and try again." + [ -e $apt_source_path ] && rm $apt_source_path + exit 1 else - echo "done." + echo "done." fi echo -n "Importing packagecloud gpg key... " @@ -207,21 +207,21 @@ main () CURR_USER=$SUDO_USER if [ "$CURR_USER" == "" ]; then - CURR_USER=$USER + CURR_USER=$USER fi - + if [ "$CURR_USER" == "root" ] || [ "$CURR_USER" == "" ]; then - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - echo "WARNING: You are either running this script as root or the" - echo " \$USER variable is empty. In order to have a" - echo " working PM2 installation, you need to add your" - echo " user in the pm2 group using the following" - echo " command: usermod -aG pm2 " - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo "WARNING: You are either running this script as root or the" + echo " \$USER variable is empty. In order to have a" + echo " working PM2 installation, you need to add your" + echo " user in the pm2 group using the following" + echo " command: usermod -aG pm2 " + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" else - echo -n "Adding $CURR_USER to group pm2..." - usermod -aG pm2 $CURR_USER - echo "done." + echo -n "Adding $CURR_USER to group pm2..." + usermod -aG pm2 $CURR_USER + echo "done." fi echo echo "Installation done." diff --git a/packager/setup.rpm.sh b/packager/setup.rpm.sh index 15322c822..b9791a39f 100755 --- a/packager/setup.rpm.sh +++ b/packager/setup.rpm.sh @@ -4,7 +4,7 @@ REPOSITORY_OWNER="Keymetrics" show_banner () { - echo + echo echo "__/\\\\\\\\\\\\\\\\\\\\\\\\\\____/\\\\\\\\____________/\\\\\\\\____/\\\\\\\\\\\\\\\\\\_____" echo " _\\/\\\\\\/////////\\\\\\_\\/\\\\\\\\\\\\________/\\\\\\\\\\\\__/\\\\\\///////\\\\\\___" echo " _\\/\\\\\\_______\\/\\\\\\_\\/\\\\\\//\\\\\\____/\\\\\\//\\\\\\_\\///______\\//\\\\\\__" @@ -33,10 +33,10 @@ curl_check () { echo "Checking for curl..." if command -v curl > /dev/null; then - echo "Detected curl..." + echo "Detected curl..." else - echo "Installing curl..." - yum install -d0 -e0 -y curl + echo "Installing curl..." + yum install -d0 -e0 -y curl fi } @@ -44,60 +44,60 @@ curl_check () detect_os () { if [[ ( -z "${os}" ) && ( -z "${dist}" ) ]]; then - if [ -e /etc/os-release ]; then - . /etc/os-release - os=${ID} - if [ "${os}" = "poky" ]; then - dist=`echo ${VERSION_ID}` - elif [ "${os}" = "sles" ]; then - dist=`echo ${VERSION_ID}` - elif [ "${os}" = "opensuse" ]; then - dist=`echo ${VERSION_ID}` - else - dist=`echo ${VERSION_ID} | awk -F '.' '{ print $1 }'` - fi - - elif [ `which lsb_release 2>/dev/null` ]; then - # get major version (e.g. '5' or '6') - dist=`lsb_release -r | cut -f2 | awk -F '.' '{ print $1 }'` - - # get os (e.g. 'centos', 'redhatenterpriseserver', etc) - os=`lsb_release -i | cut -f2 | awk '{ print tolower($1) }'` - - elif [ -e /etc/oracle-release ]; then - dist=`cut -f5 --delimiter=' ' /etc/oracle-release | awk -F '.' '{ print $1 }'` - os='ol' - - elif [ -e /etc/fedora-release ]; then - dist=`cut -f3 --delimiter=' ' /etc/fedora-release` - os='fedora' - - elif [ -e /etc/redhat-release ]; then - os_hint=`cat /etc/redhat-release | awk '{ print tolower($1) }'` - if [ "${os_hint}" = "centos" ]; then - dist=`cat /etc/redhat-release | awk '{ print $3 }' | awk -F '.' '{ print $1 }'` - os='centos' - elif [ "${os_hint}" = "scientific" ]; then - dist=`cat /etc/redhat-release | awk '{ print $4 }' | awk -F '.' '{ print $1 }'` - os='scientific' - else - dist=`cat /etc/redhat-release | awk '{ print tolower($7) }' | cut -f1 --delimiter='.'` - os='redhatenterpriseserver' - fi - - else - aws=`grep -q Amazon /etc/issue` - if [ "$?" = "0" ]; then - dist='6' - os='aws' - else - unknown_os - fi - fi + if [ -e /etc/os-release ]; then + . /etc/os-release + os=${ID} + if [ "${os}" = "poky" ]; then + dist=`echo ${VERSION_ID}` + elif [ "${os}" = "sles" ]; then + dist=`echo ${VERSION_ID}` + elif [ "${os}" = "opensuse" ]; then + dist=`echo ${VERSION_ID}` + else + dist=`echo ${VERSION_ID} | awk -F '.' '{ print $1 }'` + fi + + elif [ `which lsb_release 2>/dev/null` ]; then + # get major version (e.g. '5' or '6') + dist=`lsb_release -r | cut -f2 | awk -F '.' '{ print $1 }'` + + # get os (e.g. 'centos', 'redhatenterpriseserver', etc) + os=`lsb_release -i | cut -f2 | awk '{ print tolower($1) }'` + + elif [ -e /etc/oracle-release ]; then + dist=`cut -f5 --delimiter=' ' /etc/oracle-release | awk -F '.' '{ print $1 }'` + os='ol' + + elif [ -e /etc/fedora-release ]; then + dist=`cut -f3 --delimiter=' ' /etc/fedora-release` + os='fedora' + + elif [ -e /etc/redhat-release ]; then + os_hint=`cat /etc/redhat-release | awk '{ print tolower($1) }'` + if [ "${os_hint}" = "centos" ]; then + dist=`cat /etc/redhat-release | awk '{ print $3 }' | awk -F '.' '{ print $1 }'` + os='centos' + elif [ "${os_hint}" = "scientific" ]; then + dist=`cat /etc/redhat-release | awk '{ print $4 }' | awk -F '.' '{ print $1 }'` + os='scientific' + else + dist=`cat /etc/redhat-release | awk '{ print tolower($7) }' | cut -f1 --delimiter='.'` + os='redhatenterpriseserver' + fi + + else + aws=`grep -q Amazon /etc/issue` + if [ "$?" = "0" ]; then + dist='6' + os='aws' + else + unknown_os + fi + fi fi if [[ ( -z "${os}" ) || ( -z "${dist}" ) ]]; then - unknown_os + unknown_os fi # remove whitespace from OS and dist name @@ -113,25 +113,25 @@ finalize_yum_repo () yum install -y pygpgme --disablerepo='Keymetrics_pm2' pypgpme_check=`rpm -qa | grep -qw pygpgme` if [ "$?" != "0" ]; then - echo - echo "WARNING: " - echo "The pygpgme package could not be installed. This means GPG verification is not possible for any RPM installed on your system. " - echo "To fix this, add a repository with pygpgme. Usualy, the EPEL repository for your system will have this. " - echo "More information: https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F" - echo - - # set the repo_gpgcheck option to 0 - sed -i'' 's/repo_gpgcheck=1/repo_gpgcheck=0/' /etc/yum.repos.d/Keymetrics_pm2.repo + echo + echo "WARNING: " + echo "The pygpgme package could not be installed. This means GPG verification is not possible for any RPM installed on your system. " + echo "To fix this, add a repository with pygpgme. Usualy, the EPEL repository for your system will have this. " + echo "More information: https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F" + echo + + # set the repo_gpgcheck option to 0 + sed -i'' 's/repo_gpgcheck=1/repo_gpgcheck=0/' /etc/yum.repos.d/Keymetrics_pm2.repo fi echo "Installing yum-utils..." yum install -y yum-utils --disablerepo='Keymetrics_pm2' yum_utils_check=`rpm -qa | grep -qw yum-utils` if [ "$?" != "0" ]; then - echo - echo "WARNING: " - echo "The yum-utils package could not be installed. This means you may not be able to install source RPMs or use other yum features." - echo + echo + echo "WARNING: " + echo "The yum-utils package could not be installed. This means you may not be able to install source RPMs or use other yum features." + echo fi echo "Generating yum cache for Keymetrics_pm2..." @@ -156,22 +156,22 @@ install_pm2 () CURR_USER=$SUDO_USER if [ "$CURR_USER" == "" ]; then - CURR_USER=$USER + CURR_USER=$USER fi - + if [ "$CURR_USER" == "root" ] || [ "$CURR_USER" == "" ]; then - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - echo "WARNING: You are either running this script as root or the" - echo " \$USER variable is empty. In order to have a" - echo " working PM2 installation, you need to add your" - echo " user in the pm2 group using the following" - echo " command: usermod -aG pm2 " - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo "WARNING: You are either running this script as root or the" + echo " \$USER variable is empty. In order to have a" + echo " working PM2 installation, you need to add your" + echo " user in the pm2 group using the following" + echo " command: usermod -aG pm2 " + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" else - echo -n "Adding $CURR_USER to group pm2..." - usermod -aG pm2 $CURR_USER - echo "done." - fi + echo -n "Adding $CURR_USER to group pm2..." + usermod -aG pm2 $CURR_USER + echo "done." + fi } main () @@ -183,65 +183,65 @@ main () yum_repo_config_url="https://packagecloud.io/install/repositories/$REPOSITORY_OWNER/pm2/config_file.repo?os=${os}&dist=${dist}&source=script" if [ "${os}" = "sles" ] || [ "${os}" = "opensuse" ]; then - yum_repo_path=/etc/zypp/repos.d/Keymetrics_pm2.repo + yum_repo_path=/etc/zypp/repos.d/Keymetrics_pm2.repo else - yum_repo_path=/etc/yum.repos.d/Keymetrics_pm2.repo - install_node + yum_repo_path=/etc/yum.repos.d/Keymetrics_pm2.repo + install_node fi - + echo "Downloading repository file: ${yum_repo_config_url}" curl -sSf "${yum_repo_config_url}" > $yum_repo_path curl_exit_code=$? if [ "$curl_exit_code" = "22" ]; then - echo - echo - echo -n "Unable to download repo config from: " - echo "${yum_repo_config_url}" - echo - echo "This usually happens if your operating system is not supported by " - echo "packagecloud.io, or this script's OS detection failed." - echo - echo "You can override the OS detection by setting os= and dist= prior to running this script." - echo "You can find a list of supported OSes and distributions on our website: https://packagecloud.io/docs#os_distro_version" - echo - echo "For example, to force CentOS 6: os=el dist=6 ./script.sh" - echo - echo "If you are running a supported OS, please email support@packagecloud.io and report this." - [ -e $yum_repo_path ] && rm $yum_repo_path - exit 1 + echo + echo + echo -n "Unable to download repo config from: " + echo "${yum_repo_config_url}" + echo + echo "This usually happens if your operating system is not supported by " + echo "packagecloud.io, or this script's OS detection failed." + echo + echo "You can override the OS detection by setting os= and dist= prior to running this script." + echo "You can find a list of supported OSes and distributions on our website: https://packagecloud.io/docs#os_distro_version" + echo + echo "For example, to force CentOS 6: os=el dist=6 ./script.sh" + echo + echo "If you are running a supported OS, please email support@packagecloud.io and report this." + [ -e $yum_repo_path ] && rm $yum_repo_path + exit 1 elif [ "$curl_exit_code" = "35" -o "$curl_exit_code" = "60" ]; then - echo - echo "curl is unable to connect to packagecloud.io over TLS when running: " - echo " curl ${yum_repo_config_url}" - echo - echo "This is usually due to one of two things:" - echo - echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)" - echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version" - echo - echo "Contact support@packagecloud.io with information about your system for help." - [ -e $yum_repo_path ] && rm $yum_repo_path - exit 1 + echo + echo "curl is unable to connect to packagecloud.io over TLS when running: " + echo " curl ${yum_repo_config_url}" + echo + echo "This is usually due to one of two things:" + echo + echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)" + echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version" + echo + echo "Contact support@packagecloud.io with information about your system for help." + [ -e $yum_repo_path ] && rm $yum_repo_path + exit 1 elif [ "$curl_exit_code" -gt "0" ]; then - echo - echo "Unable to run: " - echo " curl ${yum_repo_config_url}" - echo - echo "Double check your curl installation and try again." - [ -e $yum_repo_path ] && rm $yum_repo_path - exit 1 + echo + echo "Unable to run: " + echo " curl ${yum_repo_config_url}" + echo + echo "Double check your curl installation and try again." + [ -e $yum_repo_path ] && rm $yum_repo_path + exit 1 else - echo "done." + echo "done." fi if [ "${os}" = "sles" ] || [ "${os}" = "opensuse" ]; then - finalize_zypper_repo - install_pm2 zypper + finalize_zypper_repo + install_pm2 zypper else - finalize_yum_repo - install_pm2 yum + finalize_yum_repo + install_pm2 yum fi echo diff --git a/pres/TMP.md b/pres/TMP.md new file mode 100644 index 000000000..19a17b17e --- /dev/null +++ b/pres/TMP.md @@ -0,0 +1,68 @@ +### Commands Cheatsheet + +
+ Commands Cheatsheet + +```bash +# General +$ npm install pm2 -g # Install PM2 +$ pm2 start app.js # Start, Daemonize and auto-restart application (Node) +$ pm2 start app.py # Start, Daemonize and auto-restart application (Python) +$ pm2 start npm -- start # Start, Daemonize and auto-restart Node application + +# Cluster Mode (Node.js only) +$ pm2 start app.js -i 4 # Start 4 instances of application in cluster mode + # it will load balance network queries to each app +$ pm2 reload all # Zero Second Downtime Reload +$ pm2 scale [app-name] 10 # Scale Cluster app to 10 process + +# Process Monitoring +$ pm2 list # List all processes started with PM2 +$ pm2 list --sort= # Sort all processes started with PM2 +$ pm2 monit # Display memory and cpu usage of each app +$ pm2 show [app-name] # Show all information about application + +# Log management +$ pm2 logs # Display logs of all apps +$ pm2 logs [app-name] # Display logs for a specific app +$ pm2 logs --json # Logs in JSON format +$ pm2 flush +$ pm2 reloadLogs + +# Process State Management +$ pm2 start app.js --name="api" # Start application and name it "api" +$ pm2 start app.js -- -a 34 # Start app and pass option "-a 34" as argument +$ pm2 start app.js --watch # Restart application on file change +$ pm2 start script.sh # Start bash script +$ pm2 start app.json # Start all applications declared in app.json +$ pm2 reset [app-name] # Reset all counters +$ pm2 stop all # Stop all apps +$ pm2 stop 0 # Stop process with id 0 +$ pm2 restart all # Restart all apps +$ pm2 delete all # Kill and delete all apps +$ pm2 delete 0 # Delete app with id 0 + +# Startup/Boot management +$ pm2 startup # Detect init system, generate and configure pm2 boot on startup +$ pm2 save # Save current process list +$ pm2 resurrect # Restore previously saved processes +$ pm2 unstartup # Disable and remove startup system + +$ pm2 update # Save processes, kill PM2 and restore processes +$ pm2 init # Generate a sample js configuration file + +# Deployment +$ pm2 deploy app.json prod setup # Setup "prod" remote server +$ pm2 deploy app.json prod # Update "prod" remote server +$ pm2 deploy app.json prod revert 2 # Revert "prod" remote server by 2 + +# Module system +$ pm2 module:generate [name] # Generate sample module with name [name] +$ pm2 install pm2-logrotate # Install module (here a log rotation system) +$ pm2 uninstall pm2-logrotate # Uninstall module +$ pm2 publish # Increment version, git push and npm publish +``` + +
+ +Also check out the [example folder](https://github.com/Unitech/pm2/tree/master/examples) to discover all features. diff --git a/pres/app-overview.png b/pres/app-overview.png new file mode 100644 index 000000000..9286fdc17 Binary files /dev/null and b/pres/app-overview.png differ diff --git a/pres/bttn.png b/pres/bttn.png new file mode 100644 index 000000000..7afb1880a Binary files /dev/null and b/pres/bttn.png differ diff --git a/pres/flamegraph.png b/pres/flamegraph.png new file mode 100644 index 000000000..287767be2 Binary files /dev/null and b/pres/flamegraph.png differ diff --git a/pres/memory-profiling.png b/pres/memory-profiling.png new file mode 100644 index 000000000..2aa6afd48 Binary files /dev/null and b/pres/memory-profiling.png differ diff --git a/pres/pm2-ls-multi.png b/pres/pm2-ls-multi.png new file mode 100644 index 000000000..f9087cee7 Binary files /dev/null and b/pres/pm2-ls-multi.png differ diff --git a/pres/pm2-plus_black.png b/pres/pm2-plus_black.png new file mode 100644 index 000000000..c9c7efb65 Binary files /dev/null and b/pres/pm2-plus_black.png differ diff --git a/test/benchmarks/monit.sh b/test/benchmarks/monit.sh index 5ea4f80dc..b84e63b6c 100755 --- a/test/benchmarks/monit.sh +++ b/test/benchmarks/monit.sh @@ -6,7 +6,7 @@ export RESULT_FILE=$RESULT_FILE launch() { echo "========= `date`" >> $RESULT_FILE - nohup ./monit-daemon.sh &> monit.log & + nohup ./monit-daemon.sh &> monit.log & } ppkill() { diff --git a/test/e2e/cli/plus.sh b/test/e2e/cli/plus.sh new file mode 100644 index 000000000..770bdf7a9 --- /dev/null +++ b/test/e2e/cli/plus.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +SRC=$(cd $(dirname "$0"); pwd) +source "${SRC}/../include.sh" + +echo -e "\033[1mRunning tests:\033[0m" + +cd $file_path + +$pm2 start echo.js +$pm2 prettylist | grep "km_link: false" +spec "should km_link not be enabled" + +$pm2 plus alcz82ewyhy2va6 litfrsovr52celr --install-all + +should 'have started 3 apps' 'online' 3 +should 'all application be monitored' 'km_link: true' 3 + +$pm2 plus delete + +should 'have started 1 apps' 'online' 1 +$pm2 prettylist | grep "km_link: false" +spec "should km_link be disabled" diff --git a/test/e2e/logs/log-entire.sh b/test/e2e/logs/log-entire.sh index d09804bc8..23a2270a3 100644 --- a/test/e2e/logs/log-entire.sh +++ b/test/e2e/logs/log-entire.sh @@ -66,7 +66,7 @@ $pm2 start throw-later.js -i 1 -o out.log -e err.log -l entire.log test -head ">> START CLUSTERMODE (ENTIRE DO NOT EXISTS)" +head ">> START CLUSTERMODE (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -i 1 -o out.log -e err.log @@ -78,7 +78,7 @@ $pm2 start throw-later.js -i 1 -o out.log -e err.log -l entire.log --merge-logs test -head ">> START CLUSTERMODE WITH --merge-logs (ENTIRE DO NOT EXISTS)" +head ">> START CLUSTERMODE WITH --merge-logs (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -i 1 -o out.log -e err.log --merge-logs @@ -91,7 +91,7 @@ $pm2 start throw-later.js -o out.log -e err.log -l entire.log test -head ">> START FORKMODE (ENTIRE DO NOT EXISTS)" +head ">> START FORKMODE (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log @@ -103,7 +103,7 @@ $pm2 start throw-later.js -o out.log -e err.log -l entire.log --merge-logs test -head ">> START FORKMODE WITH --merge-logs (ENTIRE DO NOT EXISTS)" +head ">> START FORKMODE WITH --merge-logs (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs @@ -117,7 +117,7 @@ $pm2 reloadLogs test -head ">> RELOAD LOGS (ENTIRE DO NOT EXISTS)" +head ">> RELOAD LOGS (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs @@ -133,7 +133,7 @@ $pm2 restart all test -head ">> RESTART (ENTIRE DO NOT EXISTS)" +head ">> RESTART (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs @@ -149,7 +149,7 @@ $pm2 reload all test -head ">> RELOAD (ENTIRE DO NOT EXISTS)" +head ">> RELOAD (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs @@ -166,12 +166,12 @@ spec "\"entire log path\" should exists." test -head ">> DESCRIBE (ENTIRE DO NOT EXISTS)" +head ">> DESCRIBE (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs $pm2 desc "throw-later" | grep -w "entire log path" -ispec "\"entire log path\" should not exists." +ispec "\"entire log path\" should not exist." test "NE" @@ -183,7 +183,7 @@ $pm2 flush test -head ">> FLUSH (ENTIRE DO NOT EXISTS)" +head ">> FLUSH (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs @@ -200,12 +200,12 @@ spec "\"entire log path\" should exists." test -head ">> JLIST (ENTIRE DO NOT EXISTS)" +head ">> JLIST (ENTIRE DOES NOT EXIST)" $pm2 start throw-later.js -o out.log -e err.log --merge-logs $pm2 jlist | grep -w "pm_log_path" -ispec "\"entire log path\" should not exists." +ispec "\"entire log path\" should not exist." test "NE" @@ -215,7 +215,7 @@ $pm2 start throw-later.json test -head ">> START JSON (ENTIRE DO NOT EXISTS)" +head ">> START JSON (ENTIRE DOES NOT EXIST)" $pm2 start throw-later1.json diff --git a/test/e2e/modules/get-set.sh b/test/e2e/modules/get-set.sh index c1a649848..601ff27ae 100644 --- a/test/e2e/modules/get-set.sh +++ b/test/e2e/modules/get-set.sh @@ -19,6 +19,6 @@ spec "Should key exists" $pm2 unset key1 cat ~/.pm2/module_conf.json | grep "key1" -ispec "Should key not exists" +ispec "Should key does not exist" rm -rf ~/.pm2 diff --git a/test/e2e/process-file/json-file.sh b/test/e2e/process-file/json-file.sh index c6c984f5a..733c2b102 100644 --- a/test/e2e/process-file/json-file.sh +++ b/test/e2e/process-file/json-file.sh @@ -108,4 +108,9 @@ should 'should start processes' 'online' 4 $pm2 reload all.json --only child should 'should all script been restarted one time' 'restart_time: 2' 4 +######## multu only + +$pm2 start all.json --only "echo,child" +should 'should start processes' 'online' 5 + $pm2 kill diff --git a/test/fixtures/args.js b/test/fixtures/args.js index e6ce188ff..bb1ad890e 100644 --- a/test/fixtures/args.js +++ b/test/fixtures/args.js @@ -5,5 +5,5 @@ if (process.argv.indexOf('-d') == -1 || process.argv.indexOf('-a') == -1) { } else { setInterval(function() { console.log('ok'); - }, 500); + }, 500); } diff --git a/test/fixtures/git/index b/test/fixtures/git/index index 1f2626ff4..a79f428b8 100644 Binary files a/test/fixtures/git/index and b/test/fixtures/git/index differ diff --git a/test/fixtures/mjs/ecosystem.config.js b/test/fixtures/mjs/ecosystem.config.js index 03d8ed502..30f8edcc8 100644 --- a/test/fixtures/mjs/ecosystem.config.js +++ b/test/fixtures/mjs/ecosystem.config.js @@ -1,5 +1,5 @@ module.exports = { - + apps : [ diff --git a/test/helpers/plan.js b/test/helpers/plan.js index fabe21fce..8d1991611 100644 --- a/test/helpers/plan.js +++ b/test/helpers/plan.js @@ -6,7 +6,7 @@ var assert = require('assert'); * @method Plan * @param {} count * @param {} done - * @return + * @return */ function Plan(count, done) { this.done = done; @@ -17,7 +17,7 @@ function Plan(count, done) { * Description * @method ok * @param {} expression - * @return + * @return */ Plan.prototype.ok = function(expression) { assert(expression); diff --git a/test/interface/bus.fork.spec.mocha.js b/test/interface/bus.fork.spec.mocha.js index 5ad9f6625..72e35829b 100644 --- a/test/interface/bus.fork.spec.mocha.js +++ b/test/interface/bus.fork.spec.mocha.js @@ -170,22 +170,6 @@ describe('PM2 BUS / RPC', function() { should(err).be.null(); }); }); - - it('should (transaction:http)', function(done) { - - pm2_bus.on('*', function(event, data) { - if (event == 'http:transaction') { - data.should.have.properties(TRANSACTION_HTTP_EVENT); - data.process.should.have.properties(PROCESS_ARCH); - done(); - } - }); - - pm2.start('./http_transaction.js', {}, function(err, data) { - should(err).be.null(); - }); - }); - }); }); diff --git a/test/interface/bus.spec.mocha.js b/test/interface/bus.spec.mocha.js index 3fcf29e27..4db6b9c35 100644 --- a/test/interface/bus.spec.mocha.js +++ b/test/interface/bus.spec.mocha.js @@ -171,20 +171,6 @@ describe('PM2 BUS / RPC', function() { }); }); - it('should (transaction:http)', function(done) { - pm2_bus.on('*', function(event, data) { - if (event == 'http:transaction') { - data.should.have.properties(TRANSACTION_HTTP_EVENT); - data.process.should.have.properties(PROCESS_ARCH); - done(); - } - }); - - pm2.start('./http_transaction.js', {instances : 1}, function(err, data) { - should(err).be.null(); - }); - }); - }); }); diff --git a/test/parallel.js b/test/parallel.js index 838520e2b..a001a3b53 100644 --- a/test/parallel.js +++ b/test/parallel.js @@ -1,5 +1,5 @@ -const async = require('async') +const forEachLimit = require('async/forEachLimit') const fs = require('fs') const exec = require('child_process').exec const path = require('path') @@ -34,7 +34,7 @@ function listAllTest(cb) { var test_suite = [] fs.readdir(testFolder, (err, folders) => { - async.forEachLimit(folders, 4, (folder, next) => { + forEachLimit(folders, 4, (folder, next) => { var fold = path.join(testFolder, folder) fs.readdir(fold, (err, files) => { if (err) return next() @@ -50,7 +50,7 @@ function listAllTest(cb) { } function launchTestSuite(files, cb) { - async.forEachLimit(files, CONCURRENT_TEST, function(file, next) { + forEachLimit(files, CONCURRENT_TEST, function(file, next) { var cmd = `docker run -v ${path.resolve(__dirname, '..')}:/var/pm2 ${DOCKER_IMAGE_NAME} bash ${file}` console.log(chalk.bold(`Running test ${file}`)) diff --git a/test/programmatic/flush.mocha.js b/test/programmatic/flush.mocha.js new file mode 100644 index 000000000..a9302b76d --- /dev/null +++ b/test/programmatic/flush.mocha.js @@ -0,0 +1,81 @@ +process.env.NODE_ENV = 'test'; + +var PM2 = require('../..'); +var should = require('should'); +var fs = require('fs'); +var path = require('path'); + +describe('Programmatic flush feature test', function() { + var proc1 = null; + var procs = []; + + var pm2 = new PM2.custom({ + cwd : __dirname + '/../fixtures' + }); + + before(function(done) { + pm2.delete('all', function() { + done(); + }); + }); + + after(function(done) { + pm2.disconnect(done); + }); + + afterEach(function(done) { + pm2.delete('all', done); + }); + + describe('Flush test', function() { + it('flush all logs', function(done) { + pm2.start({ + script: './echo.js', + error_file : 'error-echo.log', + out_file : 'out-echo.log', + merge_logs: false + }, function(err, procs) { + should(err).be.null(); + + var out_file = procs[0].pm2_env.pm_out_log_path; + var err_file = procs[0].pm2_env.pm_err_log_path; + out_file.should.containEql('out-echo-0.log'); + err_file.should.containEql('error-echo-0.log'); + pm2.flush(undefined, function(){ + fs.readFileSync(out_file, "utf8").should.be.empty(); + fs.readFileSync(err_file, "utf8").should.be.empty(); + done(); + }); + }); + }); + it('flush only echo logs', function(done) { + pm2.start({ + script: './echo.js', + error_file : 'error-echo.log', + out_file : 'out-echo.log', + merge_logs: false + }, function(err, procs) { + should(err).be.null(); + var out_file = procs[0].pm2_env.pm_out_log_path; + var err_file = procs[0].pm2_env.pm_err_log_path; + pm2.start({ + script: './001-test.js', + error_file : 'error-001-test.log', + out_file : 'out-001-test.log', + merge_logs: false + }, function(err, procs, $out_file, $err_file) { + should(err).be.null(); + var out_file1 = procs[0].pm2_env.pm_out_log_path; + var err_file1 = procs[0].pm2_env.pm_err_log_path; + pm2.flush('echo', function(){ + fs.readFileSync(out_file, "utf8").toString().should.be.empty(); + fs.readFileSync(err_file, "utf8").toString().should.be.empty(); + fs.readFileSync(out_file1, "utf8").toString().should.not.be.empty(); + fs.readFileSync(err_file1, "utf8").toString().should.not.be.empty(); + done(); + }); + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/test/programmatic/god.mocha.js b/test/programmatic/god.mocha.js index 5c22cd533..b672a88c0 100644 --- a/test/programmatic/god.mocha.js +++ b/test/programmatic/god.mocha.js @@ -6,6 +6,7 @@ var fs = require('fs'); var path = require('path'); var should = require('should'); var Common = require('../../lib/Common'); +var eachLimit = require('async/eachLimit'); var cst = require('../../constants.js'); @@ -55,12 +56,10 @@ function getConf4() { }); } -var async = require('async'); - function deleteAll(data, cb) { var processes = God.getFormatedProcesses(); - async.eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { + eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) { console.log('Deleting process %s', proc.pm2_env.pm_id); God.deleteProcessId(proc.pm2_env.pm_id, function() { return next(); diff --git a/test/programmatic/misc_commands.js b/test/programmatic/misc_commands.js index b0b7aa153..ac80e5b85 100644 --- a/test/programmatic/misc_commands.js +++ b/test/programmatic/misc_commands.js @@ -34,7 +34,7 @@ describe('Misc commands', function() { should(err).be.null(); done(); }); - }); + }); it('should restart them', function(done) { pm2.restart('all', function(err, data) { diff --git a/test/unit.sh b/test/unit.sh index 7dd0f9307..1fb7143dc 100644 --- a/test/unit.sh +++ b/test/unit.sh @@ -33,61 +33,61 @@ $pm2 uninstall all # fi cd test/programmatic -mocha --opts ./mocha.opts ./god.mocha.js +mocha --exit --opts ./mocha.opts ./god.mocha.js spec "God test" -mocha --opts ./mocha.opts ./programmatic.js +mocha --exit --opts ./mocha.opts ./programmatic.js spec "Programmatic test" -mocha --opts ./mocha.opts ./containerizer.mocha.js +mocha --exit --opts ./mocha.opts ./containerizer.mocha.js spec "Dockerfile parser test" -mocha --opts ./mocha.opts ./api.mocha.js +mocha --exit --opts ./mocha.opts ./api.mocha.js spec "API tests" -mocha --opts ./mocha.opts ./path_resolution.mocha.js +mocha --exit --opts ./mocha.opts ./path_resolution.mocha.js spec "API tests" -mocha --opts ./mocha.opts ./lazy_api.mocha.js +mocha --exit --opts ./mocha.opts ./lazy_api.mocha.js spec "API tests" -mocha --opts ./mocha.opts ./reload-locker.mocha.js +mocha --exit --opts ./mocha.opts ./reload-locker.mocha.js spec "Reload locker tests" -mocha --opts ./mocha.opts ./api.backward.compatibility.mocha.js +mocha --exit --opts ./mocha.opts ./api.backward.compatibility.mocha.js spec "API Backward compatibility tests" -mocha --opts ./mocha.opts ./custom_action.mocha.js +mocha --exit --opts ./mocha.opts ./custom_action.mocha.js spec "Custom Actions tests" -mocha --opts ./mocha.opts ./logs.js +mocha --exit --opts ./mocha.opts ./logs.js spec "Logs test" -mocha --opts ./mocha.opts ./watcher.js +mocha --exit --opts ./mocha.opts ./watcher.js spec "Watcher" -mocha --opts ./mocha.opts ./max_memory_limit.js +mocha --exit --opts ./mocha.opts ./max_memory_limit.js spec "Max memory tests" -# mocha --opts ./mocha.opts ./module_configuration.mocha.js +# mocha --exit --opts ./mocha.opts ./module_configuration.mocha.js # spec "Max memory tests" -mocha --opts ./mocha.opts ./cluster.mocha.js +mocha --exit --opts ./mocha.opts ./cluster.mocha.js spec "Cluster tests" -mocha --opts ./mocha.opts ./graceful.mocha.js +mocha --exit --opts ./mocha.opts ./graceful.mocha.js spec "Graceful tests" -mocha --opts ./mocha.opts ./inside.mocha.js +mocha --exit --opts ./mocha.opts ./inside.mocha.js spec "Inside pm2 call tests" -mocha --opts ./mocha.opts ./misc_commands.js +mocha --exit --opts ./mocha.opts ./misc_commands.js spec "MISC tests" -mocha --opts ./mocha.opts ./signals.js +mocha --exit --opts ./mocha.opts ./signals.js spec "SIGINT signal interception + delay customization" -mocha --opts ./mocha.opts ./send_data_process.mocha.js +mocha --exit --opts ./mocha.opts ./send_data_process.mocha.js spec "Send data to a process" -mocha --opts ./mocha.opts ./modules.mocha.js +mocha --exit --opts ./mocha.opts ./modules.mocha.js spec "Module API testing" -# mocha --opts ./mocha.opts ./module_retrocompat.mocha.js +# mocha --exit --opts ./mocha.opts ./module_retrocompat.mocha.js # spec "Module retrocompatibility system" -mocha --opts ./mocha.opts ./json_validation.mocha.js +mocha --exit --opts ./mocha.opts ./json_validation.mocha.js spec "JSON validation test" -mocha --opts ./mocha.opts ./env_switching.js +mocha --exit --opts ./mocha.opts ./env_switching.js spec "JSON environment switching on JSON restart with --env" -mocha --opts ./mocha.opts ./configuration.mocha.js +mocha --exit --opts ./mocha.opts ./configuration.mocha.js spec "Configuration system working" -mocha --opts ./mocha.opts ./id.mocha.js +mocha --exit --opts ./mocha.opts ./id.mocha.js spec "Uniqueness id for each process" # @@ -97,9 +97,9 @@ cd ../interface # echo $PM2_HOME -mocha --opts ./mocha.opts ./bus.spec.mocha.js +mocha --exit --opts ./mocha.opts ./bus.spec.mocha.js spec "Protocol communication test" -mocha --opts ./mocha.opts ./bus.fork.spec.mocha.js +mocha --exit --opts ./mocha.opts ./bus.fork.spec.mocha.js spec "Protocol communication test" -mocha --opts ./mocha.opts ./utility.mocha.js +mocha --exit --opts ./mocha.opts ./utility.mocha.js spec "PM2 Utility" diff --git a/types/index.d.ts b/types/index.d.ts index 42ff4293a..49c058d2f 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -311,7 +311,7 @@ export interface StartOptions { * Eg “–harmony” or [”–harmony”,”–debug”]. Only applies if interpreter is something other * than “none” (its “node” by default). */ - interpreterArgs?: string | string[]; + interpreter_args?: string | string[]; /** * The working directory to start the process with. */ @@ -328,7 +328,7 @@ export interface StartOptions { /** * The display format for log timestamps (eg “YYYY-MM-DD HH:mm Z”). The format is a moment display format. */ - logDateFormat?: string; + log_date_format?: string; /** * Default: “~/.pm2/logs/~/.pm2/pids/app_name-id.pid”) * The path to a file to write the pid of the started process. The file will be overwritten. @@ -339,26 +339,26 @@ export interface StartOptions { /** * The minimum uptime of the script before it’s considered successfully started. */ - minUptime?: number; + min_uptime?: number; /** * The maximum number of times in a row a script will be restarted if it exits in less than min_uptime. */ - maxRestarts?: number; + max_restarts?: number; /** * If sets and script’s memory usage goes about the configured number, pm2 restarts the script. * Uses human-friendly suffixes: ‘K’ for kilobytes, ‘M’ for megabytes, ‘G’ for gigabytes’, etc. Eg “150M”. */ - maxMemoryRestart?: number; + max_memory_restart?: number; /** * (Default: 1600) * The number of milliseconds to wait after a stop or restart command issues a SIGINT signal to kill the * script forceably with a SIGKILL signal. */ - killTimeout?: number; + kill_timeout?: number; /** * (Default: 0) Number of millseconds to wait before restarting a script that has exited. */ - restartDelay?: number; + restart_delay?: number; /** * (Default: “node”) The interpreter for your script (eg “python”, “ruby”, “bash”, etc). * The value “none” will execute the ‘script’ as a binary executable. @@ -368,7 +368,7 @@ export interface StartOptions { * (Default: ‘fork’) If sets to ‘cluster’, will enable clustering * (running multiple instances of the script). */ - execMode?: string; + exec_mode?: string; /** * (Default: 1) How many instances of script to create. Only relevant in exec_mode ‘cluster’. */ @@ -379,7 +379,7 @@ export interface StartOptions { * ‘test.js’ started via pm2, normally you would have 4 stdout log files and 4 stderr log files, * but with this option set to true you would only have one stdout file and one stderr file. */ - mergeLogs?: boolean; + merge_logs?: boolean; /** * If set to true, the application will be restarted on change of the script file. */ @@ -391,10 +391,10 @@ export interface StartOptions { */ force?: boolean; cron?: any; - executeCommand?: any; + execute_command?: any; write?: any; - sourceMapSupport?: any; - disableSourceMapSupport?: any; + source_map_support?: any; + disable_source_map_support?: any; /** * The environment variables to pass on to the process. */ diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 0d6ed766a..000000000 --- a/yarn.lock +++ /dev/null @@ -1,1894 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@keymetrics/pmx@^2.0.0-alpha11": - version "2.0.0-alpha11" - resolved "https://registry.yarnpkg.com/@keymetrics/pmx/-/pmx-2.0.0-alpha11.tgz#6429672ee942dc30c200acaac1e305ec30a9cb32" - dependencies: - async "^2.6.0" - debug "^3.1.0" - deep-metrics "0.0.2" - deepmerge "^2.1.0" - json-stringify-safe "^5.0.1" - semver "^5.5.0" - signal-exit "^3.0.2" - tslib "^1.6.0" - vxx "^1.2.2" - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -amp-message@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/amp-message/-/amp-message-0.1.2.tgz#a78f1c98995087ad36192a41298e4db49e3dfc45" - dependencies: - amp "0.3.1" - -amp@0.3.1, amp@~0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/amp/-/amp-0.3.1.tgz#6adf8d58a74f361e82c1fa8d389c079e139fc47d" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - -are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - -async-listener@^0.6.0: - version "0.6.9" - resolved "https://registry.yarnpkg.com/async-listener/-/async-listener-0.6.9.tgz#51bc95e41095417f33922fb4dee4f232b3226488" - dependencies: - semver "^5.3.0" - shimmer "^1.1.0" - -async@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" - -async@^1.5: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -async@^2.5, async@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - dependencies: - lodash "^4.14.0" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -atob@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws4@^1.2.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - dependencies: - tweetnacl "^0.14.3" - -binary-extensions@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" - -blessed@^0.1.81: - version "0.1.81" - resolved "https://registry.yarnpkg.com/blessed/-/blessed-0.1.81.tgz#f962d687ec2c369570ae71af843256e6d0ca1129" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.0, braces@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - kind-of "^6.0.2" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -charm@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296" - -chokidar@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7" - dependencies: - anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" - glob-parent "^3.1.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^2.1.1" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.0" - optionalDependencies: - fsevents "^1.0.0" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cli-table-redemption@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cli-table-redemption/-/cli-table-redemption-1.0.1.tgz#0359d8c34df74980029d76dff071a05a127c4fdd" - dependencies: - chalk "^1.1.3" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -commander@2.14.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - -component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -continuation-local-storage@^3.1.4: - version "3.2.1" - resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz#11f613f74e914fe9b34c92ad2d28fe6ae1db7ffb" - dependencies: - async-listener "^0.6.0" - emitter-listener "^1.1.1" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -cron@^1.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/cron/-/cron-1.3.0.tgz#7e459968eaf94e1a445be796ce402166c234659d" - dependencies: - moment-timezone "^0.5.x" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -debug@2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - dependencies: - ms "2.0.0" - -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" - -debug@^3.0, debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - dependencies: - ms "2.0.0" - -debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - -deep-metrics@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/deep-metrics/-/deep-metrics-0.0.2.tgz#180900dea82a2c4b976be2b7684914748f5a0931" - dependencies: - semver "^5.3.0" - -deepmerge@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.0.tgz#511a54fff405fc346f0240bb270a3e9533a31102" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -emitter-listener@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.1.tgz#e8bbbe8244bc8e0d0b4ef71cd14294c7f241c7ec" - dependencies: - shimmer "^1.2.0" - -escape-regexp@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/escape-regexp/-/escape-regexp-0.0.1.tgz#f44bda12d45bbdf9cb7f862ee7e4827b3dd32254" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -eventemitter2@5.0.1, eventemitter2@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452" - -eventemitter2@~0.4.14: - version "0.4.14" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0, extend@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fclone@1.0.11, fclone@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - dependencies: - map-cache "^0.2.2" - -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fsevents@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" - dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.39" - -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -"gkt@https://tgz.pm2.io/gkt-1.0.0.tgz": - version "1.0.0" - resolved "https://tgz.pm2.io/gkt-1.0.0.tgz#405502b007f319c3f47175c4474527300f2ab5ad" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.5: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - -handy-http@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/handy-http/-/handy-http-1.0.2.tgz#24860dca376a69fbb7cd1a604a221e2a56639126" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -hawk@3.1.3, hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -iconv-lite@^0.4.4: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - -interpret@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - dependencies: - kind-of "^6.0.0" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - dependencies: - is-extglob "^2.1.1" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - -is-odd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" - dependencies: - is-number "^4.0.0" - -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - dependencies: - isobject "^3.0.1" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - -is@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is/-/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -keymetrics-agent@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/keymetrics-agent/-/keymetrics-agent-0.4.0.tgz#9c23bb33427faaea6ed4dfdbd8316de4f3a229c9" - dependencies: - async "^2.6.0" - eventemitter2 "^5.0.1" - fclone "^1.0.11" - handy-http "^1.0.2" - moment "^2.21.0" - nssocket "^0.6.0" - pm2-axon "3.0.2" - pm2-axon-rpc "^0.5.0" - ws "^5.1.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - -lazy@~1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/lazy/-/lazy-1.0.11.tgz#daa068206282542c088288e975c297c1ae77b690" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.findindex@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.findindex/-/lodash.findindex-4.6.0.tgz#a3245dee61fb9b6e0624b535125624bb69c11106" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.merge@^4.6.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" - -lodash@^4.14.0: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - dependencies: - object-visit "^1.0.0" - -methods@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - -micromatch@^3.1.4: - version "3.1.9" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.9.tgz#15dc93175ae39e52e93087847096effc73efcf89" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - -mime-types@^2.1.12, mime-types@~2.1.7: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - dependencies: - mime-db "~1.33.0" - -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@^3.5: - version "3.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" - escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - he "1.1.1" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -moment-timezone@^0.5.x: - version "0.5.14" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.14.tgz#4eb38ff9538b80108ba467a458f3ed4268ccfcb1" - dependencies: - moment ">= 2.9.0" - -"moment@>= 2.9.0", moment@^2.19, moment@^2.21.0: - version "2.21.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -mute-stream@~0.0.4: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - -nan@^2.3.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - -nanomatch@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-odd "^2.0.0" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -needle@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.0.tgz#f14efc69cee1024b72c8b21c7bdf94a731dc12fa" - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" - -node-pre-gyp@^0.6.39: - version "0.6.39" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" - dependencies: - detect-libc "^1.0.2" - hawk "3.1.3" - mkdirp "^0.5.1" - nopt "^4.0.1" - npmlog "^4.0.2" - rc "^1.1.7" - request "2.81.0" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nssocket@0.6.0, nssocket@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/nssocket/-/nssocket-0.6.0.tgz#59f96f6ff321566f33c70f7dbeeecdfdc07154fa" - dependencies: - eventemitter2 "~0.4.14" - lazy "~1.0.11" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - dependencies: - isobject "^3.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - dependencies: - isobject "^3.0.1" - -once@^1.3.0, once@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -pidusage@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/pidusage/-/pidusage-2.0.6.tgz#32bc37e57ca828f46b1c1e679a9cfc56ef945850" - -pm2-axon-rpc@^0.5.0, pm2-axon-rpc@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/pm2-axon-rpc/-/pm2-axon-rpc-0.5.1.tgz#ad3c43c43811c71f13e5eee2821194d03ceb03fe" - dependencies: - debug "^3.0" - -pm2-axon@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pm2-axon/-/pm2-axon-3.0.2.tgz#53de1d34edbf266d58f6b1dea2d8244c71ad24b9" - dependencies: - amp "~0.3.1" - amp-message "~0.1.1" - debug "~2.2.0" - escape-regexp "0.0.1" - -pm2-axon@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pm2-axon/-/pm2-axon-3.1.0.tgz#1b4527f3385e203adc1a5b0488bb52f0322731da" - dependencies: - amp "~0.3.1" - amp-message "~0.1.1" - debug "^3.0" - escape-regexp "0.0.1" - -pm2-deploy@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/pm2-deploy/-/pm2-deploy-0.3.9.tgz#adeee775c56d52b8f251ba9b0abe0db50a01dfc7" - dependencies: - async "^1.5" - tv4 "^1.3" - -pm2-multimeter@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz#1a1e55153d41a05534cea23cfe860abaa0eb4ace" - dependencies: - charm "~0.1.1" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - -promptly@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/promptly/-/promptly-2.2.0.tgz#2a13fa063688a2a5983b161fff0108a07d26fc74" - dependencies: - read "^1.0.4" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - -rc@^1.1.7: - version "1.2.6" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -read@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - dependencies: - mute-stream "~0.0.4" - -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4: - version "2.3.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" - readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -request@2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - -resolve@^1.1.6: - version "1.6.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" - dependencies: - path-parse "^1.0.5" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - -rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - dependencies: - glob "^7.0.5" - -safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - dependencies: - ret "~0.1.10" - -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - -semver@^5.0.1, semver@^5.3, semver@^5.3.0, semver@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -shelljs@0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.1.tgz#729e038c413a2254c4078b95ed46e0397154a9f1" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -shimmer@^1.0.0, shimmer@^1.1.0, shimmer@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.0.tgz#f966f7555789763e74d8841193685a5e78736665" - -should-equal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" - dependencies: - should-type "^1.4.0" - -should-format@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" - dependencies: - should-type "^1.3.0" - should-type-adaptors "^1.0.1" - -should-type-adaptors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" - dependencies: - should-type "^1.3.0" - should-util "^1.0.0" - -should-type@^1.3.0, should-type@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" - -should-util@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.0.tgz#c98cda374aa6b190df8ba87c9889c2b4db620063" - -should@^13: - version "13.2.1" - resolved "https://registry.yarnpkg.com/should/-/should-13.2.1.tgz#84e6ebfbb145c79e0ae42307b25b3f62dcaf574e" - dependencies: - should-equal "^2.0.0" - should-format "^3.0.3" - should-type "^1.4.0" - should-type-adaptors "^1.0.1" - should-util "^1.0.0" - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -source-map-resolve@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" - dependencies: - atob "^2.0.0" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.5: - version "0.5.4" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8" - dependencies: - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -sshpk@^1.7.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - dependencies: - has-flag "^1.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" - dependencies: - has-flag "^3.0.0" - -tar-pack@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -tough-cookie@~2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - dependencies: - punycode "^1.4.1" - -tslib@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tv4@^1.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/tv4/-/tv4-1.3.0.tgz#d020c846fadd50c855abb25ebaecc68fc10f7963" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - -universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - -use@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" - dependencies: - kind-of "^6.0.2" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -uuid@^3.0.0, uuid@^3.0.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - -v8-compile-cache@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz#8d32e4f16974654657e676e0e467a348e89b0dc4" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vizion@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/vizion/-/vizion-0.2.0.tgz#9cfb9e710e06e7b3d0e67474d38ab6b9f6a0c55b" - dependencies: - async "0.9.0" - -vxx@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/vxx/-/vxx-1.2.2.tgz#741fb51c6f11d3383da6f9b92018a5d7ba807611" - dependencies: - continuation-local-storage "^3.1.4" - debug "^2.6.3" - extend "^3.0.0" - is "^3.2.0" - lodash.findindex "^4.4.0" - lodash.isequal "^4.0.0" - lodash.merge "^4.6.0" - methods "^1.1.1" - semver "^5.0.1" - shimmer "^1.0.0" - uuid "^3.0.1" - -wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - dependencies: - string-width "^1.0.2" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -ws@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.1.1.tgz#1d43704689711ac1942fd2f283e38f825c4b8b95" - dependencies: - async-limiter "~1.0.0" - -yamljs@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.3.0.tgz#dc060bf267447b39f7304e9b2bfbe8b5a7ddb03b" - dependencies: - argparse "^1.0.7" - glob "^7.0.5"