├── .eslintrc.js ├── .gitignore ├── .npmrc ├── README.md ├── development.js ├── package-lock.json ├── package.json ├── pm2.json ├── production.js ├── runtime ├── .gitkeep └── logs │ └── .gitkeep ├── src ├── common │ ├── app.js │ ├── controller.js │ ├── entry.js │ ├── logger │ │ └── logger.js │ ├── monit │ │ ├── index.js │ │ ├── nedb.js │ │ └── tools.js │ ├── service.js │ ├── taskCheck │ │ └── index.js │ └── tools.js ├── config │ ├── config.js │ ├── config.pro.js │ └── config.test.js ├── controller │ └── http.js ├── index.js ├── model │ ├── test │ │ └── article.js │ └── user.js ├── service │ ├── http.js │ ├── render.js │ └── router.js └── tools │ ├── excel.js │ └── mail.js └── testing.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "parserOptions": { 7 | "ecmaVersion": 2017 8 | }, 9 | "globals": { 10 | "tools": false, 11 | "logger": false 12 | }, 13 | "rules": { 14 | 'no-control-regex': 'error' 15 | } 16 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | 4 | # Runtime data 5 | pids 6 | *.pid 7 | *.seed 8 | *.gz 9 | task.db 10 | 11 | # Dependency directory 12 | /node_modules/ 13 | 14 | # IDE config 15 | .idea 16 | .vscode 17 | 18 | 19 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | PUPPETEER_DOWNLOAD_HOST = https://npm.taobao.org/mirrors -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 这是什么? 2 | 这是一个高性能的基于`puppeteer`的`SSR`方案, 他使用Headless Chrome从网页中生成html,然后以http的方法返回html内容 3 | 4 | ## 解决了什么问题 5 | 很多公司和开发者使用JavaScript框架(包括AngularJS,BackboneJS,ReactJS, VueJS)开发应用程序和网站。但很多搜索引擎,社交媒体,爬虫不支持抓取JavaScript的网页,也就无法做网站SEO。 6 | 7 | 通过UserAgent判断,如果是来自于爬虫, 则通过nginx(tomcat, Apache)等反向代理到本服务,则可以把渲染好的html网页内容传递给搜索引擎, 从而间接实现SEO,, 从而间接实现 SEO, 这样,既可以保持纯粹的前端开始思路, 还能节省 SSR 造成的服务器负担 8 | 9 | 也可以使用在爬虫采集, 生成网页截图,生成网页PDF场景 10 | 11 | ## 使用 12 | ```js 13 | git clone 14 | cd sparender 15 | npm i 16 | npm start 17 | ``` 18 | ## 免费接入 19 | 免费接入SSR渲染 20 | 21 | 请求地址: http://api.zuoyanit.com/render 22 | 23 | 请求方式: GET 24 | 25 | 请求示例: http://api.zuoyanit.com/render/http://www.zuoyanit.com 26 | 27 | 反向代理配置请参阅: 文档 28 | 29 | * 为了防止滥用,使用前请联系作者,设置域名白名单 30 | 31 | * 免费提供200个页面(以redis中存的记录条数为准) 32 | 33 | ## 查看效果 34 | ```js 35 | http://127.0.0.1:3001/render?url=http://www.example.com 36 | ``` 37 | 38 | ### 功能 39 | * puppeteer连接池 40 | * render并发限制 41 | * log4j 日志 42 | * 已集成任务调度 43 | * 生产,开发环境配置 44 | * redis缓存 45 | * 自动来路, 如果来自移动端则自动设置请求UA和viewpoint(使用iphoneX的环境参数) 46 | 47 | 48 | #### 性能对比 49 | 50 | 服务器: 12核16G 51 | 并发:10 52 | 运行时间:60S 53 | 54 | 项目配置: 不使用缓存, 屏蔽图片,字体,多媒体等 55 | 56 | 请求地址: http://xxxx/render?url=https://www.baidu.com 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
单次渲染并发QPS
prerender2054ms5.05(已经有errors)
sparender476ms17.47
75 | 76 | ### 渲染方式对比 77 | 78 | 一下内容摘自 https://markdowner.net/article/73058307795021824, 并根据自己经验做了部分改动 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
方式优点缺点
CSR 客户端渲染SPA 的优点(用户体验较好) * SEO不友好(爬虫如果没有执行js的能力,如百度,获取到的页面是空的,不利于网站推广)
89 | 首屏加载慢(到达浏览器端后再加载数据,增加用户等待时间
SSR 服务端渲染SEO 友好, 首屏渲染快(可在服务端缓存页面,请求到来直接给 html) 代码改动大、需要做特定SSR框架的改动(经过我们实践、原有SPA代码改动非常大)

丢失了部分SPA体验

node 容易成为性能瓶颈
服务端动态渲染(利用user-agent)兼顾 SPA优点同时解决SEO问题需要服务端应用(但动态渲染只针对爬虫、不会成为性能瓶颈)
102 | 103 | #### 服务端动态渲染(利用user-agent) 104 | 105 | 为了提高用户体验我们用了SPA技术、为了SEO 我们用了 SSR、预渲染等技术。不同技术方案有一定差距,不能兼顾优点。但仔细想,需要这些技术优点的`用户`,其实时不一样的,SPA 针对的是浏览器普通用户、SSR 针对的是网页爬虫,如 googlebot、baiduspider 等,那为什么我们不能给不同`用户`不同的页面呢,服务端动态渲染就是这种方案。 106 | 107 | 基本原理: 服务端对请求的 user-agent 进行判断,浏览器端直接给 SPA 页面,如果是爬虫,给经过动态渲染的 html 页面(因为蜘蛛不会造成DDOS,所以这种方案相对于SSR能节省不少服务器资源) 108 | 109 | PS: 你可能会问,给了爬虫不同的页面,会不会被认为是网页作弊行为呢? 110 | Google 给了回复: 111 | 112 | Dynamic rendering is not cloaking 113 | Googlebot generally doesn't consider dynamic rendering as cloaking. As long as your dynamic rendering produces similar content, Googlebot won't view dynamic rendering as cloaking. 114 | When you're setting up dynamic rendering, your site may produce error pages. Googlebot doesn't consider these error pages as cloaking and treats the error as any other error page. 115 | Using dynamic rendering to serve completely different content to users and crawlers can be considered cloaking. For example, a website that serves a page about cats to users and a page about dogs to crawlers can be considered cloaking. 116 | 117 | 也就是说,如果我们没有刻意去作弊,而是使用动态渲染方案去解决SEO问题,爬虫经过对比网站内容,没有明显差异,不会认为这是作弊行为。 118 | 119 | 至于百度,请参考 120 | 豆丁网是在做黑帽 SEO 吗? 121 | 122 | 通过user-agent判断,将Baiduspider定向到http页面 123 | 124 | 基本的解释是: 125 | > 126 | >的确从单一feature来讲,会比较难区分cloaking型的spam和豆丁类的搜索优化,但是搜索引擎判断spam绝对不会只用一个维度的feature。docin这样的网站,依靠它的外链关系、alexa流量、用户在搜索结果里面的点击行为等等众多信号,都足以将其从spam里面拯救出来了。 127 | > 128 | > 何况,一般的spam肯定还有关键词堆砌、文本语义前后不搭、link farm等等众多特征。总之antispam一门综合性的算法,会参考很多要素,最后给出判断。 129 | > 130 | > 实在不行了,还可以有白名单作为最后的弥补手段,拯救这批大网站是没什么问题的啦。 131 | 132 | 所以不做过多的黑帽或者灰帽, 百度也不会做作弊处理 133 | 134 | 135 | -------------------------------------------------------------------------------- /development.js: -------------------------------------------------------------------------------- 1 | const app = require('./src/common/app'); 2 | app.start('development'); -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "task", 3 | "version": "2.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/color-name": { 8 | "version": "1.1.1", 9 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 10 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" 11 | }, 12 | "@types/debug": { 13 | "version": "4.1.5", 14 | "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", 15 | "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" 16 | }, 17 | "@types/node": { 18 | "version": "12.12.3", 19 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.3.tgz", 20 | "integrity": "sha512-opgSsy+cEF9N8MgaVPnWVtdJ3o4mV2aMHvDq7thkQUFt0EuOHJon4rQpJfhjmNHB+ikl0Cd6WhWIErOyQ+f7tw==" 21 | }, 22 | "@types/puppeteer": { 23 | "version": "5.4.2", 24 | "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.2.tgz", 25 | "integrity": "sha512-yjbHoKjZFOGqA6bIEI2dfBE5UPqU0YGWzP+ipDVP1iGzmlhksVKTBVZfT3Aj3wnvmcJ2PQ9zcncwOwyavmafBw==", 26 | "requires": { 27 | "@types/node": "*" 28 | } 29 | }, 30 | "@types/yauzl": { 31 | "version": "2.9.1", 32 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", 33 | "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", 34 | "optional": true, 35 | "requires": { 36 | "@types/node": "*" 37 | } 38 | }, 39 | "abbrev": { 40 | "version": "1.1.1", 41 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 42 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 43 | }, 44 | "adler-32": { 45 | "version": "1.2.0", 46 | "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", 47 | "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", 48 | "requires": { 49 | "exit-on-epipe": "~1.0.1", 50 | "printj": "~1.1.0" 51 | } 52 | }, 53 | "agent-base": { 54 | "version": "5.1.1", 55 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", 56 | "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" 57 | }, 58 | "ansi-escapes": { 59 | "version": "4.3.1", 60 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", 61 | "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", 62 | "requires": { 63 | "type-fest": "^0.11.0" 64 | } 65 | }, 66 | "ansi-regex": { 67 | "version": "2.1.1", 68 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 69 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 70 | }, 71 | "ansi-styles": { 72 | "version": "2.2.1", 73 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 74 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 75 | }, 76 | "ansi-term": { 77 | "version": "0.0.2", 78 | "resolved": "https://registry.npmjs.org/ansi-term/-/ansi-term-0.0.2.tgz", 79 | "integrity": "sha1-/XU++kvq2g6smZgbxSo/b/AZ3rc=", 80 | "requires": { 81 | "x256": ">=0.0.1" 82 | } 83 | }, 84 | "ansicolors": { 85 | "version": "0.3.2", 86 | "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", 87 | "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" 88 | }, 89 | "anymatch": { 90 | "version": "2.0.0", 91 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", 92 | "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", 93 | "requires": { 94 | "micromatch": "^3.1.4", 95 | "normalize-path": "^2.1.1" 96 | }, 97 | "dependencies": { 98 | "normalize-path": { 99 | "version": "2.1.1", 100 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", 101 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", 102 | "requires": { 103 | "remove-trailing-separator": "^1.0.1" 104 | } 105 | } 106 | } 107 | }, 108 | "arr-diff": { 109 | "version": "4.0.0", 110 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", 111 | "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" 112 | }, 113 | "arr-flatten": { 114 | "version": "1.1.0", 115 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", 116 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" 117 | }, 118 | "arr-union": { 119 | "version": "3.1.0", 120 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", 121 | "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" 122 | }, 123 | "array-unique": { 124 | "version": "0.3.2", 125 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", 126 | "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" 127 | }, 128 | "assign-symbols": { 129 | "version": "1.0.0", 130 | "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", 131 | "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" 132 | }, 133 | "async": { 134 | "version": "0.2.10", 135 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", 136 | "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" 137 | }, 138 | "async-each": { 139 | "version": "1.0.3", 140 | "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", 141 | "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" 142 | }, 143 | "asynckit": { 144 | "version": "0.4.0", 145 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 146 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 147 | }, 148 | "at-least-node": { 149 | "version": "1.0.0", 150 | "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", 151 | "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" 152 | }, 153 | "atob": { 154 | "version": "2.1.2", 155 | "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", 156 | "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" 157 | }, 158 | "balanced-match": { 159 | "version": "1.0.0", 160 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 161 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 162 | }, 163 | "base": { 164 | "version": "0.11.2", 165 | "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", 166 | "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", 167 | "requires": { 168 | "cache-base": "^1.0.1", 169 | "class-utils": "^0.3.5", 170 | "component-emitter": "^1.2.1", 171 | "define-property": "^1.0.0", 172 | "isobject": "^3.0.1", 173 | "mixin-deep": "^1.2.0", 174 | "pascalcase": "^0.1.1" 175 | }, 176 | "dependencies": { 177 | "define-property": { 178 | "version": "1.0.0", 179 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 180 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 181 | "requires": { 182 | "is-descriptor": "^1.0.0" 183 | } 184 | }, 185 | "is-accessor-descriptor": { 186 | "version": "1.0.0", 187 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 188 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 189 | "requires": { 190 | "kind-of": "^6.0.0" 191 | } 192 | }, 193 | "is-data-descriptor": { 194 | "version": "1.0.0", 195 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 196 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 197 | "requires": { 198 | "kind-of": "^6.0.0" 199 | } 200 | }, 201 | "is-descriptor": { 202 | "version": "1.0.2", 203 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 204 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 205 | "requires": { 206 | "is-accessor-descriptor": "^1.0.0", 207 | "is-data-descriptor": "^1.0.0", 208 | "kind-of": "^6.0.2" 209 | } 210 | } 211 | } 212 | }, 213 | "base64-js": { 214 | "version": "1.5.1", 215 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 216 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 217 | }, 218 | "bignumber.js": { 219 | "version": "9.0.0", 220 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", 221 | "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" 222 | }, 223 | "binary-extensions": { 224 | "version": "1.13.1", 225 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", 226 | "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" 227 | }, 228 | "binary-search-tree": { 229 | "version": "0.2.5", 230 | "resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz", 231 | "integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=", 232 | "requires": { 233 | "underscore": "~1.4.4" 234 | } 235 | }, 236 | "bl": { 237 | "version": "4.0.3", 238 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", 239 | "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", 240 | "requires": { 241 | "buffer": "^5.5.0", 242 | "inherits": "^2.0.4", 243 | "readable-stream": "^3.4.0" 244 | }, 245 | "dependencies": { 246 | "inherits": { 247 | "version": "2.0.4", 248 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 249 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 250 | }, 251 | "readable-stream": { 252 | "version": "3.6.0", 253 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 254 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 255 | "requires": { 256 | "inherits": "^2.0.3", 257 | "string_decoder": "^1.1.1", 258 | "util-deprecate": "^1.0.1" 259 | } 260 | } 261 | } 262 | }, 263 | "blessed": { 264 | "version": "0.1.81", 265 | "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", 266 | "integrity": "sha1-+WLWh+wsNpVwrnGvhDJW5tDKESk=" 267 | }, 268 | "blessed-contrib": { 269 | "version": "4.8.20", 270 | "resolved": "https://registry.npmjs.org/blessed-contrib/-/blessed-contrib-4.8.20.tgz", 271 | "integrity": "sha512-jLLXR9pjjm/T2jY0Q8OCCpuDquWiMULkPyT8YNaiLUR0j1MchTQK/Q7SiuD63jn9ekn9BrohwP1Kom/FylmeHQ==", 272 | "requires": { 273 | "ansi-term": ">=0.0.2", 274 | "chalk": "^1.1.0", 275 | "drawille-canvas-blessed-contrib": ">=0.1.3", 276 | "lodash": "~>=4.17.11", 277 | "map-canvas": ">=0.1.5", 278 | "marked": "^0.7.0", 279 | "marked-terminal": "^4.0.0", 280 | "memory-streams": "^0.1.0", 281 | "memorystream": "^0.3.1", 282 | "picture-tuber": "^1.0.1", 283 | "sparkline": "^0.1.1", 284 | "strip-ansi": "^3.0.0", 285 | "term-canvas": "0.0.5", 286 | "x256": ">=0.0.1" 287 | } 288 | }, 289 | "boolbase": { 290 | "version": "1.0.0", 291 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 292 | "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" 293 | }, 294 | "brace-expansion": { 295 | "version": "1.1.11", 296 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 297 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 298 | "requires": { 299 | "balanced-match": "^1.0.0", 300 | "concat-map": "0.0.1" 301 | } 302 | }, 303 | "braces": { 304 | "version": "2.3.2", 305 | "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", 306 | "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", 307 | "requires": { 308 | "arr-flatten": "^1.1.0", 309 | "array-unique": "^0.3.2", 310 | "extend-shallow": "^2.0.1", 311 | "fill-range": "^4.0.0", 312 | "isobject": "^3.0.1", 313 | "repeat-element": "^1.1.2", 314 | "snapdragon": "^0.8.1", 315 | "snapdragon-node": "^2.0.1", 316 | "split-string": "^3.0.2", 317 | "to-regex": "^3.0.1" 318 | }, 319 | "dependencies": { 320 | "extend-shallow": { 321 | "version": "2.0.1", 322 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 323 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 324 | "requires": { 325 | "is-extendable": "^0.1.0" 326 | } 327 | } 328 | } 329 | }, 330 | "bresenham": { 331 | "version": "0.0.3", 332 | "resolved": "https://registry.npmjs.org/bresenham/-/bresenham-0.0.3.tgz", 333 | "integrity": "sha1-q9q55bGU4nx1fNMU2ERDFPKZh3o=" 334 | }, 335 | "buffer": { 336 | "version": "5.7.1", 337 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 338 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 339 | "requires": { 340 | "base64-js": "^1.3.1", 341 | "ieee754": "^1.1.13" 342 | } 343 | }, 344 | "buffer-crc32": { 345 | "version": "0.2.13", 346 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 347 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" 348 | }, 349 | "buffers": { 350 | "version": "0.1.1", 351 | "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", 352 | "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" 353 | }, 354 | "cache-base": { 355 | "version": "1.0.1", 356 | "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", 357 | "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", 358 | "requires": { 359 | "collection-visit": "^1.0.0", 360 | "component-emitter": "^1.2.1", 361 | "get-value": "^2.0.6", 362 | "has-value": "^1.0.0", 363 | "isobject": "^3.0.1", 364 | "set-value": "^2.0.0", 365 | "to-object-path": "^0.3.0", 366 | "union-value": "^1.0.0", 367 | "unset-value": "^1.0.0" 368 | } 369 | }, 370 | "cardinal": { 371 | "version": "2.1.1", 372 | "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", 373 | "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", 374 | "requires": { 375 | "ansicolors": "~0.3.2", 376 | "redeyed": "~2.1.0" 377 | } 378 | }, 379 | "cfb": { 380 | "version": "1.2.0", 381 | "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.0.tgz", 382 | "integrity": "sha512-sXMvHsKCICVR3Naq+J556K+ExBo9n50iKl6LGarlnvuA2035uMlGA/qVrc0wQtow5P1vJEw9UyrKLCbtIKz+TQ==", 383 | "requires": { 384 | "adler-32": "~1.2.0", 385 | "crc-32": "~1.2.0", 386 | "printj": "~1.1.2" 387 | } 388 | }, 389 | "chalk": { 390 | "version": "1.1.3", 391 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 392 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 393 | "requires": { 394 | "ansi-styles": "^2.2.1", 395 | "escape-string-regexp": "^1.0.2", 396 | "has-ansi": "^2.0.0", 397 | "strip-ansi": "^3.0.0", 398 | "supports-color": "^2.0.0" 399 | } 400 | }, 401 | "charm": { 402 | "version": "0.1.2", 403 | "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", 404 | "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" 405 | }, 406 | "cheerio": { 407 | "version": "1.0.0-rc.3", 408 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", 409 | "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", 410 | "requires": { 411 | "css-select": "~1.2.0", 412 | "dom-serializer": "~0.1.1", 413 | "entities": "~1.1.1", 414 | "htmlparser2": "^3.9.1", 415 | "lodash": "^4.15.0", 416 | "parse5": "^3.0.1" 417 | } 418 | }, 419 | "chokidar": { 420 | "version": "2.1.2", 421 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", 422 | "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", 423 | "requires": { 424 | "anymatch": "^2.0.0", 425 | "async-each": "^1.0.1", 426 | "braces": "^2.3.2", 427 | "fsevents": "^1.2.7", 428 | "glob-parent": "^3.1.0", 429 | "inherits": "^2.0.3", 430 | "is-binary-path": "^1.0.0", 431 | "is-glob": "^4.0.0", 432 | "normalize-path": "^3.0.0", 433 | "path-is-absolute": "^1.0.0", 434 | "readdirp": "^2.2.1", 435 | "upath": "^1.1.0" 436 | } 437 | }, 438 | "chownr": { 439 | "version": "1.1.4", 440 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 441 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" 442 | }, 443 | "class-utils": { 444 | "version": "0.3.6", 445 | "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", 446 | "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", 447 | "requires": { 448 | "arr-union": "^3.1.0", 449 | "define-property": "^0.2.5", 450 | "isobject": "^3.0.0", 451 | "static-extend": "^0.1.1" 452 | }, 453 | "dependencies": { 454 | "define-property": { 455 | "version": "0.2.5", 456 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 457 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 458 | "requires": { 459 | "is-descriptor": "^0.1.0" 460 | } 461 | } 462 | } 463 | }, 464 | "cli-table": { 465 | "version": "0.3.1", 466 | "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", 467 | "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", 468 | "requires": { 469 | "colors": "1.0.3" 470 | } 471 | }, 472 | "clone-deep": { 473 | "version": "0.2.4", 474 | "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", 475 | "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", 476 | "requires": { 477 | "for-own": "^0.1.3", 478 | "is-plain-object": "^2.0.1", 479 | "kind-of": "^3.0.2", 480 | "lazy-cache": "^1.0.3", 481 | "shallow-clone": "^0.1.2" 482 | }, 483 | "dependencies": { 484 | "kind-of": { 485 | "version": "3.2.2", 486 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 487 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 488 | "requires": { 489 | "is-buffer": "^1.1.5" 490 | } 491 | } 492 | } 493 | }, 494 | "cluster-key-slot": { 495 | "version": "1.1.0", 496 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", 497 | "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" 498 | }, 499 | "codepage": { 500 | "version": "1.14.0", 501 | "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz", 502 | "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", 503 | "requires": { 504 | "commander": "~2.14.1", 505 | "exit-on-epipe": "~1.0.1" 506 | }, 507 | "dependencies": { 508 | "commander": { 509 | "version": "2.14.1", 510 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", 511 | "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==" 512 | } 513 | } 514 | }, 515 | "collection-visit": { 516 | "version": "1.0.0", 517 | "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", 518 | "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", 519 | "requires": { 520 | "map-visit": "^1.0.0", 521 | "object-visit": "^1.0.0" 522 | } 523 | }, 524 | "color-convert": { 525 | "version": "2.0.1", 526 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 527 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 528 | "requires": { 529 | "color-name": "~1.1.4" 530 | } 531 | }, 532 | "color-name": { 533 | "version": "1.1.4", 534 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 535 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 536 | }, 537 | "colors": { 538 | "version": "1.0.3", 539 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", 540 | "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" 541 | }, 542 | "combined-stream": { 543 | "version": "1.0.8", 544 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 545 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 546 | "requires": { 547 | "delayed-stream": "~1.0.0" 548 | } 549 | }, 550 | "commander": { 551 | "version": "2.17.1", 552 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", 553 | "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" 554 | }, 555 | "component-emitter": { 556 | "version": "1.3.0", 557 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 558 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 559 | }, 560 | "concat-map": { 561 | "version": "0.0.1", 562 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 563 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 564 | }, 565 | "cookiejar": { 566 | "version": "2.1.2", 567 | "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", 568 | "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" 569 | }, 570 | "copy-descriptor": { 571 | "version": "0.1.1", 572 | "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", 573 | "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" 574 | }, 575 | "core-util-is": { 576 | "version": "1.0.2", 577 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 578 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 579 | }, 580 | "crc-32": { 581 | "version": "1.2.0", 582 | "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", 583 | "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", 584 | "requires": { 585 | "exit-on-epipe": "~1.0.1", 586 | "printj": "~1.1.0" 587 | } 588 | }, 589 | "cron-parser": { 590 | "version": "2.11.0", 591 | "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.11.0.tgz", 592 | "integrity": "sha512-L5LAGlvq2xmCLErhjQRX8IL5v72y8jhGOaxrarYOhse0kJjJGb/vY/0sV/c7F/SylJGkUIY2iZPPJXZD3glZqA==", 593 | "requires": { 594 | "is-nan": "^1.2.1", 595 | "moment-timezone": "^0.5.23" 596 | } 597 | }, 598 | "css-select": { 599 | "version": "1.2.0", 600 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", 601 | "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", 602 | "requires": { 603 | "boolbase": "~1.0.0", 604 | "css-what": "2.1", 605 | "domutils": "1.5.1", 606 | "nth-check": "~1.0.1" 607 | } 608 | }, 609 | "css-what": { 610 | "version": "2.1.3", 611 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", 612 | "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" 613 | }, 614 | "date-format": { 615 | "version": "3.0.0", 616 | "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", 617 | "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==" 618 | }, 619 | "dayjs": { 620 | "version": "1.9.7", 621 | "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.7.tgz", 622 | "integrity": "sha512-IC877KBdMhBrCfBfJXHQlo0G8keZ0Opy7YIIq5QKtUbCuHMzim8S4PyiVK4YmihI3iOF9lhfUBW4AQWHTR5WHA==" 623 | }, 624 | "debug": { 625 | "version": "4.1.1", 626 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 627 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 628 | "requires": { 629 | "ms": "^2.1.1" 630 | } 631 | }, 632 | "decode-uri-component": { 633 | "version": "0.2.0", 634 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 635 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" 636 | }, 637 | "deepmerge": { 638 | "version": "4.2.2", 639 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 640 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" 641 | }, 642 | "define-properties": { 643 | "version": "1.1.3", 644 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 645 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 646 | "requires": { 647 | "object-keys": "^1.0.12" 648 | } 649 | }, 650 | "define-property": { 651 | "version": "2.0.2", 652 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", 653 | "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", 654 | "requires": { 655 | "is-descriptor": "^1.0.2", 656 | "isobject": "^3.0.1" 657 | }, 658 | "dependencies": { 659 | "is-accessor-descriptor": { 660 | "version": "1.0.0", 661 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 662 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 663 | "requires": { 664 | "kind-of": "^6.0.0" 665 | } 666 | }, 667 | "is-data-descriptor": { 668 | "version": "1.0.0", 669 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 670 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 671 | "requires": { 672 | "kind-of": "^6.0.0" 673 | } 674 | }, 675 | "is-descriptor": { 676 | "version": "1.0.2", 677 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 678 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 679 | "requires": { 680 | "is-accessor-descriptor": "^1.0.0", 681 | "is-data-descriptor": "^1.0.0", 682 | "kind-of": "^6.0.2" 683 | } 684 | } 685 | } 686 | }, 687 | "delayed-stream": { 688 | "version": "1.0.0", 689 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 690 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 691 | }, 692 | "denque": { 693 | "version": "1.4.1", 694 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", 695 | "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" 696 | }, 697 | "devtools-protocol": { 698 | "version": "0.0.818844", 699 | "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", 700 | "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==" 701 | }, 702 | "dom-serializer": { 703 | "version": "0.1.1", 704 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", 705 | "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", 706 | "requires": { 707 | "domelementtype": "^1.3.0", 708 | "entities": "^1.1.1" 709 | } 710 | }, 711 | "domelementtype": { 712 | "version": "1.3.1", 713 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", 714 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" 715 | }, 716 | "domhandler": { 717 | "version": "2.4.2", 718 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", 719 | "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", 720 | "requires": { 721 | "domelementtype": "1" 722 | } 723 | }, 724 | "domutils": { 725 | "version": "1.5.1", 726 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", 727 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", 728 | "requires": { 729 | "dom-serializer": "0", 730 | "domelementtype": "1" 731 | } 732 | }, 733 | "drawille-blessed-contrib": { 734 | "version": "1.0.0", 735 | "resolved": "https://registry.npmjs.org/drawille-blessed-contrib/-/drawille-blessed-contrib-1.0.0.tgz", 736 | "integrity": "sha1-FcJ5NPV6AFatE1luFWFje8lB8Lc=" 737 | }, 738 | "drawille-canvas-blessed-contrib": { 739 | "version": "0.1.3", 740 | "resolved": "https://registry.npmjs.org/drawille-canvas-blessed-contrib/-/drawille-canvas-blessed-contrib-0.1.3.tgz", 741 | "integrity": "sha1-IS8HinIr/S7MJn6oarbd3BCB/Ug=", 742 | "requires": { 743 | "ansi-term": ">=0.0.2", 744 | "bresenham": "0.0.3", 745 | "drawille-blessed-contrib": ">=0.0.1", 746 | "gl-matrix": "^2.1.0", 747 | "x256": ">=0.0.1" 748 | } 749 | }, 750 | "end-of-stream": { 751 | "version": "1.4.4", 752 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 753 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 754 | "requires": { 755 | "once": "^1.4.0" 756 | } 757 | }, 758 | "entities": { 759 | "version": "1.1.2", 760 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", 761 | "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" 762 | }, 763 | "escape-string-regexp": { 764 | "version": "1.0.5", 765 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 766 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 767 | }, 768 | "eslint-plugin-promise": { 769 | "version": "4.2.1", 770 | "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", 771 | "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", 772 | "dev": true 773 | }, 774 | "esprima": { 775 | "version": "4.0.1", 776 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 777 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 778 | }, 779 | "event-stream": { 780 | "version": "0.9.8", 781 | "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-0.9.8.tgz", 782 | "integrity": "sha1-XanPPHkAl1mJ21powo5bPJjr4Do=", 783 | "requires": { 784 | "optimist": "0.2" 785 | }, 786 | "dependencies": { 787 | "optimist": { 788 | "version": "0.2.8", 789 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.2.8.tgz", 790 | "integrity": "sha1-6YGrfiaLRXlIWTtVZ0wJmoFcrDE=", 791 | "requires": { 792 | "wordwrap": ">=0.0.1 <0.1.0" 793 | } 794 | } 795 | } 796 | }, 797 | "exit-on-epipe": { 798 | "version": "1.0.1", 799 | "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", 800 | "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" 801 | }, 802 | "expand-brackets": { 803 | "version": "2.1.4", 804 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", 805 | "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", 806 | "requires": { 807 | "debug": "^2.3.3", 808 | "define-property": "^0.2.5", 809 | "extend-shallow": "^2.0.1", 810 | "posix-character-classes": "^0.1.0", 811 | "regex-not": "^1.0.0", 812 | "snapdragon": "^0.8.1", 813 | "to-regex": "^3.0.1" 814 | }, 815 | "dependencies": { 816 | "debug": { 817 | "version": "2.6.9", 818 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 819 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 820 | "requires": { 821 | "ms": "2.0.0" 822 | } 823 | }, 824 | "define-property": { 825 | "version": "0.2.5", 826 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 827 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 828 | "requires": { 829 | "is-descriptor": "^0.1.0" 830 | } 831 | }, 832 | "extend-shallow": { 833 | "version": "2.0.1", 834 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 835 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 836 | "requires": { 837 | "is-extendable": "^0.1.0" 838 | } 839 | }, 840 | "ms": { 841 | "version": "2.0.0", 842 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 843 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 844 | } 845 | } 846 | }, 847 | "extend-shallow": { 848 | "version": "3.0.2", 849 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", 850 | "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", 851 | "requires": { 852 | "assign-symbols": "^1.0.0", 853 | "is-extendable": "^1.0.1" 854 | }, 855 | "dependencies": { 856 | "is-extendable": { 857 | "version": "1.0.1", 858 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 859 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 860 | "requires": { 861 | "is-plain-object": "^2.0.4" 862 | } 863 | } 864 | } 865 | }, 866 | "extglob": { 867 | "version": "2.0.4", 868 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", 869 | "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", 870 | "requires": { 871 | "array-unique": "^0.3.2", 872 | "define-property": "^1.0.0", 873 | "expand-brackets": "^2.1.4", 874 | "extend-shallow": "^2.0.1", 875 | "fragment-cache": "^0.2.1", 876 | "regex-not": "^1.0.0", 877 | "snapdragon": "^0.8.1", 878 | "to-regex": "^3.0.1" 879 | }, 880 | "dependencies": { 881 | "define-property": { 882 | "version": "1.0.0", 883 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 884 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 885 | "requires": { 886 | "is-descriptor": "^1.0.0" 887 | } 888 | }, 889 | "extend-shallow": { 890 | "version": "2.0.1", 891 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 892 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 893 | "requires": { 894 | "is-extendable": "^0.1.0" 895 | } 896 | }, 897 | "is-accessor-descriptor": { 898 | "version": "1.0.0", 899 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 900 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 901 | "requires": { 902 | "kind-of": "^6.0.0" 903 | } 904 | }, 905 | "is-data-descriptor": { 906 | "version": "1.0.0", 907 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 908 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 909 | "requires": { 910 | "kind-of": "^6.0.0" 911 | } 912 | }, 913 | "is-descriptor": { 914 | "version": "1.0.2", 915 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 916 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 917 | "requires": { 918 | "is-accessor-descriptor": "^1.0.0", 919 | "is-data-descriptor": "^1.0.0", 920 | "kind-of": "^6.0.2" 921 | } 922 | } 923 | } 924 | }, 925 | "extract-zip": { 926 | "version": "2.0.1", 927 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 928 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 929 | "requires": { 930 | "@types/yauzl": "^2.9.1", 931 | "debug": "^4.1.1", 932 | "get-stream": "^5.1.0", 933 | "yauzl": "^2.10.0" 934 | } 935 | }, 936 | "fast-safe-stringify": { 937 | "version": "2.0.7", 938 | "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", 939 | "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" 940 | }, 941 | "fd-slicer": { 942 | "version": "1.1.0", 943 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 944 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 945 | "requires": { 946 | "pend": "~1.2.0" 947 | } 948 | }, 949 | "fill-range": { 950 | "version": "4.0.0", 951 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", 952 | "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", 953 | "requires": { 954 | "extend-shallow": "^2.0.1", 955 | "is-number": "^3.0.0", 956 | "repeat-string": "^1.6.1", 957 | "to-regex-range": "^2.1.0" 958 | }, 959 | "dependencies": { 960 | "extend-shallow": { 961 | "version": "2.0.1", 962 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 963 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 964 | "requires": { 965 | "is-extendable": "^0.1.0" 966 | } 967 | } 968 | } 969 | }, 970 | "find-up": { 971 | "version": "4.1.0", 972 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 973 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 974 | "requires": { 975 | "locate-path": "^5.0.0", 976 | "path-exists": "^4.0.0" 977 | } 978 | }, 979 | "flatted": { 980 | "version": "2.0.2", 981 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", 982 | "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" 983 | }, 984 | "for-in": { 985 | "version": "1.0.2", 986 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 987 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" 988 | }, 989 | "for-own": { 990 | "version": "0.1.5", 991 | "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", 992 | "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", 993 | "requires": { 994 | "for-in": "^1.0.1" 995 | } 996 | }, 997 | "form-data": { 998 | "version": "3.0.0", 999 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", 1000 | "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", 1001 | "requires": { 1002 | "asynckit": "^0.4.0", 1003 | "combined-stream": "^1.0.8", 1004 | "mime-types": "^2.1.12" 1005 | } 1006 | }, 1007 | "formidable": { 1008 | "version": "1.2.2", 1009 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", 1010 | "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" 1011 | }, 1012 | "frac": { 1013 | "version": "1.1.2", 1014 | "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", 1015 | "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" 1016 | }, 1017 | "fragment-cache": { 1018 | "version": "0.2.1", 1019 | "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", 1020 | "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", 1021 | "requires": { 1022 | "map-cache": "^0.2.2" 1023 | } 1024 | }, 1025 | "fs-constants": { 1026 | "version": "1.0.0", 1027 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 1028 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 1029 | }, 1030 | "fs-extra": { 1031 | "version": "9.0.1", 1032 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", 1033 | "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", 1034 | "requires": { 1035 | "at-least-node": "^1.0.0", 1036 | "graceful-fs": "^4.2.0", 1037 | "jsonfile": "^6.0.1", 1038 | "universalify": "^1.0.0" 1039 | } 1040 | }, 1041 | "fs.realpath": { 1042 | "version": "1.0.0", 1043 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1044 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 1045 | }, 1046 | "fsevents": { 1047 | "version": "1.2.9", 1048 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", 1049 | "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", 1050 | "optional": true, 1051 | "requires": { 1052 | "nan": "^2.12.1", 1053 | "node-pre-gyp": "^0.12.0" 1054 | }, 1055 | "dependencies": { 1056 | "abbrev": { 1057 | "version": "1.1.1", 1058 | "bundled": true, 1059 | "optional": true 1060 | }, 1061 | "ansi-regex": { 1062 | "version": "2.1.1", 1063 | "bundled": true, 1064 | "optional": true 1065 | }, 1066 | "aproba": { 1067 | "version": "1.2.0", 1068 | "bundled": true, 1069 | "optional": true 1070 | }, 1071 | "are-we-there-yet": { 1072 | "version": "1.1.5", 1073 | "bundled": true, 1074 | "optional": true, 1075 | "requires": { 1076 | "delegates": "^1.0.0", 1077 | "readable-stream": "^2.0.6" 1078 | } 1079 | }, 1080 | "balanced-match": { 1081 | "version": "1.0.0", 1082 | "bundled": true, 1083 | "optional": true 1084 | }, 1085 | "brace-expansion": { 1086 | "version": "1.1.11", 1087 | "bundled": true, 1088 | "optional": true, 1089 | "requires": { 1090 | "balanced-match": "^1.0.0", 1091 | "concat-map": "0.0.1" 1092 | } 1093 | }, 1094 | "chownr": { 1095 | "version": "1.1.1", 1096 | "bundled": true, 1097 | "optional": true 1098 | }, 1099 | "code-point-at": { 1100 | "version": "1.1.0", 1101 | "bundled": true, 1102 | "optional": true 1103 | }, 1104 | "concat-map": { 1105 | "version": "0.0.1", 1106 | "bundled": true, 1107 | "optional": true 1108 | }, 1109 | "console-control-strings": { 1110 | "version": "1.1.0", 1111 | "bundled": true, 1112 | "optional": true 1113 | }, 1114 | "core-util-is": { 1115 | "version": "1.0.2", 1116 | "bundled": true, 1117 | "optional": true 1118 | }, 1119 | "debug": { 1120 | "version": "4.1.1", 1121 | "bundled": true, 1122 | "optional": true, 1123 | "requires": { 1124 | "ms": "^2.1.1" 1125 | } 1126 | }, 1127 | "deep-extend": { 1128 | "version": "0.6.0", 1129 | "bundled": true, 1130 | "optional": true 1131 | }, 1132 | "delegates": { 1133 | "version": "1.0.0", 1134 | "bundled": true, 1135 | "optional": true 1136 | }, 1137 | "detect-libc": { 1138 | "version": "1.0.3", 1139 | "bundled": true, 1140 | "optional": true 1141 | }, 1142 | "fs-minipass": { 1143 | "version": "1.2.5", 1144 | "bundled": true, 1145 | "optional": true, 1146 | "requires": { 1147 | "minipass": "^2.2.1" 1148 | } 1149 | }, 1150 | "fs.realpath": { 1151 | "version": "1.0.0", 1152 | "bundled": true, 1153 | "optional": true 1154 | }, 1155 | "gauge": { 1156 | "version": "2.7.4", 1157 | "bundled": true, 1158 | "optional": true, 1159 | "requires": { 1160 | "aproba": "^1.0.3", 1161 | "console-control-strings": "^1.0.0", 1162 | "has-unicode": "^2.0.0", 1163 | "object-assign": "^4.1.0", 1164 | "signal-exit": "^3.0.0", 1165 | "string-width": "^1.0.1", 1166 | "strip-ansi": "^3.0.1", 1167 | "wide-align": "^1.1.0" 1168 | } 1169 | }, 1170 | "glob": { 1171 | "version": "7.1.3", 1172 | "bundled": true, 1173 | "optional": true, 1174 | "requires": { 1175 | "fs.realpath": "^1.0.0", 1176 | "inflight": "^1.0.4", 1177 | "inherits": "2", 1178 | "minimatch": "^3.0.4", 1179 | "once": "^1.3.0", 1180 | "path-is-absolute": "^1.0.0" 1181 | } 1182 | }, 1183 | "has-unicode": { 1184 | "version": "2.0.1", 1185 | "bundled": true, 1186 | "optional": true 1187 | }, 1188 | "iconv-lite": { 1189 | "version": "0.4.24", 1190 | "bundled": true, 1191 | "optional": true, 1192 | "requires": { 1193 | "safer-buffer": ">= 2.1.2 < 3" 1194 | } 1195 | }, 1196 | "ignore-walk": { 1197 | "version": "3.0.1", 1198 | "bundled": true, 1199 | "optional": true, 1200 | "requires": { 1201 | "minimatch": "^3.0.4" 1202 | } 1203 | }, 1204 | "inflight": { 1205 | "version": "1.0.6", 1206 | "bundled": true, 1207 | "optional": true, 1208 | "requires": { 1209 | "once": "^1.3.0", 1210 | "wrappy": "1" 1211 | } 1212 | }, 1213 | "inherits": { 1214 | "version": "2.0.3", 1215 | "bundled": true, 1216 | "optional": true 1217 | }, 1218 | "ini": { 1219 | "version": "1.3.5", 1220 | "bundled": true, 1221 | "optional": true 1222 | }, 1223 | "is-fullwidth-code-point": { 1224 | "version": "1.0.0", 1225 | "bundled": true, 1226 | "optional": true, 1227 | "requires": { 1228 | "number-is-nan": "^1.0.0" 1229 | } 1230 | }, 1231 | "isarray": { 1232 | "version": "1.0.0", 1233 | "bundled": true, 1234 | "optional": true 1235 | }, 1236 | "minimatch": { 1237 | "version": "3.0.4", 1238 | "bundled": true, 1239 | "optional": true, 1240 | "requires": { 1241 | "brace-expansion": "^1.1.7" 1242 | } 1243 | }, 1244 | "minimist": { 1245 | "version": "0.0.8", 1246 | "bundled": true, 1247 | "optional": true 1248 | }, 1249 | "minipass": { 1250 | "version": "2.3.5", 1251 | "bundled": true, 1252 | "optional": true, 1253 | "requires": { 1254 | "safe-buffer": "^5.1.2", 1255 | "yallist": "^3.0.0" 1256 | } 1257 | }, 1258 | "minizlib": { 1259 | "version": "1.2.1", 1260 | "bundled": true, 1261 | "optional": true, 1262 | "requires": { 1263 | "minipass": "^2.2.1" 1264 | } 1265 | }, 1266 | "mkdirp": { 1267 | "version": "0.5.1", 1268 | "bundled": true, 1269 | "optional": true, 1270 | "requires": { 1271 | "minimist": "0.0.8" 1272 | } 1273 | }, 1274 | "ms": { 1275 | "version": "2.1.1", 1276 | "bundled": true, 1277 | "optional": true 1278 | }, 1279 | "needle": { 1280 | "version": "2.3.0", 1281 | "bundled": true, 1282 | "optional": true, 1283 | "requires": { 1284 | "debug": "^4.1.0", 1285 | "iconv-lite": "^0.4.4", 1286 | "sax": "^1.2.4" 1287 | } 1288 | }, 1289 | "node-pre-gyp": { 1290 | "version": "0.12.0", 1291 | "bundled": true, 1292 | "optional": true, 1293 | "requires": { 1294 | "detect-libc": "^1.0.2", 1295 | "mkdirp": "^0.5.1", 1296 | "needle": "^2.2.1", 1297 | "nopt": "^4.0.1", 1298 | "npm-packlist": "^1.1.6", 1299 | "npmlog": "^4.0.2", 1300 | "rc": "^1.2.7", 1301 | "rimraf": "^2.6.1", 1302 | "semver": "^5.3.0", 1303 | "tar": "^4" 1304 | } 1305 | }, 1306 | "nopt": { 1307 | "version": "4.0.1", 1308 | "bundled": true, 1309 | "optional": true, 1310 | "requires": { 1311 | "abbrev": "1", 1312 | "osenv": "^0.1.4" 1313 | } 1314 | }, 1315 | "npm-bundled": { 1316 | "version": "1.0.6", 1317 | "bundled": true, 1318 | "optional": true 1319 | }, 1320 | "npm-packlist": { 1321 | "version": "1.4.1", 1322 | "bundled": true, 1323 | "optional": true, 1324 | "requires": { 1325 | "ignore-walk": "^3.0.1", 1326 | "npm-bundled": "^1.0.1" 1327 | } 1328 | }, 1329 | "npmlog": { 1330 | "version": "4.1.2", 1331 | "bundled": true, 1332 | "optional": true, 1333 | "requires": { 1334 | "are-we-there-yet": "~1.1.2", 1335 | "console-control-strings": "~1.1.0", 1336 | "gauge": "~2.7.3", 1337 | "set-blocking": "~2.0.0" 1338 | } 1339 | }, 1340 | "number-is-nan": { 1341 | "version": "1.0.1", 1342 | "bundled": true, 1343 | "optional": true 1344 | }, 1345 | "object-assign": { 1346 | "version": "4.1.1", 1347 | "bundled": true, 1348 | "optional": true 1349 | }, 1350 | "once": { 1351 | "version": "1.4.0", 1352 | "bundled": true, 1353 | "optional": true, 1354 | "requires": { 1355 | "wrappy": "1" 1356 | } 1357 | }, 1358 | "os-homedir": { 1359 | "version": "1.0.2", 1360 | "bundled": true, 1361 | "optional": true 1362 | }, 1363 | "os-tmpdir": { 1364 | "version": "1.0.2", 1365 | "bundled": true, 1366 | "optional": true 1367 | }, 1368 | "osenv": { 1369 | "version": "0.1.5", 1370 | "bundled": true, 1371 | "optional": true, 1372 | "requires": { 1373 | "os-homedir": "^1.0.0", 1374 | "os-tmpdir": "^1.0.0" 1375 | } 1376 | }, 1377 | "path-is-absolute": { 1378 | "version": "1.0.1", 1379 | "bundled": true, 1380 | "optional": true 1381 | }, 1382 | "process-nextick-args": { 1383 | "version": "2.0.0", 1384 | "bundled": true, 1385 | "optional": true 1386 | }, 1387 | "rc": { 1388 | "version": "1.2.8", 1389 | "bundled": true, 1390 | "optional": true, 1391 | "requires": { 1392 | "deep-extend": "^0.6.0", 1393 | "ini": "~1.3.0", 1394 | "minimist": "^1.2.0", 1395 | "strip-json-comments": "~2.0.1" 1396 | }, 1397 | "dependencies": { 1398 | "minimist": { 1399 | "version": "1.2.0", 1400 | "bundled": true, 1401 | "optional": true 1402 | } 1403 | } 1404 | }, 1405 | "readable-stream": { 1406 | "version": "2.3.6", 1407 | "bundled": true, 1408 | "optional": true, 1409 | "requires": { 1410 | "core-util-is": "~1.0.0", 1411 | "inherits": "~2.0.3", 1412 | "isarray": "~1.0.0", 1413 | "process-nextick-args": "~2.0.0", 1414 | "safe-buffer": "~5.1.1", 1415 | "string_decoder": "~1.1.1", 1416 | "util-deprecate": "~1.0.1" 1417 | } 1418 | }, 1419 | "rimraf": { 1420 | "version": "2.6.3", 1421 | "bundled": true, 1422 | "optional": true, 1423 | "requires": { 1424 | "glob": "^7.1.3" 1425 | } 1426 | }, 1427 | "safe-buffer": { 1428 | "version": "5.1.2", 1429 | "bundled": true, 1430 | "optional": true 1431 | }, 1432 | "safer-buffer": { 1433 | "version": "2.1.2", 1434 | "bundled": true, 1435 | "optional": true 1436 | }, 1437 | "sax": { 1438 | "version": "1.2.4", 1439 | "bundled": true, 1440 | "optional": true 1441 | }, 1442 | "semver": { 1443 | "version": "5.7.0", 1444 | "bundled": true, 1445 | "optional": true 1446 | }, 1447 | "set-blocking": { 1448 | "version": "2.0.0", 1449 | "bundled": true, 1450 | "optional": true 1451 | }, 1452 | "signal-exit": { 1453 | "version": "3.0.2", 1454 | "bundled": true, 1455 | "optional": true 1456 | }, 1457 | "string-width": { 1458 | "version": "1.0.2", 1459 | "bundled": true, 1460 | "optional": true, 1461 | "requires": { 1462 | "code-point-at": "^1.0.0", 1463 | "is-fullwidth-code-point": "^1.0.0", 1464 | "strip-ansi": "^3.0.0" 1465 | } 1466 | }, 1467 | "string_decoder": { 1468 | "version": "1.1.1", 1469 | "bundled": true, 1470 | "optional": true, 1471 | "requires": { 1472 | "safe-buffer": "~5.1.0" 1473 | } 1474 | }, 1475 | "strip-ansi": { 1476 | "version": "3.0.1", 1477 | "bundled": true, 1478 | "optional": true, 1479 | "requires": { 1480 | "ansi-regex": "^2.0.0" 1481 | } 1482 | }, 1483 | "strip-json-comments": { 1484 | "version": "2.0.1", 1485 | "bundled": true, 1486 | "optional": true 1487 | }, 1488 | "tar": { 1489 | "version": "4.4.8", 1490 | "bundled": true, 1491 | "optional": true, 1492 | "requires": { 1493 | "chownr": "^1.1.1", 1494 | "fs-minipass": "^1.2.5", 1495 | "minipass": "^2.3.4", 1496 | "minizlib": "^1.1.1", 1497 | "mkdirp": "^0.5.0", 1498 | "safe-buffer": "^5.1.2", 1499 | "yallist": "^3.0.2" 1500 | } 1501 | }, 1502 | "util-deprecate": { 1503 | "version": "1.0.2", 1504 | "bundled": true, 1505 | "optional": true 1506 | }, 1507 | "wide-align": { 1508 | "version": "1.1.3", 1509 | "bundled": true, 1510 | "optional": true, 1511 | "requires": { 1512 | "string-width": "^1.0.2 || 2" 1513 | } 1514 | }, 1515 | "wrappy": { 1516 | "version": "1.0.2", 1517 | "bundled": true, 1518 | "optional": true 1519 | }, 1520 | "yallist": { 1521 | "version": "3.0.3", 1522 | "bundled": true, 1523 | "optional": true 1524 | } 1525 | } 1526 | }, 1527 | "generic-pool": { 1528 | "version": "3.7.1", 1529 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.7.1.tgz", 1530 | "integrity": "sha512-ug6DAZoNgWm6q5KhPFA+hzXfBLFQu5sTXxPpv44DmE0A2g+CiHoq9LTVdkXpZMkYVMoGw83F6W+WT0h0MFMK/w==" 1531 | }, 1532 | "get-stream": { 1533 | "version": "5.2.0", 1534 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 1535 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 1536 | "requires": { 1537 | "pump": "^3.0.0" 1538 | } 1539 | }, 1540 | "get-value": { 1541 | "version": "2.0.6", 1542 | "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", 1543 | "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" 1544 | }, 1545 | "gl-matrix": { 1546 | "version": "2.8.1", 1547 | "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.8.1.tgz", 1548 | "integrity": "sha512-0YCjVpE3pS5XWlN3J4X7AiAx65+nqAI54LndtVFnQZB6G/FVLkZH8y8V6R3cIoOQR4pUdfwQGd1iwyoXHJ4Qfw==" 1549 | }, 1550 | "glob": { 1551 | "version": "7.1.6", 1552 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 1553 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 1554 | "requires": { 1555 | "fs.realpath": "^1.0.0", 1556 | "inflight": "^1.0.4", 1557 | "inherits": "2", 1558 | "minimatch": "^3.0.4", 1559 | "once": "^1.3.0", 1560 | "path-is-absolute": "^1.0.0" 1561 | } 1562 | }, 1563 | "glob-parent": { 1564 | "version": "3.1.0", 1565 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", 1566 | "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", 1567 | "requires": { 1568 | "is-glob": "^3.1.0", 1569 | "path-dirname": "^1.0.0" 1570 | }, 1571 | "dependencies": { 1572 | "is-glob": { 1573 | "version": "3.1.0", 1574 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", 1575 | "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", 1576 | "requires": { 1577 | "is-extglob": "^2.1.0" 1578 | } 1579 | } 1580 | } 1581 | }, 1582 | "graceful-fs": { 1583 | "version": "4.2.0", 1584 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", 1585 | "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" 1586 | }, 1587 | "has-ansi": { 1588 | "version": "2.0.0", 1589 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 1590 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 1591 | "requires": { 1592 | "ansi-regex": "^2.0.0" 1593 | } 1594 | }, 1595 | "has-flag": { 1596 | "version": "4.0.0", 1597 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1598 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 1599 | }, 1600 | "has-value": { 1601 | "version": "1.0.0", 1602 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", 1603 | "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", 1604 | "requires": { 1605 | "get-value": "^2.0.6", 1606 | "has-values": "^1.0.0", 1607 | "isobject": "^3.0.0" 1608 | } 1609 | }, 1610 | "has-values": { 1611 | "version": "1.0.0", 1612 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", 1613 | "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", 1614 | "requires": { 1615 | "is-number": "^3.0.0", 1616 | "kind-of": "^4.0.0" 1617 | }, 1618 | "dependencies": { 1619 | "kind-of": { 1620 | "version": "4.0.0", 1621 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", 1622 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", 1623 | "requires": { 1624 | "is-buffer": "^1.1.5" 1625 | } 1626 | } 1627 | } 1628 | }, 1629 | "here": { 1630 | "version": "0.0.2", 1631 | "resolved": "https://registry.npmjs.org/here/-/here-0.0.2.tgz", 1632 | "integrity": "sha1-acGvPwISHz2HiOAuhNyLOQXXEZU=" 1633 | }, 1634 | "hmacsha1": { 1635 | "version": "1.0.0", 1636 | "resolved": "https://registry.npmjs.org/hmacsha1/-/hmacsha1-1.0.0.tgz", 1637 | "integrity": "sha1-wbeuA6TqEWNICQrxT4FIwSk4qRc=" 1638 | }, 1639 | "htmlparser2": { 1640 | "version": "3.10.1", 1641 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", 1642 | "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", 1643 | "requires": { 1644 | "domelementtype": "^1.3.1", 1645 | "domhandler": "^2.3.0", 1646 | "domutils": "^1.5.1", 1647 | "entities": "^1.1.1", 1648 | "inherits": "^2.0.1", 1649 | "readable-stream": "^3.1.1" 1650 | }, 1651 | "dependencies": { 1652 | "readable-stream": { 1653 | "version": "3.4.0", 1654 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", 1655 | "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", 1656 | "requires": { 1657 | "inherits": "^2.0.3", 1658 | "string_decoder": "^1.1.1", 1659 | "util-deprecate": "^1.0.1" 1660 | } 1661 | } 1662 | } 1663 | }, 1664 | "https-proxy-agent": { 1665 | "version": "4.0.0", 1666 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", 1667 | "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", 1668 | "requires": { 1669 | "agent-base": "5", 1670 | "debug": "4" 1671 | } 1672 | }, 1673 | "ieee754": { 1674 | "version": "1.2.1", 1675 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 1676 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 1677 | }, 1678 | "immediate": { 1679 | "version": "3.0.6", 1680 | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", 1681 | "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" 1682 | }, 1683 | "inflight": { 1684 | "version": "1.0.6", 1685 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1686 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1687 | "requires": { 1688 | "once": "^1.3.0", 1689 | "wrappy": "1" 1690 | } 1691 | }, 1692 | "inherits": { 1693 | "version": "2.0.3", 1694 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1695 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1696 | }, 1697 | "interpret": { 1698 | "version": "1.2.0", 1699 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", 1700 | "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" 1701 | }, 1702 | "ioredis": { 1703 | "version": "4.19.2", 1704 | "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.19.2.tgz", 1705 | "integrity": "sha512-SZSIwMrbd96b7rJvJwyTWSP6XQ0m1kAIIqBnwglJKrIJ6na7TeY4F2EV2vDY0xm/fLrUY8cEg81dR7kVFt2sKA==", 1706 | "requires": { 1707 | "cluster-key-slot": "^1.1.0", 1708 | "debug": "^4.1.1", 1709 | "denque": "^1.1.0", 1710 | "lodash.defaults": "^4.2.0", 1711 | "lodash.flatten": "^4.4.0", 1712 | "p-map": "^2.1.0", 1713 | "redis-commands": "1.6.0", 1714 | "redis-errors": "^1.2.0", 1715 | "redis-parser": "^3.0.0", 1716 | "standard-as-callback": "^2.0.1" 1717 | } 1718 | }, 1719 | "is-accessor-descriptor": { 1720 | "version": "0.1.6", 1721 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", 1722 | "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", 1723 | "requires": { 1724 | "kind-of": "^3.0.2" 1725 | }, 1726 | "dependencies": { 1727 | "kind-of": { 1728 | "version": "3.2.2", 1729 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1730 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1731 | "requires": { 1732 | "is-buffer": "^1.1.5" 1733 | } 1734 | } 1735 | } 1736 | }, 1737 | "is-binary-path": { 1738 | "version": "1.0.1", 1739 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", 1740 | "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", 1741 | "requires": { 1742 | "binary-extensions": "^1.0.0" 1743 | } 1744 | }, 1745 | "is-buffer": { 1746 | "version": "1.1.6", 1747 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1748 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 1749 | }, 1750 | "is-data-descriptor": { 1751 | "version": "0.1.4", 1752 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", 1753 | "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", 1754 | "requires": { 1755 | "kind-of": "^3.0.2" 1756 | }, 1757 | "dependencies": { 1758 | "kind-of": { 1759 | "version": "3.2.2", 1760 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1761 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1762 | "requires": { 1763 | "is-buffer": "^1.1.5" 1764 | } 1765 | } 1766 | } 1767 | }, 1768 | "is-descriptor": { 1769 | "version": "0.1.6", 1770 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", 1771 | "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", 1772 | "requires": { 1773 | "is-accessor-descriptor": "^0.1.6", 1774 | "is-data-descriptor": "^0.1.4", 1775 | "kind-of": "^5.0.0" 1776 | }, 1777 | "dependencies": { 1778 | "kind-of": { 1779 | "version": "5.1.0", 1780 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", 1781 | "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" 1782 | } 1783 | } 1784 | }, 1785 | "is-empty": { 1786 | "version": "1.2.0", 1787 | "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", 1788 | "integrity": "sha1-3pu1snhzigWgsJpX4ftNSjQan2s=" 1789 | }, 1790 | "is-extendable": { 1791 | "version": "0.1.1", 1792 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 1793 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" 1794 | }, 1795 | "is-extglob": { 1796 | "version": "2.1.1", 1797 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1798 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" 1799 | }, 1800 | "is-glob": { 1801 | "version": "4.0.1", 1802 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1803 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1804 | "requires": { 1805 | "is-extglob": "^2.1.1" 1806 | } 1807 | }, 1808 | "is-nan": { 1809 | "version": "1.2.1", 1810 | "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.2.1.tgz", 1811 | "integrity": "sha1-n69ltvttskt/XAYoR16nH5iEAeI=", 1812 | "requires": { 1813 | "define-properties": "^1.1.1" 1814 | } 1815 | }, 1816 | "is-number": { 1817 | "version": "3.0.0", 1818 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", 1819 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", 1820 | "requires": { 1821 | "kind-of": "^3.0.2" 1822 | }, 1823 | "dependencies": { 1824 | "kind-of": { 1825 | "version": "3.2.2", 1826 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1827 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1828 | "requires": { 1829 | "is-buffer": "^1.1.5" 1830 | } 1831 | } 1832 | } 1833 | }, 1834 | "is-plain-object": { 1835 | "version": "2.0.4", 1836 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1837 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1838 | "requires": { 1839 | "isobject": "^3.0.1" 1840 | } 1841 | }, 1842 | "is-windows": { 1843 | "version": "1.0.2", 1844 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1845 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" 1846 | }, 1847 | "isarray": { 1848 | "version": "1.0.0", 1849 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1850 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1851 | }, 1852 | "isobject": { 1853 | "version": "3.0.1", 1854 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1855 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 1856 | }, 1857 | "jsonfile": { 1858 | "version": "6.0.1", 1859 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", 1860 | "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", 1861 | "requires": { 1862 | "graceful-fs": "^4.1.6", 1863 | "universalify": "^1.0.0" 1864 | } 1865 | }, 1866 | "kind-of": { 1867 | "version": "6.0.2", 1868 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 1869 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 1870 | }, 1871 | "kleur": { 1872 | "version": "4.0.2", 1873 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.0.2.tgz", 1874 | "integrity": "sha512-FGCCxczbrZuF5CtMeO0xfnjhzkVZSXfcWK90IPLucDWZwskrpYN7pmRIgvd8muU0mrPrzy4A2RBGuwCjLHI+nw==" 1875 | }, 1876 | "lazy-cache": { 1877 | "version": "1.0.4", 1878 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 1879 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" 1880 | }, 1881 | "lie": { 1882 | "version": "3.1.1", 1883 | "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", 1884 | "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", 1885 | "requires": { 1886 | "immediate": "~3.0.5" 1887 | } 1888 | }, 1889 | "localforage": { 1890 | "version": "1.9.0", 1891 | "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.9.0.tgz", 1892 | "integrity": "sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g==", 1893 | "requires": { 1894 | "lie": "3.1.1" 1895 | } 1896 | }, 1897 | "locate-path": { 1898 | "version": "5.0.0", 1899 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1900 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1901 | "requires": { 1902 | "p-locate": "^4.1.0" 1903 | } 1904 | }, 1905 | "lodash": { 1906 | "version": "4.17.15", 1907 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1908 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 1909 | }, 1910 | "lodash.defaults": { 1911 | "version": "4.2.0", 1912 | "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", 1913 | "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" 1914 | }, 1915 | "lodash.flatten": { 1916 | "version": "4.4.0", 1917 | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", 1918 | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" 1919 | }, 1920 | "lodash.toarray": { 1921 | "version": "4.4.0", 1922 | "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", 1923 | "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" 1924 | }, 1925 | "log4js": { 1926 | "version": "6.3.0", 1927 | "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", 1928 | "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", 1929 | "requires": { 1930 | "date-format": "^3.0.0", 1931 | "debug": "^4.1.1", 1932 | "flatted": "^2.0.1", 1933 | "rfdc": "^1.1.4", 1934 | "streamroller": "^2.2.4" 1935 | } 1936 | }, 1937 | "long-timeout": { 1938 | "version": "0.1.1", 1939 | "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", 1940 | "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=" 1941 | }, 1942 | "map-cache": { 1943 | "version": "0.2.2", 1944 | "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", 1945 | "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" 1946 | }, 1947 | "map-canvas": { 1948 | "version": "0.1.5", 1949 | "resolved": "https://registry.npmjs.org/map-canvas/-/map-canvas-0.1.5.tgz", 1950 | "integrity": "sha1-i+a63gvz6fmotW6INqHR0TPKsYY=", 1951 | "requires": { 1952 | "drawille-canvas-blessed-contrib": ">=0.0.1", 1953 | "xml2js": "^0.4.5" 1954 | } 1955 | }, 1956 | "map-visit": { 1957 | "version": "1.0.0", 1958 | "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", 1959 | "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", 1960 | "requires": { 1961 | "object-visit": "^1.0.0" 1962 | } 1963 | }, 1964 | "marked": { 1965 | "version": "0.7.0", 1966 | "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", 1967 | "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==" 1968 | }, 1969 | "marked-terminal": { 1970 | "version": "4.1.0", 1971 | "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-4.1.0.tgz", 1972 | "integrity": "sha512-5KllfAOW02WS6hLRQ7cNvGOxvKW1BKuXELH4EtbWfyWgxQhROoMxEvuQ/3fTgkNjledR0J48F4HbapvYp1zWkQ==", 1973 | "requires": { 1974 | "ansi-escapes": "^4.3.1", 1975 | "cardinal": "^2.1.1", 1976 | "chalk": "^4.0.0", 1977 | "cli-table": "^0.3.1", 1978 | "node-emoji": "^1.10.0", 1979 | "supports-hyperlinks": "^2.1.0" 1980 | }, 1981 | "dependencies": { 1982 | "ansi-styles": { 1983 | "version": "4.2.1", 1984 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 1985 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 1986 | "requires": { 1987 | "@types/color-name": "^1.1.1", 1988 | "color-convert": "^2.0.1" 1989 | } 1990 | }, 1991 | "chalk": { 1992 | "version": "4.0.0", 1993 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", 1994 | "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", 1995 | "requires": { 1996 | "ansi-styles": "^4.1.0", 1997 | "supports-color": "^7.1.0" 1998 | } 1999 | }, 2000 | "supports-color": { 2001 | "version": "7.1.0", 2002 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 2003 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 2004 | "requires": { 2005 | "has-flag": "^4.0.0" 2006 | } 2007 | } 2008 | } 2009 | }, 2010 | "memory-streams": { 2011 | "version": "0.1.3", 2012 | "resolved": "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.3.tgz", 2013 | "integrity": "sha512-qVQ/CjkMyMInPaaRMrwWNDvf6boRZXaT/DbQeMYcCWuXPEBf1v8qChOc9OlEVQp2uOvRXa1Qu30fLmKhY6NipA==", 2014 | "requires": { 2015 | "readable-stream": "~1.0.2" 2016 | }, 2017 | "dependencies": { 2018 | "isarray": { 2019 | "version": "0.0.1", 2020 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 2021 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 2022 | }, 2023 | "readable-stream": { 2024 | "version": "1.0.34", 2025 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 2026 | "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 2027 | "requires": { 2028 | "core-util-is": "~1.0.0", 2029 | "inherits": "~2.0.1", 2030 | "isarray": "0.0.1", 2031 | "string_decoder": "~0.10.x" 2032 | } 2033 | }, 2034 | "string_decoder": { 2035 | "version": "0.10.31", 2036 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 2037 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 2038 | } 2039 | } 2040 | }, 2041 | "memorystream": { 2042 | "version": "0.3.1", 2043 | "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", 2044 | "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" 2045 | }, 2046 | "merge-deep": { 2047 | "version": "3.0.2", 2048 | "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz", 2049 | "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==", 2050 | "requires": { 2051 | "arr-union": "^3.1.0", 2052 | "clone-deep": "^0.2.4", 2053 | "kind-of": "^3.0.2" 2054 | }, 2055 | "dependencies": { 2056 | "kind-of": { 2057 | "version": "3.2.2", 2058 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2059 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2060 | "requires": { 2061 | "is-buffer": "^1.1.5" 2062 | } 2063 | } 2064 | } 2065 | }, 2066 | "methods": { 2067 | "version": "1.1.2", 2068 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2069 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 2070 | }, 2071 | "micromatch": { 2072 | "version": "3.1.10", 2073 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", 2074 | "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", 2075 | "requires": { 2076 | "arr-diff": "^4.0.0", 2077 | "array-unique": "^0.3.2", 2078 | "braces": "^2.3.1", 2079 | "define-property": "^2.0.2", 2080 | "extend-shallow": "^3.0.2", 2081 | "extglob": "^2.0.4", 2082 | "fragment-cache": "^0.2.1", 2083 | "kind-of": "^6.0.2", 2084 | "nanomatch": "^1.2.9", 2085 | "object.pick": "^1.3.0", 2086 | "regex-not": "^1.0.0", 2087 | "snapdragon": "^0.8.1", 2088 | "to-regex": "^3.0.2" 2089 | } 2090 | }, 2091 | "mime": { 2092 | "version": "2.4.6", 2093 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", 2094 | "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" 2095 | }, 2096 | "mime-db": { 2097 | "version": "1.44.0", 2098 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 2099 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 2100 | }, 2101 | "mime-types": { 2102 | "version": "2.1.27", 2103 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 2104 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 2105 | "requires": { 2106 | "mime-db": "1.44.0" 2107 | } 2108 | }, 2109 | "minimatch": { 2110 | "version": "3.0.4", 2111 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 2112 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 2113 | "requires": { 2114 | "brace-expansion": "^1.1.7" 2115 | } 2116 | }, 2117 | "minimist": { 2118 | "version": "1.2.5", 2119 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 2120 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 2121 | }, 2122 | "mixin-deep": { 2123 | "version": "1.3.2", 2124 | "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", 2125 | "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", 2126 | "requires": { 2127 | "for-in": "^1.0.2", 2128 | "is-extendable": "^1.0.1" 2129 | }, 2130 | "dependencies": { 2131 | "is-extendable": { 2132 | "version": "1.0.1", 2133 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 2134 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 2135 | "requires": { 2136 | "is-plain-object": "^2.0.4" 2137 | } 2138 | } 2139 | } 2140 | }, 2141 | "mixin-object": { 2142 | "version": "2.0.1", 2143 | "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", 2144 | "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", 2145 | "requires": { 2146 | "for-in": "^0.1.3", 2147 | "is-extendable": "^0.1.1" 2148 | }, 2149 | "dependencies": { 2150 | "for-in": { 2151 | "version": "0.1.8", 2152 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", 2153 | "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=" 2154 | } 2155 | } 2156 | }, 2157 | "mkdirp": { 2158 | "version": "0.5.5", 2159 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 2160 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 2161 | "requires": { 2162 | "minimist": "^1.2.5" 2163 | } 2164 | }, 2165 | "mkdirp-classic": { 2166 | "version": "0.5.3", 2167 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 2168 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" 2169 | }, 2170 | "moment": { 2171 | "version": "2.27.0", 2172 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", 2173 | "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" 2174 | }, 2175 | "moment-timezone": { 2176 | "version": "0.5.25", 2177 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz", 2178 | "integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==", 2179 | "requires": { 2180 | "moment": ">= 2.9.0" 2181 | } 2182 | }, 2183 | "ms": { 2184 | "version": "2.1.2", 2185 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2186 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2187 | }, 2188 | "mysql": { 2189 | "version": "2.18.1", 2190 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", 2191 | "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", 2192 | "requires": { 2193 | "bignumber.js": "9.0.0", 2194 | "readable-stream": "2.3.7", 2195 | "safe-buffer": "5.1.2", 2196 | "sqlstring": "2.3.1" 2197 | }, 2198 | "dependencies": { 2199 | "readable-stream": { 2200 | "version": "2.3.7", 2201 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 2202 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 2203 | "requires": { 2204 | "core-util-is": "~1.0.0", 2205 | "inherits": "~2.0.3", 2206 | "isarray": "~1.0.0", 2207 | "process-nextick-args": "~2.0.0", 2208 | "safe-buffer": "~5.1.1", 2209 | "string_decoder": "~1.1.1", 2210 | "util-deprecate": "~1.0.1" 2211 | } 2212 | } 2213 | } 2214 | }, 2215 | "nan": { 2216 | "version": "2.14.0", 2217 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", 2218 | "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", 2219 | "optional": true 2220 | }, 2221 | "nanomatch": { 2222 | "version": "1.2.13", 2223 | "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", 2224 | "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", 2225 | "requires": { 2226 | "arr-diff": "^4.0.0", 2227 | "array-unique": "^0.3.2", 2228 | "define-property": "^2.0.2", 2229 | "extend-shallow": "^3.0.2", 2230 | "fragment-cache": "^0.2.1", 2231 | "is-windows": "^1.0.2", 2232 | "kind-of": "^6.0.2", 2233 | "object.pick": "^1.3.0", 2234 | "regex-not": "^1.0.0", 2235 | "snapdragon": "^0.8.1", 2236 | "to-regex": "^3.0.1" 2237 | } 2238 | }, 2239 | "nedb": { 2240 | "version": "1.8.0", 2241 | "resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz", 2242 | "integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=", 2243 | "requires": { 2244 | "async": "0.2.10", 2245 | "binary-search-tree": "0.2.5", 2246 | "localforage": "^1.3.0", 2247 | "mkdirp": "~0.5.1", 2248 | "underscore": "~1.4.4" 2249 | } 2250 | }, 2251 | "nedb-promises": { 2252 | "version": "4.1.0", 2253 | "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-4.1.0.tgz", 2254 | "integrity": "sha512-nTdx7jX/Vu24L05Cy0ee7CL3L4SEHCb1jlLlegPl0VlE8jsUXgnSyNOjq3FEc3cdUSDK05X7hSzb3+a07PigmQ==", 2255 | "requires": { 2256 | "nedb": "^1.8.0" 2257 | } 2258 | }, 2259 | "node-emoji": { 2260 | "version": "1.10.0", 2261 | "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", 2262 | "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", 2263 | "requires": { 2264 | "lodash.toarray": "^4.4.0" 2265 | } 2266 | }, 2267 | "node-fetch": { 2268 | "version": "2.6.1", 2269 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 2270 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" 2271 | }, 2272 | "node-schedule": { 2273 | "version": "1.3.2", 2274 | "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-1.3.2.tgz", 2275 | "integrity": "sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw==", 2276 | "requires": { 2277 | "cron-parser": "^2.7.3", 2278 | "long-timeout": "0.1.1", 2279 | "sorted-array-functions": "^1.0.0" 2280 | } 2281 | }, 2282 | "nodejs-tail": { 2283 | "version": "1.1.0", 2284 | "resolved": "https://registry.npmjs.org/nodejs-tail/-/nodejs-tail-1.1.0.tgz", 2285 | "integrity": "sha512-Gt2fi69P9tgdj41Xl9vFoLVcmnXW9uKQbWJsfgParmQZAPFnoBPHiLNoLY1ytF720UGozVD0tg6cAESP9hUrgA==", 2286 | "requires": { 2287 | "chokidar": "2.1.2" 2288 | } 2289 | }, 2290 | "nodemailer": { 2291 | "version": "6.4.11", 2292 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.11.tgz", 2293 | "integrity": "sha512-BVZBDi+aJV4O38rxsUh164Dk1NCqgh6Cm0rQSb9SK/DHGll/DrCMnycVDD7msJgZCnmVa8ASo8EZzR7jsgTukQ==" 2294 | }, 2295 | "nopt": { 2296 | "version": "2.1.2", 2297 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz", 2298 | "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", 2299 | "requires": { 2300 | "abbrev": "1" 2301 | } 2302 | }, 2303 | "normalize-path": { 2304 | "version": "3.0.0", 2305 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2306 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" 2307 | }, 2308 | "nth-check": { 2309 | "version": "1.0.2", 2310 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", 2311 | "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", 2312 | "requires": { 2313 | "boolbase": "~1.0.0" 2314 | } 2315 | }, 2316 | "object-copy": { 2317 | "version": "0.1.0", 2318 | "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", 2319 | "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", 2320 | "requires": { 2321 | "copy-descriptor": "^0.1.0", 2322 | "define-property": "^0.2.5", 2323 | "kind-of": "^3.0.3" 2324 | }, 2325 | "dependencies": { 2326 | "define-property": { 2327 | "version": "0.2.5", 2328 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2329 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2330 | "requires": { 2331 | "is-descriptor": "^0.1.0" 2332 | } 2333 | }, 2334 | "kind-of": { 2335 | "version": "3.2.2", 2336 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2337 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2338 | "requires": { 2339 | "is-buffer": "^1.1.5" 2340 | } 2341 | } 2342 | } 2343 | }, 2344 | "object-keys": { 2345 | "version": "1.1.1", 2346 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 2347 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 2348 | }, 2349 | "object-visit": { 2350 | "version": "1.0.1", 2351 | "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", 2352 | "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", 2353 | "requires": { 2354 | "isobject": "^3.0.0" 2355 | } 2356 | }, 2357 | "object.pick": { 2358 | "version": "1.3.0", 2359 | "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", 2360 | "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", 2361 | "requires": { 2362 | "isobject": "^3.0.1" 2363 | } 2364 | }, 2365 | "once": { 2366 | "version": "1.4.0", 2367 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2368 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2369 | "requires": { 2370 | "wrappy": "1" 2371 | } 2372 | }, 2373 | "optimist": { 2374 | "version": "0.3.7", 2375 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", 2376 | "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", 2377 | "requires": { 2378 | "wordwrap": "~0.0.2" 2379 | } 2380 | }, 2381 | "p-limit": { 2382 | "version": "2.3.0", 2383 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2384 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2385 | "requires": { 2386 | "p-try": "^2.0.0" 2387 | } 2388 | }, 2389 | "p-locate": { 2390 | "version": "4.1.0", 2391 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2392 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2393 | "requires": { 2394 | "p-limit": "^2.2.0" 2395 | } 2396 | }, 2397 | "p-map": { 2398 | "version": "2.1.0", 2399 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", 2400 | "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" 2401 | }, 2402 | "p-try": { 2403 | "version": "2.2.0", 2404 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 2405 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 2406 | }, 2407 | "parse5": { 2408 | "version": "3.0.3", 2409 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", 2410 | "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", 2411 | "requires": { 2412 | "@types/node": "*" 2413 | } 2414 | }, 2415 | "pascalcase": { 2416 | "version": "0.1.1", 2417 | "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", 2418 | "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" 2419 | }, 2420 | "path-dirname": { 2421 | "version": "1.0.2", 2422 | "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", 2423 | "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" 2424 | }, 2425 | "path-exists": { 2426 | "version": "4.0.0", 2427 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2428 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" 2429 | }, 2430 | "path-is-absolute": { 2431 | "version": "1.0.1", 2432 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2433 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 2434 | }, 2435 | "path-parse": { 2436 | "version": "1.0.6", 2437 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 2438 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 2439 | }, 2440 | "pend": { 2441 | "version": "1.2.0", 2442 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 2443 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" 2444 | }, 2445 | "pending-xhr-puppeteer": { 2446 | "version": "2.3.2", 2447 | "resolved": "https://registry.npmjs.org/pending-xhr-puppeteer/-/pending-xhr-puppeteer-2.3.2.tgz", 2448 | "integrity": "sha512-ETd4nUVjSr7pKzQGjGu80lkXF70tjAJDMLK1EZTGPixs0jj0Yx78nSDNEUSk1Y/Zo3humdMR2pVebN07AP2x2A==" 2449 | }, 2450 | "picture-tuber": { 2451 | "version": "1.0.2", 2452 | "resolved": "https://registry.npmjs.org/picture-tuber/-/picture-tuber-1.0.2.tgz", 2453 | "integrity": "sha512-49/xq+wzbwDeI32aPvwQJldM8pr7dKDRuR76IjztrkmiCkAQDaWFJzkmfVqCHmt/iFoPFhHmI9L0oKhthrTOQw==", 2454 | "requires": { 2455 | "buffers": "~0.1.1", 2456 | "charm": "~0.1.0", 2457 | "event-stream": "~0.9.8", 2458 | "optimist": "~0.3.4", 2459 | "png-js": "~0.1.0", 2460 | "x256": "~0.0.1" 2461 | } 2462 | }, 2463 | "pkg-dir": { 2464 | "version": "4.2.0", 2465 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 2466 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 2467 | "requires": { 2468 | "find-up": "^4.0.0" 2469 | } 2470 | }, 2471 | "png-js": { 2472 | "version": "0.1.1", 2473 | "resolved": "https://registry.npmjs.org/png-js/-/png-js-0.1.1.tgz", 2474 | "integrity": "sha1-HMfCEjA6yr50Jj7DrHgAlYAkLZM=" 2475 | }, 2476 | "posix-character-classes": { 2477 | "version": "0.1.1", 2478 | "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", 2479 | "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" 2480 | }, 2481 | "printj": { 2482 | "version": "1.1.2", 2483 | "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", 2484 | "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" 2485 | }, 2486 | "process-nextick-args": { 2487 | "version": "2.0.0", 2488 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 2489 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 2490 | }, 2491 | "progress": { 2492 | "version": "2.0.3", 2493 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2494 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" 2495 | }, 2496 | "proxy-from-env": { 2497 | "version": "1.1.0", 2498 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 2499 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 2500 | }, 2501 | "pump": { 2502 | "version": "3.0.0", 2503 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 2504 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 2505 | "requires": { 2506 | "end-of-stream": "^1.1.0", 2507 | "once": "^1.3.1" 2508 | } 2509 | }, 2510 | "puppeteer": { 2511 | "version": "5.5.0", 2512 | "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz", 2513 | "integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==", 2514 | "requires": { 2515 | "debug": "^4.1.0", 2516 | "devtools-protocol": "0.0.818844", 2517 | "extract-zip": "^2.0.0", 2518 | "https-proxy-agent": "^4.0.0", 2519 | "node-fetch": "^2.6.1", 2520 | "pkg-dir": "^4.2.0", 2521 | "progress": "^2.0.1", 2522 | "proxy-from-env": "^1.0.0", 2523 | "rimraf": "^3.0.2", 2524 | "tar-fs": "^2.0.0", 2525 | "unbzip2-stream": "^1.3.3", 2526 | "ws": "^7.2.3" 2527 | } 2528 | }, 2529 | "puppeteer-extra": { 2530 | "version": "3.1.15", 2531 | "resolved": "https://registry.npmjs.org/puppeteer-extra/-/puppeteer-extra-3.1.15.tgz", 2532 | "integrity": "sha512-TFKcluoNSYCT3xmZjDcqOkBuxZePbwvaL5mrW5Gvp5c9QsJEei5TYixoenMQaB3QZuRW0Aura4yyjVrJDNlWFA==", 2533 | "requires": { 2534 | "@types/debug": "^4.1.0", 2535 | "@types/puppeteer": "*", 2536 | "debug": "^4.1.1", 2537 | "deepmerge": "^4.2.2" 2538 | } 2539 | }, 2540 | "puppeteer-extra-plugin": { 2541 | "version": "3.1.7", 2542 | "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.1.7.tgz", 2543 | "integrity": "sha512-In3o89X06Q4w1wt0RsAvvdRIp7BzWttVHh24srzlfcBvsGq+zCqhPuwbOYbxnwemtNLaiD/hcYGLvNMEqeUo/Q==", 2544 | "requires": { 2545 | "@types/debug": "^4.1.0", 2546 | "debug": "^4.1.1", 2547 | "merge-deep": "^3.0.1" 2548 | } 2549 | }, 2550 | "puppeteer-extra-plugin-stealth": { 2551 | "version": "2.6.5", 2552 | "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-stealth/-/puppeteer-extra-plugin-stealth-2.6.5.tgz", 2553 | "integrity": "sha512-AMR5lflH51kZART1hSuag/pFCgSoy8U/t23rH6deXN6CirS6S4HzVF72KltGxYnlH9oHRo7ZzoG/aRTsUN8H8A==", 2554 | "requires": { 2555 | "debug": "^4.1.1", 2556 | "puppeteer-extra-plugin": "^3.1.7" 2557 | } 2558 | }, 2559 | "qs": { 2560 | "version": "6.9.4", 2561 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", 2562 | "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" 2563 | }, 2564 | "readable-stream": { 2565 | "version": "2.3.6", 2566 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 2567 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 2568 | "requires": { 2569 | "core-util-is": "~1.0.0", 2570 | "inherits": "~2.0.3", 2571 | "isarray": "~1.0.0", 2572 | "process-nextick-args": "~2.0.0", 2573 | "safe-buffer": "~5.1.1", 2574 | "string_decoder": "~1.1.1", 2575 | "util-deprecate": "~1.0.1" 2576 | } 2577 | }, 2578 | "readdirp": { 2579 | "version": "2.2.1", 2580 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", 2581 | "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", 2582 | "requires": { 2583 | "graceful-fs": "^4.1.11", 2584 | "micromatch": "^3.1.10", 2585 | "readable-stream": "^2.0.2" 2586 | } 2587 | }, 2588 | "rechoir": { 2589 | "version": "0.6.2", 2590 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 2591 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 2592 | "requires": { 2593 | "resolve": "^1.1.6" 2594 | } 2595 | }, 2596 | "redeyed": { 2597 | "version": "2.1.1", 2598 | "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", 2599 | "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", 2600 | "requires": { 2601 | "esprima": "~4.0.0" 2602 | } 2603 | }, 2604 | "redis-commands": { 2605 | "version": "1.6.0", 2606 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.6.0.tgz", 2607 | "integrity": "sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ==" 2608 | }, 2609 | "redis-errors": { 2610 | "version": "1.2.0", 2611 | "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", 2612 | "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" 2613 | }, 2614 | "redis-parser": { 2615 | "version": "3.0.0", 2616 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", 2617 | "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", 2618 | "requires": { 2619 | "redis-errors": "^1.0.0" 2620 | } 2621 | }, 2622 | "regex-not": { 2623 | "version": "1.0.2", 2624 | "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", 2625 | "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", 2626 | "requires": { 2627 | "extend-shallow": "^3.0.2", 2628 | "safe-regex": "^1.1.0" 2629 | } 2630 | }, 2631 | "remove-trailing-separator": { 2632 | "version": "1.1.0", 2633 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", 2634 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" 2635 | }, 2636 | "repeat-element": { 2637 | "version": "1.1.3", 2638 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", 2639 | "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" 2640 | }, 2641 | "repeat-string": { 2642 | "version": "1.6.1", 2643 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 2644 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 2645 | }, 2646 | "resolve": { 2647 | "version": "1.17.0", 2648 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 2649 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 2650 | "requires": { 2651 | "path-parse": "^1.0.6" 2652 | } 2653 | }, 2654 | "resolve-url": { 2655 | "version": "0.2.1", 2656 | "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", 2657 | "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" 2658 | }, 2659 | "ret": { 2660 | "version": "0.1.15", 2661 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 2662 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" 2663 | }, 2664 | "rfdc": { 2665 | "version": "1.1.4", 2666 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", 2667 | "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==" 2668 | }, 2669 | "rimraf": { 2670 | "version": "3.0.2", 2671 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2672 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2673 | "requires": { 2674 | "glob": "^7.1.3" 2675 | } 2676 | }, 2677 | "safe-buffer": { 2678 | "version": "5.1.2", 2679 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2680 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 2681 | }, 2682 | "safe-regex": { 2683 | "version": "1.1.0", 2684 | "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", 2685 | "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", 2686 | "requires": { 2687 | "ret": "~0.1.10" 2688 | } 2689 | }, 2690 | "sax": { 2691 | "version": "1.2.4", 2692 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 2693 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 2694 | }, 2695 | "semver": { 2696 | "version": "7.3.2", 2697 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 2698 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" 2699 | }, 2700 | "set-value": { 2701 | "version": "2.0.1", 2702 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", 2703 | "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", 2704 | "requires": { 2705 | "extend-shallow": "^2.0.1", 2706 | "is-extendable": "^0.1.1", 2707 | "is-plain-object": "^2.0.3", 2708 | "split-string": "^3.0.1" 2709 | }, 2710 | "dependencies": { 2711 | "extend-shallow": { 2712 | "version": "2.0.1", 2713 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2714 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2715 | "requires": { 2716 | "is-extendable": "^0.1.0" 2717 | } 2718 | } 2719 | } 2720 | }, 2721 | "shallow-clone": { 2722 | "version": "0.1.2", 2723 | "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", 2724 | "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", 2725 | "requires": { 2726 | "is-extendable": "^0.1.1", 2727 | "kind-of": "^2.0.1", 2728 | "lazy-cache": "^0.2.3", 2729 | "mixin-object": "^2.0.1" 2730 | }, 2731 | "dependencies": { 2732 | "kind-of": { 2733 | "version": "2.0.1", 2734 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", 2735 | "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", 2736 | "requires": { 2737 | "is-buffer": "^1.0.2" 2738 | } 2739 | }, 2740 | "lazy-cache": { 2741 | "version": "0.2.7", 2742 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", 2743 | "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=" 2744 | } 2745 | } 2746 | }, 2747 | "shelljs": { 2748 | "version": "0.8.4", 2749 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", 2750 | "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", 2751 | "requires": { 2752 | "glob": "^7.0.0", 2753 | "interpret": "^1.0.0", 2754 | "rechoir": "^0.6.2" 2755 | } 2756 | }, 2757 | "snapdragon": { 2758 | "version": "0.8.2", 2759 | "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", 2760 | "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", 2761 | "requires": { 2762 | "base": "^0.11.1", 2763 | "debug": "^2.2.0", 2764 | "define-property": "^0.2.5", 2765 | "extend-shallow": "^2.0.1", 2766 | "map-cache": "^0.2.2", 2767 | "source-map": "^0.5.6", 2768 | "source-map-resolve": "^0.5.0", 2769 | "use": "^3.1.0" 2770 | }, 2771 | "dependencies": { 2772 | "debug": { 2773 | "version": "2.6.9", 2774 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2775 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2776 | "requires": { 2777 | "ms": "2.0.0" 2778 | } 2779 | }, 2780 | "define-property": { 2781 | "version": "0.2.5", 2782 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2783 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2784 | "requires": { 2785 | "is-descriptor": "^0.1.0" 2786 | } 2787 | }, 2788 | "extend-shallow": { 2789 | "version": "2.0.1", 2790 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2791 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2792 | "requires": { 2793 | "is-extendable": "^0.1.0" 2794 | } 2795 | }, 2796 | "ms": { 2797 | "version": "2.0.0", 2798 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2799 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 2800 | } 2801 | } 2802 | }, 2803 | "snapdragon-node": { 2804 | "version": "2.1.1", 2805 | "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", 2806 | "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", 2807 | "requires": { 2808 | "define-property": "^1.0.0", 2809 | "isobject": "^3.0.0", 2810 | "snapdragon-util": "^3.0.1" 2811 | }, 2812 | "dependencies": { 2813 | "define-property": { 2814 | "version": "1.0.0", 2815 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 2816 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 2817 | "requires": { 2818 | "is-descriptor": "^1.0.0" 2819 | } 2820 | }, 2821 | "is-accessor-descriptor": { 2822 | "version": "1.0.0", 2823 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 2824 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 2825 | "requires": { 2826 | "kind-of": "^6.0.0" 2827 | } 2828 | }, 2829 | "is-data-descriptor": { 2830 | "version": "1.0.0", 2831 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 2832 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 2833 | "requires": { 2834 | "kind-of": "^6.0.0" 2835 | } 2836 | }, 2837 | "is-descriptor": { 2838 | "version": "1.0.2", 2839 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 2840 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 2841 | "requires": { 2842 | "is-accessor-descriptor": "^1.0.0", 2843 | "is-data-descriptor": "^1.0.0", 2844 | "kind-of": "^6.0.2" 2845 | } 2846 | } 2847 | } 2848 | }, 2849 | "snapdragon-util": { 2850 | "version": "3.0.1", 2851 | "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", 2852 | "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", 2853 | "requires": { 2854 | "kind-of": "^3.2.0" 2855 | }, 2856 | "dependencies": { 2857 | "kind-of": { 2858 | "version": "3.2.2", 2859 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2860 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2861 | "requires": { 2862 | "is-buffer": "^1.1.5" 2863 | } 2864 | } 2865 | } 2866 | }, 2867 | "sorted-array-functions": { 2868 | "version": "1.2.0", 2869 | "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.2.0.tgz", 2870 | "integrity": "sha512-sWpjPhIZJtqO77GN+LD8dDsDKcWZ9GCOJNqKzi1tvtjGIzwfoyuRH8S0psunmc6Z5P+qfDqztSbwYR5X/e1UTg==" 2871 | }, 2872 | "source-map": { 2873 | "version": "0.5.7", 2874 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2875 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 2876 | }, 2877 | "source-map-resolve": { 2878 | "version": "0.5.2", 2879 | "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", 2880 | "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", 2881 | "requires": { 2882 | "atob": "^2.1.1", 2883 | "decode-uri-component": "^0.2.0", 2884 | "resolve-url": "^0.2.1", 2885 | "source-map-url": "^0.4.0", 2886 | "urix": "^0.1.0" 2887 | } 2888 | }, 2889 | "source-map-url": { 2890 | "version": "0.4.0", 2891 | "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", 2892 | "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" 2893 | }, 2894 | "sparkline": { 2895 | "version": "0.1.2", 2896 | "resolved": "https://registry.npmjs.org/sparkline/-/sparkline-0.1.2.tgz", 2897 | "integrity": "sha1-w73kYlKxNU5xDEsgDVSBa9nwejI=", 2898 | "requires": { 2899 | "here": "0.0.2", 2900 | "nopt": "~2.1.2" 2901 | } 2902 | }, 2903 | "split-string": { 2904 | "version": "3.1.0", 2905 | "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", 2906 | "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", 2907 | "requires": { 2908 | "extend-shallow": "^3.0.0" 2909 | } 2910 | }, 2911 | "sqlstring": { 2912 | "version": "2.3.1", 2913 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", 2914 | "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" 2915 | }, 2916 | "ssf": { 2917 | "version": "0.11.2", 2918 | "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", 2919 | "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", 2920 | "requires": { 2921 | "frac": "~1.1.2" 2922 | } 2923 | }, 2924 | "standard-as-callback": { 2925 | "version": "2.0.1", 2926 | "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", 2927 | "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" 2928 | }, 2929 | "static-extend": { 2930 | "version": "0.1.2", 2931 | "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", 2932 | "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", 2933 | "requires": { 2934 | "define-property": "^0.2.5", 2935 | "object-copy": "^0.1.0" 2936 | }, 2937 | "dependencies": { 2938 | "define-property": { 2939 | "version": "0.2.5", 2940 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2941 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2942 | "requires": { 2943 | "is-descriptor": "^0.1.0" 2944 | } 2945 | } 2946 | } 2947 | }, 2948 | "streamroller": { 2949 | "version": "2.2.4", 2950 | "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", 2951 | "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", 2952 | "requires": { 2953 | "date-format": "^2.1.0", 2954 | "debug": "^4.1.1", 2955 | "fs-extra": "^8.1.0" 2956 | }, 2957 | "dependencies": { 2958 | "date-format": { 2959 | "version": "2.1.0", 2960 | "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", 2961 | "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==" 2962 | }, 2963 | "fs-extra": { 2964 | "version": "8.1.0", 2965 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 2966 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 2967 | "requires": { 2968 | "graceful-fs": "^4.2.0", 2969 | "jsonfile": "^4.0.0", 2970 | "universalify": "^0.1.0" 2971 | } 2972 | }, 2973 | "jsonfile": { 2974 | "version": "4.0.0", 2975 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 2976 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 2977 | "requires": { 2978 | "graceful-fs": "^4.1.6" 2979 | } 2980 | }, 2981 | "universalify": { 2982 | "version": "0.1.2", 2983 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 2984 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" 2985 | } 2986 | } 2987 | }, 2988 | "string_decoder": { 2989 | "version": "1.1.1", 2990 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2991 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2992 | "requires": { 2993 | "safe-buffer": "~5.1.0" 2994 | } 2995 | }, 2996 | "strip-ansi": { 2997 | "version": "3.0.1", 2998 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 2999 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 3000 | "requires": { 3001 | "ansi-regex": "^2.0.0" 3002 | } 3003 | }, 3004 | "superagent": { 3005 | "version": "5.3.1", 3006 | "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", 3007 | "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", 3008 | "requires": { 3009 | "component-emitter": "^1.3.0", 3010 | "cookiejar": "^2.1.2", 3011 | "debug": "^4.1.1", 3012 | "fast-safe-stringify": "^2.0.7", 3013 | "form-data": "^3.0.0", 3014 | "formidable": "^1.2.2", 3015 | "methods": "^1.1.2", 3016 | "mime": "^2.4.6", 3017 | "qs": "^6.9.4", 3018 | "readable-stream": "^3.6.0", 3019 | "semver": "^7.3.2" 3020 | }, 3021 | "dependencies": { 3022 | "readable-stream": { 3023 | "version": "3.6.0", 3024 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 3025 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 3026 | "requires": { 3027 | "inherits": "^2.0.3", 3028 | "string_decoder": "^1.1.1", 3029 | "util-deprecate": "^1.0.1" 3030 | } 3031 | } 3032 | } 3033 | }, 3034 | "supports-color": { 3035 | "version": "2.0.0", 3036 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 3037 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 3038 | }, 3039 | "supports-hyperlinks": { 3040 | "version": "2.1.0", 3041 | "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz", 3042 | "integrity": "sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==", 3043 | "requires": { 3044 | "has-flag": "^4.0.0", 3045 | "supports-color": "^7.0.0" 3046 | }, 3047 | "dependencies": { 3048 | "supports-color": { 3049 | "version": "7.1.0", 3050 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 3051 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 3052 | "requires": { 3053 | "has-flag": "^4.0.0" 3054 | } 3055 | } 3056 | } 3057 | }, 3058 | "tar-fs": { 3059 | "version": "2.1.1", 3060 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 3061 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 3062 | "requires": { 3063 | "chownr": "^1.1.1", 3064 | "mkdirp-classic": "^0.5.2", 3065 | "pump": "^3.0.0", 3066 | "tar-stream": "^2.1.4" 3067 | } 3068 | }, 3069 | "tar-stream": { 3070 | "version": "2.1.4", 3071 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", 3072 | "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", 3073 | "requires": { 3074 | "bl": "^4.0.3", 3075 | "end-of-stream": "^1.4.1", 3076 | "fs-constants": "^1.0.0", 3077 | "inherits": "^2.0.3", 3078 | "readable-stream": "^3.1.1" 3079 | }, 3080 | "dependencies": { 3081 | "readable-stream": { 3082 | "version": "3.6.0", 3083 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 3084 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 3085 | "requires": { 3086 | "inherits": "^2.0.3", 3087 | "string_decoder": "^1.1.1", 3088 | "util-deprecate": "^1.0.1" 3089 | } 3090 | } 3091 | } 3092 | }, 3093 | "term-canvas": { 3094 | "version": "0.0.5", 3095 | "resolved": "https://registry.npmjs.org/term-canvas/-/term-canvas-0.0.5.tgz", 3096 | "integrity": "sha1-WXr6wvpjaabxeGC86cX2bW6gypY=" 3097 | }, 3098 | "think-cache": { 3099 | "version": "1.1.1", 3100 | "resolved": "https://registry.npmjs.org/think-cache/-/think-cache-1.1.1.tgz", 3101 | "integrity": "sha512-94UiU4DkUUE8jwI0XTgeQC4gkyyI3h1NP0uJuvIintALAwmLOYP47KUjsjlNxRmnCxHt7gnrEiMRk6rGcda00w==", 3102 | "requires": { 3103 | "think-debounce": "^1.0.0", 3104 | "think-helper": "^1.0.0" 3105 | } 3106 | }, 3107 | "think-debounce": { 3108 | "version": "1.0.4", 3109 | "resolved": "https://registry.npmjs.org/think-debounce/-/think-debounce-1.0.4.tgz", 3110 | "integrity": "sha512-DWRFd3dQEGKK1Mh5kENsVA0+O12NxJbFRKk6X3cxpK0aplPQDFbdrfyS+C2Z2jomt1RbPniXUt0mGh1YrNGbAQ==" 3111 | }, 3112 | "think-helper": { 3113 | "version": "1.1.2", 3114 | "resolved": "https://registry.npmjs.org/think-helper/-/think-helper-1.1.2.tgz", 3115 | "integrity": "sha512-4VIXTKpCXtwPMaN6T+1d2PDCZ4Z9xeU/ruK3zslkDijH2E2ecbssqhXnGMfcEwlI6Mil9KMYUnFoBCOXoc8zGA==", 3116 | "requires": { 3117 | "core-util-is": "^1.0.2", 3118 | "ms": "^1.0.0", 3119 | "uuid": "^3.0.1" 3120 | }, 3121 | "dependencies": { 3122 | "ms": { 3123 | "version": "1.0.0", 3124 | "resolved": "https://registry.npmjs.org/ms/-/ms-1.0.0.tgz", 3125 | "integrity": "sha1-Wa3NIu3FQ/e1OBhi0xOHsfS8lHM=" 3126 | } 3127 | } 3128 | }, 3129 | "think-instance": { 3130 | "version": "1.0.1", 3131 | "resolved": "https://registry.npmjs.org/think-instance/-/think-instance-1.0.1.tgz", 3132 | "integrity": "sha1-O98R7xpKo7zDtKHKLcX3AsJ9HTg=", 3133 | "requires": { 3134 | "think-helper": "^1.0.0" 3135 | } 3136 | }, 3137 | "think-model": { 3138 | "version": "1.5.1", 3139 | "resolved": "https://registry.npmjs.org/think-model/-/think-model-1.5.1.tgz", 3140 | "integrity": "sha512-N6I5gNDLmrIC7LdiXQVV/KUaB63i8xAKuBrz07szrFRpNaj5rJy9LRDbswQMndZ/gbK+JE9fMqD5Gy/GVWN2SA==", 3141 | "requires": { 3142 | "think-cache": "^1.0.7", 3143 | "think-debounce": "^1.0.3", 3144 | "think-helper": "^1.0.22", 3145 | "think-model-abstract": "^1.2.0" 3146 | } 3147 | }, 3148 | "think-model-abstract": { 3149 | "version": "1.6.2", 3150 | "resolved": "https://registry.npmjs.org/think-model-abstract/-/think-model-abstract-1.6.2.tgz", 3151 | "integrity": "sha512-APhllbwqIv+I6AjQakdgA3W8qyL6IDcedIEhpx8RrEXpaI7KDJXYMPftopbfySK8TdVqU4v9Ud8jmMsP1Qlgrw==", 3152 | "requires": { 3153 | "debug": "^3.0.0", 3154 | "think-helper": "^1.0.5" 3155 | }, 3156 | "dependencies": { 3157 | "debug": { 3158 | "version": "3.2.6", 3159 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 3160 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 3161 | "requires": { 3162 | "ms": "^2.1.1" 3163 | } 3164 | } 3165 | } 3166 | }, 3167 | "think-model-mysql": { 3168 | "version": "1.1.2", 3169 | "resolved": "https://registry.npmjs.org/think-model-mysql/-/think-model-mysql-1.1.2.tgz", 3170 | "integrity": "sha512-BYBpLYFJTvHedQuLIOsFPmK7OaYpKZSaoy9AUcgGRWSuCMX9UUoqexC60LAqiyHheGguJCKjGRGq1mx3n4v5vg==", 3171 | "requires": { 3172 | "think-debounce": "^1.0.4", 3173 | "think-helper": "^1.1.2", 3174 | "think-model-abstract": "^1.2.2", 3175 | "think-mysql": "^1.2.4" 3176 | } 3177 | }, 3178 | "think-mysql": { 3179 | "version": "1.4.3", 3180 | "resolved": "https://registry.npmjs.org/think-mysql/-/think-mysql-1.4.3.tgz", 3181 | "integrity": "sha512-u+WFrOAz9/usUJ68QbAkAzlncp67R8bAZVqlE0E6FGrSoE3M8evsyNC9XU8zN3O4lTXRkd0uytkSDKzlSCNCHA==", 3182 | "requires": { 3183 | "debug": "^2.6.4", 3184 | "mysql": "^2.16.0", 3185 | "think-debounce": "^1.0.3", 3186 | "think-helper": "^1.0.5", 3187 | "think-instance": "^1.0.0" 3188 | }, 3189 | "dependencies": { 3190 | "debug": { 3191 | "version": "2.6.9", 3192 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 3193 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 3194 | "requires": { 3195 | "ms": "2.0.0" 3196 | } 3197 | }, 3198 | "ms": { 3199 | "version": "2.0.0", 3200 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 3201 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 3202 | } 3203 | } 3204 | }, 3205 | "through": { 3206 | "version": "2.3.8", 3207 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 3208 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 3209 | }, 3210 | "to-object-path": { 3211 | "version": "0.3.0", 3212 | "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", 3213 | "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", 3214 | "requires": { 3215 | "kind-of": "^3.0.2" 3216 | }, 3217 | "dependencies": { 3218 | "kind-of": { 3219 | "version": "3.2.2", 3220 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 3221 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 3222 | "requires": { 3223 | "is-buffer": "^1.1.5" 3224 | } 3225 | } 3226 | } 3227 | }, 3228 | "to-regex": { 3229 | "version": "3.0.2", 3230 | "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", 3231 | "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", 3232 | "requires": { 3233 | "define-property": "^2.0.2", 3234 | "extend-shallow": "^3.0.2", 3235 | "regex-not": "^1.0.2", 3236 | "safe-regex": "^1.1.0" 3237 | } 3238 | }, 3239 | "to-regex-range": { 3240 | "version": "2.1.1", 3241 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", 3242 | "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", 3243 | "requires": { 3244 | "is-number": "^3.0.0", 3245 | "repeat-string": "^1.6.1" 3246 | } 3247 | }, 3248 | "type-fest": { 3249 | "version": "0.11.0", 3250 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", 3251 | "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" 3252 | }, 3253 | "unbzip2-stream": { 3254 | "version": "1.4.3", 3255 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 3256 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 3257 | "requires": { 3258 | "buffer": "^5.2.1", 3259 | "through": "^2.3.8" 3260 | } 3261 | }, 3262 | "underscore": { 3263 | "version": "1.4.4", 3264 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", 3265 | "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=" 3266 | }, 3267 | "union-value": { 3268 | "version": "1.0.1", 3269 | "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", 3270 | "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", 3271 | "requires": { 3272 | "arr-union": "^3.1.0", 3273 | "get-value": "^2.0.6", 3274 | "is-extendable": "^0.1.1", 3275 | "set-value": "^2.0.1" 3276 | } 3277 | }, 3278 | "universalify": { 3279 | "version": "1.0.0", 3280 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", 3281 | "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" 3282 | }, 3283 | "unset-value": { 3284 | "version": "1.0.0", 3285 | "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", 3286 | "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", 3287 | "requires": { 3288 | "has-value": "^0.3.1", 3289 | "isobject": "^3.0.0" 3290 | }, 3291 | "dependencies": { 3292 | "has-value": { 3293 | "version": "0.3.1", 3294 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", 3295 | "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", 3296 | "requires": { 3297 | "get-value": "^2.0.3", 3298 | "has-values": "^0.1.4", 3299 | "isobject": "^2.0.0" 3300 | }, 3301 | "dependencies": { 3302 | "isobject": { 3303 | "version": "2.1.0", 3304 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", 3305 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", 3306 | "requires": { 3307 | "isarray": "1.0.0" 3308 | } 3309 | } 3310 | } 3311 | }, 3312 | "has-values": { 3313 | "version": "0.1.4", 3314 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", 3315 | "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" 3316 | } 3317 | } 3318 | }, 3319 | "upath": { 3320 | "version": "1.2.0", 3321 | "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", 3322 | "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" 3323 | }, 3324 | "urix": { 3325 | "version": "0.1.0", 3326 | "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", 3327 | "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" 3328 | }, 3329 | "use": { 3330 | "version": "3.1.1", 3331 | "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", 3332 | "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" 3333 | }, 3334 | "util-deprecate": { 3335 | "version": "1.0.2", 3336 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 3337 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 3338 | }, 3339 | "uuid": { 3340 | "version": "3.4.0", 3341 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 3342 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 3343 | }, 3344 | "wmf": { 3345 | "version": "1.0.2", 3346 | "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", 3347 | "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==" 3348 | }, 3349 | "word": { 3350 | "version": "0.3.0", 3351 | "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", 3352 | "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==" 3353 | }, 3354 | "wordwrap": { 3355 | "version": "0.0.3", 3356 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 3357 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 3358 | }, 3359 | "wrappy": { 3360 | "version": "1.0.2", 3361 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3362 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 3363 | }, 3364 | "ws": { 3365 | "version": "7.4.1", 3366 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", 3367 | "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==" 3368 | }, 3369 | "x256": { 3370 | "version": "0.0.2", 3371 | "resolved": "https://registry.npmjs.org/x256/-/x256-0.0.2.tgz", 3372 | "integrity": "sha1-ya8Yh296F1gB1WT+cK2egxd4STQ=" 3373 | }, 3374 | "xlsx": { 3375 | "version": "0.16.4", 3376 | "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.16.4.tgz", 3377 | "integrity": "sha512-l1xqTdXRK3DCxkxHGj3OxZM1ertzeqjWodi0jevBNSivoyYMPEJAHhVW7BAfM3gFXK35dCM0CacGUXbATdFvqQ==", 3378 | "requires": { 3379 | "adler-32": "~1.2.0", 3380 | "cfb": "^1.1.4", 3381 | "codepage": "~1.14.0", 3382 | "commander": "~2.17.1", 3383 | "crc-32": "~1.2.0", 3384 | "exit-on-epipe": "~1.0.1", 3385 | "ssf": "~0.11.2", 3386 | "wmf": "~1.0.1", 3387 | "word": "~0.3.0" 3388 | } 3389 | }, 3390 | "xml2js": { 3391 | "version": "0.4.23", 3392 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 3393 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 3394 | "requires": { 3395 | "sax": ">=0.6.0", 3396 | "xmlbuilder": "~11.0.0" 3397 | } 3398 | }, 3399 | "xmlbuilder": { 3400 | "version": "11.0.1", 3401 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 3402 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 3403 | }, 3404 | "yauzl": { 3405 | "version": "2.10.0", 3406 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 3407 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 3408 | "requires": { 3409 | "buffer-crc32": "~0.2.3", 3410 | "fd-slicer": "~1.1.0" 3411 | } 3412 | } 3413 | } 3414 | } 3415 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sparender", 3 | "version": "2.0.1", 4 | "description": "动态渲染SPA站点, 为搜索引擎提供JavaScript站点SEO优化方案", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node development.js", 8 | "testing": "node testing.js", 9 | "monit": "LANG=en_US.utf8 TERM=xterm-256color node ./src/common/monit/index.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/zuoyanart/sparender" 14 | }, 15 | "author": "左盐", 16 | "license": "ISC", 17 | "dependencies": { 18 | "bignumber.js": "^9.0.0", 19 | "blessed": "^0.1.81", 20 | "blessed-contrib": "^4.8.20", 21 | "cheerio": "^1.0.0-rc.3", 22 | "dayjs": "^1.9.1", 23 | "fs-extra": "^9.0.1", 24 | "generic-pool": "^3.7.1", 25 | "hmacsha1": "^1.0.0", 26 | "ioredis": "^4.19.2", 27 | "is-empty": "^1.2.0", 28 | "kleur": "^4.0.2", 29 | "log4js": "^6.3.0", 30 | "nedb-promises": "^4.1.0", 31 | "node-schedule": "^1.3.2", 32 | "nodejs-tail": "^1.1.0", 33 | "nodemailer": "^6.4.11", 34 | "pending-xhr-puppeteer": "^2.3.2", 35 | "puppeteer": "^5.5.0", 36 | "puppeteer-extra": "^3.1.15", 37 | "puppeteer-extra-plugin-stealth": "^2.6.5", 38 | "shelljs": "^0.8.4", 39 | "superagent": "^5.3.1", 40 | "think-model": "^1.5.1", 41 | "think-model-mysql": "^1.1.2", 42 | "xlsx": "^0.16.4" 43 | }, 44 | "devDependencies": { 45 | "eslint-plugin-promise": "^4.2.1" 46 | } 47 | } -------------------------------------------------------------------------------- /pm2.json: -------------------------------------------------------------------------------- 1 | { 2 | "apps": [{ 3 | "name": "sparender3001", 4 | "script": "production.js", 5 | "cwd": "./", 6 | "exec_mode": "fork", 7 | "instances": 1, 8 | "max_memory_restart": "1G", 9 | "autorestart": true, 10 | "node_args": [], 11 | "args": [], 12 | "env": { 13 | 14 | } 15 | }] 16 | } -------------------------------------------------------------------------------- /production.js: -------------------------------------------------------------------------------- 1 | const app = require('./src/common/app'); 2 | app.start('production'); -------------------------------------------------------------------------------- /runtime/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuoyanart/sparender/06f59c7ea23bcce34de2aea7cc7bbfa8b9cfd186/runtime/.gitkeep -------------------------------------------------------------------------------- /runtime/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuoyanart/sparender/06f59c7ea23bcce34de2aea7cc7bbfa8b9cfd186/runtime/logs/.gitkeep -------------------------------------------------------------------------------- /src/common/app.js: -------------------------------------------------------------------------------- 1 | const Tools = require('./tools'); 2 | const Logger = require('./logger/logger'); 3 | const path = require('path'); 4 | const Model = require('think-model/lib/model'); 5 | const Service = require('./service.js'); 6 | const Controller = require('./controller'); 7 | const Entry = require('./entry'); 8 | const taskCheck = require('./taskCheck/index'); 9 | const Redis = require('ioredis'); 10 | 11 | 12 | 13 | async function start(env) { 14 | global.tools = new Tools(env); //注册全局helper函数 15 | global.logger = new Logger(env); //注册全局日志函数 16 | global.taskCheck = new taskCheck(path.resolve(__dirname, '../../src/common/taskCheck/task.db')); 17 | if (tools.config('redis')) { 18 | global.zyRedis = new Redis(tools.config('redis')); 19 | } 20 | global.zuoyan = { 21 | env, 22 | ROOT_PATH: path.resolve(__dirname, '../../'), 23 | RUNTIME_PATH: path.resolve(__dirname, '../../runtime'), 24 | SRC_PATH: path.resolve(__dirname, '../../src'), 25 | db: {}, 26 | Model, 27 | Service, 28 | Controller, 29 | Entry 30 | }; 31 | // const load = require('./common/loader'); 32 | // const loader = new load(); 33 | // loader.loadMysql(env); 34 | 35 | //所有的任务调度状态被重置为待执行 36 | await global.taskCheck.init(); 37 | 38 | try { 39 | const Index = require('../index'); 40 | const index = new Index(env); 41 | await index.start(env); 42 | } catch (e) { 43 | logger.error(e); 44 | } 45 | }; 46 | 47 | const App = { 48 | start 49 | }; 50 | 51 | module.exports = App; -------------------------------------------------------------------------------- /src/common/controller.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | module.exports = class service { 3 | constructor() { 4 | 5 | } 6 | /** 7 | * 8 | * @param {*} name 9 | * @param {*} config 10 | */ 11 | service(name = '', ...args) { 12 | // console.log(path.join(zuoyan.ROOT_PATH, './model/' + name)); 13 | const s = require(path.join(zuoyan.SRC_PATH, './service/' + name)); 14 | return new s(...args); 15 | } 16 | 17 | /** 18 | * 19 | * @param {*} name 20 | * @param {*} config 21 | */ 22 | model(name = '', modelConfig = '') { 23 | const dataBaseconfig = tools.config('database'); 24 | if (tools.isEmpty(modelConfig)) { 25 | modelConfig = 'mysql'; 26 | } 27 | modelConfig = Object.assign(dataBaseconfig[modelConfig], dataBaseconfig.common); 28 | const m = require(path.join(zuoyan.SRC_PATH, './model/' + name)); 29 | const modePath = name.split('/'); 30 | return new m(modePath[modePath.length - 1], modelConfig); 31 | } 32 | }; -------------------------------------------------------------------------------- /src/common/entry.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | module.exports = class service { 3 | constructor() { 4 | 5 | } 6 | /** 7 | * 8 | * @param {*} name 9 | * @param {*} config 10 | */ 11 | controller(name = '', ...args) { 12 | const s = require(path.join(zuoyan.SRC_PATH, './controller/' + name)); 13 | return new s(...args); 14 | } 15 | /** 16 | * 17 | * @param {*} name 18 | * @param {*} config 19 | */ 20 | service(name = '', ...args) { 21 | const s = require(path.join(zuoyan.SRC_PATH, './service/' + name)); 22 | return new s(...args); 23 | } 24 | }; -------------------------------------------------------------------------------- /src/common/logger/logger.js: -------------------------------------------------------------------------------- 1 | const log4js = require('log4js'); 2 | 3 | module.exports = class { 4 | constructor(env = 'production') { 5 | this.env = env; 6 | log4js.configure({ 7 | appenders: { 8 | file: { 9 | type: 'file', 10 | filename: __dirname + '/../../../runtime/logs/app.log', 11 | maxLogSize: 31457280, // = 30Mb 12 | numBackups: 10, // keep five backup files 13 | compress: false, // compress the backups 14 | encoding: 'utf-8', 15 | }, 16 | dateFile: { 17 | type: 'dateFile', 18 | filename: __dirname + '/../../../runtime/logs/app', 19 | alwaysIncludePattern: true, 20 | maxLogSize: 31457280, // = 30Mb 21 | pattern: 'yyyy-MM-dd.log', 22 | compress: false, 23 | daysToKeep: 30, 24 | layout: { 25 | type: 'pattern', 26 | pattern: '%r %p - %m', 27 | } 28 | }, 29 | console: { 30 | type: 'console' 31 | } 32 | }, 33 | categories: { 34 | default: { 35 | appenders: ['console'], 36 | level: 'all' 37 | }, 38 | file: { 39 | appenders: ['file'], 40 | level: 'info' 41 | }, 42 | dateFile: { 43 | appenders: ['dateFile'], 44 | level: 'debug' 45 | }, 46 | } 47 | }); 48 | const dev = (env === 'production'); 49 | const output = dev ? 'dateFile' : 'default'; 50 | this.logger = log4js.getLogger(output); 51 | } 52 | 53 | trace(...str) { 54 | this.logger.trace(...str); 55 | } 56 | 57 | debug(...str) { 58 | this.logger.debug(...str); 59 | } 60 | 61 | info(...str) { 62 | this.logger.info(...str); 63 | } 64 | 65 | warn(...str) { 66 | this.logger.warn(...str); 67 | } 68 | 69 | sql(...str) { 70 | if (this.env === 'development') { 71 | this.logger.warn(...str); 72 | } 73 | } 74 | 75 | error(...str) { 76 | this.logger.error(...str); 77 | } 78 | 79 | fatal(...str) { 80 | this.logger.fatal(...str); 81 | } 82 | 83 | }; -------------------------------------------------------------------------------- /src/common/monit/index.js: -------------------------------------------------------------------------------- 1 | const blessed = require('blessed'); 2 | const contrib = require('blessed-contrib'); 3 | const Datastore = require('nedb-promises'); 4 | const Nedb = require('./nedb'); 5 | const Tools = require('./tools'); 6 | const Tail = require('nodejs-tail'); 7 | const path = require('path'); 8 | 9 | class Monit { 10 | constructor() { 11 | this.tools = new Tools(); 12 | // this.logTail = 13 | //// 14 | this.screen = blessed.screen({ 15 | fullUnicode: true 16 | }); 17 | this.grid = new contrib.grid({ 18 | rows: 12, 19 | cols: 12, 20 | screen: this.screen 21 | }); 22 | this.screen.key(['escape', 'q', 'C-c'], function (ch, key) { 23 | 24 | return process.exit(0); 25 | }); 26 | } 27 | 28 | /** 29 | * 30 | */ 31 | async start() { 32 | //布局 33 | this.screen.render(); 34 | //运行状态 35 | await this.runStatus(); 36 | await this.runLog(); 37 | } 38 | //运行状态 39 | async runStatus() { 40 | let table = this.grid.set(0, 0, 5, 12, contrib.table, { 41 | keys: true, 42 | fg: 'white', 43 | selectedFg: 'white', 44 | selectedBg: 'blue', 45 | interactive: true, 46 | label: 'runtime', 47 | width: '100%', 48 | height: '100%', 49 | border: { 50 | type: "line", 51 | fg: "cyan" 52 | }, 53 | columnSpacing: 1, //in chars, 54 | columnWidth: [30, 30, 20] /*in chars*/ 55 | }); 56 | 57 | table.focus(); 58 | this.screen.append(table) 59 | 60 | setInterval(async () => { 61 | const nedb = new Nedb(); 62 | const taskList = await nedb.pageAll(); 63 | let tableData = []; 64 | for (let i = 0, len = taskList.length; i < len; i++) { 65 | const item = [taskList[i].name, this.tools.formatTime(taskList[i].lasttime, 'MM-DD HH:mm:ss'), taskList[i].isexe === 1 ? 'run' : 'sleep']; 66 | tableData.push(item); 67 | 68 | } 69 | table.setData({ 70 | headers: ['name', 'lastTime', 'state'], 71 | data: tableData 72 | }); 73 | this.screen.render(); 74 | }, 1000); 75 | } 76 | 77 | async runLog() { 78 | const log = this.grid.set(5, 0, 7, 12, contrib.log, { 79 | fg: "green", 80 | selectedFg: "green", 81 | label: 'Runtime Log', 82 | height: "20%", 83 | tags: true, 84 | border: { 85 | type: "line", 86 | fg: "cyan" 87 | } 88 | 89 | }); 90 | this.screen.append(log); 91 | const tail = new Tail(path.resolve('.', './runtime/logs/app.' + this.tools.formatTime(this.tools.getUnixTime(), 'YYYY-MM-DD') + '.log')); 92 | 93 | tail.on('line', (line) => { 94 | log.log(line); 95 | }); 96 | tail.watch(); 97 | 98 | } 99 | }; 100 | 101 | const moint = new Monit(); 102 | moint.start(); -------------------------------------------------------------------------------- /src/common/monit/nedb.js: -------------------------------------------------------------------------------- 1 | const Datastore = require('nedb-promises'); 2 | const path = require('path'); 3 | 4 | module.exports = class { 5 | constructor() { 6 | this.dataSource = Datastore.create(path.resolve('.', './src/common/taskCheck/task.db')); 7 | } 8 | 9 | /** 10 | * 获取任务信息 11 | * @param {*} name 12 | */ 13 | async pageAll() { 14 | try { 15 | let doc = await this.dataSource.find({}).sort({ 16 | 'create_time': -1 17 | }); 18 | return doc; 19 | } catch (e) { 20 | return []; 21 | } 22 | } 23 | 24 | }; -------------------------------------------------------------------------------- /src/common/monit/tools.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @Author: 左盐 3 | * @Date: 2017-12-03 16:44:45 4 | * @Email: huabinglan@163.com 5 | * @Project: xxxx 6 | * @Last modified by: 左盐 7 | * @Last modified time: 2018-06-06 22:57:30 8 | */ 9 | 10 | const fs = require('fs-extra'); // fs 11 | const superagent = require('superagent'); // 爬虫 12 | const crypto = require('crypto'); // 加密 13 | const dayjs = require('dayjs'); // 时间处理 14 | const hmacsha1 = require('hmacsha1'); // 时间处理 15 | const empty = require('is-empty'); 16 | const BigNumber = require('bignumber.js'); 17 | 18 | module.exports = class { 19 | constructor() { 20 | 21 | } 22 | /** 23 | * 24 | * @param {*} ms 25 | */ 26 | sleep(ms) { // 等待一段时间 27 | return new Promise(resolve => setTimeout(resolve, ms)); 28 | }; 29 | /** 30 | * 读取文件 31 | * @method readFile 32 | * @param {[type]} filePath 文件路径 33 | * @return {[Promise]} [description] 34 | */ 35 | readJsonFile(filePath) { 36 | fs.ensureFileSync(filePath); 37 | try { 38 | return fs.readJsonSync(filePath); 39 | } catch (e) { 40 | return {}; //fs.readFileSync(filePath); 41 | } 42 | }; 43 | /** 44 | * 写入文件 45 | * @method writeFile 46 | * @param {[type]} filePath [description] 47 | * @param {[type]} data [description] 48 | * @return {[type]} [description] 49 | */ 50 | writeJsonFile(filePath, data) { 51 | fs.ensureFileSync(filePath); 52 | fs.writeJsonSync(filePath, data); 53 | }; 54 | /** 55 | * 获取文件字符编码 56 | * @param {*} filePath 57 | */ 58 | async checkFileEncode(filePath) { 59 | let encoding = 'utf81'; 60 | const readable = fs.createReadStream(filePath, { 61 | encoding: null, 62 | start: 0, 63 | end: 30 64 | }); 65 | readable.on('data', (chunk) => { 66 | const item1 = chunk[0].toString(16); 67 | const item2 = chunk[1].toString(16); 68 | if (item1 === 'ef' && item2 === 'bb') { 69 | encoding = 'utf8'; 70 | } else if (item1 === 'bf' && item2 === 'cd') { 71 | encoding = 'GB2312'; 72 | } else { 73 | encoding = 'GBK'; 74 | } 75 | }); 76 | readable.on('end', () => { 77 | 78 | }); 79 | await sleep(20); 80 | return encoding; 81 | }; 82 | /** 83 | * http请求 84 | * @method httpAgent 85 | * @param {[type]} url [description] 86 | * @param {[type]} method [description] 87 | * @param {[type]} data [description] 88 | * @return {[type]} [description] 89 | */ 90 | httpAgent(url, method = 'get', data = '') { 91 | method = method.toLowerCase(); 92 | if (method == 'get' || method == 'del') { 93 | return new Promise(function (resolve, reject) { 94 | superagent[method].call(this, url).query(data).end(function (err, res) { 95 | if (err || !res.ok) { 96 | reject(err || res.ok); 97 | } 98 | resolve(res.body); 99 | }); 100 | }); 101 | } else { 102 | return new Promise(function (resolve, reject) { 103 | superagent[method].call(this, url).send(data).end(function (err, res) { 104 | if (err || !res.ok) { 105 | reject(err || res.ok); 106 | } 107 | resolve(res.body); 108 | }); 109 | }); 110 | } 111 | }; 112 | /** 113 | * http请求 114 | * @method httpAgent 115 | * @param {[type]} url [description] 116 | * @param {[type]} method [description] 117 | * @param {[type]} data [description] 118 | * @return {[type]} [description] 119 | */ 120 | httpSpider(url, method = 'get', data = '') { 121 | const startTime = new Date().getTime(); 122 | method = method.toLowerCase(); 123 | if (method == 'get' || method == 'del') { 124 | return new Promise(function (resolve, reject) { 125 | superagent[method].call(this, url).timeout({ 126 | response: 60000 127 | }).query(data).end(function (err, res) { 128 | if (err || !res.ok) { 129 | logger.error(url + '--' + JSON.stringify(data) + '--' + err.message); 130 | reject(err || res.ok); 131 | } 132 | const endTime = new Date().getTime(); 133 | // logger.info('http exe time:' + (endTime - startTime) + 'ms'); 134 | try { 135 | resolve(JSON.parse(res.text)); 136 | } catch (e) { 137 | resolve(res.text); 138 | } 139 | }); 140 | }); 141 | } else { 142 | return new Promise(function (resolve, reject) { 143 | superagent[method].call(this, url).timeout({ 144 | response: 60000 145 | }).send(data).end(function (err, res) { 146 | if (err || !res.ok) { 147 | logger.error(err); 148 | reject(err || res.ok); 149 | } 150 | const endTime = new Date().getTime(); 151 | // logger.info('http exe time:' + (endTime - startTime) + 'ms'); 152 | try { 153 | resolve(JSON.parse(res.text)); 154 | } catch (e) { 155 | try { 156 | resolve(res.text); 157 | } catch (e) { 158 | console.log('res', res); 159 | resolve(res.text); 160 | } 161 | } 162 | }); 163 | }); 164 | } 165 | }; 166 | /** 167 | * 格式化http参数,组合成字符串的形式 168 | * @method formatHttpParam 169 | * @return {[type]} [description] 170 | */ 171 | httpParam(param) { 172 | var s = ''; 173 | for (var key in param) { 174 | s += key + '=' + param[key] + '&'; 175 | } 176 | if (s != '') { 177 | s = s.substring(0, s.length - 1); 178 | } 179 | return s; 180 | }; 181 | /** 182 | * sha1加密 183 | * @param str 将加密的字符串 184 | * @returns {*} 185 | */ 186 | sha1(str) { 187 | return crypto.createHash('sha1').update(str).digest('hex'); 188 | }; 189 | /** 190 | * 生成随机字符串 191 | * @method randomChar 192 | * @return {[type]} [description] 193 | */ 194 | randomChar(len, charType) { 195 | const en = 'qwertyioplkjhgfsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM'; 196 | const number = '0123456789'; 197 | const special = '~!@#$%^&*()_+{}[]:<>,.?'; 198 | let x = en + number; 199 | if (charType == 'number') { 200 | x = number; 201 | } else if (charType == 'en') { 202 | x = en; 203 | } else if (charType === 'special') { 204 | x = en + number + special; 205 | } 206 | let tmp = ''; 207 | for (var i = 0; i < len; i++) { 208 | tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length); 209 | } 210 | return tmp; 211 | }; 212 | /** 213 | * 格式化:201903011024 这种类型的时间为unix时间戳 214 | */ 215 | formatStrTime(timeStr) { 216 | timeStr = timeStr + ''; 217 | const y = timeStr.substring(0, 4); 218 | const M = timeStr.substring(4, 6); 219 | const d = timeStr.substring(6, 8); 220 | const h = timeStr.substring(8, 10); 221 | const m = timeStr.substring(10, 12); 222 | const s = timeStr.substring(12, 14); 223 | const time = y + '-' + M + '-' + d + ' ' + h + ':' + m + ':' + s; 224 | // logger.warn(timeStr, time, Math.round(new Date(time).getTime() / 1000)); 225 | return Math.round(new Date(time).getTime() / 1000); 226 | } 227 | /** 228 | * 获取unix时间 229 | * @method 230 | * @return {[type]} [description] 231 | */ 232 | getUnixTime() { 233 | return Math.round(new Date().getTime() / 1000); 234 | }; 235 | /** 236 | * 获取字符串长度,却分中英文 237 | * @method 238 | * @param {[type]} str [description] 239 | * @return {[type]} [description] 240 | */ 241 | getCharLen(str) { 242 | return str.replace(/[^\x00-\xff]/g, 'rr').length; 243 | }; 244 | /** 245 | * 生成订单id 246 | * @param {*} prix 247 | */ 248 | orderid(prefix = 'OD') { 249 | return prefix + new Date().getTime() + this.randomChar(3).toUpperCase(); 250 | }; 251 | /** 252 | * 截取字符串, 区分中英文 253 | * @param s 254 | * @param l 长度 255 | * @param st 补充的结尾字符 256 | * @returns {*} 257 | */ 258 | subStr(s, l = 200, st = '') { 259 | var T = false; 260 | if (this.getCharLen(s) > l) { 261 | l -= this.getCharLen(st); 262 | var S = escape(s); 263 | var M = S.length; 264 | var r = ''; 265 | var C = 0; 266 | for (var i = 0; i < M; i++) { 267 | if (C < l) { 268 | var t = S.charAt(i); 269 | if (t == '%') { 270 | t = S.charAt(i + 1); 271 | if (t == 'u') { 272 | r += S.substring(i, i + 6); 273 | C += 2; 274 | i += 5; 275 | } else { 276 | r += S.substring(i, i + 3); 277 | C++; 278 | i += 2; 279 | } 280 | } else { 281 | r += t; 282 | C++; 283 | } 284 | } else { 285 | T = true; 286 | break; 287 | } 288 | } 289 | } 290 | return T ? unescape(r) + st : s; 291 | }; 292 | /** 293 | * 时间格式化,传值为unix时间 294 | * @method function 295 | * @param {[type]} format [description] 296 | * @return {[type]} [description] 297 | */ 298 | formatTime(time = tools.getUnixTime(), format = 'YYYY-MM-DD HH:mm:ss') { 299 | if (time.toString().length === 13) { 300 | return dayjs(time).format(format); 301 | } 302 | return dayjs.unix(time).format(format); 303 | }; 304 | /** 305 | * 306 | * @param {*} format 307 | */ 308 | toUnixTime(time) { //2018-12-05 02:07:10 309 | return new Date(time).getTime() / 1000; 310 | } 311 | /** 312 | * 转换value是否是int值,如果不是则用default代替 313 | * @method 314 | * @return {[type]} [description] 315 | */ 316 | getInt(value, def = 0) { 317 | value = parseInt(value); 318 | if (isNaN(value) || value == null) { 319 | return def; 320 | } 321 | return parseInt(value); 322 | }; 323 | 324 | getFloat(value, def = 0) { 325 | value = parseFloat(value); 326 | if (isNaN(value) || value == null) { 327 | return def; 328 | } 329 | return parseFloat(value); 330 | }; 331 | /** 332 | * 去除所有的html代码 333 | * @param {[type]} str = "" [description] 334 | * @return {[type]} [description] 335 | */ 336 | removeHtml(str = '') { 337 | return str.replace(/<[^>]+>/g, '').replace(/ /g, ''); 338 | }; 339 | /** 340 | * 是否是错误对象 341 | * @param {} value 342 | */ 343 | isError(value) { 344 | switch (Object.prototype.toString.call(value)) { 345 | case '[object Error]': 346 | return true; 347 | case '[object Exception]': 348 | return true; 349 | case '[object DOMException]': 350 | return true; 351 | default: 352 | return value instanceof Error; 353 | } 354 | } 355 | /** 356 | * 357 | * @param {*} value 358 | */ 359 | isEmpty(value) { 360 | return empty(value); 361 | } 362 | /** 363 | * 返回状态码等 364 | */ 365 | stateJson(data = '', code = 200) { 366 | return { 367 | code: code, 368 | data: data 369 | }; 370 | }; 371 | 372 | }; -------------------------------------------------------------------------------- /src/common/service.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | module.exports = class service { 3 | constructor() { 4 | 5 | } 6 | /** 7 | * 8 | * @param {*} name 9 | * @param {*} config 10 | */ 11 | service(name = '', ...args) { 12 | // console.log(path.join(zuoyan.ROOT_PATH, './model/' + name)); 13 | const s = require(path.join(zuoyan.SRC_PATH, './service/' + name)); 14 | return new s(...args); 15 | } 16 | /** 17 | * 18 | * @param {*} name 19 | * @param {*} config 20 | */ 21 | model(name = '', modelConfig = '') { 22 | const dataBaseconfig = tools.config('database'); 23 | if (tools.isEmpty(modelConfig)) { 24 | modelConfig = 'mysql'; 25 | } 26 | modelConfig = Object.assign(dataBaseconfig[modelConfig], dataBaseconfig.common); 27 | const m = require(path.join(zuoyan.SRC_PATH, './model/' + name)); 28 | const modePath = name.split('/'); 29 | return new m(modePath[modePath.length - 1], modelConfig); 30 | } 31 | }; -------------------------------------------------------------------------------- /src/common/taskCheck/index.js: -------------------------------------------------------------------------------- 1 | const Datastore = require('nedb-promises'); 2 | const path = require('path'); 3 | 4 | module.exports = class { 5 | constructor(path = '') { 6 | this.dataSource = Datastore.create(path); 7 | this.dataSource.persistence.setAutocompactionInterval(1000 * 100); //自动压缩数据库,单位ms,>5000ms 8 | } 9 | 10 | async init() { 11 | await this.dataSource.update({ 12 | isexe: 1 13 | }, { 14 | '$set': { 15 | isexe: 0 16 | } 17 | }, { 18 | multi: true 19 | }); 20 | } 21 | /** 22 | * 获取任务信息 23 | * @param {*} name 24 | */ 25 | async start(name) { 26 | let doc = await this.dataSource.findOne({ 27 | name 28 | }); 29 | if (tools.isEmpty(doc)) { 30 | doc = { 31 | name, 32 | isexe: 0, 33 | lasttime: 0, 34 | create_time: tools.getUnixTime() 35 | }; 36 | await this.dataSource.insert(doc); 37 | } 38 | if (doc.isexe === 0) { 39 | await this.dataSource.update({ 40 | name 41 | }, { 42 | '$set': { 43 | isexe: 1 44 | } 45 | }); 46 | } else { 47 | logger.warn('[' + name + ']正在执行,此调度将被终止'); 48 | } 49 | return doc; 50 | } 51 | /** 52 | * 任务结束但未完成 53 | * @param {*} name 54 | */ 55 | async end(name) { 56 | await this.dataSource.update({ 57 | name 58 | }, { 59 | '$set': { 60 | isexe: 0 61 | } 62 | }); 63 | } 64 | 65 | /** 66 | * 任务完成 67 | * @param {*} name 68 | */ 69 | async finish(name, lasttime = tools.getUnixTime()) { 70 | await this.dataSource.update({ 71 | name 72 | }, { 73 | '$set': { 74 | isexe: 0, 75 | lasttime, 76 | } 77 | }); 78 | } 79 | 80 | 81 | 82 | }; -------------------------------------------------------------------------------- /src/common/tools.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @Author: 左盐 3 | * @Date: 2017-12-03 16:44:45 4 | * @Email: huabinglan@163.com 5 | * @Project: xxxx 6 | * @Last modified by: 左盐 7 | * @Last modified time: 2018-06-06 22:57:30 8 | */ 9 | 10 | const fs = require('fs-extra'); // fs 11 | const superagent = require('superagent'); // 爬虫 12 | const crypto = require('crypto'); // 加密 13 | const dayjs = require('dayjs'); // 时间处理 14 | const hmacsha1 = require('hmacsha1'); // 时间处理 15 | const empty = require('is-empty'); 16 | const BigNumber = require('bignumber.js'); 17 | 18 | const configN = require('../config/config'); 19 | const configTest = require('../config/config.test'); 20 | const configPro = require('../config/config.pro'); 21 | 22 | module.exports = class { 23 | constructor(env = 'production') { 24 | this.env = env; 25 | } 26 | /** 27 | * 获取运行环境 28 | */ 29 | getEnv() { 30 | return this.env; 31 | } 32 | /** 33 | * 获取配置 34 | * @param {*} key 35 | */ 36 | config(key) { 37 | let c = configN; 38 | if (this.env === 'production') { 39 | c = Object.assign(configN, configPro); 40 | } else if (this.env === 'test') { 41 | c = Object.assign(configN, configTest); 42 | } 43 | if (this.isEmpty(key)) { 44 | return c; 45 | } 46 | return c[key] 47 | } 48 | /** 49 | * 50 | * @param {*} ms 51 | */ 52 | sleep(ms) { // 等待一段时间 53 | return new Promise(resolve => setTimeout(resolve, ms)); 54 | }; 55 | /** 56 | * 读取文件 57 | * @method readFile 58 | * @param {[type]} filePath 文件路径 59 | * @return {[Promise]} [description] 60 | */ 61 | readJsonFile(filePath) { 62 | fs.ensureFileSync(filePath); 63 | try { 64 | return fs.readJsonSync(filePath); 65 | } catch (e) { 66 | return {}; //fs.readFileSync(filePath); 67 | } 68 | }; 69 | /** 70 | * 写入文件 71 | * @method writeFile 72 | * @param {[type]} filePath [description] 73 | * @param {[type]} data [description] 74 | * @return {[type]} [description] 75 | */ 76 | writeJsonFile(filePath, data) { 77 | fs.ensureFileSync(filePath); 78 | fs.writeJsonSync(filePath, data); 79 | }; 80 | /** 81 | * 获取文件字符编码 82 | * @param {*} filePath 83 | */ 84 | async checkFileEncode(filePath) { 85 | let encoding = 'utf81'; 86 | const readable = fs.createReadStream(filePath, { 87 | encoding: null, 88 | start: 0, 89 | end: 30 90 | }); 91 | readable.on('data', (chunk) => { 92 | const item1 = chunk[0].toString(16); 93 | const item2 = chunk[1].toString(16); 94 | if (item1 === 'ef' && item2 === 'bb') { 95 | encoding = 'utf8'; 96 | } else if (item1 === 'bf' && item2 === 'cd') { 97 | encoding = 'GB2312'; 98 | } else { 99 | encoding = 'GBK'; 100 | } 101 | }); 102 | readable.on('end', () => { 103 | 104 | }); 105 | await sleep(20); 106 | return encoding; 107 | }; 108 | /** 109 | * http请求 110 | * @method httpAgent 111 | * @param {[type]} url [description] 112 | * @param {[type]} method [description] 113 | * @param {[type]} data [description] 114 | * @return {[type]} [description] 115 | */ 116 | httpAgent(url, method = 'get', data = '') { 117 | method = method.toLowerCase(); 118 | if (method == 'get' || method == 'del') { 119 | return new Promise(function (resolve, reject) { 120 | superagent[method].call(this, url).query(data).end(function (err, res) { 121 | if (err || !res.ok) { 122 | reject(err || res.ok); 123 | } 124 | resolve(res.body); 125 | }); 126 | }); 127 | } else { 128 | return new Promise(function (resolve, reject) { 129 | superagent[method].call(this, url).send(data).end(function (err, res) { 130 | if (err || !res.ok) { 131 | reject(err || res.ok); 132 | } 133 | resolve(res.body); 134 | }); 135 | }); 136 | } 137 | }; 138 | /** 139 | * http请求 140 | * @method httpAgent 141 | * @param {[type]} url [description] 142 | * @param {[type]} method [description] 143 | * @param {[type]} data [description] 144 | * @return {[type]} [description] 145 | */ 146 | httpSpider(url, method = 'get', data = '') { 147 | const startTime = new Date().getTime(); 148 | method = method.toLowerCase(); 149 | if (method == 'get' || method == 'del') { 150 | return new Promise(function (resolve, reject) { 151 | superagent[method].call(this, url).timeout({ 152 | response: 60000 153 | }).query(data).end(function (err, res) { 154 | if (err || !res.ok) { 155 | logger.error(url + '--' + JSON.stringify(data) + '--' + err.message); 156 | reject(err || res.ok); 157 | } 158 | const endTime = new Date().getTime(); 159 | // logger.info('http exe time:' + (endTime - startTime) + 'ms'); 160 | try { 161 | resolve(JSON.parse(res.text)); 162 | } catch (e) { 163 | resolve(res.text); 164 | } 165 | }); 166 | }); 167 | } else { 168 | return new Promise(function (resolve, reject) { 169 | superagent[method].call(this, url).timeout({ 170 | response: 60000 171 | }).send(data).end(function (err, res) { 172 | if (err || !res.ok) { 173 | logger.error(err); 174 | reject(err || res.ok); 175 | } 176 | const endTime = new Date().getTime(); 177 | // logger.info('http exe time:' + (endTime - startTime) + 'ms'); 178 | try { 179 | resolve(JSON.parse(res.text)); 180 | } catch (e) { 181 | try { 182 | resolve(res.text); 183 | } catch (e) { 184 | console.log('res', res); 185 | resolve(res.text); 186 | } 187 | } 188 | }); 189 | }); 190 | } 191 | }; 192 | /** 193 | * 爬虫实体字符转义 194 | * @method htmlDecode 195 | * @param {[type]} str [description] 196 | * @return {[type]} [description] 197 | */ 198 | htmlDecode(str) { 199 | // 一般可以先转换为标准 unicode 格式(有需要就添加:当返回的数据呈现太多\\\u 之类的时) 200 | str = unescape(str.replace(/\\u/g, '%u')); 201 | // 再对实体符进行转义 202 | // 有 x 则表示是16进制,$1 就是匹配是否有 x,$2 就是匹配出的第二个括号捕获到的内容,将 $2 以对应进制表示转换 203 | str = str.replace(/&#(x)?(\w+);/g, function ($, $1, $2) { 204 | return String.fromCharCode(parseInt($2, $1 ? 16 : 10)); 205 | }); 206 | return str; 207 | }; 208 | /** 209 | * 格式化http参数,组合成字符串的形式 210 | * @method formatHttpParam 211 | * @return {[type]} [description] 212 | */ 213 | httpParam(param) { 214 | var s = ''; 215 | for (var key in param) { 216 | s += key + '=' + param[key] + '&'; 217 | } 218 | if (s != '') { 219 | s = s.substring(0, s.length - 1); 220 | } 221 | return s; 222 | }; 223 | /** 224 | * API签名 225 | * 使用UTF - 8 字符集按照RFC3986规则编码请求参数和参数取值, 编码规则如下: * 226 | × 字符A~Z、 a~z、 0~9 以及字符 - 、_、.、~不编码。 * 227 | × 其它字符编码成 % XY的格式, 其中XY是字符对应ASCII码的16进制。 示例: 半角双引号( ")对应%22。 228 | × 扩展的UTF - 8 字符, 编码成 % XY % ZA… 的格式。 229 | × 空格() 编码成 % 20, 而不是加号( + ) 230 | */ 231 | getApiSign(data, key = 'kG8by9pl^d') { 232 | let paramsJson = {}; 233 | if (typeof (data) === 'string') { 234 | data = data.split('&'); 235 | for (let i = 0, len = data.length; i < len; i++) { 236 | const a = data[i].split('='); 237 | paramsJson[a[0]] = a[1]; 238 | } 239 | } else { 240 | paramsJson = data; 241 | } 242 | const keys = []; 243 | for (const key in paramsJson) { 244 | keys.push(key); 245 | } 246 | keys.sort(); 247 | 248 | let paramStr = []; 249 | for (let i = 0, len = keys.length; i < len; i++) { 250 | paramStr.push(keys[i] + '=' + paramsJson[keys[i]]); 251 | } 252 | 253 | paramStr = encodeURIComponent(paramStr.join('&')); 254 | let sign = hmacsha1(key, paramStr); 255 | sign = encodeURIComponent(sign); 256 | return sign; 257 | }; 258 | /** 259 | * sha1加密 260 | * @param str 将加密的字符串 261 | * @returns {*} 262 | */ 263 | sha1(str) { 264 | return crypto.createHash('sha1').update(str).digest('hex'); 265 | }; 266 | /** 267 | * 生成随机字符串 268 | * @method randomChar 269 | * @return {[type]} [description] 270 | */ 271 | randomChar(len, charType) { 272 | const en = 'qwertyioplkjhgfsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM'; 273 | const number = '0123456789'; 274 | const special = '~!@#$%^&*()_+{}[]:<>,.?'; 275 | let x = en + number; 276 | if (charType == 'number') { 277 | x = number; 278 | } else if (charType == 'en') { 279 | x = en; 280 | } else if (charType === 'special') { 281 | x = en + number + special; 282 | } 283 | let tmp = ''; 284 | for (var i = 0; i < len; i++) { 285 | tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length); 286 | } 287 | return tmp; 288 | }; 289 | /** 290 | * 获取unix时间 291 | * @method 292 | * @return {[type]} [description] 293 | */ 294 | getUnixTime() { 295 | return Math.round(new Date().getTime() / 1000); 296 | }; 297 | /** 298 | * 获取字符串长度,却分中英文 299 | * @method 300 | * @param {[type]} str [description] 301 | * @return {[type]} [description] 302 | */ 303 | getCharLen(str) { 304 | return str.replace(/[^\x00-\xff]/g, 'rr').length; 305 | }; 306 | /** 307 | * 生成订单id 308 | * @param {*} prix 309 | */ 310 | orderid(prefix = 'OD') { 311 | return prefix + new Date().getTime() + this.randomChar(3).toUpperCase(); 312 | }; 313 | /** 314 | * 截取字符串, 区分中英文 315 | * @param s 316 | * @param l 长度 317 | * @param st 补充的结尾字符 318 | * @returns {*} 319 | */ 320 | subStr(s, l = 200, st = '') { 321 | var T = false; 322 | if (this.getCharLen(s) > l) { 323 | l -= this.getCharLen(st); 324 | var S = escape(s); 325 | var M = S.length; 326 | var r = ''; 327 | var C = 0; 328 | for (var i = 0; i < M; i++) { 329 | if (C < l) { 330 | var t = S.charAt(i); 331 | if (t == '%') { 332 | t = S.charAt(i + 1); 333 | if (t == 'u') { 334 | r += S.substring(i, i + 6); 335 | C += 2; 336 | i += 5; 337 | } else { 338 | r += S.substring(i, i + 3); 339 | C++; 340 | i += 2; 341 | } 342 | } else { 343 | r += t; 344 | C++; 345 | } 346 | } else { 347 | T = true; 348 | break; 349 | } 350 | } 351 | } 352 | return T ? unescape(r) + st : s; 353 | }; 354 | /** 355 | * 时间格式化,传值为unix时间 356 | * @method function 357 | * @param {[type]} format [description] 358 | * @return {[type]} [description] 359 | */ 360 | formatTime(time = tools.getUnixTime(), format = 'YYYY-MM-DD HH:mm:ss') { 361 | if (time.toString().length === 13) { 362 | return dayjs(time).format(format); 363 | } 364 | return dayjs.unix(time).format(format); 365 | }; 366 | /** 367 | * 368 | * @param {*} format 369 | */ 370 | toUnixTime(time) { //2018-12-05 02:07:10 371 | return new Date(time).getTime() / 1000; 372 | } 373 | /** 374 | * 转换value是否是int值,如果不是则用default代替 375 | * @method 376 | * @return {[type]} [description] 377 | */ 378 | getInt(value, def = 0) { 379 | value = parseInt(value); 380 | if (isNaN(value) || value == null) { 381 | return def; 382 | } 383 | return parseInt(value); 384 | }; 385 | 386 | getFloat(value, def = 0) { 387 | value = parseFloat(value); 388 | if (isNaN(value) || value == null) { 389 | return def; 390 | } 391 | return parseFloat(value); 392 | }; 393 | /** 394 | * 去除所有的html代码 395 | * @param {[type]} str = "" [description] 396 | * @return {[type]} [description] 397 | */ 398 | removeHtml(str = '') { 399 | return str.replace(/<[^>]+>/g, '').replace(/ /g, ''); 400 | }; 401 | /** 402 | * 是否是错误对象 403 | * @param {} value 404 | */ 405 | isError(value) { 406 | switch (Object.prototype.toString.call(value)) { 407 | case '[object Error]': 408 | return true; 409 | case '[object Exception]': 410 | return true; 411 | case '[object DOMException]': 412 | return true; 413 | default: 414 | return value instanceof Error; 415 | } 416 | } 417 | /** 418 | * 419 | * @param {*} value 420 | */ 421 | isEmpty(value) { 422 | return empty(value); 423 | } 424 | /** 425 | * 返回状态码等 426 | */ 427 | stateJson(data = '', code = 200) { 428 | return { 429 | code: code, 430 | data: data 431 | }; 432 | }; 433 | /** 434 | * 判断是不是移动端 435 | */ 436 | checkMobile(agent) { 437 | let flag = false; 438 | agent = agent.toLowerCase(); 439 | const keywords = ['android', 'iphone', 'ipod', 'ipad', 'windows phone', 'mqqbrowser']; 440 | // 排除 Windows 桌面系统 441 | if (!(agent.indexOf('windows nt') > -1) || (agent.indexOf('windows nt') > -1 && agent.indexOf('compatible; msie 9.0;') > -1)) { 442 | // 排除苹果桌面系统 443 | if (!(agent.indexOf('windows nt') > -1) && !agent.indexOf('macintosh') > -1) { 444 | for (const item of keywords) { 445 | if (agent.indexOf(item) > -1) { 446 | flag = true; 447 | break; 448 | } 449 | } 450 | } 451 | } 452 | return flag; 453 | } 454 | }; -------------------------------------------------------------------------------- /src/config/config.js: -------------------------------------------------------------------------------- 1 | const mysql = require('think-model-mysql'); 2 | module.exports = { 3 | port: 3001, 4 | renderLimit: 10, 5 | pageTimeout: 1000 * 20, 6 | redis: { 7 | port: 6379, 8 | host: '127.0.0.1', 9 | ex: 60 * 60 * 24 * 7 10 | }, 11 | mobileRender: { 12 | name: 'iPhone X', 13 | userAgent: 14 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', 15 | viewport: { 16 | width: 375, 17 | height: 812, 18 | deviceScaleFactor: 3, 19 | isMobile: false, 20 | hasTouch: false, 21 | isLandscape: false, 22 | } 23 | }, 24 | puppeteer: { 25 | max: 4,//最多产生多少个 puppeteer 实例 。如果你设置它,请确保 在引用关闭时调用清理池。 pool.drain().then(()=>pool.clear()) 26 | min: 1,//保证池中最少有多少个实例存活 27 | maxUses: 2048,//每一个 实例 最大可重用次数,超过后将重启实例。0表示不检验 28 | testOnBorrow: true,// 在将 实例 提供给用户之前,池应该验证这些实例。 29 | autostart: false,//是不是需要在 池 初始化时 初始化 实例 30 | idleTimeoutMillis: 1000 * 60 * 60,//如果一个实例 60分钟 都没访问就关掉他 31 | evictionRunIntervalMillis: 1000 * 60 * 3,//每 3分钟 检查一次 实例的访问状态 32 | start: { 33 | headless: true, 34 | devtools: false, 35 | ignoreHTTPSErrors: true, 36 | args: [ 37 | '--disable-gpu', 38 | '--disable-dev-shm-usage', 39 | '--disable-setuid-sandbox', 40 | "--disable-xss-auditor",//关闭 XSS Auditor 41 | '--no-first-run', 42 | '--no-sandbox', 43 | '–disable-extensions', 44 | '--no-zygote', 45 | '--single-process', 46 | '--disable-web-security', 47 | '--blink-settings=imagesEnabled=false', 48 | '--enable-features=NetworkService', 49 | '--disable-popup-blocking' 50 | ] 51 | } 52 | }, 53 | database: { 54 | common: { // 通用配置 55 | logConnect: true, // 是否打印数据库连接信息 56 | logSql: true, // 是否打印 SQL 语句 57 | logger: msg => logger.info(msg) // 打印信息的 logger 58 | }, 59 | mysql: { 60 | handle: mysql, 61 | database: 'cms', 62 | prefix: 'pz_', 63 | encoding: 'utf8', 64 | host: '127.0.0.1', 65 | port: '', 66 | user: 'root', 67 | password: '123456', 68 | dateStrings: true, 69 | supportBigNumbers: true, 70 | bigNumberStrings: true, 71 | connectionLimit: 10, // 连接池的连接个数,默认为 1 72 | debounce: false, // 关闭 debounce 功能 73 | } 74 | } 75 | }; -------------------------------------------------------------------------------- /src/config/config.pro.js: -------------------------------------------------------------------------------- 1 | const mysql = require('think-model-mysql'); 2 | module.exports = { 3 | port: 3001, 4 | renderLimit: 10, 5 | pageTimeout: 1000 * 10, 6 | puppeteer: { 7 | max: 3,//最多产生多少个 puppeteer 实例 。如果你设置它,请确保 在引用关闭时调用清理池。 pool.drain().then(()=>pool.clear()) 8 | min: 1,//保证池中最少有多少个实例存活 9 | maxUses: 2048,//每一个 实例 最大可重用次数,超过后将重启实例。0表示不检验 10 | testOnBorrow: true,// 在将 实例 提供给用户之前,池应该验证这些实例。 11 | autostart: false,//是不是需要在 池 初始化时 初始化 实例 12 | idleTimeoutMillis: 1000 * 60 * 60,//如果一个实例 60分钟 都没访问就关掉他 13 | evictionRunIntervalMillis: 1000 * 60 * 3,//每 3分钟 检查一次 实例的访问状态 14 | start: { 15 | headless: true, 16 | devtools: false, 17 | ignoreHTTPSErrors: true, 18 | args: [ 19 | '--disable-gpu', 20 | '--disable-dev-shm-usage', 21 | '--disable-setuid-sandbox', 22 | "--disable-xss-auditor",//关闭 XSS Auditor 23 | '--no-first-run', 24 | '--no-sandbox', 25 | '–disable-extensions', 26 | '--no-zygote', 27 | '--single-process', 28 | '--disable-web-security', 29 | '--blink-settings=imagesEnabled=false', 30 | '--enable-features=NetworkService', 31 | '--disable-popup-blocking' 32 | ] 33 | } 34 | }, 35 | database: { 36 | common: { // 通用配置 37 | logConnect: true, // 是否打印数据库连接信息 38 | logSql: true, // 是否打印 SQL 语句 39 | logger: msg => logger.info(msg) // 打印信息的 logger 40 | }, 41 | mysql: { 42 | handle: mysql, 43 | database: 'xxxx', 44 | prefix: 'pz_', 45 | encoding: 'utf8', 46 | host: '127.0.0.1', 47 | port: '', 48 | user: 'xxxx', 49 | password: 'xxxx', 50 | dateStrings: true, 51 | supportBigNumbers: true, 52 | bigNumberStrings: true, 53 | connectionLimit: 10, // 连接池的连接个数,默认为 1 54 | debounce: false, // 关闭 debounce 功能 55 | } 56 | } 57 | }; -------------------------------------------------------------------------------- /src/config/config.test.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | }; -------------------------------------------------------------------------------- /src/controller/http.js: -------------------------------------------------------------------------------- 1 | 2 | const http = require('http'); 3 | const url = require('url'); 4 | 5 | module.exports = class extends zuoyan.Controller { 6 | constructor() { 7 | super(); 8 | this.routerS = this.service('router'); 9 | global.renderLimit = 0; 10 | } 11 | 12 | async startServer() { 13 | const server = http.createServer(async (req, res) => { 14 | let urlObj = url.parse(req.url, true); 15 | req.urlObj = urlObj; 16 | console.log(urlObj, req.url); 17 | console.log(req.headers['user-agent']); 18 | 19 | //连接关闭事件 20 | res.on('close', async () => { 21 | const data = await zyRedis.get(urlObj.href); 22 | if (data) { 23 | global.renderLimit--; 24 | zyRedis.del(urlObj.href); 25 | } 26 | // logger.warn('close', req.url); 27 | }); 28 | this.routerS.router(req, res); 29 | }); 30 | 31 | 32 | server.listen(tools.config('port'), function () { 33 | console.log('服务器启动成功!'); 34 | console.log('正在监听 ' + tools.config('port') + ' 端口'); 35 | 36 | }); 37 | } 38 | 39 | 40 | 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const schedule = require('node-schedule'); 2 | 3 | 4 | module.exports = class extends zuoyan.Entry { 5 | async start(env) { 6 | //任务列表 7 | if (env === 'development') { 8 | const renderS = this.service('render'); 9 | renderS.init(); 10 | 11 | const httpC = this.controller('http'); 12 | httpC.startServer(); 13 | } else { 14 | const renderS = this.service('render'); 15 | renderS.init(); 16 | 17 | const httpC = this.controller('http'); 18 | httpC.startServer(); 19 | } 20 | } 21 | }; -------------------------------------------------------------------------------- /src/model/test/article.js: -------------------------------------------------------------------------------- 1 | /** 2 | * model 3 | */ 4 | module.exports = class extends zuoyan.Model { 5 | /** 6 | * 根据父节点获取所有子节点 7 | * @method checkUserLogin 8 | * @param {[type]} username [description] 9 | * @param {[type]} password [description] 10 | * @return {[type]} [description] 11 | */ 12 | async page(kw, nodeid, cp, mp) { 13 | const rows = await this.alias('a').join({ 14 | table: 'node', 15 | as: 'node', 16 | join: 'inner', 17 | on: ['nodeid', 'node.id'] 18 | }).join({ 19 | table: 'user_admin', 20 | as: 'user', 21 | join: 'inner', 22 | on: ['uid', 'id'] 23 | }) 24 | .where({ 25 | 'node.nodepath': ['like', '%,' + nodeid + ',%'], 26 | 'title': ['like', '%' + kw + '%'] 27 | }).field('a.*,node.name as nodename,user.username') 28 | .order('a.id desc') 29 | .limit((cp - 1) * mp, mp).countSelect(); 30 | return { 31 | data: rows.data, 32 | total: rows.count 33 | }; 34 | } 35 | /** 36 | * 获取文章by id 37 | * @method get 38 | * @param {[type]} nodeid [description] 39 | * @return {[type]} [description] 40 | */ 41 | async get(id) { 42 | const row = await this.where({ 43 | id: id 44 | }).find(); 45 | return row; 46 | } 47 | /** 48 | * 更新节点 49 | * @method update 50 | * @param {[type]} node [description] 51 | * @return {[type]} [description] 52 | */ 53 | async edit(id, articleInfo) { 54 | const row = await this.where({ 55 | id 56 | }).update(articleInfo); 57 | return row; 58 | } 59 | /** 60 | * 创建文章 61 | * @method create 62 | * @param {[type]} node [description] 63 | * @return {[type]} [description] 64 | */ 65 | async create(article) { 66 | const id = await this.add(article); 67 | return id; 68 | } 69 | /** 70 | * 更新审核状态 71 | * @method pass 72 | * @param {[type]} id [description] 73 | * @param {[type]} ispass [description] 74 | * @return {[type]} [description] 75 | */ 76 | async pass(id, ispass) { 77 | const row = await this.where({ 78 | id: ['IN', id.split(',')] 79 | }).update({ 80 | pass: ispass, 81 | update_time: tools.getUnixTime() 82 | }); 83 | return row; 84 | } 85 | /** 86 | * 删除文章 87 | * @method del 88 | * @param {[type]} id [description] 89 | * @return {[type]} [description] 90 | */ 91 | async del(id) { 92 | const row = await this.where({ 93 | id: ['IN', id.split(',')] 94 | }).delete(); 95 | return row; 96 | } 97 | }; -------------------------------------------------------------------------------- /src/model/user.js: -------------------------------------------------------------------------------- 1 | module.exports = class extends zuoyan.Model { 2 | get tableName() { 3 | return 'pz_user'; 4 | } 5 | 6 | /** 7 | * 获取列表 8 | * @param {[type]} kw [description] 9 | * @param {[type]} cp [description] 10 | * @param {[type]} mp [description] 11 | * @return {Promise} [description] 12 | */ 13 | async page(kw = '', cp = 1, mp = 30) { 14 | let where = '1=1'; 15 | if (!tools.isEmpty(kw)) { 16 | where = { 17 | name: ['like', '%' + kw + '%'], 18 | }; 19 | } 20 | const rows = await this.where(where) 21 | .order('id desc') 22 | .limit((cp - 1) * mp, mp).select(); 23 | return rows; 24 | } 25 | 26 | /** 27 | * 获取列表 28 | * @param {[type]} kw [description] 29 | * @param {[type]} cp [description] 30 | * @param {[type]} mp [description] 31 | * @return {Promise} [description] 32 | */ 33 | async pageByPid(pid = '', cp = 1, mp = 30) { 34 | let where = { 35 | pid 36 | }; 37 | const rows = await this.where(where) 38 | .order('sort desc,id desc') 39 | .select(); 40 | return rows; 41 | } 42 | /** 43 | * 创建 44 | * @method create 45 | * @param {[type]} node [description] 46 | * @return {[type]} [description] 47 | */ 48 | async create(json) { 49 | if (tools.isEmpty(json.create_time)) { 50 | json.create_time = tools.getUnixTime(); 51 | } 52 | const id = await this.add(json); 53 | return id; 54 | } 55 | 56 | /** 57 | * 获取 58 | * @method get 59 | * @param {[type]} nodeid [description] 60 | * @return {[type]} [description] 61 | */ 62 | async get(id) { 63 | const row = await this.where({ 64 | id 65 | }).find(); 66 | return row; 67 | } 68 | /** 69 | * 70 | * @param {[type]} json [description] 71 | * @return {Promise} [description] 72 | */ 73 | async edit(id, json) { 74 | if (tools.isEmpty(json.update_time)) { 75 | json.update_time = tools.getUnixTime(); 76 | } 77 | const row = await this.where({ 78 | id 79 | }).update(json); 80 | return row; 81 | } 82 | /** 83 | * 删除 84 | * @param {[type]} id [description] 85 | * @return {Promise} [description] 86 | */ 87 | async del(id) { 88 | const row = await this.where({ 89 | id 90 | }).delete(); 91 | return row; 92 | } 93 | 94 | 95 | }; -------------------------------------------------------------------------------- /src/service/http.js: -------------------------------------------------------------------------------- 1 | module.exports = class extends zuoyan.Service { 2 | constructor() { 3 | super(); 4 | this.renderS = this.service('render'); 5 | } 6 | /*** 7 | * 获取渲染后的内容 8 | */ 9 | async getRenderContent(href = '', url, userAgent = '') { 10 | try { 11 | if (this._checkRenderUrl(url)) { 12 | if (this._checkRenderLimit()) { 13 | const isMobile = userAgent && tools.checkMobile(userAgent); 14 | logger.error('isMobile', isMobile); 15 | const redisKey = this._formatUrlKey(url, isMobile); 16 | 17 | const data = await zyRedis.get(redisKey); 18 | if (tools.isEmpty(data)) { 19 | global.renderLimit++; 20 | await zyRedis.set(href, 'limit', 'ex', 5 * 60); 21 | const content = await this.renderS.htmlRender(url, isMobile); 22 | zyRedis.set(redisKey, content, 'ex', tools.config('redis').ex); 23 | return (content.replace(/]*>[\s\S]*?<\/[^>]*script>/gi, '')); 24 | } else { 25 | return (data.replace(/]*>[\s\S]*?<\/[^>]*script>/gi, '')); 26 | } 27 | } else { 28 | return 'error:超出并发限制,请稍后重试'; 29 | } 30 | } else { 31 | return 'error:渲染的url不合法'; 32 | } 33 | } catch (e) { 34 | // logger.error(e); 35 | return 'error:' + e.message; 36 | } 37 | } 38 | /** 39 | * check url地址是否合法 40 | * @param {*} url 41 | */ 42 | _checkRenderUrl(url) { 43 | if (url && /^(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/i.test(url)) { 44 | return true; 45 | } 46 | return false; 47 | } 48 | /** 49 | * check render并发限制 50 | */ 51 | _checkRenderLimit() { 52 | if (global.renderLimit >= tools.config('renderLimit')) { 53 | return false; 54 | } else { 55 | return true; 56 | } 57 | } 58 | /** 59 | * 格式化redis的key 60 | * @param {*} url 61 | * @param {*} isMobile 62 | */ 63 | _formatUrlKey(url, isMobile) { 64 | if (isMobile) { 65 | return 'm-' + url; 66 | } 67 | return url; 68 | } 69 | }; 70 | 71 | -------------------------------------------------------------------------------- /src/service/render.js: -------------------------------------------------------------------------------- 1 | // 载入puppeteer 2 | const puppeteer = require('puppeteer-extra'); 3 | const genericPool = require('generic-pool'); 4 | const { PendingXHR } = require('pending-xhr-puppeteer'); 5 | const StealthPlugin = require('puppeteer-extra-plugin-stealth'); 6 | puppeteer.use(StealthPlugin()); 7 | 8 | module.exports = class extends zuoyan.Service { 9 | constructor() { 10 | super(); 11 | } 12 | 13 | /** 14 | * 初始化一个 Puppeteer 池 15 | * @param {Object} [options.puppeteerArgs={}] puppeteer.launch 启动的参数 16 | * @param {Function} [options.validator=(instance)=>Promise.resolve(true))] 用户自定义校验 参数是 取到的一个实例 17 | * @param {Object} [options.otherConfig={}] 剩余的其他参数 18 | * @return {Object} pool 19 | */ 20 | initPuppeteerPool() { 21 | if (global.pptPoll) { 22 | global.pptPoll.drain().then(() => global.pptPoll.clear()); 23 | }; 24 | const options = Object.assign(tools.config('puppeteer'), { 25 | validator: () => Promise.resolve(true), 26 | }); 27 | const factory = { 28 | create: () => 29 | puppeteer.launch(options.start).then(instance => { 30 | // 创建一个 puppeteer 实例 ,并且初始化使用次数为 0 31 | instance.useCount = 0; 32 | return instance; 33 | }), 34 | destroy: instance => { 35 | instance.close() 36 | }, 37 | validate: instance => { 38 | // 执行一次自定义校验,并且校验 实例已使用次数。 当 返回 reject 时 表示实例不可用 39 | return options.validator(instance).then(valid => Promise.resolve(valid && (options.maxUses <= 0 || instance.useCount < options.maxUses))); 40 | } 41 | }; 42 | const pool = genericPool.createPool(factory, options) 43 | const genericAcquire = pool.acquire.bind(pool) 44 | // 重写了原有池的消费实例的方法。添加一个实例使用次数的增加 45 | pool.acquire = () => 46 | genericAcquire().then(instance => { 47 | instance.useCount += 1 48 | return instance 49 | }); 50 | 51 | pool.use = fn => { 52 | let resource; 53 | return pool 54 | .acquire() 55 | .then(r => { 56 | resource = r; 57 | return resource; 58 | }) 59 | .then(fn) 60 | .then( 61 | result => { 62 | // 不管业务方使用实例成功与后都表示一下实例消费完成 63 | pool.release(resource); 64 | return result; 65 | }, 66 | err => { 67 | pool.release(resource); 68 | throw err; 69 | } 70 | ) 71 | } 72 | return pool; 73 | } 74 | 75 | 76 | async init() { 77 | global.pptPoll = this.initPuppeteerPool(); 78 | } 79 | 80 | /** 81 | * 82 | */ 83 | async htmlRender(url = 'http://127.0.0.1:8181/', isMobile = false) { 84 | // 在业务中取出实例使用 85 | return await global.pptPoll.use(async instance => { 86 | return new Promise(async (resolve, reject) => { 87 | try { 88 | const page = await instance.newPage(); 89 | //如果是移动端则设置UA和视图 90 | if (isMobile) { 91 | let iPhoneX = tools.config('mobileRender'); 92 | await page.setUserAgent(iPhoneX.userAgent); 93 | // await page.setViewport(iPhoneX.viewport); 94 | } 95 | 96 | const pendingXHR = new PendingXHR(page); 97 | // 开启请求拦截, 无头模式下有效 98 | const blockTypes = ['image', 'media', 'font', 'manifest', 'other', 'texttrack', 'websocket']; 99 | await page.setRequestInterception(true); //开启请求拦截 100 | page.on('request', async request => { 101 | const type = request.resourceType(); 102 | if (blockTypes.indexOf(type) > -1) { 103 | //直接阻止请求 104 | return request.abort(); 105 | } else { 106 | return request.continue({ 107 | headers: Object.assign({}, request.headers(), { 108 | 'ppt': 'true' 109 | }) 110 | }); 111 | } 112 | }); 113 | //响应 114 | page.on('response', async response => { 115 | logger.info(await response.url() + ' ' + await response.request().method() + ' ' + await response.status() + ' ' + await response.request().resourceType()); 116 | }); 117 | const timeStart = new Date().getTime(); 118 | try { 119 | await page.goto(url, { 120 | // waitUntil: "networkidle0", 121 | timeout: tools.config('pageTimeout') 122 | }); 123 | } catch (e) { 124 | 125 | } 126 | 127 | await pendingXHR.waitForAllXhrFinished(); 128 | const html = await page.content(); 129 | logger.warn(url + ' ' + (new Date().getTime() - timeStart) + 'ms'); 130 | page.close(); 131 | resolve(html); 132 | } catch (e) { 133 | logger.error(url, e); 134 | reject(e); 135 | } 136 | 137 | }); 138 | }); 139 | 140 | }; 141 | }; -------------------------------------------------------------------------------- /src/service/router.js: -------------------------------------------------------------------------------- 1 | module.exports = class extends zuoyan.Service { 2 | constructor() { 3 | super(); 4 | this.httpS = this.service('http'); 5 | } 6 | /** 7 | * 路由 8 | */ 9 | async router(req, res) { 10 | try { 11 | let result = ''; 12 | 13 | const pathName = req.urlObj.pathname; 14 | switch (pathName) { 15 | case '/render': 16 | req.urlObj.query.url = decodeURIComponent(req.urlObj.query.url || ''); 17 | console.log(req.urlObj.href, req.urlObj.query.url); 18 | result = await this.httpS.getRenderContent(req.urlObj.href, req.urlObj.query.url, req.headers['user-agent']); 19 | break; 20 | default: 21 | const tUrl = decodeURIComponent(req.urlObj.href.substring(1)); 22 | console.log('tUrl', tUrl); 23 | result = await this.httpS.getRenderContent(req.urlObj.href, tUrl, req.headers['user-agent']); 24 | break; 25 | } 26 | 27 | this._sendResponseHtml(res, result); 28 | } catch (e) { 29 | // logger.error(e); 30 | this._sendResponseHtml(res, e.message); 31 | } 32 | } 33 | 34 | //发送html响应 35 | _sendResponseHtml(res, content = 'error:未知错误') { 36 | res.writeHead(200, { 'Content-Type': 'text/html; charset=UTF-8' }); 37 | res.write(content); 38 | res.end(); 39 | } 40 | 41 | 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /src/tools/excel.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @Author: 左盐 3 | * @Date: 2018-03-05 23:30:57 4 | * @Email: huabinglan@163.com 5 | * @Last modified by: 左盐 6 | * @Last modified time: 2018-03-06 12:11:27 7 | */ 8 | 9 | 10 | const path = require('path'); 11 | const XLSX = require('xlsx'); 12 | const fsExtra = require('fs-extra'); 13 | const range = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 14 | const rangeArr = range.split(''); 15 | 16 | module.exports = class { 17 | /** 18 | * 格式数据 19 | * @param {[type]} data [description] 20 | * @return {Promise} [description] 21 | */ 22 | formatData(data, column) { 23 | let json = {}; 24 | json.data = data; 25 | json.fieldLen = 0; 26 | json.head = {}; 27 | if (json.data[0]) { 28 | json.fieldLen = column.length; //Object.keys(json.data[0]).length; 29 | json.head = this.formatHead(json.data[0], column); 30 | } 31 | 32 | json.len = json.data.length; 33 | json.headRange = this.formatHeadRange(json.fieldLen, json.len + 1); 34 | 35 | return json; 36 | } 37 | /** 38 | * 组织范围 39 | * @type {String} 40 | */ 41 | formatHeadRange(len, dataLen) { 42 | let headRange = 'A1:'; 43 | if (len <= 26) { 44 | headRange += (rangeArr[len - 1] + dataLen); 45 | } else { 46 | headRange += (rangeArr[parseInt(len / 26) - 1] + rangeArr[len % 26 - 1] + dataLen); 47 | } 48 | return headRange; 49 | } 50 | /** 51 | * 格式化head 52 | * @param {[type]} data [description] 53 | * @return {[type]} [description] 54 | */ 55 | formatHead(data, column) { 56 | let head = {}; 57 | let index = 0; 58 | if (column.length == 0) { 59 | for (let key in data) { 60 | if (index > 26) { 61 | head[rangeArr[parseInt(index / 26) - 1] + rangeArr[index % 26 - 1] + "1"] = key; 62 | } else { 63 | head[rangeArr[index] + "1"] = { 64 | v: key 65 | }; 66 | } 67 | index++; 68 | } 69 | } else { 70 | for (let i = 0, len = column.length; i < len; i++) { 71 | if (index > 26) { 72 | head[rangeArr[parseInt(index / 26) - 1] + rangeArr[index % 26 - 1] + "1"] = column[i].label; 73 | } else { 74 | head[rangeArr[index] + "1"] = { 75 | v: column[i].label 76 | }; 77 | } 78 | index++; 79 | } 80 | } 81 | return head; 82 | } 83 | 84 | 85 | /** 86 | * 生成excel 87 | * @return {Promise} [description] 88 | */ 89 | create(data, column = [], param = {}) { 90 | let doc = this.formatData(data, column); 91 | 92 | //workbook 93 | let workbook = { 94 | SheetNames: ["reports"], 95 | Sheets: { 96 | 'reports': { 97 | '!ref': doc.headRange, 98 | } 99 | } 100 | }; 101 | 102 | let mySheet1 = Object.assign(workbook.Sheets.reports, doc.head); 103 | let index = 0; 104 | 105 | for (let i = 0; i < doc.len; i++) { 106 | index = 0; 107 | let dataItem = doc.data[i]; 108 | for (let j = 0, len = column.length; j < len; j++) { 109 | if (index <= 26) { 110 | mySheet1[rangeArr[index] + (i + 2)] = { 111 | v: dataItem[column[j].field], 112 | t: this.formatCell(dataItem[column[j].field]) 113 | } 114 | } else { 115 | mySheet1[rangeArr[parseInt(index / 26) - 1] + rangeArr[parseInt(index % 26) - 1] + (i + 2)] = { 116 | v: dataItem[column[j].field], 117 | t: this.formatCell(dataItem[column[j].field]) 118 | } 119 | } 120 | index++; 121 | } 122 | 123 | // for (let key in dataItem) { 124 | // if (index <= 26) { 125 | // mySheet1[rangeArr[index] + (i + 2)] = { 126 | // v: dataItem[key], 127 | // t: this.formatCell(dataItem[key]) 128 | // } 129 | // } else { 130 | // mySheet1[rangeArr[parseInt(index / 26) - 1] + rangeArr[parseInt(index % 26) - 1] + (i + 2)] = { 131 | // v: dataItem[key], 132 | // t: this.formatCell(dataItem[key]) 133 | // } 134 | // } 135 | // index++; 136 | // } 137 | } 138 | let file = param.path + '/'; //path.join(param.path, 'www/xlsx/'); //think.RESOURCE_PATH + '/xlsx/'; 139 | let fileName = param.fileName + '.xlsx'; 140 | 141 | fsExtra.ensureDirSync(file); 142 | XLSX.writeFile(workbook, file + fileName); 143 | 144 | return file + fileName; //返回 145 | } 146 | /** 147 | * 判断单元格格式 148 | * @param {[type]} val [description] 149 | * @return {Boolean} [description] 150 | */ 151 | formatCell(val) { //cell type: b Boolean, n Number, e error, s String, d Date 152 | let t = 's'; 153 | let v = parseInt(val); 154 | if (!isNaN(v)) { 155 | t = 'n'; 156 | } 157 | return t; 158 | } 159 | 160 | } -------------------------------------------------------------------------------- /src/tools/mail.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require('nodemailer'); 2 | 3 | module.exports = class { 4 | constructor() { 5 | this.transporter = nodemailer.createTransport({ 6 | service: 'qq', // 使用了内置传输发送邮件 查看支持列表:https://nodemailer.com/smtp/well-known/ 7 | port: 465, // SMTP 端口 8 | secureConnection: true, // 使用了 SSL 9 | auth: { 10 | user: '', 11 | // 这里密码不是qq密码,是你设置的smtp授权码 12 | pass: 'xxxxxx', 13 | } 14 | }); 15 | } 16 | /** 17 | *发送邮件 18 | * 19 | */ 20 | async send(to = '', subject = '', html = '') { 21 | let mailOptions = { 22 | from: '"task任务通知" <>', // sender address 23 | to, // list of receivers 24 | subject, // Subject line 25 | html // html body 26 | }; 27 | const doc = await this._sendMail(mailOptions); 28 | return doc; 29 | } 30 | 31 | /** 32 | * 33 | * @param {*} mailOptions 34 | */ 35 | _sendMail(mailOptions) { 36 | return new Promise((resolve, reject) => { 37 | this.transporter.sendMail(mailOptions, (error, info) => { 38 | if (error) { 39 | reject(error); 40 | return; 41 | } 42 | resolve(info); 43 | }); 44 | }); 45 | } 46 | }; -------------------------------------------------------------------------------- /testing.js: -------------------------------------------------------------------------------- 1 | const app = require('./src/common/app'); 2 | 3 | app.start('test'); --------------------------------------------------------------------------------