From e4430aea1225852e9c9a6541141c630cf6d00e06 Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:02:06 +0900 Subject: [PATCH 001/194] install aws-sdk --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 585e8640..80743cfc 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "coverage": "make coverage" }, "dependencies": { + "aws-sdk": "^2.7.0", "bcrypt": "^0.8.7", "bluebird": "^3.4.1", "body-parser": "^1.15.2", From 328bf8b074f8f5b962ca50584f74c6ba92864117 Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:04:16 +0900 Subject: [PATCH 002/194] conf for s3 --- config/config.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/config.js b/config/config.js index 2880643f..a8241c3c 100644 --- a/config/config.js +++ b/config/config.js @@ -15,6 +15,12 @@ config.development = { bucketName: "", downloadUrl: "" //文件下载域名地址 }, + // conf for s3 + s3: { + bucketName: process.env.BUCKET_NAME, + region: process.env.REGION, + downloadUrl: process.env.DOWNLOAD_URL, + }, //文件存储在本地配置 当storageType为local时需要配置 local: { storageDir: "/Users/tablee/workspaces/storage", From c2e3efbc15e7e0903b464e805b150ce68a11c3a2 Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:06:41 +0900 Subject: [PATCH 003/194] uploadFileToS3 function --- core/utils/common.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/core/utils/common.js b/core/utils/common.js index 20e856ca..ce15dc96 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -6,6 +6,7 @@ var unzip = require('node-unzip-2'); var config = require('../config'); var _ = require('lodash'); var qiniu = require("qiniu"); +var AWS = require('aws-skd'); var common = {}; module.exports = common; @@ -185,6 +186,32 @@ common.uploadFileToQiniu = function (key, filePath) { }); }; +common.uploadFileToS3 = function (key, filePath) { + return ( + new Promise(function(resolve, reject) { + AWS.config.update({ + region: 'cn-north-1' + }) + var s3 = new AWS.S3({ + params: {Bucket: 'code-push'} + }); + fs.readFile(filePath, function(err, data) { + s3.upload({ + Key: key, + Body: data, + ACL:'public-read', + }, function(err, response) { + if(err) { + reject(new Error(JSON.stringify(err))); + } else { + resolve(response.ETag) + } + }) + }) + }) + ); +}; + common.diffCollectionsSync = function (collection1, collection2) { var diffFiles = []; var collection1Only = []; From f7f35bd2e26dd3aefec72a746351cce0e8703735 Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:07:48 +0900 Subject: [PATCH 004/194] call uploadFileToS3 when storage type is s3 --- core/utils/common.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/utils/common.js b/core/utils/common.js index ce15dc96..c5862c76 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -113,6 +113,8 @@ common.uptoken = function (bucket, key) { common.uploadFileToStorage = function (key, filePath) { if (_.get(config, 'common.storageType') === 'local') { return common.uploadFileToLocal(key, filePath); + } else if (_.get(config, 'common.storageType') === 's3') { + return common.uploadFileToS3(key, filePath); } return common.uploadFileToQiniu(key, filePath); }; From 06b5da96664a9f55e1fd6826b453da1a2d7260dd Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:08:56 +0900 Subject: [PATCH 005/194] get s3 downloadUrl when storage type is s3 --- core/utils/common.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/utils/common.js b/core/utils/common.js index c5862c76..a5e95e68 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -150,6 +150,8 @@ common.uploadFileToLocal = function (key, filePath) { common.getDownloadUrl = function () { if (_.get(config, 'common.storageType') === 'local') { return _.get(config, 'local.downloadUrl'); + } else if (_.get(config, 'common.storageType') === 's3') { + return _.get(config, 's3.downloadUrl'); } return _.get(config, 'qiniu.downloadUrl'); } From 83fe7cfdf02ceef1758db8ce66972017caffcd3e Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:09:33 +0900 Subject: [PATCH 006/194] typo --- core/utils/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utils/common.js b/core/utils/common.js index a5e95e68..e9b96220 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -6,7 +6,7 @@ var unzip = require('node-unzip-2'); var config = require('../config'); var _ = require('lodash'); var qiniu = require("qiniu"); -var AWS = require('aws-skd'); +var AWS = require('aws-sdk'); var common = {}; module.exports = common; From a1a03c103ea44014e53889025a90b121db16db32 Mon Sep 17 00:00:00 2001 From: hyunjae park Date: Fri, 11 Nov 2016 19:11:25 +0900 Subject: [PATCH 007/194] use env instead hardcoded conf --- core/utils/common.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/utils/common.js b/core/utils/common.js index e9b96220..80350c0b 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -194,10 +194,10 @@ common.uploadFileToS3 = function (key, filePath) { return ( new Promise(function(resolve, reject) { AWS.config.update({ - region: 'cn-north-1' - }) + region: _.get(config, 's3.region') + }); var s3 = new AWS.S3({ - params: {Bucket: 'code-push'} + params: {Bucket: _.get(config, 's3.bucketName')} }); fs.readFile(filePath, function(err, data) { s3.upload({ @@ -211,7 +211,7 @@ common.uploadFileToS3 = function (key, filePath) { resolve(response.ETag) } }) - }) + }); }) ); }; From ca9072cab6cd240043847738f30e090dec6fc707 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 14 Nov 2016 10:30:11 +0800 Subject: [PATCH 008/194] fix config --- app.js | 4 ++-- config/config.js | 41 +++++++++++++++++++++++----------------- config/config.test.js | 26 ++----------------------- config/config.testwin.js | 25 ++---------------------- core/utils/common.js | 2 +- 5 files changed, 31 insertions(+), 67 deletions(-) diff --git a/app.js b/app.js index 772032e1..e6f2a16c 100644 --- a/app.js +++ b/app.js @@ -49,11 +49,11 @@ if (app.get('env') === 'development') { -if (_.get(config, 'common.storageType') == 'local' +if (_.get(config, 'common.storageType') === 'local' && _.get(config, 'local.storageDir') && fs.existsSync(_.get(config, 'local.storageDir')) ) { - app.use('/download', express.static(_.get(config, 'local.storageDir'))); + app.use(_.get(config, 'local.public', '/download'), express.static(_.get(config, 'local.storageDir'))); } app.use('/', routes); diff --git a/config/config.js b/config/config.js index a8241c3c..f0222e4f 100644 --- a/config/config.js +++ b/config/config.js @@ -1,6 +1,6 @@ var config = {}; config.development = { - //数据库配置 + // Config for database, only support mysql. db: { username: "root", password: null, @@ -8,40 +8,47 @@ config.development = { host: "127.0.0.1", dialect: "mysql" }, - //七牛云存储配置 当storageType为qiniu时需要配置 + // Config for qiniu (http://www.qiniu.com/) cloud storage when storageType value is "qiniu". qiniu: { accessKey: "", secretKey: "", bucketName: "", - downloadUrl: "" //文件下载域名地址 + downloadUrl: "" // Binary files download host address. }, - // conf for s3 + // Config for Amazon s3 (https://aws.amazon.com/cn/s3/) storage when storageType value is "s3". s3: { bucketName: process.env.BUCKET_NAME, region: process.env.REGION, - downloadUrl: process.env.DOWNLOAD_URL, + downloadUrl: process.env.DOWNLOAD_URL, // binary files download host address. }, - //文件存储在本地配置 当storageType为local时需要配置 + // Config for local storage when storageType value is "local". local: { + // Binary files storage dir, Do not use tmpdir and it's public download dir. storageDir: "/Users/tablee/workspaces/storage", - //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址 - downloadUrl: "http://localhost:3000/download" + // Binary files download host address which Code Push Server listen to. the files storage in storageDir. + downloadUrl: "http://localhost:3000/download", + // public static download spacename. + public: '/download' }, common: { - //登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 + // jwt sign secret for auth. you have to modify it for security. use random string instead it. loginSecret: "CodePushServer", - //当天登录密码错误尝试次数,超过次数帐户将会锁定。0:表示无限制,可能会出现暴力破解。 大于0:必须开启redis服务。 + /* + * tryLoginTimes is control login error times to avoid force attack. + * if value is 0, no limit for login auth, it may not safe for account. when it's a number, it means you can + * try that times today. but it need config redis server. + */ tryLoginTimes: 0, - //CodePush Web部署地址,也可以配置成CodePush Web地址 - //codePushWebUrl: "http://localhost:3001", - //差异化更新版本生成数目 默认为3 + // CodePush Web(https://github.com/lisong/code-push-web) login address. + //codePushWebUrl: "http://localhost:3001/login", + // create patch updates's number. default value is 3 diffNums: 3, - //数据目录,优化选项 + // data dir for caclulate diff files. it's optimization. dataDir: "/Users/tablee/workspaces/data", - //选择存储类型,目前支持local和qiniu配置 + //storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") storageType: "local" }, - //邮件配置,注册模块验证邮箱需要使用 参考https://github.com/nodemailer/nodemailer + //config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer smtpConfig:{ host: "smtp.mxhichina.com", port: 465, @@ -51,7 +58,7 @@ config.development = { pass: "" } }, - //配置redis, 注册时需要, 登录限制密码出错次数 + //config for redis (register module, tryLoginTimes module) redis: { default: { host: "127.0.0.1", diff --git a/config/config.test.js b/config/config.test.js index 375c18c6..9a6c1694 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -2,7 +2,6 @@ var os = require('os'); var config = {}; config.test = { - //数据库配置 db: { username: "root", password: null, @@ -10,54 +9,33 @@ config.test = { host: "127.0.0.1", dialect: "mysql" }, - //七牛云存储配置 当storageType为qiniu时需要配置 - qiniu: { - accessKey: "", - secretKey: "", - bucketName: "", - downloadUrl: "" //文件下载域名地址 - }, - //文件存储在本地配置 当storageType为local时需要配置 local: { storageDir: os.tmpdir(), - //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址 - downloadUrl: "http://localhost:3000/download" + downloadUrl: "http://localhost:3000/download", + public: '/download' }, common: { - //登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 loginSecret: "CodePushServer", - //当天登录密码错误尝试次数,超过次数帐户将会锁定。0:表示无限制,可能会出现暴力破解。 大于0:必须开启redis服务。 tryLoginTimes: 10, - //CodePush Web部署地址,也可以配置成CodePush Web地址 - //codePushWebUrl: "http://localhost:3001", - //差异化更新版本生成数目 默认为3 diffNums: 3, - //数据目录,优化选项 dataDir: os.tmpdir(), - //选择存储类型,目前支持local和qiniu配置 storageType: "local" }, - //邮件配置,注册模块验证邮箱需要使用 参考https://github.com/nodemailer/nodemailer smtpConfig: false, - //配置redis, 注册时需要, 登录限制密码出错次数 redis: { default: { host: "127.0.0.1", port: 6379, retry_strategy: function (options) { if (options.error.code === 'ECONNREFUSED') { - // End reconnecting on a specific error and flush all commands with a individual error return new Error('The server refused the connection'); } if (options.total_retry_time > 1000 * 60 * 60) { - // End reconnecting after a specific timeout and flush all commands with a individual error return new Error('Retry time exhausted'); } if (options.times_connected > 10) { - // End reconnecting with built in error return undefined; } - // reconnect after return Math.max(options.attempt * 100, 3000); } } diff --git a/config/config.testwin.js b/config/config.testwin.js index 797bed62..f5dd9a90 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -2,7 +2,6 @@ var os = require('os'); var config = {}; config.test = { - //数据库配置 db: { username: "root", password: "Password12!", @@ -10,51 +9,31 @@ config.test = { host: "127.0.0.1", dialect: "mysql" }, - //七牛云存储配置 当storageType为qiniu时需要配置 - qiniu: { - accessKey: "", - secretKey: "", - bucketName: "", - downloadUrl: "" //文件下载域名地址 - }, - //文件存储在本地配置 当storageType为local时需要配置 local: { storageDir: os.tmpdir(), - //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址 - downloadUrl: "http://localhost:3000/download" + downloadUrl: "http://localhost:3000/download", + public: '/download' }, common: { - //登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 loginSecret: "CodePushServer", - //当天登录密码错误尝试次数,超过次数帐户将会锁定。0:表示无限制,可能会出现暴力破解。 大于0:必须开启redis服务。 tryLoginTimes: 10, - //CodePush Web部署地址,也可以配置成CodePush Web地址 - //codePushWebUrl: "http://localhost:3001", - //差异化更新版本生成数目 默认为3 diffNums: 3, - //数据目录,优化选项 dataDir: os.tmpdir(), - //选择存储类型,目前支持local和qiniu配置 storageType: "local" }, - //邮件配置,注册模块验证邮箱需要使用 参考https://github.com/nodemailer/nodemailer smtpConfig: false, - //配置redis, 注册时需要, 登录限制密码出错次数 redis: { default: { host: "127.0.0.1", port: 6379, retry_strategy: function (options) { if (options.error.code === 'ECONNREFUSED') { - // End reconnecting on a specific error and flush all commands with a individual error return new Error('The server refused the connection'); } if (options.total_retry_time > 1000 * 60 * 60) { - // End reconnecting after a specific timeout and flush all commands with a individual error return new Error('Retry time exhausted'); } if (options.times_connected > 10) { - // End reconnecting with built in error return undefined; } // reconnect after diff --git a/core/utils/common.js b/core/utils/common.js index 80350c0b..a399d1de 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -6,7 +6,6 @@ var unzip = require('node-unzip-2'); var config = require('../config'); var _ = require('lodash'); var qiniu = require("qiniu"); -var AWS = require('aws-sdk'); var common = {}; module.exports = common; @@ -191,6 +190,7 @@ common.uploadFileToQiniu = function (key, filePath) { }; common.uploadFileToS3 = function (key, filePath) { + var AWS = require('aws-sdk'); return ( new Promise(function(resolve, reject) { AWS.config.update({ From 24dd6462547b06566569175e4bac8c444399975d Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 14 Nov 2016 10:52:18 +0800 Subject: [PATCH 009/194] readme add change password --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index d0299a7f..137cd847 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,12 @@ $ npm install code-push-cli@latest -g $ code-push login http://127.0.0.1:3000 #login in browser account:admin password:123456 ``` +change admin password eg. + +```shell +$ curl -X PATCH -H "Authorization: Bearer mytoken" -H "Accept: application/json" -H "Content-Type:application/json" -d '{"oldPassword":"123456","newPassword":"654321"}' http://127.0.0.1:3000/users/password +``` + ## [react-native-code-push](https://github.com/Microsoft/react-native-code-push) for react-native ```shell From 4c5281028387d31103b0e837d125915439caec9e Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 14 Nov 2016 16:04:19 +0800 Subject: [PATCH 010/194] add cache api updateCheck --- config/config.js | 6 ++-- config/config.test.js | 3 +- config/config.testwin.js | 3 +- core/services/client-manager.js | 51 +++++++++++++++++++++++++++++++++ routes/apps.js | 18 ++++++++++++ routes/index.js | 2 +- 6 files changed, 78 insertions(+), 5 deletions(-) diff --git a/config/config.js b/config/config.js index f0222e4f..beabb66b 100644 --- a/config/config.js +++ b/config/config.js @@ -45,8 +45,10 @@ config.development = { diffNums: 3, // data dir for caclulate diff files. it's optimization. dataDir: "/Users/tablee/workspaces/data", - //storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") - storageType: "local" + // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") + storageType: "local", + // options value is (true | false), when it's true, it will cache updateCheck results in redis. + updateCheckCache: false }, //config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer smtpConfig:{ diff --git a/config/config.test.js b/config/config.test.js index 9a6c1694..ef0792db 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -19,7 +19,8 @@ config.test = { tryLoginTimes: 10, diffNums: 3, dataDir: os.tmpdir(), - storageType: "local" + storageType: "local", + updateCheckCache: true }, smtpConfig: false, redis: { diff --git a/config/config.testwin.js b/config/config.testwin.js index f5dd9a90..71e99d53 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -19,7 +19,8 @@ config.test = { tryLoginTimes: 10, diffNums: 3, dataDir: os.tmpdir(), - storageType: "local" + storageType: "local", + updateCheckCache: true }, smtpConfig: false, redis: { diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 7dc2f789..7f59995c 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -3,6 +3,7 @@ var Promise = require('bluebird'); var models = require('../../models'); var _ = require('lodash'); var common = require('../utils/common'); +var factory = require('../utils/factory'); var proto = module.exports = function (){ function ClientManager() { @@ -12,6 +13,56 @@ var proto = module.exports = function (){ return ClientManager; }; +const UPDATE_CHECK = "UPDATE_CHECK"; +const EXPIRED = 600; + +proto.getUpdateCheckCacheKey = function(deploymentKey, appVersion, label, packageHash) { + return [UPDATE_CHECK, deploymentKey, appVersion, label, packageHash].join(':'); +} + +proto.clearUpdateCheckCache = function(deploymentKey, appVersion, label, packageHash) { + let redisCacheKey = this.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); + var client = factory.getRedisClient("default"); + return client.keysAsync(redisCacheKey) + .then(function(data) { + if (_.isArray(data)) { + return Promise.map(data, function(key){ + return client.delAsync(key); + }); + } + return null; + }); +} + +proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageHash) { + const self = this; + let redisCacheKey = self.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); + var updateCheckCache = _.get(require('../config'), 'common.updateCheckCache', false); + if (updateCheckCache === false) { + return self.updateCheck(deploymentKey, appVersion, label, packageHash); + } + var client = factory.getRedisClient("default"); + return client.getAsync(redisCacheKey) + .then(function(data){ + if (data) { + try { + var obj = JSON.parse(data); + return obj; + } catch (e) { + } + } + return self.updateCheck(deploymentKey, appVersion, label, packageHash) + .then(function(rs){ + try { + var strRs = JSON.stringify(rs); + client.setexAsync(redisCacheKey, EXPIRED, strRs); + } catch (e) { + } + return rs; + }); + }) +} + proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { var rs = { downloadURL: "", diff --git a/routes/apps.js b/routes/apps.js index 14670973..7992df69 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -240,6 +240,15 @@ router.post('/:appName/deployments/:deploymentName/release', }); }); } + //clear cache if exists. + if (_.get(config, 'common.updateCheckCache', false) !== false) { + Promise.delay(2500) + .then(function () { + var ClientManager = require('../core/services/client-manager'); + var clientManager = new ClientManager(); + clientManager.clearUpdateCheckCache(deploymentInfo.deployment_key, '*', '*', '*'); + }); + } return null; }); }); @@ -274,6 +283,15 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment if (!destDeploymentInfo) { throw new Error(`${destDeploymentName} does not exist.`); } + //clear cache if exists. + if (_.get(config, 'common.updateCheckCache', false) !== false) { + Promise.delay(2500) + .then(function () { + var ClientManager = require('../core/services/client-manager'); + var clientManager = new ClientManager(); + clientManager.clearUpdateCheckCache(destDeploymentInfo.deployment_key, '*', '*', '*'); + }); + } return [sourceDeploymentInfo.id, destDeploymentInfo.id]; }) .spread(function (sourceDeploymentId, destDeploymentId) { diff --git a/routes/index.js b/routes/index.js index 8f18855a..97f2911f 100644 --- a/routes/index.js +++ b/routes/index.js @@ -36,7 +36,7 @@ router.get('/updateCheck', function(req, res){ var label = _.get(req, "query.label"); var packageHash = _.get(req, "query.packageHash") var clientManager = new ClientManager(); - clientManager.updateCheck(deploymentKey, appVersion, label, packageHash) + clientManager.updateCheckFromCache(deploymentKey, appVersion, label, packageHash) .then(function (rs) { res.send({"updateInfo":rs}); }) From 33cabc1bd648a754ac8ab46572d2000d27844b29 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 14 Nov 2016 16:05:47 +0800 Subject: [PATCH 011/194] 0.2.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 80743cfc..b7afc6a4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.9", + "version": "0.2.10", "license": "MIT", "repository": { "type": "git", From cc9f4a9bfd00e0c556059d6a6f471c9a752435ac Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 14 Nov 2016 19:11:56 +0800 Subject: [PATCH 012/194] change description limit length --- sql/codepush.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/codepush.sql b/sql/codepush.sql index 45d114c2..4d1322b7 100644 --- a/sql/codepush.sql +++ b/sql/codepush.sql @@ -84,7 +84,7 @@ CREATE TABLE `deployments` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `appid` int(10) unsigned NOT NULL DEFAULT '0', `name` varchar(20) NOT NULL DEFAULT '', - `description` varchar(200) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', `deployment_key` varchar(64) NOT NULL, `last_deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', `label_id` int(11) unsigned NOT NULL DEFAULT '0', @@ -145,7 +145,7 @@ DROP TABLE IF EXISTS `packages`; CREATE TABLE `packages` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `deployment_id` int(10) unsigned NOT NULL DEFAULT '0', - `description` varchar(100) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', `package_hash` varchar(64) NOT NULL DEFAULT '', `blob_url` varchar(255) NOT NULL DEFAULT '', `size` int(11) unsigned NOT NULL DEFAULT '0', From fd156d5927e1fc4b1a874edd89a686618d4adea5 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 14 Nov 2016 20:04:59 +0800 Subject: [PATCH 013/194] fix dir --- app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index e6f2a16c..fbe4a409 100644 --- a/app.js +++ b/app.js @@ -51,8 +51,10 @@ if (app.get('env') === 'development') { if (_.get(config, 'common.storageType') === 'local' && _.get(config, 'local.storageDir') - && fs.existsSync(_.get(config, 'local.storageDir')) ) { + if (!fs.existsSync(_.get(config, 'local.storageDir'))) { + throw new Error(`Please create dir ${_.get(config, 'local.storageDir')}`); + } app.use(_.get(config, 'local.public', '/download'), express.static(_.get(config, 'local.storageDir'))); } From a4ac2d77c8a31dfbef5620bdc09334428b2b618c Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 15 Nov 2016 12:14:02 +0800 Subject: [PATCH 014/194] fix --- appveyor.yml | 12 +----------- core/services/client-manager.js | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e75f3916..8f45ad6b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,17 +6,7 @@ environment: - nodejs_version: "6" - nodejs_version: "6.1" - nodejs_version: "5" - - nodejs_version: "5.11" - - nodejs_version: "5.10" - - nodejs_version: "5.9" - - nodejs_version: "5.8" - - nodejs_version: "5.7" - - nodejs_version: "5.6" - - nodejs_version: "5.5" - - nodejs_version: "5.4" - - nodejs_version: "5.3" - - nodejs_version: "5.2" - - nodejs_version: "5.1" + services: - mysql install: diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 7f59995c..fa4808e7 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -36,11 +36,11 @@ proto.clearUpdateCheckCache = function(deploymentKey, appVersion, label, package proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageHash) { const self = this; - let redisCacheKey = self.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); var updateCheckCache = _.get(require('../config'), 'common.updateCheckCache', false); if (updateCheckCache === false) { return self.updateCheck(deploymentKey, appVersion, label, packageHash); } + let redisCacheKey = self.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); var client = factory.getRedisClient("default"); return client.getAsync(redisCacheKey) .then(function(data){ From 15f04667d67754443c246a21da946c0a2ee5cbd2 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 16 Nov 2016 11:34:33 +0800 Subject: [PATCH 015/194] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 137cd847..0596a5c0 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ $ curl -X PATCH -H "Authorization: Bearer mytoken" -H "Accept: application/json" ```shell $ cd /path/to/project -$ npm install react-native-code-push@latest +$ npm install react-native-code-push@latest --save ``` ## config react-native project From b7989f86f35078d85457b760a089d2bf56654082 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 16 Nov 2016 20:11:13 +0800 Subject: [PATCH 016/194] fix rollback bug --- routes/apps.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/routes/apps.js b/routes/apps.js index 7992df69..49b29dfa 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -330,6 +330,15 @@ var rollbackCb = function (req, res) { return deployments.findDeloymentByName(deploymentName, col.appid); }) .then(function(dep){ + //clear cache if exists. + if (_.get(config, 'common.updateCheckCache', false) !== false) { + Promise.delay(2500) + .then(function () { + var ClientManager = require('../core/services/client-manager'); + var clientManager = new ClientManager(); + clientManager.clearUpdateCheckCache(dep.deployment_key, '*', '*', '*'); + }); + } return packageManager.rollbackPackage(dep.last_deployment_version_id, targetLabel, uid); }) .then(function () { From 1f943cd90df0858ee252ee6f7994c1b8991b2fe5 Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 18 Nov 2016 23:17:02 +0800 Subject: [PATCH 017/194] fix readme --- README.md | 2 +- config/config.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0596a5c0..7a4f752d 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ $ vim config/config.js read [config.js](https://github.com/lisong/code-push-server/blob/master/config/config.js) -## Storage mode [local/qiniu] +## Storage mode [local/qiniu/s3] - 配置local存储,修改config/config.js中storageType值为local,配置中local下面storageDir和downloadUrl,如果不在同一台机器上,downloadUrl请指定域名或者ip地址 diff --git a/config/config.js b/config/config.js index beabb66b..096816aa 100644 --- a/config/config.js +++ b/config/config.js @@ -50,7 +50,7 @@ config.development = { // options value is (true | false), when it's true, it will cache updateCheck results in redis. updateCheckCache: false }, - //config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer + // Config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer smtpConfig:{ host: "smtp.mxhichina.com", port: 465, @@ -60,7 +60,7 @@ config.development = { pass: "" } }, - //config for redis (register module, tryLoginTimes module) + // Config for redis (register module, tryLoginTimes module) redis: { default: { host: "127.0.0.1", From 777e684127a13e5e6d038ffd2f9d2a8b6b55622e Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 18 Nov 2016 23:18:04 +0800 Subject: [PATCH 018/194] 0.2.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b7afc6a4..a95d0388 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.10", + "version": "0.2.11", "license": "MIT", "repository": { "type": "git", From 4cc20acee787c407d236025cf79a6a5dd6e1d333 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 21 Nov 2016 17:54:07 +0800 Subject: [PATCH 019/194] readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a4f752d..7ae8f217 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in - react-native-code-push只更新资源文件,不会更新java和Objective C,所以npm升级依赖包版本的时候,如果依赖包使用的本地化实现, 这时候必须更改应用版本号(ios修改Info.plist中的CFBundleShortVersionString, android修改build.gradle中的versionName), 然后重新编译app发布到应用商店。 - 推荐使用code-push release-react 命令发布应用,该命令合并了打包和发布命令(eg. code-push release-react CodePushDemo-ios ios -d Production) -## EXAMPLE +## EXAMPLE +codepush.19910225.com 只是一个测试server,不要将自己生产环境的项目放在上面,服务器的宽带只有1M,而且服务没有做负载均衡和监控,稳定性不能保证,烦请大家自己搭建自己的服务。 ### shell命令行端 From 5f162ab3e90ba59407a2c371394994a8ff60a451 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 26 Nov 2016 12:07:48 +0800 Subject: [PATCH 020/194] fix jwt token --- README.md | 11 +++++++---- config/config.js | 7 +++++-- config/config.test.js | 4 +++- config/config.testwin.js | 4 +++- core/middleware.js | 4 ++-- routes/auth.js | 4 ++-- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7ae8f217..eee5101f 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,13 @@ $ vim config/config.js //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址 downloadUrl: "http://localhost:3000/download" }, + jwt: { + // 登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 + // Recommended: 63 random alpha-numeric characters + // Generate using: https://www.grc.com/passwords.htm + tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' + }, common: { - //登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 - loginSecret: "CodePushServer", dataDir: "/Users/tablee/workspaces/data", //选择存储类型,目前支持local和qiniu配置 storageType: "local" @@ -110,7 +114,7 @@ or point config file and ENV $ CONFIG_FILE=/path/to/config.js NODE_ENV=production node ./bin/www # or CONFIG_FILE=/path/to/config.js NODE_ENV=production code-push-server ``` -notice. you have to change `loginSecret` in config.js for security. +notice. you have to change `tokenSecret` in config.js for security. ## Default listen Host/Port 0.0.0.0/3000 you can change like this. @@ -215,7 +219,6 @@ eg. ```json ... "common": { - "loginSecret": "CodePushServer", "codePushWebUrl": "Your CodePush Web address", } ... diff --git a/config/config.js b/config/config.js index 096816aa..19dd8ecb 100644 --- a/config/config.js +++ b/config/config.js @@ -30,9 +30,12 @@ config.development = { // public static download spacename. public: '/download' }, + jwt: { + // Recommended: 63 random alpha-numeric characters + // Generate using: https://www.grc.com/passwords.htm + tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' + }, common: { - // jwt sign secret for auth. you have to modify it for security. use random string instead it. - loginSecret: "CodePushServer", /* * tryLoginTimes is control login error times to avoid force attack. * if value is 0, no limit for login auth, it may not safe for account. when it's a number, it means you can diff --git a/config/config.test.js b/config/config.test.js index ef0792db..cb3aff60 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -14,8 +14,10 @@ config.test = { downloadUrl: "http://localhost:3000/download", public: '/download' }, + jwt: { + tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' + }, common: { - loginSecret: "CodePushServer", tryLoginTimes: 10, diffNums: 3, dataDir: os.tmpdir(), diff --git a/config/config.testwin.js b/config/config.testwin.js index 71e99d53..408f6753 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -14,8 +14,10 @@ config.test = { downloadUrl: "http://localhost:3000/download", public: '/download' }, + jwt: { + tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' + }, common: { - loginSecret: "CodePushServer", tryLoginTimes: 10, diffNums: 3, dataDir: os.tmpdir(), diff --git a/core/middleware.js b/core/middleware.js index 56e7ea24..058b3153 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -36,9 +36,9 @@ var checkAccessToken = function (accessToken) { throw new Error('401 Unauthorized'); } var config = require('../core/config'); - var loginSecret = _.get(config, 'common.loginSecret'); + var tokenSecret = _.get(config, 'jwt.tokenSecret'); var jwt = require('jsonwebtoken'); - var authData = jwt.verify(accessToken, loginSecret); + var authData = jwt.verify(accessToken, tokenSecret); var uid = _.get(authData, 'uid', null); var hash = _.get(authData, 'hash', null); if (parseInt(uid) > 0) { diff --git a/routes/auth.js b/routes/auth.js index 4d6cff42..5f805b86 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -50,11 +50,11 @@ router.post('/login', function(req, res) { var account = _.trim(req.body.account); var password = _.trim(req.body.password); var config = require('../core/config'); - var loginSecret = _.get(config, 'common.loginSecret'); + var tokenSecret = _.get(config, 'jwt.tokenSecret'); accountManager.login(account, password) .then(function (users) { var jwt = require('jsonwebtoken'); - return jwt.sign({ uid: users.id, hash: security.md5(users.ack_code), expiredIn: 7200 }, loginSecret); + return jwt.sign({ uid: users.id, hash: security.md5(users.ack_code), expiredIn: 7200 }, tokenSecret); }) .then(function (token) { res.send({status:'OK', results: {tokens: token}}); From 1e30abc4c6c71841e567aa42ee998307522c3a9f Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 1 Dec 2016 17:40:30 +0800 Subject: [PATCH 021/194] update Dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a95d0388..2353c815 100644 --- a/package.json +++ b/package.json @@ -40,23 +40,23 @@ "bluebird": "^3.4.1", "body-parser": "^1.15.2", "cookie-parser": "^1.4.3", - "debug": "~2.2.0", + "debug": "^2.3.3", "express": "^4.14.0", "formidable": "^1.0.17", - "fs-extra": "^0.30.0", - "helmet": "^2.1.0", + "fs-extra": "^1.0.0", + "helmet": "^3.1.0", "jsonwebtoken": "^7.1.7", "lodash": "^4.5.1", "markdown-it": "^8.0.1", "moment": "^2.14.1", - "morgan": "~1.6.1", + "morgan": "^1.7.0", "mysql": "^2.10.2", "node-unzip-2": "^0.2.1", "nodemailer": "^2.5.0", "pug": "^2.0.0-beta6", "qiniu": "^6.1.10", "rand-token": "^0.2.1", - "recursive-fs": "^0.1.4", + "recursive-fs": "^1.0.0", "redis": "^2.6.2", "request": "^2.72.0", "sequelize": "^3.24.5", From 291ff0e67980becd6e6c17494c61c2db63f11475 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 1 Dec 2016 18:36:11 +0800 Subject: [PATCH 022/194] 0.2.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2353c815..142e025b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.11", + "version": "0.2.12", "license": "MIT", "repository": { "type": "git", From b9bba3cf9742e0cc6ba76aac55172d81c0ca7d42 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 4 Dec 2016 15:10:52 +0800 Subject: [PATCH 023/194] add qq contract --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index eee5101f..46fc7cfc 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use local storage, just modify config.js file, it's simple configure. +## qq交流群 535491067 + ## 正确使用code-push热更新 - 苹果允许使用热更新[Apple's developer agreement](https://developer.apple.com/programs/ios/information/iOS_Program_Information_4_3_15.pdf), 但是规定不能弹框提示用户更新,影响用户体验。 而Google Play恰好相反,必须弹框告知用户更新。然而中国的android市场都必须关闭更新弹框,否则会在审核应用时以“请上传最新版本的二进制应用包”驳回应用。 From e3cd5855afde21236a3a2aad8dc72265cbd5b5cb Mon Sep 17 00:00:00 2001 From: simonxu Date: Tue, 13 Dec 2016 10:43:21 +0800 Subject: [PATCH 024/194] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/db | 22 +++++++++++++--------- config/config.js | 1 + config/config.test.js | 1 + config/config.testwin.js | 1 + 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/bin/db b/bin/db index 7b2c5942..30703e83 100755 --- a/bin/db +++ b/bin/db @@ -6,39 +6,43 @@ var fs = require('fs'); var path = require('path'); var _ = require('lodash'); +var mysql = require('mysql'); +var Promise = require("bluebird"); var yargs = require('yargs') .usage('Usage: $0 [options]') .command('init', '初始化数据库') - .example('$0 init --dbname codepush --dbhost localhost --dbuser root --dbpassword 123456', '初始化code-push-server数据库') + .example('$0 init --dbname codepush --dbhost localhost --dbuser root --dbpassword 123456 --dbport 3306 --force', '初始化code-push-server数据库') .default({dbname: 'codepush', dbhost: 'localhost', dbuser: 'root', dbpassword: null}) .help('h') .alias('h', 'help'); -var argv = yargs - .argv; +var argv = yargs.argv; var command = argv._[0]; -var mysql = require('mysql'); -var Promise = require("bluebird"); var dbname = argv.dbname ? argv.dbname : 'codepush'; var dbhost = argv.dbhost ? argv.dbhost : 'localhost'; var dbuser = argv.dbuser ? argv.dbuser : 'root'; +var dbport = argv.dbport ? argv.dbport : 3306; var dbpassword = _.isString(argv.dbpassword) ? argv.dbpassword : null; if (command === 'init') { var connection2; var connection = mysql.createConnection({ host: dbhost, user: dbuser, - password: dbpassword + password: dbpassword, + port: dbport }); + var createDatabaseSql = argv.force ? `CREATE DATABASE if not exists ${dbname}` : + `CREATE DATABASE ${dbname}`; Promise.promisifyAll(connection); connection.connect(); - connection.queryAsync(`CREATE DATABASE ${dbname}`) + connection.queryAsync(createDatabaseSql) .then(function(){ connection2 = mysql.createConnection({ host: dbhost, user: dbuser, password: dbpassword, database: dbname, - multipleStatements: true + multipleStatements: true, + port: dbport }); connection2.connect(); Promise.promisifyAll(connection2); @@ -68,4 +72,4 @@ if (command === 'init') { }); } else { yargs.showHelp(); -} \ No newline at end of file +} diff --git a/config/config.js b/config/config.js index 19dd8ecb..8d8d4bba 100644 --- a/config/config.js +++ b/config/config.js @@ -6,6 +6,7 @@ config.development = { password: null, database: "codepush", host: "127.0.0.1", + port: 3306, dialect: "mysql" }, // Config for qiniu (http://www.qiniu.com/) cloud storage when storageType value is "qiniu". diff --git a/config/config.test.js b/config/config.test.js index cb3aff60..4e0722be 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -7,6 +7,7 @@ config.test = { password: null, database: "codepush_test", host: "127.0.0.1", + port: 3306, dialect: "mysql" }, local: { diff --git a/config/config.testwin.js b/config/config.testwin.js index 408f6753..24d017cd 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -7,6 +7,7 @@ config.test = { password: "Password12!", database: "codepush_test", host: "127.0.0.1", + port: 3306, dialect: "mysql" }, local: { From 7f6b196c118becc50346029de82aa98607a397c2 Mon Sep 17 00:00:00 2001 From: simonxu Date: Tue, 13 Dec 2016 10:50:52 +0800 Subject: [PATCH 025/194] =?UTF-8?q?=E4=BD=BF=E7=94=A8bcryptjs=EF=BC=8Cbcry?= =?UTF-8?q?pt=E5=AE=89=E8=A3=85=E5=A4=AA=E6=8B=BC=E4=BA=BA=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/utils/security.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/utils/security.js b/core/utils/security.js index a38a5dcd..edb3e730 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -1,5 +1,5 @@ 'use strict'; -var bcrypt = require('bcrypt'); +var bcrypt = require('bcryptjs'); var crypto = require('crypto'); var fs = require('fs'); var Promise = require('bluebird'); diff --git a/package.json b/package.json index 142e025b..ea62885e 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "aws-sdk": "^2.7.0", - "bcrypt": "^0.8.7", + "bcryptjs": "^2.3.0", "bluebird": "^3.4.1", "body-parser": "^1.15.2", "cookie-parser": "^1.4.3", From 67ee5179664280783bf57c6c4a9b818c32e3e8b7 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 13 Dec 2016 11:39:07 +0800 Subject: [PATCH 026/194] fixbug --- app.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index fbe4a409..6f3ca588 100644 --- a/app.js +++ b/app.js @@ -40,10 +40,10 @@ app.use(express.static(path.join(__dirname, 'public'))); //use nginx in production if (app.get('env') === 'development') { app.all('*', function(req, res, next) { - res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); - res.header("Access-Control-Allow-Methods","PUT,POST,GET,PATCH,DELETE,OPTIONS"); - next(); + res.header("Access-Control-Allow-Origin", "*"); + res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); + res.header("Access-Control-Allow-Methods","PUT,POST,GET,PATCH,DELETE,OPTIONS"); + next(); }); } @@ -53,7 +53,8 @@ if (_.get(config, 'common.storageType') === 'local' && _.get(config, 'local.storageDir') ) { if (!fs.existsSync(_.get(config, 'local.storageDir'))) { - throw new Error(`Please create dir ${_.get(config, 'local.storageDir')}`); + var dir = _.get(config, 'local.storageDir'); + throw new Error(`Please create dir ${dir}`); } app.use(_.get(config, 'local.public', '/download'), express.static(_.get(config, 'local.storageDir'))); } From de4c7b5791b3a4805f198f8a97319421ed1e886b Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 13 Dec 2016 11:39:46 +0800 Subject: [PATCH 027/194] 0.2.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea62885e..259b606e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.12", + "version": "0.2.13", "license": "MIT", "repository": { "type": "git", From 472d7157ae4f7a81c27295dae6c5f0f9db351132 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 20 Dec 2016 09:27:07 +0800 Subject: [PATCH 028/194] fix --- core/services/account-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/services/account-manager.js b/core/services/account-manager.js index 44250c5b..4b12cd81 100644 --- a/core/services/account-manager.js +++ b/core/services/account-manager.js @@ -21,7 +21,7 @@ proto.collaboratorCan = function(uid, appName) { return this.getCollaborator(uid, appName) .then(function (data) { if (!data) { - throw new Error("Permission Deny!"); + throw new Error(`App ${appName} not exists.`); } return data; }); From fe95ba8d4528f386622136c56eb841b087d27bb1 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 2 Jan 2017 18:06:21 +0800 Subject: [PATCH 029/194] add db upgrade and fix is_mandatory --- app.js | 2 - bin/db | 59 +++++-- bin/www | 19 ++- core/services/client-manager.js | 2 +- core/services/deployments.js | 2 +- core/services/package-manager.js | 40 ++++- models/deployments_versions.js | 1 - models/packages.js | 1 + models/versions.js | 20 +++ routes/apps.js | 5 + sql/{codepush.sql => codepush-all.sql} | 205 +++++-------------------- sql/codepush-v0.0.1.sql | 154 +++++++++++++++++++ sql/codepush-v0.1.1.sql | 3 - sql/codepush-v0.1.5.sql | 13 -- sql/codepush-v0.2.24.sql | 16 ++ test/api/init/database.js | 21 +-- 16 files changed, 332 insertions(+), 231 deletions(-) create mode 100644 models/versions.js rename sql/{codepush.sql => codepush-all.sql} (51%) create mode 100644 sql/codepush-v0.0.1.sql delete mode 100644 sql/codepush-v0.1.1.sql delete mode 100644 sql/codepush-v0.1.5.sql create mode 100644 sql/codepush-v0.2.24.sql diff --git a/app.js b/app.js index 6f3ca588..707c45ec 100644 --- a/app.js +++ b/app.js @@ -47,8 +47,6 @@ if (app.get('env') === 'development') { }); } - - if (_.get(config, 'common.storageType') === 'local' && _.get(config, 'local.storageDir') ) { diff --git a/bin/db b/bin/db index 30703e83..c47ede8f 100755 --- a/bin/db +++ b/bin/db @@ -11,7 +11,9 @@ var Promise = require("bluebird"); var yargs = require('yargs') .usage('Usage: $0 [options]') .command('init', '初始化数据库') + .command('upgrade', '升级数据库') .example('$0 init --dbname codepush --dbhost localhost --dbuser root --dbpassword 123456 --dbport 3306 --force', '初始化code-push-server数据库') + .example('$0 upgrade --dbname codepush --dbhost localhost --dbuser root --dbpassword 123456 --dbport 3306', '升级code-push-server数据库') .default({dbname: 'codepush', dbhost: 'localhost', dbuser: 'root', dbpassword: null}) .help('h') .alias('h', 'help'); @@ -22,6 +24,7 @@ var dbhost = argv.dbhost ? argv.dbhost : 'localhost'; var dbuser = argv.dbuser ? argv.dbuser : 'root'; var dbport = argv.dbport ? argv.dbport : 3306; var dbpassword = _.isString(argv.dbpassword) ? argv.dbpassword : null; + if (command === 'init') { var connection2; var connection = mysql.createConnection({ @@ -30,7 +33,7 @@ if (command === 'init') { password: dbpassword, port: dbport }); - var createDatabaseSql = argv.force ? `CREATE DATABASE if not exists ${dbname}` : + var createDatabaseSql = argv.force ? `CREATE DATABASE IF NOT EXISTS ${dbname}` : `CREATE DATABASE ${dbname}`; Promise.promisifyAll(connection); connection.connect(); @@ -49,16 +52,8 @@ if (command === 'init') { return connection2; }) .then(function(connection2){ - var sql = fs.readFileSync(path.resolve(__dirname, '../sql/codepush.sql'), 'utf-8'); - var sql2 = fs.readFileSync(path.resolve(__dirname, '../sql/codepush-v0.1.1.sql'), 'utf-8'); - var sql3 = fs.readFileSync(path.resolve(__dirname, '../sql/codepush-v0.1.5.sql'), 'utf-8'); - return connection2.queryAsync(sql) - .then(function(){ - return connection2.queryAsync(sql2); - }) - .then(function(){ - return connection2.queryAsync(sql3); - }); + var sql = fs.readFileSync(path.resolve(__dirname, '../sql/codepush-all.sql'), 'utf-8'); + return connection2.queryAsync(sql); }) .then(function(){ console.log('success.'); @@ -70,6 +65,48 @@ if (command === 'init') { if(connection) connection.end(); if(connection2) connection2.end() }); +} else if (command == 'upgrade'){ + var connection = mysql.createConnection({ + host: dbhost, + user: dbuser, + password: dbpassword, + database: dbname, + multipleStatements: true, + port: dbport + }); + Promise.promisifyAll(connection); + connection.connect(); + return Promise.coroutine(function*(val){ + var version_no = '0.0.1'; + try { + var rs = yield connection.queryAsync('select `version` from `versions` where `type`=1 limit 1'); + version_no = _.get(rs,'0.version', '0.0.1'); + } catch (e) { + } + if (version_no == '0.2.14') { + console.log('Everything up-to-date.'); + process.exit(1); + } + var allSqlFile = [ + {version:'0.2.24', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.24.sql')} + ]; + for (var i = 0; i < allSqlFile.length; i++) { + if(!_.gt(allSqlFile[i]['version'], version_no)) { + continue; + } + var sql = fs.readFileSync(allSqlFile[i]['path'], 'utf-8'); + yield connection.queryAsync(sql); + } + })() + .then(function(){ + console.log('Upgrade success.'); + }) + .catch(function(e){ + console.error(e); + }) + .finally(function(){ + if(connection) connection.end(); + }); } else { yargs.showHelp(); } diff --git a/bin/www b/bin/www index 8cdddd19..ced1a790 100755 --- a/bin/www +++ b/bin/www @@ -28,10 +28,21 @@ var server = http.createServer(app); /** * Listen on provided port, on all network interfaces. */ - -server.listen(port, host); -server.on('error', onError); -server.on('listening', onListening); +var models = require('../models'); +models.Versions.findOne({type:1}) +.then(function(v){ + if (!v) { + throw new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); + } + server.listen(port, host); + server.on('error', onError); + server.on('listening', onListening); + return; +}) +.catch(function(e){ + console.error(e); + process.exit(1); +}); /** * Normalize a port into a number, string, or false. diff --git a/core/services/client-manager.js b/core/services/client-manager.js index fa4808e7..4b5e0ba4 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -100,7 +100,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { rs.downloadURL = `${downloadURL}/${_.get(packages, 'blob_url')}`; rs.description = _.get(packages, 'description', ''); rs.isAvailable = true; - rs.isMandatory = _.eq(deploymentsVersions.is_mandatory, 1) ? true : false; + rs.isMandatory = _.eq(packages.is_mandatory, 1) ? true : false; rs.appVersion = appVersion; rs.packageHash = _.get(packages, 'package_hash', ''); rs.label = _.get(packages, 'label', ''); diff --git a/core/services/deployments.js b/core/services/deployments.js index 2034f57d..47208204 100644 --- a/core/services/deployments.js +++ b/core/services/deployments.js @@ -135,7 +135,7 @@ proto.formatPackage = function(packageVersion) { return { description: _.get(packageVersion, "packageInfo.description"), isDisabled: false, - isMandatory: _.get(packageVersion, "deploymentsVersions.is_mandatory") == 2 ? true : false, + isMandatory: _.get(packageVersion, "packageInfo.is_mandatory") == 1 ? true : false, rollout: 100, appVersion: _.get(packageVersion, "deploymentsVersions.app_version"), packageHash: _.get(packageVersion, "packageInfo.package_hash"), diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 3d771163..72a403d8 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -54,7 +54,6 @@ proto.existPackageHashAndCreateVersions = function (deploymentId, appVersion, pa return models.DeploymentsVersions.create({ deployment_id: deploymentId, app_version: appVersion, - is_mandatory: false, }).then(function () { return false; }); @@ -91,7 +90,6 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH .then(function (deploymentsVersions) { if (!deploymentsVersions) { return models.DeploymentsVersions.create({ - is_mandatory: isMandatory, current_package_id: 0, deployment_id: deploymentId, app_version: appVersion @@ -111,11 +109,11 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH release_method: releaseMethod, label: "v" + labelId, released_by: releaseUid, + is_mandatory: isMandatory, original_label: originalLabel, original_deployment: originalDeployment },{transaction: t}) .then(function (packages) { - deploymentsVersions.set('is_mandatory', isMandatory); deploymentsVersions.set('current_package_id', packages.id); return Promise.all([ deploymentsVersions.save({transaction: t}), @@ -275,7 +273,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, var self = this; var appVersion = packageInfo.appVersion; if (!/^([0-9.]+)$/.test(appVersion)) { - return Promise.reject(new Error(`targetBinaryVersion not support.`)) + return Promise.reject(new Error(`targetBinaryVersion ${appVersion} not support.`)) } var description = packageInfo.description; var isMandatory = packageInfo.isMandatory; @@ -352,6 +350,36 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, }); }; +proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, packageInfo) { + var appVersion = _.get(packageInfo, 'appVersion'); + var description = _.get(packageInfo, 'description'); + var isMandatory = _.get(packageInfo, 'isMandatory'); + var isDisabled = _.get(packageInfo, 'isDisabled'); + return models.DeploymentsVersions.findById(deploymentVersionId) + .then(function(deploymentsVersions){ + if (_.isBoolean(isDisabled)) { + throw new Error(`--disabled -x function is not implements`); + } + if (!appVersion) { + if (!/^([0-9.]+)$/.test(appVersion)) { + return Promise.reject(new Error(`targetBinaryVersion ${appVersion} not support.`)) + } + return models.DeploymentsVersions.findOne({deployment_id: deploymentId, app_version: appVersion}) + .then(function(d){ + if (d) { + throw new Error(`version ${appVersion} already exist`); + } + }); + } + if(!deploymentsVersions) { + throw new Error(`packages were not found in db`); + } + }) + .then(function(){ + + }); +}; + proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUid) { var self = this; return models.Deployments.findById(sourceDeploymentId) @@ -387,7 +415,7 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUi var params = { releaseMethod: 'Promote', releaseUid: promoteUid, - isMandatory: deploymentsVersions.is_mandatory, + isMandatory: packages.is_mandatory == 1 ? true : false, size: packages.size, description: packages.description, originalLabel: packages.label, @@ -432,7 +460,7 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) var params = { releaseMethod: 'Rollback', releaseUid: rollbackUid, - isMandatory: deploymentsVersions.is_mandatory, + isMandatory: rollbackPackage.is_mandatory == 1 ? true : false, size: rollbackPackage.size, description: rollbackPackage.description, originalLabel: rollbackPackage.label, diff --git a/models/deployments_versions.js b/models/deployments_versions.js index b95596b2..67f474ca 100644 --- a/models/deployments_versions.js +++ b/models/deployments_versions.js @@ -10,7 +10,6 @@ module.exports = function(sequelize, DataTypes) { }, deployment_id: DataTypes.INTEGER(10), app_version: DataTypes.STRING, - is_mandatory: DataTypes.INTEGER(3), current_package_id: DataTypes.INTEGER(10), created_at: DataTypes.DATE, updated_at: DataTypes.DATE, diff --git a/models/packages.js b/models/packages.js index 29d5eb3f..6d6a0b0e 100644 --- a/models/packages.js +++ b/models/packages.js @@ -20,6 +20,7 @@ module.exports = function(sequelize, DataTypes) { original_label: DataTypes.STRING, original_deployment: DataTypes.STRING, released_by: DataTypes.STRING, + is_mandatory: DataTypes.INTEGER(3), created_at: DataTypes.DATE, updated_at: DataTypes.DATE, }, { diff --git a/models/versions.js b/models/versions.js new file mode 100644 index 00000000..69279d1d --- /dev/null +++ b/models/versions.js @@ -0,0 +1,20 @@ +"use strict"; + +module.exports = function(sequelize, DataTypes) { + var Versions = sequelize.define("Versions", { + id: { + type: DataTypes.INTEGER(10), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + type: DataTypes.INTEGER, + version: DataTypes.STRING + }, { + tableName: 'versions', + updatedAt: false, + createdAt: false + }); + + return Versions; +}; diff --git a/routes/apps.js b/routes/apps.js index 49b29dfa..1e3dcb40 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -261,6 +261,11 @@ router.post('/:appName/deployments/:deploymentName/release', }); }); +router.patch('/:appName/deployments/:deploymentName/release', + middleware.checkToken, function (req, res) { + res.status(406).send('Not supported currently'); +}); + router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeploymentName', middleware.checkToken, function (req, res) { var appName = _.trim(req.params.appName); diff --git a/sql/codepush.sql b/sql/codepush-all.sql similarity index 51% rename from sql/codepush.sql rename to sql/codepush-all.sql index 4d1322b7..99d12ea9 100644 --- a/sql/codepush.sql +++ b/sql/codepush-all.sql @@ -1,27 +1,4 @@ --- MySQL dump 10.13 Distrib 5.6.27, for osx10.11 (x86_64) --- --- Host: localhost Database: codepush --- ------------------------------------------------------ --- Server version 5.6.27 - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `apps` --- - DROP TABLE IF EXISTS `apps`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `apps` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '', @@ -32,24 +9,8 @@ CREATE TABLE `apps` ( PRIMARY KEY (`id`), KEY `idx_name` (`name`(12)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `apps` --- - -LOCK TABLES `apps` WRITE; -/*!40000 ALTER TABLE `apps` DISABLE KEYS */; -/*!40000 ALTER TABLE `apps` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `collaborators` --- DROP TABLE IF EXISTS `collaborators`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `collaborators` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `appid` int(10) unsigned NOT NULL DEFAULT '0', @@ -62,24 +23,9 @@ CREATE TABLE `collaborators` ( KEY `idx_appid` (`appid`), KEY `idx_uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `collaborators` --- - -LOCK TABLES `collaborators` WRITE; -/*!40000 ALTER TABLE `collaborators` DISABLE KEYS */; -/*!40000 ALTER TABLE `collaborators` ENABLE KEYS */; -UNLOCK TABLES; --- --- Table structure for table `deployments` --- DROP TABLE IF EXISTS `deployments`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `deployments` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `appid` int(10) unsigned NOT NULL DEFAULT '0', @@ -95,55 +41,35 @@ CREATE TABLE `deployments` ( KEY `idx_appid` (`appid`), KEY `idx_deploymentkey` (`deployment_key`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; --- --- Dumping data for table `deployments` --- - -LOCK TABLES `deployments` WRITE; -/*!40000 ALTER TABLE `deployments` DISABLE KEYS */; -/*!40000 ALTER TABLE `deployments` ENABLE KEYS */; -UNLOCK TABLES; +DROP TABLE IF EXISTS `deployments_history`; +CREATE TABLE `deployments_history` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_deployment_id` (`deployment_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- --- Table structure for table `deployments_versions` --- DROP TABLE IF EXISTS `deployments_versions`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `deployments_versions` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', `app_version` varchar(14) NOT NULL DEFAULT '', - `is_mandatory` tinyint(4) NOT NULL DEFAULT '0', `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', PRIMARY KEY (`id`), UNIQUE KEY `idx_did_appversion` (`deployment_id`,`app_version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `deployments_versions` --- - -LOCK TABLES `deployments_versions` WRITE; -/*!40000 ALTER TABLE `deployments_versions` DISABLE KEYS */; -/*!40000 ALTER TABLE `deployments_versions` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `packages` --- DROP TABLE IF EXISTS `packages`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `packages` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', `deployment_id` int(10) unsigned NOT NULL DEFAULT '0', `description` varchar(500) NOT NULL DEFAULT '', `package_hash` varchar(64) NOT NULL DEFAULT '', @@ -157,27 +83,13 @@ CREATE TABLE `packages` ( `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', `released_by` bigint(20) unsigned NOT NULL, + `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), - KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)) + KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), + KEY `idx_versions_id` (`deployment_version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `packages` --- - -LOCK TABLES `packages` WRITE; -/*!40000 ALTER TABLE `packages` DISABLE KEYS */; -/*!40000 ALTER TABLE `packages` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `packages_diff` --- DROP TABLE IF EXISTS `packages_diff`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `packages_diff` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `package_id` int(11) unsigned NOT NULL DEFAULT '0', @@ -189,24 +101,8 @@ CREATE TABLE `packages_diff` ( PRIMARY KEY (`id`), KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `packages_diff` --- - -LOCK TABLES `packages_diff` WRITE; -/*!40000 ALTER TABLE `packages_diff` DISABLE KEYS */; -/*!40000 ALTER TABLE `packages_diff` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `packages_metrics` --- DROP TABLE IF EXISTS `packages_metrics`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `packages_metrics` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `package_id` int(10) unsigned NOT NULL DEFAULT '0', @@ -219,30 +115,16 @@ CREATE TABLE `packages_metrics` ( PRIMARY KEY (`id`), UNIQUE KEY `udx_packageid` (`package_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `packages_metrics` --- - -LOCK TABLES `packages_metrics` WRITE; -/*!40000 ALTER TABLE `packages_metrics` DISABLE KEYS */; -/*!40000 ALTER TABLE `packages_metrics` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `user_tokens` --- DROP TABLE IF EXISTS `user_tokens`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `user_tokens` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `name` varchar(50) NOT NULL DEFAULT '', `tokens` varchar(64) NOT NULL DEFAULT '', `created_by` varchar(64) NOT NULL DEFAULT '', - `description` varchar(64) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', + `is_session` tinyint(3) unsigned NOT NULL DEFAULT '0', `expires_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `deleted_at` timestamp NULL DEFAULT NULL, @@ -250,56 +132,39 @@ CREATE TABLE `user_tokens` ( KEY `idx_uid` (`uid`), KEY `idx_tokens` (`tokens`) KEY_BLOCK_SIZE=16 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `user_tokens` --- - -LOCK TABLES `user_tokens` WRITE; -/*!40000 ALTER TABLE `user_tokens` DISABLE KEYS */; -/*!40000 ALTER TABLE `user_tokens` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `users` --- DROP TABLE IF EXISTS `users`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE `users` ( `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL DEFAULT '', `password` varchar(255) NOT NULL DEFAULT '', `email` varchar(100) NOT NULL DEFAULT '', `identical` varchar(10) NOT NULL DEFAULT '', + `ack_code` varchar(10) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', PRIMARY KEY (`id`), UNIQUE KEY `udx_identical` (`identical`), KEY `udx_username` (`username`), KEY `idx_email` (`email`) KEY_BLOCK_SIZE=20 -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- --- Dumping data for table `users` --- +INSERT INTO `users` (`id`, `username`, `password`, `email`, `identical`, `ack_code`, `updated_at`, `created_at`) +VALUES + (1,'admin','$2a$12$mvUY9kTqW4kSoGuZFDW0sOSgKmNY8SPHVyVrSckBTLtXKf6vKX3W.','lisong2010@gmail.com','4ksvOXqog','oZmGE','2016-11-14 10:46:55','2016-02-29 21:24:49'); -LOCK TABLES `users` WRITE; -/*!40000 ALTER TABLE `users` DISABLE KEYS */; -INSERT INTO `users` VALUES (1,'admin','$2a$12$mvUY9kTqW4kSoGuZFDW0sOSgKmNY8SPHVyVrSckBTLtXKf6vKX3W.','lisong2010@gmail.com','4ksvOXqog','2016-03-16 08:04:51','2016-02-29 13:24:49'); -/*!40000 ALTER TABLE `users` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +DROP TABLE IF EXISTS `versions`; +CREATE TABLE `versions` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '1.DBversion', + `version` varchar(10) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + UNIQUE KEY `udx_type` (`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- Dump completed on 2016-03-16 16:06:10 +LOCK TABLES `versions` WRITE; +INSERT INTO `versions` (`id`, `type`, `version`) +VALUES + (1,1,'0.2.14'); +UNLOCK TABLES; \ No newline at end of file diff --git a/sql/codepush-v0.0.1.sql b/sql/codepush-v0.0.1.sql new file mode 100644 index 00000000..3db07c2a --- /dev/null +++ b/sql/codepush-v0.0.1.sql @@ -0,0 +1,154 @@ +DROP TABLE IF EXISTS `apps`; +CREATE TABLE `apps` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL DEFAULT '', + `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`(12)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `collaborators`; +CREATE TABLE `collaborators` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `appid` int(10) unsigned NOT NULL DEFAULT '0', + `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `roles` varchar(20) NOT NULL DEFAULT '', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_appid` (`appid`), + KEY `idx_uid` (`uid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `deployments`; +CREATE TABLE `deployments` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `appid` int(10) unsigned NOT NULL DEFAULT '0', + `name` varchar(20) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', + `deployment_key` varchar(64) NOT NULL, + `last_deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', + `label_id` int(11) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_appid` (`appid`), + KEY `idx_deploymentkey` (`deployment_key`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `deployments_history`; +CREATE TABLE `deployments_history` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_deployment_id` (`deployment_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `deployments_versions`; +CREATE TABLE `deployments_versions` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', + `app_version` varchar(14) NOT NULL DEFAULT '', + `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_did_appversion` (`deployment_id`,`app_version`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `packages`; +CREATE TABLE `packages` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', + `deployment_id` int(10) unsigned NOT NULL DEFAULT '0', + `description` varchar(500) NOT NULL DEFAULT '', + `package_hash` varchar(64) NOT NULL DEFAULT '', + `blob_url` varchar(255) NOT NULL DEFAULT '', + `size` int(11) unsigned NOT NULL DEFAULT '0', + `manifest_blob_url` varchar(255) NOT NULL DEFAULT '', + `release_method` varchar(20) NOT NULL DEFAULT '', + `label` varchar(20) NOT NULL DEFAULT '', + `original_label` varchar(20) NOT NULL DEFAULT '', + `original_deployment` varchar(20) NOT NULL DEFAULT '', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `released_by` bigint(20) unsigned NOT NULL, + `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), + KEY `idx_versions_id` (`deployment_version_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `packages_diff`; +CREATE TABLE `packages_diff` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(11) unsigned NOT NULL DEFAULT '0', + `diff_against_package_hash` varchar(64) NOT NULL DEFAULT '', + `diff_blob_url` varchar(255) NOT NULL DEFAULT '', + `diff_size` int(11) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + PRIMARY KEY (`id`), + KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `packages_metrics`; +CREATE TABLE `packages_metrics` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `active` int(10) unsigned NOT NULL DEFAULT '0', + `downloaded` int(10) unsigned NOT NULL DEFAULT '0', + `failed` int(10) unsigned NOT NULL DEFAULT '0', + `installed` int(10) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + PRIMARY KEY (`id`), + UNIQUE KEY `udx_packageid` (`package_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `user_tokens`; +CREATE TABLE `user_tokens` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `name` varchar(50) NOT NULL DEFAULT '', + `tokens` varchar(64) NOT NULL DEFAULT '', + `created_by` varchar(64) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', + `is_session` tinyint(3) unsigned NOT NULL DEFAULT '0', + `expires_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_uid` (`uid`), + KEY `idx_tokens` (`tokens`) KEY_BLOCK_SIZE=16 +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL DEFAULT '', + `password` varchar(255) NOT NULL DEFAULT '', + `email` varchar(100) NOT NULL DEFAULT '', + `identical` varchar(10) NOT NULL DEFAULT '', + `ack_code` varchar(10) NOT NULL DEFAULT '', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + PRIMARY KEY (`id`), + UNIQUE KEY `udx_identical` (`identical`), + KEY `udx_username` (`username`), + KEY `idx_email` (`email`) KEY_BLOCK_SIZE=20 +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `users` (`id`, `username`, `password`, `email`, `identical`, `ack_code`, `updated_at`, `created_at`) +VALUES + (1,'admin','$2a$12$mvUY9kTqW4kSoGuZFDW0sOSgKmNY8SPHVyVrSckBTLtXKf6vKX3W.','lisong2010@gmail.com','4ksvOXqog','oZmGE','2016-11-14 10:46:55','2016-02-29 21:24:49'); diff --git a/sql/codepush-v0.1.1.sql b/sql/codepush-v0.1.1.sql deleted file mode 100644 index d5bd5f01..00000000 --- a/sql/codepush-v0.1.1.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE `users` ADD `ack_code` VARCHAR(10) NOT NULL DEFAULT '' AFTER `identical`; -ALTER TABLE `user_tokens` ADD `name` VARCHAR(50) NOT NULL DEFAULT '' AFTER `uid`; -ALTER TABLE `user_tokens` ADD `is_session` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `description`; \ No newline at end of file diff --git a/sql/codepush-v0.1.5.sql b/sql/codepush-v0.1.5.sql deleted file mode 100644 index 3beac716..00000000 --- a/sql/codepush-v0.1.5.sql +++ /dev/null @@ -1,13 +0,0 @@ -ALTER TABLE `packages` ADD `deployment_version_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `id`; -ALTER TABLE `packages` ADD INDEX `idx_versions_id` (`deployment_version_id`); - -DROP TABLE IF EXISTS `deployments_history`; -CREATE TABLE `deployments_history` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', - `package_id` int(10) unsigned NOT NULL DEFAULT '0', - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `deleted_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_deployment_id` (`deployment_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/sql/codepush-v0.2.24.sql b/sql/codepush-v0.2.24.sql new file mode 100644 index 00000000..99e6963a --- /dev/null +++ b/sql/codepush-v0.2.24.sql @@ -0,0 +1,16 @@ +DROP TABLE IF EXISTS `versions`; +CREATE TABLE `versions` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '1.DBversion', + `version` varchar(10) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + UNIQUE KEY `udx_type` (`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +LOCK TABLES `versions` WRITE; +INSERT INTO `versions` (`id`, `type`, `version`) +VALUES + (1,1,'0.2.14'); +UNLOCK TABLES; + +ALTER TABLE `packages` ADD `is_mandatory` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0'; diff --git a/test/api/init/database.js b/test/api/init/database.js index 6566de1f..90b7238e 100644 --- a/test/api/init/database.js +++ b/test/api/init/database.js @@ -51,30 +51,13 @@ describe('api/init/database.js', function() { connection.end(); }); - it('should import data codepush.sql successful', function(done) { - var sql = fs.readFileSync(path.resolve(__dirname, '../../../sql/codepush.sql'), 'utf-8'); + it('should import data codepush-all.sql successful', function(done) { + var sql = fs.readFileSync(path.resolve(__dirname, '../../../sql/codepush-all.sql'), 'utf-8'); connection.query(sql, function(err, results) { should.not.exist(err); done(); }); }); - - it('should import data codepush-v0.1.1.sql successful', function(done) { - var sql = fs.readFileSync(path.resolve(__dirname, '../../../sql/codepush-v0.1.1.sql'), 'utf-8'); - connection.query(sql, function(err, results) { - should.not.exist(err); - done(); - }); - }); - - it('should import data codepush-v0.1.5.sql successful', function(done) { - var sql = fs.readFileSync(path.resolve(__dirname, '../../../sql/codepush-v0.1.5.sql'), 'utf-8'); - connection.query(sql, function(err, results) { - should.not.exist(err); - done(); - }); - }); - }); }); From db0f48a39c1f55bc50ffd817a6fcad592f86cb8a Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 2 Jan 2017 18:17:25 +0800 Subject: [PATCH 030/194] fix created_at --- sql/codepush-all.sql | 18 +++++++++--------- sql/codepush-v0.0.1.sql | 19 +++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sql/codepush-all.sql b/sql/codepush-all.sql index 99d12ea9..f7971c82 100644 --- a/sql/codepush-all.sql +++ b/sql/codepush-all.sql @@ -4,7 +4,7 @@ CREATE TABLE `apps` ( `name` varchar(50) NOT NULL DEFAULT '', `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name` (`name`(12)) @@ -17,7 +17,7 @@ CREATE TABLE `collaborators` ( `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `roles` varchar(20) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_appid` (`appid`), @@ -35,7 +35,7 @@ CREATE TABLE `deployments` ( `last_deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', `label_id` int(11) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_appid` (`appid`), @@ -61,7 +61,7 @@ CREATE TABLE `deployments_versions` ( `app_version` varchar(14) NOT NULL DEFAULT '', `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_did_appversion` (`deployment_id`,`app_version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -81,7 +81,7 @@ CREATE TABLE `packages` ( `original_label` varchar(20) NOT NULL DEFAULT '', `original_deployment` varchar(20) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `released_by` bigint(20) unsigned NOT NULL, `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), @@ -97,7 +97,7 @@ CREATE TABLE `packages_diff` ( `diff_blob_url` varchar(255) NOT NULL DEFAULT '', `diff_size` int(11) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -111,7 +111,7 @@ CREATE TABLE `packages_metrics` ( `failed` int(10) unsigned NOT NULL DEFAULT '0', `installed` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `udx_packageid` (`package_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -125,7 +125,7 @@ CREATE TABLE `user_tokens` ( `created_by` varchar(64) NOT NULL DEFAULT '', `description` varchar(500) NOT NULL DEFAULT '', `is_session` tinyint(3) unsigned NOT NULL DEFAULT '0', - `expires_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `expires_at` timestamp NULL DEFAULT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), @@ -142,7 +142,7 @@ CREATE TABLE `users` ( `identical` varchar(10) NOT NULL DEFAULT '', `ack_code` varchar(10) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `udx_identical` (`identical`), KEY `udx_username` (`username`), diff --git a/sql/codepush-v0.0.1.sql b/sql/codepush-v0.0.1.sql index 3db07c2a..ee7ed007 100644 --- a/sql/codepush-v0.0.1.sql +++ b/sql/codepush-v0.0.1.sql @@ -4,7 +4,7 @@ CREATE TABLE `apps` ( `name` varchar(50) NOT NULL DEFAULT '', `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name` (`name`(12)) @@ -17,7 +17,7 @@ CREATE TABLE `collaborators` ( `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `roles` varchar(20) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_appid` (`appid`), @@ -35,7 +35,7 @@ CREATE TABLE `deployments` ( `last_deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', `label_id` int(11) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_appid` (`appid`), @@ -61,7 +61,7 @@ CREATE TABLE `deployments_versions` ( `app_version` varchar(14) NOT NULL DEFAULT '', `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_did_appversion` (`deployment_id`,`app_version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -81,9 +81,8 @@ CREATE TABLE `packages` ( `original_label` varchar(20) NOT NULL DEFAULT '', `original_deployment` varchar(20) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, `released_by` bigint(20) unsigned NOT NULL, - `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), KEY `idx_versions_id` (`deployment_version_id`) @@ -97,7 +96,7 @@ CREATE TABLE `packages_diff` ( `diff_blob_url` varchar(255) NOT NULL DEFAULT '', `diff_size` int(11) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -111,7 +110,7 @@ CREATE TABLE `packages_metrics` ( `failed` int(10) unsigned NOT NULL DEFAULT '0', `installed` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `udx_packageid` (`package_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -125,7 +124,7 @@ CREATE TABLE `user_tokens` ( `created_by` varchar(64) NOT NULL DEFAULT '', `description` varchar(500) NOT NULL DEFAULT '', `is_session` tinyint(3) unsigned NOT NULL DEFAULT '0', - `expires_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `expires_at` timestamp NULL DEFAULT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), @@ -142,7 +141,7 @@ CREATE TABLE `users` ( `identical` varchar(10) NOT NULL DEFAULT '', `ack_code` varchar(10) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01', + `created_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `udx_identical` (`identical`), KEY `udx_username` (`username`), From 64034167018f4e786bde73276063c032b33f5e72 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 2 Jan 2017 18:33:01 +0800 Subject: [PATCH 031/194] fix version --- bin/db | 2 +- bin/www | 13 +++++++---- routes/apps.js | 22 +++++++++++++++++++ ...epush-v0.2.24.sql => codepush-v0.2.14.sql} | 0 4 files changed, 32 insertions(+), 5 deletions(-) rename sql/{codepush-v0.2.24.sql => codepush-v0.2.14.sql} (100%) diff --git a/bin/db b/bin/db index c47ede8f..81ae3560 100755 --- a/bin/db +++ b/bin/db @@ -88,7 +88,7 @@ if (command === 'init') { process.exit(1); } var allSqlFile = [ - {version:'0.2.24', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.24.sql')} + {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14.sql')} ]; for (var i = 0; i < allSqlFile.length; i++) { if(!_.gt(allSqlFile[i]['version'], version_no)) { diff --git a/bin/www b/bin/www index ced1a790..b55c17f1 100755 --- a/bin/www +++ b/bin/www @@ -5,9 +5,10 @@ */ var app = require('../app'); -var debug = require('debug')('myapp1:server'); +var debug = require('debug')('codepush:server'); var http = require('http'); var validator = require('validator') +var _ = require('lodash') /** * Get port from environment and store in Express. */ @@ -29,9 +30,9 @@ var server = http.createServer(app); * Listen on provided port, on all network interfaces. */ var models = require('../models'); -models.Versions.findOne({type:1}) +models.Versions.findOne({where:{type:1}}) .then(function(v){ - if (!v) { + if (!v || v.get('version') != '0.2.14') { throw new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); } server.listen(port, host); @@ -40,7 +41,11 @@ models.Versions.findOne({type:1}) return; }) .catch(function(e){ - console.error(e); + if (_.startsWith(e.message, 'ER_NO_SUCH_TABLE')) { + console.error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); + } else { + console.error(e); + } process.exit(1); }); diff --git a/routes/apps.js b/routes/apps.js index 1e3dcb40..078dc5ef 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -264,6 +264,28 @@ router.post('/:appName/deployments/:deploymentName/release', router.patch('/:appName/deployments/:deploymentName/release', middleware.checkToken, function (req, res) { res.status(406).send('Not supported currently'); + var appName = _.trim(req.params.appName); + var deploymentName = _.trim(req.params.deploymentName); + var uid = req.users.id; + var deployments = new Deployments(); + var packageManager = new PackageManager(); + accountManager.collaboratorCan(uid, appName) + .then(function (col) { + return deployments.findDeloymentByName(deploymentName, col.appid) + .then(function (deploymentInfo) { + if (_.isEmpty(deploymentInfo)) { + throw new Error("does not find the deployment"); + } + var label = deploymentInfo.label; + var deploymentVersionId = deploymentInfo.last_deployment_version_id; + return packageManager.modifyReleasePackage(deploymentInfo.id, deploymentVersionId, _.get(req, 'body.packageInfo')); + }); + }).then(function (data) { + res.send(""); + }) + .catch(function (e) { + res.status(406).send(e.message); + }); }); router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeploymentName', diff --git a/sql/codepush-v0.2.24.sql b/sql/codepush-v0.2.14.sql similarity index 100% rename from sql/codepush-v0.2.24.sql rename to sql/codepush-v0.2.14.sql From cde3c36a61d73442881ec80cbcc2074d74074831 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 2 Jan 2017 18:36:44 +0800 Subject: [PATCH 032/194] fix --- routes/apps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/apps.js b/routes/apps.js index 078dc5ef..4577599d 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -263,7 +263,7 @@ router.post('/:appName/deployments/:deploymentName/release', router.patch('/:appName/deployments/:deploymentName/release', middleware.checkToken, function (req, res) { - res.status(406).send('Not supported currently'); + return res.status(406).send('Not supported currently'); var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var uid = req.users.id; From 3428bd280202b4b12cbd75d66d8b9bbb2c91da89 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 8 Jan 2017 13:59:29 +0800 Subject: [PATCH 033/194] calculate basic diff --- core/services/package-manager.js | 21 +++++++++++++++++++++ routes/apps.js | 8 ++++++++ 2 files changed, 29 insertions(+) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 72a403d8..669b8119 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -245,6 +245,27 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { }); }; +/** 基于第一个版本创建补丁更新**/ +proto.createBaseDiffPackages = function (packageId) { + var self = this; + return models.Packages.findById(packageId) + .then(function (originalPackage) { + if (_.isEmpty(originalPackage)) { + throw Error('can\'t find Package'); + } + return models.Packages.findAll({ + where:{ + deployment_version_id: originalPackage.deployment_version_id, + id: {$lt: packageId}}, + order: [['id','asc']], + limit: 2 + }) + .then(function (lastNumsPackages) { + return self.createDiffPackages(originalPackage, lastNumsPackages); + }); + }); +}; + proto.createDiffPackages = function (originalPackage, destPackages) { if (!_.isArray(destPackages)) { return Promise.reject(new Error('第二个参数必须是数组')); diff --git a/routes/apps.js b/routes/apps.js index 4577599d..0265994d 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -234,6 +234,10 @@ router.post('/:appName/deployments/:deploymentName/release', if (packages) { Promise.delay(2000) .then(function () { + packageManager.createBaseDiffPackages(packages.id) + .catch(function(e){ + console.log(e); + }); packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch(function(e){ console.log(e); @@ -329,6 +333,10 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment if (packages) { Promise.delay(2000) .then(function () { + packageManager.createBaseDiffPackages(packages.id) + .catch(function(e){ + console.log(e); + }); packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch(function(e){ console.log(e); From c36aa79a7c1642a93fb1aef25251df843b7a8e7b Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 8 Jan 2017 15:00:45 +0800 Subject: [PATCH 034/194] calculate basic diff2 --- core/services/package-manager.js | 48 +++++++++++++------------------- routes/apps.js | 8 ------ 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 669b8119..d47d1105 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -232,35 +232,27 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { if (_.isEmpty(originalPackage)) { throw Error('can\'t find Package'); } - return models.Packages.findAll({ - where:{ - deployment_version_id: originalPackage.deployment_version_id, - id: {$lt: packageId}}, - order: [['id','desc']], - limit: num + return Promise.all([ + models.Packages.findAll({ + where:{ + deployment_version_id: originalPackage.deployment_version_id, + id: {$lt: packageId}}, + order: [['id','desc']], + limit: num + }), + models.Packages.findAll({ + where:{ + deployment_version_id: originalPackage.deployment_version_id, + id: {$lt: packageId}}, + order: [['id','asc']], + limit: 2 }) - .then(function (lastNumsPackages) { - return self.createDiffPackages(originalPackage, lastNumsPackages); - }); - }); -}; - -/** 基于第一个版本创建补丁更新**/ -proto.createBaseDiffPackages = function (packageId) { - var self = this; - return models.Packages.findById(packageId) - .then(function (originalPackage) { - if (_.isEmpty(originalPackage)) { - throw Error('can\'t find Package'); - } - return models.Packages.findAll({ - where:{ - deployment_version_id: originalPackage.deployment_version_id, - id: {$lt: packageId}}, - order: [['id','asc']], - limit: 2 - }) - .then(function (lastNumsPackages) { + ]) + .spread(function (lastNumsPackages, basePackages) { + return _.unionBy(lastNumsPackages, basePackages, 'id'); + }) + .then(function(lastNumsPackages){ + console.log(lastNumsPackages); return self.createDiffPackages(originalPackage, lastNumsPackages); }); }); diff --git a/routes/apps.js b/routes/apps.js index 0265994d..4577599d 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -234,10 +234,6 @@ router.post('/:appName/deployments/:deploymentName/release', if (packages) { Promise.delay(2000) .then(function () { - packageManager.createBaseDiffPackages(packages.id) - .catch(function(e){ - console.log(e); - }); packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch(function(e){ console.log(e); @@ -333,10 +329,6 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment if (packages) { Promise.delay(2000) .then(function () { - packageManager.createBaseDiffPackages(packages.id) - .catch(function(e){ - console.log(e); - }); packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch(function(e){ console.log(e); From 37cf83c9cd83d3d762be7601311e74e74bf0f4f3 Mon Sep 17 00:00:00 2001 From: Max Liu Date: Tue, 10 Jan 2017 17:25:01 +0800 Subject: [PATCH 035/194] Add Aliyun OSS storage support (#35) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Aliyun OSS storage support。 * Add Aliyun OSS storage support, add Readme.md --- README.md | 9 +++++++++ config/config.js | 9 +++++++++ core/utils/common.js | 29 +++++++++++++++++++++++++++++ package.json | 2 ++ 4 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 46fc7cfc..63b20fef 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,15 @@ $ vim config/config.js bucketName: "", downloadUrl: "" //文件下载域名地址 }, + //阿里云存储配置 当storageType为oss时需要配置 + oss: { + accessKeyId: "", + secretAccessKey: "", + endpoint: "", + bucketName: "", + prefix: "", // 对象Key的前缀,允许放到子文件夹里面 + downloadUrl: "", // 文件下载域名地址,需要包含前缀 + }, //文件存储在本地配置 当storageType为local时需要配置 local: { storageDir: "/Users/tablee/workspaces/storage", diff --git a/config/config.js b/config/config.js index 8d8d4bba..0490837c 100644 --- a/config/config.js +++ b/config/config.js @@ -22,6 +22,15 @@ config.development = { region: process.env.REGION, downloadUrl: process.env.DOWNLOAD_URL, // binary files download host address. }, + // Config for Aliyun OSS (https://www.aliyun.com/product/oss) when storageType value is "oss". + oss: { + accessKeyId: "", + secretAccessKey: "", + endpoint: "", + bucketName: "", + prefix: "", // Key prefix in object key + downloadUrl: "", // binary files download host address. + }, // Config for local storage when storageType value is "local". local: { // Binary files storage dir, Do not use tmpdir and it's public download dir. diff --git a/core/utils/common.js b/core/utils/common.js index a399d1de..bca8de26 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -114,6 +114,8 @@ common.uploadFileToStorage = function (key, filePath) { return common.uploadFileToLocal(key, filePath); } else if (_.get(config, 'common.storageType') === 's3') { return common.uploadFileToS3(key, filePath); + } else if (_.get(config, 'common.storageType') === 'oss') { + return common.uploadFileToOSS(key, filePath); } return common.uploadFileToQiniu(key, filePath); }; @@ -151,6 +153,8 @@ common.getDownloadUrl = function () { return _.get(config, 'local.downloadUrl'); } else if (_.get(config, 'common.storageType') === 's3') { return _.get(config, 's3.downloadUrl'); + } else if (_.get(config, 'common.storageType') === 'oss') { + return _.get(config, 'oss.downloadUrl'); } return _.get(config, 'qiniu.downloadUrl'); } @@ -216,6 +220,31 @@ common.uploadFileToS3 = function (key, filePath) { ); }; +common.uploadFileToOSS = function (key, filePath) { + var ALY = require('aliyun-sdk'); + var ossStream = require('aliyun-oss-upload-stream')(new ALY.OSS({ + accessKeyId: _.get(config, 'oss.accessKeyId'), + secretAccessKey: _.get(config, 'oss.secretAccessKey'), + endpoint: _.get(config, 'oss.endpoint'), + apiVersion: '2013-10-15', + })); + var upload = ossStream.upload({ + Bucket: _.get(config, 'oss.bucketName'), + Key: `${_.get(config, 'oss.prefix')}/${key}`, + }); + + return new Promise(function (resolve, reject) { + upload.on('error', function (error) { + reject(error); + }); + + upload.on('uploaded', function (details) { + resolve(details.ETag); + }); + fs.createReadStream(filePath).pipe(upload); + }); +}; + common.diffCollectionsSync = function (collection1, collection2) { var diffFiles = []; var collection1Only = []; diff --git a/package.json b/package.json index 259b606e..fa478a3f 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,8 @@ "coverage": "make coverage" }, "dependencies": { + "aliyun-oss-upload-stream": "^1.3.0", + "aliyun-sdk": "^1.9.17", "aws-sdk": "^2.7.0", "bcryptjs": "^2.3.0", "bluebird": "^3.4.1", From 0a6d7c2ba0d9ba5d85c8cc1c40ff8e90c71f0a00 Mon Sep 17 00:00:00 2001 From: Hyunjae Park Date: Mon, 16 Jan 2017 21:13:13 +0900 Subject: [PATCH 036/194] Hide confs (#38) * Use env variables first and then use raw string --- config/config.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/config/config.js b/config/config.js index 0490837c..75254bc7 100644 --- a/config/config.js +++ b/config/config.js @@ -2,11 +2,11 @@ var config = {}; config.development = { // Config for database, only support mysql. db: { - username: "root", - password: null, - database: "codepush", - host: "127.0.0.1", - port: 3306, + username: process.env.RDS_USERNAME || "root", + password: process.env.RDS_PASSWORD || null, + database: process.env.DATA_BASE || "codepush", + host: process.env.RDS_HOST || "127.0.0.1", + port: process.env.RDS_PORT || 3306, dialect: "mysql" }, // Config for qiniu (http://www.qiniu.com/) cloud storage when storageType value is "qiniu". @@ -34,16 +34,16 @@ config.development = { // Config for local storage when storageType value is "local". local: { // Binary files storage dir, Do not use tmpdir and it's public download dir. - storageDir: "/Users/tablee/workspaces/storage", + storageDir: process.env.STORAGE_DIR || "/Users/tablee/workspaces/storage", // Binary files download host address which Code Push Server listen to. the files storage in storageDir. - downloadUrl: "http://localhost:3000/download", + downloadUrl: process.env.LOCAL_DOWNLOAD_URL || "http://localhost:3000/download", // public static download spacename. - public: '/download' + public: process.env.PUBLIC || '/download' }, jwt: { // Recommended: 63 random alpha-numeric characters // Generate using: https://www.grc.com/passwords.htm - tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' + tokenSecret: process.env.TOKEN_SECRET ||'INSERT_RANDOM_TOKEN_KEY' }, common: { /* @@ -57,9 +57,9 @@ config.development = { // create patch updates's number. default value is 3 diffNums: 3, // data dir for caclulate diff files. it's optimization. - dataDir: "/Users/tablee/workspaces/data", + dataDir: process.env.DATA_DIR || "/Users/tablee/workspaces/data", // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") - storageType: "local", + storageType: process.env.STORAGE_TYPE || "local", // options value is (true | false), when it's true, it will cache updateCheck results in redis. updateCheckCache: false }, From 56957a86f00fc88142276021e865920d9e78d99c Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 17 Jan 2017 13:14:23 +0800 Subject: [PATCH 037/194] fix init db bug --- README.md | 6 ++++-- bin/db | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 63b20fef..9b4cd3ac 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,9 @@ $ vim config/config.js local: { storageDir: "/Users/tablee/workspaces/storage", //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址 - downloadUrl: "http://localhost:3000/download" + downloadUrl: "http://localhost:3000/download", + // public static download spacename. + public: '/download' }, jwt: { // 登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 @@ -101,7 +103,7 @@ $ vim config/config.js }, common: { dataDir: "/Users/tablee/workspaces/data", - //选择存储类型,目前支持local和qiniu配置 + //选择存储类型,目前支持local,oss,qiniu,s3配置 storageType: "local" }, ``` diff --git a/bin/db b/bin/db index 81ae3560..0551740a 100755 --- a/bin/db +++ b/bin/db @@ -23,7 +23,10 @@ var dbname = argv.dbname ? argv.dbname : 'codepush'; var dbhost = argv.dbhost ? argv.dbhost : 'localhost'; var dbuser = argv.dbuser ? argv.dbuser : 'root'; var dbport = argv.dbport ? argv.dbport : 3306; -var dbpassword = _.isString(argv.dbpassword) ? argv.dbpassword : null; +var dbpassword = null; +if (_.isString(argv.dbpassword) || _.isNumber(argv.dbpassword)) { + dbpassword = argv.dbpassword; +} if (command === 'init') { var connection2; From 94bf713b567f0ac1832ab06aae6e38330bd2c9b6 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 17 Jan 2017 18:45:34 +0800 Subject: [PATCH 038/194] 0.2.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa478a3f..68ec8f2e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.13", + "version": "0.2.14", "license": "MIT", "repository": { "type": "git", From cd7259e9335875c6d4da37b8ff4f9ae8ebea3ed6 Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 20 Jan 2017 18:42:11 +0800 Subject: [PATCH 039/194] catch deleteFolder error --- core/middleware.js | 16 +++++++++------- core/services/datacenter-manager.js | 14 ++++++++------ core/services/package-manager.js | 9 +++++---- core/utils/common.js | 16 +++++++--------- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/core/middleware.js b/core/middleware.js index 058b3153..48e79d1c 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -7,6 +7,8 @@ var moment = require('moment'); var middleware = module.exports +const UNAUTHORIZED_TEXT = `401 Unauthorized`; + var checkAuthToken = function (authToken) { var objToken = security.parseToken(authToken); return models.Users.findOne({ @@ -14,14 +16,14 @@ var checkAuthToken = function (authToken) { }) .then(function(users) { if (_.isEmpty(users)) { - throw new Error('401 Unauthorized'); + throw new Error(UNAUTHORIZED_TEXT); } return models.UserTokens.findOne({ where: {tokens: authToken, uid: users.id, expires_at: { gt: moment().format('YYYY-MM-DD HH:mm:ss') }} }) .then(function(tokenInfo){ if (_.isEmpty(tokenInfo)){ - throw new Error('401 Unauthorized') + throw new Error(UNAUTHORIZED_TEXT) } return users; }) @@ -33,7 +35,7 @@ var checkAuthToken = function (authToken) { var checkAccessToken = function (accessToken) { return new Promise(function (resolve, reject) { if (_.isEmpty(accessToken)) { - throw new Error('401 Unauthorized'); + throw new Error(UNAUTHORIZED_TEXT); } var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); @@ -47,10 +49,10 @@ var checkAccessToken = function (accessToken) { }) .then(function(users) { if (_.isEmpty(users)) { - throw new Error('401 Unauthorized'); + throw new Error(UNAUTHORIZED_TEXT); } if (!_.eq(hash, security.md5(users.get('ack_code')))){ - throw new Error('401 Unauthorized'); + throw new Error(UNAUTHORIZED_TEXT); } resolve(users); }) @@ -58,7 +60,7 @@ var checkAccessToken = function (accessToken) { reject(e); }); } else { - throw new Error('401 Unauthorized'); + throw new Error(UNAUTHORIZED_TEXT); } }); } @@ -100,6 +102,6 @@ middleware.checkToken = function(req, res, next) { res.status(401).send(e.message); }); } else { - res.status(401).send('401 Unauthorized'); + res.status(401).send(UNAUTHORIZED_TEXT); } }; diff --git a/core/services/datacenter-manager.js b/core/services/datacenter-manager.js index 31832849..ab1309d5 100644 --- a/core/services/datacenter-manager.js +++ b/core/services/datacenter-manager.js @@ -93,12 +93,14 @@ proto.storePackage = function (sourceDst, force) { if (!force && self.hasPackageStoreSync(packageHash)) { return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); } else { - common.createEmptyFolderSync(packageHashPath); - return common.move(sourceDst, contentPath) - .then(function () { - var manifestString = JSON.stringify(manifestJson); - fs.writeFileSync(manifestFile, manifestString); - return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); + return common.createEmptyFolder(packageHashPath) + .then(function(){ + return common.move(sourceDst, contentPath) + .then(function () { + var manifestString = JSON.stringify(manifestJson); + fs.writeFileSync(manifestFile, manifestString); + return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); + }); }); } }); diff --git a/core/services/package-manager.js b/core/services/package-manager.js index d47d1105..9a593bde 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -252,7 +252,6 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { return _.unionBy(lastNumsPackages, basePackages, 'id'); }) .then(function(lastNumsPackages){ - console.log(lastNumsPackages); return self.createDiffPackages(originalPackage, lastNumsPackages); }); }); @@ -270,8 +269,10 @@ proto.createDiffPackages = function (originalPackage, destPackages) { var manifest_blob_url = _.get(originalPackage, 'manifest_blob_url'); var blob_url = _.get(originalPackage, 'blob_url'); var workDirectoryPath = path.join(os.tmpdir(), 'codepush_' + security.randToken(32)); - common.createEmptyFolderSync(workDirectoryPath); - return self.downloadPackageAndExtract(workDirectoryPath, package_hash, blob_url) + return common.createEmptyFolder(workDirectoryPath) + .then(function(){ + return self.downloadPackageAndExtract(workDirectoryPath, package_hash, blob_url) + }) .then(function (dataCenter) { return Promise.map(destPackages, function (v) { return self.generateOneDiffPackage(workDirectoryPath, originalPackage.id, dataCenter, v.package_hash, v.manifest_blob_url); @@ -360,7 +361,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, }) .finally(function () { common.deleteFolderSync(directoryPath); - }); + }) }; proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, packageInfo) { diff --git a/core/utils/common.js b/core/utils/common.js index bca8de26..be0daefa 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -66,15 +66,13 @@ common.deleteFolderSync = function (folderPath) { }; common.createEmptyFolder = function (folderPath) { - return new Promise(function (resolve, reject) { - common.deleteFolder(folderPath).then(function (data) { - fsextra.mkdirs(folderPath, function (err) { - if (err) { - reject(new Error("create error")); - } else { - resolve(folderPath); - } - }); + return common.deleteFolder(folderPath) + .then(function (data) { + fsextra.mkdirs(folderPath, function (err) { + if (err) { + throw err; + } + return folderPath; }); }); }; From 45f24fad89b50f9124822a06f431c139e3e3df0a Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 20 Jan 2017 19:23:26 +0800 Subject: [PATCH 040/194] getdownloadurl --- core/services/client-manager.js | 5 ++--- core/services/package-manager.js | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 4b5e0ba4..8e27ae79 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -91,13 +91,12 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { if (_.eq(packageId, 0) ) { return; } - var downloadURL = common.getDownloadUrl(); return models.Packages.findById(packageId) .then(function (packages) { if (packages && _.eq(packages.deployment_id, deploymentsVersions.deployment_id) && !_.eq(packages.package_hash, packageHash)) { - rs.downloadURL = `${downloadURL}/${_.get(packages, 'blob_url')}`; + rs.downloadURL = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); rs.description = _.get(packages, 'description', ''); rs.isAvailable = true; rs.isMandatory = _.eq(packages.is_mandatory, 1) ? true : false; @@ -116,7 +115,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { return models.PackagesDiff.findOne({where: {package_id:packages.id, diff_against_package_hash: packageHash}}) .then(function (diffPackage) { if (!_.isEmpty(diffPackage)) { - rs.downloadURL = `${downloadURL}/${_.get(diffPackage, 'diff_blob_url')}`; + rs.downloadURL = common.getBlobDownloadUrl(_.get(diffPackage, 'diff_blob_url')); rs.packageSize = _.get(diffPackage, 'diff_size', 0); } return; diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 9a593bde..6d931cab 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -145,7 +145,7 @@ proto.downloadPackageAndExtract = function (workDirectoryPath, packageHash, blob if (isValidate) { return dataCenterManager.getPackageInfo(packageHash); } else { - var downloadURL = `${common.getDownloadUrl()}/${blobHash}`; + var downloadURL = common.getBlobDownloadUrl(blobHash); return common.createFileFromRequest(downloadURL, `${workDirectoryPath}/${blobHash}`) .then(function (download) { return common.unzipFile(`${workDirectoryPath}/${blobHash}`, `${workDirectoryPath}/current`) @@ -192,7 +192,7 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente if (!_.isEmpty(diffPackage)) { return; } - var downloadURL = `${common.getDownloadUrl()}/${diffManifestBlobHash}`; + var downloadURL = common.getBlobDownloadUrl(diffManifestBlobHash); return common.createFileFromRequest(downloadURL, `${workDirectoryPath}/${diffManifestBlobHash}`) .then(function(){ var originContentPath = dataCenter.contentPath; From 676c7e9d6b22c6ce822d99aa1f13a55971696778 Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 3 Feb 2017 21:32:14 +0800 Subject: [PATCH 041/194] fix clear history --- bin/db | 5 ++-- bin/www | 2 +- core/services/deployments.js | 40 ++++++++++++++++++++++++++------ core/services/package-manager.js | 25 ++++++++++---------- models/deployments_versions.js | 1 + models/packages.js | 1 + models/packages_diff.js | 1 + models/packages_metrics.js | 1 + sql/codepush-all.sql | 10 +++++--- sql/codepush-v0.2.15.sql | 4 ++++ 10 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 sql/codepush-v0.2.15.sql diff --git a/bin/db b/bin/db index 0551740a..3e916651 100755 --- a/bin/db +++ b/bin/db @@ -86,12 +86,13 @@ if (command === 'init') { version_no = _.get(rs,'0.version', '0.0.1'); } catch (e) { } - if (version_no == '0.2.14') { + if (version_no == '0.2.15') { console.log('Everything up-to-date.'); process.exit(1); } var allSqlFile = [ - {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14.sql')} + {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14.sql')}, + {version:'0.2.15', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.15.sql')} ]; for (var i = 0; i < allSqlFile.length; i++) { if(!_.gt(allSqlFile[i]['version'], version_no)) { diff --git a/bin/www b/bin/www index b55c17f1..8203dcb6 100755 --- a/bin/www +++ b/bin/www @@ -32,7 +32,7 @@ var server = http.createServer(app); var models = require('../models'); models.Versions.findOne({where:{type:1}}) .then(function(v){ - if (!v || v.get('version') != '0.2.14') { + if (!v || v.get('version') != '0.2.15') { throw new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); } server.listen(port, host); diff --git a/core/services/deployments.js b/core/services/deployments.js index 47208204..570e605f 100644 --- a/core/services/deployments.js +++ b/core/services/deployments.js @@ -57,8 +57,8 @@ proto.renameDeloymentByName = function (deploymentName, appId, newName) { .then(function () { return models.Deployments.update( {name: newName}, - {where: {name: deploymentName,appid: appId} - }) + {where: {name: deploymentName,appid: appId}} + ) .spread(function (affectedCount, affectedRow) { if (_.gt(affectedCount, 0)) { return {name: newName}; @@ -185,11 +185,37 @@ proto.getDeploymentHistory = function (deploymentId) { }; proto.deleteDeploymentHistory = function(deploymentId) { - return models.DeploymentsHistory.findAll({where: {deployment_id: deploymentId }, order: [['id','desc']], limit: 100}) - .then(function(rs){ - return Promise.map(rs, function(v){ - return v.destroy(); - }); + return models.sequelize.transaction(function (t) { + return Promise.all([ + models.Deployments.update( + {last_deployment_version_id:0,label_id:0}, + {where: {id: deploymentId},transaction: t} + ), + models.DeploymentsHistory.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 1000}) + .then(function(rs){ + return Promise.map(rs, function(v){ + return v.destroy({transaction: t}); + }); + }), + models.DeploymentsVersions.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 1000}) + .then(function(rs) { + return Promise.map(rs, function(v){ + return v.destroy({transaction: t}); + }); + }), + models.Packages.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 1000}) + .then(function(rs) { + return Promise.map(rs, function(v){ + return v.destroy({transaction: t}) + .then(function(){ + return Promise.all([ + models.PackagesMetrics.destroy({where: {package_id: v.get('id')},transaction: t}), + models.PackagesDiff.destroy({where: {package_id: v.get('id')},transaction: t}) + ]); + }); + }); + }) + ]); }); } diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 6d931cab..68cc4128 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -117,19 +117,20 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH deploymentsVersions.set('current_package_id', packages.id); return Promise.all([ deploymentsVersions.save({transaction: t}), - models.Deployments.update({ - last_deployment_version_id: deploymentsVersions.id - },{where: {id: deploymentId}, transaction: t}) + models.Deployments.update( + {last_deployment_version_id: deploymentsVersions.id}, + {where: {id: deploymentId}, transaction: t} + ), + models.PackagesMetrics.create( + {package_id: packages.id}, + {transaction: t} + ), + models.DeploymentsHistory.create( + {deployment_id: deploymentId,package_id: packages.id}, + {transaction: t} + ) ]) .then(function () { - //插入日志 - models.DeploymentsHistory.create({ - deployment_id: deploymentId, - package_id: packages.id, - }) - .catch(function(e){ - console.log(e); - }); return packages; }); }); @@ -486,7 +487,7 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) rollbackPackage.manifest_blob_url, rollbackPackage.blob_url, params - ); + ); }); }); } diff --git a/models/deployments_versions.js b/models/deployments_versions.js index 67f474ca..d42d06dc 100644 --- a/models/deployments_versions.js +++ b/models/deployments_versions.js @@ -16,6 +16,7 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'deployments_versions', underscored: true, + paranoid: true }); return DeploymentsVersions; diff --git a/models/packages.js b/models/packages.js index 6d6a0b0e..6ec423db 100644 --- a/models/packages.js +++ b/models/packages.js @@ -26,6 +26,7 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'packages', underscored: true, + paranoid: true }); return Packages; diff --git a/models/packages_diff.js b/models/packages_diff.js index c184b109..869a320b 100644 --- a/models/packages_diff.js +++ b/models/packages_diff.js @@ -17,6 +17,7 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'packages_diff', underscored: true, + paranoid: true }); return PackagesDiff; diff --git a/models/packages_metrics.js b/models/packages_metrics.js index 0a00ac63..86a1acff 100644 --- a/models/packages_metrics.js +++ b/models/packages_metrics.js @@ -20,6 +20,7 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'packages_metrics', underscored: true, + paranoid: true, classMethods: { addOne : function (packageId, fieldName) { var self = this; diff --git a/sql/codepush-all.sql b/sql/codepush-all.sql index f7971c82..e20dfe06 100644 --- a/sql/codepush-all.sql +++ b/sql/codepush-all.sql @@ -62,8 +62,9 @@ CREATE TABLE `deployments_versions` ( `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `idx_did_appversion` (`deployment_id`,`app_version`) + KEY `idx_did_appversion` (`deployment_id`,`app_version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `packages`; @@ -84,6 +85,7 @@ CREATE TABLE `packages` ( `created_at` timestamp NULL DEFAULT NULL, `released_by` bigint(20) unsigned NOT NULL, `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', + `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), KEY `idx_versions_id` (`deployment_version_id`) @@ -98,6 +100,7 @@ CREATE TABLE `packages_diff` ( `diff_size` int(11) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -112,8 +115,9 @@ CREATE TABLE `packages_metrics` ( `installed` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `udx_packageid` (`package_id`) + KEY `idx_packageid` (`package_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `user_tokens`; @@ -166,5 +170,5 @@ CREATE TABLE `versions` ( LOCK TABLES `versions` WRITE; INSERT INTO `versions` (`id`, `type`, `version`) VALUES - (1,1,'0.2.14'); + (1,1,'0.2.15'); UNLOCK TABLES; \ No newline at end of file diff --git a/sql/codepush-v0.2.15.sql b/sql/codepush-v0.2.15.sql new file mode 100644 index 00000000..4b339273 --- /dev/null +++ b/sql/codepush-v0.2.15.sql @@ -0,0 +1,4 @@ +ALTER TABLE `deployments_versions` DROP INDEX idx_did_appversion, ADD INDEX `idx_did_appversion` (`deployment_id`, `app_version`),ADD `deleted_at` TIMESTAMP NULL; +ALTER TABLE `packages` ADD `deleted_at` TIMESTAMP NULL; +ALTER TABLE `packages_metrics` DROP INDEX `udx_packageid`,ADD INDEX `idx_packageid` (`package_id`),ADD `deleted_at` TIMESTAMP NULL; +ALTER TABLE `packages_diff` ADD `deleted_at` TIMESTAMP NULL; \ No newline at end of file From e4362e4eaa71ed61b8219c7f0007d00837e34d05 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 4 Feb 2017 20:02:54 +0800 Subject: [PATCH 042/194] fix version --- sql/codepush-v0.2.15.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/codepush-v0.2.15.sql b/sql/codepush-v0.2.15.sql index 4b339273..70eed3a2 100644 --- a/sql/codepush-v0.2.15.sql +++ b/sql/codepush-v0.2.15.sql @@ -1,4 +1,5 @@ ALTER TABLE `deployments_versions` DROP INDEX idx_did_appversion, ADD INDEX `idx_did_appversion` (`deployment_id`, `app_version`),ADD `deleted_at` TIMESTAMP NULL; ALTER TABLE `packages` ADD `deleted_at` TIMESTAMP NULL; ALTER TABLE `packages_metrics` DROP INDEX `udx_packageid`,ADD INDEX `idx_packageid` (`package_id`),ADD `deleted_at` TIMESTAMP NULL; -ALTER TABLE `packages_diff` ADD `deleted_at` TIMESTAMP NULL; \ No newline at end of file +ALTER TABLE `packages_diff` ADD `deleted_at` TIMESTAMP NULL; +UPDATE `versions` SET `version` = '0.2.15' WHERE `type` = '1'; From c92217bff0c28e06b43ac269e22c1c5975e3192e Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 5 Feb 2017 14:29:46 +0800 Subject: [PATCH 043/194] fix docs --- docs/react-native-code-push.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index 7294d37c..cf8593f0 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -124,6 +124,13 @@ CodePush.sync({ import CodePush from "react-native-code-push" ``` +> notice: demo.js中用到ECMAScript中Decorators语法,需要安装`$ npm install babel-preset-react-native-stage-0 --save`, +> 同时在.babelrc中添加'react-native-stage-0/decorator-support'. +> eg. +> { +> "presets": ["react-native", "react-native-stage-0/decorator-support"] +> } + ## 运行CodePushDemo react-native项目 #### iOS From 99306b490a27e5782df447f59365d134b56635ac Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 5 Feb 2017 14:31:17 +0800 Subject: [PATCH 044/194] fix docs --- docs/react-native-code-push.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index cf8593f0..e2008ae8 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -124,8 +124,11 @@ CodePush.sync({ import CodePush from "react-native-code-push" ``` -> notice: demo.js中用到ECMAScript中Decorators语法,需要安装`$ npm install babel-preset-react-native-stage-0 --save`, +> notice: +> +> demo.js中用到ECMAScript中Decorators语法,需要安装`$ npm install babel-preset-react-native-stage-0 --save`, > 同时在.babelrc中添加'react-native-stage-0/decorator-support'. +> > eg. > { > "presets": ["react-native", "react-native-stage-0/decorator-support"] From 12b0b7d2b814215ff1511f492a0c72f578c369e3 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 5 Feb 2017 15:22:16 +0800 Subject: [PATCH 045/194] fix created_at default value --- sql/codepush-v0.2.15.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sql/codepush-v0.2.15.sql b/sql/codepush-v0.2.15.sql index 70eed3a2..c91bd534 100644 --- a/sql/codepush-v0.2.15.sql +++ b/sql/codepush-v0.2.15.sql @@ -1,3 +1,14 @@ + +ALTER TABLE `apps` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `collaborators` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `deployments` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `deployments_history` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `deployments_versions` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `packages_diff` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `packages_metrics` CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `user_tokens` CHANGE `expires_at` `expires_at` TIMESTAMP NULL,CHANGE `created_at` `created_at` TIMESTAMP NULL; +ALTER TABLE `users` CHANGE `created_at` `created_at` TIMESTAMP NULL; + ALTER TABLE `deployments_versions` DROP INDEX idx_did_appversion, ADD INDEX `idx_did_appversion` (`deployment_id`, `app_version`),ADD `deleted_at` TIMESTAMP NULL; ALTER TABLE `packages` ADD `deleted_at` TIMESTAMP NULL; ALTER TABLE `packages_metrics` DROP INDEX `udx_packageid`,ADD INDEX `idx_packageid` (`package_id`),ADD `deleted_at` TIMESTAMP NULL; From a85d412c74d6e9f588afa47f9bdfe03b6dc691ce Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 5 Feb 2017 16:00:44 +0800 Subject: [PATCH 046/194] fix 0.2.14 sql error --- sql/codepush-v0.2.15.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sql/codepush-v0.2.15.sql b/sql/codepush-v0.2.15.sql index c91bd534..948fce53 100644 --- a/sql/codepush-v0.2.15.sql +++ b/sql/codepush-v0.2.15.sql @@ -9,6 +9,18 @@ ALTER TABLE `packages_metrics` CHANGE `created_at` `created_at` TIMESTAMP NULL; ALTER TABLE `user_tokens` CHANGE `expires_at` `expires_at` TIMESTAMP NULL,CHANGE `created_at` `created_at` TIMESTAMP NULL; ALTER TABLE `users` CHANGE `created_at` `created_at` TIMESTAMP NULL; +DROP PROCEDURE IF EXISTS schema_change; +CREATE PROCEDURE schema_change() +BEGIN +DECLARE CurrentDatabase VARCHAR(100); +SELECT DATABASE() INTO CurrentDatabase; +IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=CurrentDatabase AND table_name = 'packages' AND column_name = 'is_mandatory') THEN + ALTER TABLE `packages` ADD `is_mandatory` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0'; +END IF; +END; +CALL schema_change(); +DROP PROCEDURE IF EXISTS schema_change; + ALTER TABLE `deployments_versions` DROP INDEX idx_did_appversion, ADD INDEX `idx_did_appversion` (`deployment_id`, `app_version`),ADD `deleted_at` TIMESTAMP NULL; ALTER TABLE `packages` ADD `deleted_at` TIMESTAMP NULL; ALTER TABLE `packages_metrics` DROP INDEX `udx_packageid`,ADD INDEX `idx_packageid` (`package_id`),ADD `deleted_at` TIMESTAMP NULL; From 5e27a9072cc32dc195e975c656ac29ebd79f38dd Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 7 Feb 2017 13:57:09 +0800 Subject: [PATCH 047/194] 0.2.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68ec8f2e..6a1deb0c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.14", + "version": "0.2.15", "license": "MIT", "repository": { "type": "git", From 2a3d256a3905fd92c490d089bccfe3c0184dd942 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 11 Feb 2017 23:06:17 +0800 Subject: [PATCH 048/194] fix 404 error --- app.js | 36 ++++++++++++++++----------------- core/services/client-manager.js | 2 +- routes/index.js | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index 707c45ec..a97329df 100644 --- a/app.js +++ b/app.js @@ -65,16 +65,14 @@ app.use('/account', account); app.use('/users', users); app.use('/apps', apps); -// catch 404 and forward to error handler -app.use(function(req, res, next) { - var err = new Error('Not Found'); - err.status = 404; - next(err); -}); - // development error handler // will print stacktrace if (app.get('env') === 'development') { + app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); + }); app.use(function(err, req, res) { res.status(err.status || 500); res.render('error', { @@ -82,17 +80,19 @@ if (app.get('env') === 'development') { error: err }); }); -} - -// production error handler -// no stacktraces leaked to user -app.use(function(err, req, res) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: {} +} else { + app.use(function(req, res, next) { + res.status(404).send('Not Found'); }); -}); - + // production error handler + // no stacktraces leaked to user + app.use(function(err, req, res) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); + }); +} module.exports = app; diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 8e27ae79..1a877488 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -132,7 +132,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { proto.getPackagesInfo = function (deploymentKey, label) { if (_.isEmpty(deploymentKey) || _.isEmpty(label)) { - return Promise.reject(new Error("please input deploymentKey and appVersion")) + return Promise.reject(new Error("please input deploymentKey and label")) } return models.Deployments.findOne({where: {deployment_key: deploymentKey}}) .then(function (dep) { diff --git a/routes/index.js b/routes/index.js index 97f2911f..901be38e 100644 --- a/routes/index.js +++ b/routes/index.js @@ -65,7 +65,7 @@ router.post('/reportStatus/deploy', function(req, res){ clientManager.reportStatusDeploy(deploymentKey, label, clientUniqueId, req.body) .catch(function (e) { console.log(e); - });; + }); res.send('OK'); }); From 86bc7adfd026b5d28190faed51345a9c1879bae3 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 11:45:02 +0800 Subject: [PATCH 049/194] fix error tips --- core/services/package-manager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 68cc4128..9d492362 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -309,13 +309,13 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, .then(function (type) { if (type === 1) { //android - if (pubType !== 'android' ) { - throw new Error("it must be publish it by android type"); + if (pubType == 'ios' ) { + throw new Error("it must be publish it by ios type"); } } else if (type === 2) { //ios - if (pubType !== 'ios'){ - throw new Error("it must be publish it by ios type"); + if (pubType == 'android'){ + throw new Error("it must be publish it by android type"); } } else { //不验证 From b7e2a2bbb850e255c1b8822cfbecf62e6543f690 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 12:03:14 +0800 Subject: [PATCH 050/194] fix error tips --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index a97329df..e1e904bc 100644 --- a/app.js +++ b/app.js @@ -89,7 +89,7 @@ if (app.get('env') === 'development') { app.use(function(err, req, res) { res.status(err.status || 500); res.render('error', { - message: err.message, + message: '服务器繁忙,请稍后再试!', error: {} }); }); From cd6cd13bf101047fee6929df7a728ccd3a14c556 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 14:22:28 +0800 Subject: [PATCH 051/194] define user error --- app.js | 23 ++++++++++++----------- core/services/app-error.js | 25 +++++++++++++++++++++++++ core/services/client-manager.js | 11 ++++++----- routes/index.js | 32 ++++++++++++++++++++++---------- routes/sessions.js | 11 ++++++++--- 5 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 core/services/app-error.js diff --git a/app.js b/app.js index e1e904bc..c1d1e2ce 100644 --- a/app.js +++ b/app.js @@ -16,6 +16,7 @@ var sessions = require('./routes/sessions'); var account = require('./routes/account'); var users = require('./routes/users'); var apps = require('./routes/apps'); +var AppError = require('./core/services/app-error'); var app = express(); app.use(helmet()); app.disable('x-powered-by'); @@ -69,29 +70,29 @@ app.use('/apps', apps); // will print stacktrace if (app.get('env') === 'development') { app.use(function(req, res, next) { - var err = new Error('Not Found'); - err.status = 404; - next(err); + next(new AppError.NotFound()); }); - app.use(function(err, req, res) { + app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); + console.error(err.stack); }); } else { app.use(function(req, res, next) { - res.status(404).send('Not Found'); + res.status(404).send(new AppError.NotFound()); }); // production error handler // no stacktraces leaked to user - app.use(function(err, req, res) { - res.status(err.status || 500); - res.render('error', { - message: '服务器繁忙,请稍后再试!', - error: {} - }); + app.use(function(err, req, res, next) { + var status = err.status || 500; + res.status(status); + var error = new AppError.AppError(`服务器繁忙,请稍后再试!`); + error.status = status; + res.status(status).send(error); + console.error(err.stack); }); } diff --git a/core/services/app-error.js b/core/services/app-error.js new file mode 100644 index 00000000..6c9887de --- /dev/null +++ b/core/services/app-error.js @@ -0,0 +1,25 @@ +var util = require('util') + +var AppError = function (msg, constr) { + if(msg) { + msg = msg.toString(); + } + Error.captureStackTrace(this, constr || this) + this.message = msg || 'Error' + this.name = 'AppError' +} +util.inherits(AppError, Error) + +var NotFoundError = function(msg) { + NotFoundError.super_.call(this, msg, this.constructor) + this.message = msg || 'Not Found'; + this.name = 'NotFoundError' + this.status = 404 +} +util.inherits(NotFoundError, AppError) + +module.exports = { + AppError: AppError, + NotFound: NotFoundError +} + diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 1a877488..30deac55 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -4,6 +4,7 @@ var models = require('../../models'); var _ = require('lodash'); var common = require('../utils/common'); var factory = require('../utils/factory'); +var AppError = require('./app-error'); var proto = module.exports = function (){ function ClientManager() { @@ -77,12 +78,12 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { shouldRunBinaryVersion: false }; if (_.isEmpty(deploymentKey) || _.isEmpty(appVersion)) { - return Promise.reject(new Error("please input deploymentKey and appVersion")) + return Promise.reject(new AppError.AppError("please input deploymentKey and appVersion")) } return models.Deployments.findOne({where: {deployment_key: deploymentKey}}) .then(function (dep) { if (_.isEmpty(dep)) { - throw new Error('does not found deployment'); + throw new AppError.AppError('does not found deployment'); } return models.DeploymentsVersions.findOne({where: {deployment_id: dep.id, app_version: appVersion}}); }) @@ -132,18 +133,18 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { proto.getPackagesInfo = function (deploymentKey, label) { if (_.isEmpty(deploymentKey) || _.isEmpty(label)) { - return Promise.reject(new Error("please input deploymentKey and label")) + return Promise.reject(new AppError.AppError("please input deploymentKey and label")) } return models.Deployments.findOne({where: {deployment_key: deploymentKey}}) .then(function (dep) { if (_.isEmpty(dep)) { - throw new Error('does not found deployment'); + throw new AppError.AppError('does not found deployment'); } return models.Packages.findOne({where: {deployment_id: dep.id, label: label}}); }) .then(function (packages) { if (_.isEmpty(packages)) { - throw new Error('does not found packages'); + throw new AppError.AppError('does not found packages'); } return packages; }); diff --git a/routes/index.js b/routes/index.js index 901be38e..a08fdec9 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,15 +1,16 @@ var express = require('express'); var router = express.Router(); var Promise = require('bluebird'); +var AppError = require('../core/services/app-error'); var middleware = require('../core/middleware'); var ClientManager = require('../core/services/client-manager'); var _ = require('lodash'); -router.get('/', function(req, res) { +router.get('/', function(req, res, next) { res.render('index', { title: 'CodePushServer' }); }); -router.get('/README.md', function(req, res) { +router.get('/README.md', function(req, res, next) { var MarkdownIt = require('markdown-it'); const path = require('path'); const fs = require('fs'); @@ -21,16 +22,19 @@ router.get('/README.md', function(req, res) { res.send(md.render(source)); }) .catch(e=>{ - res.send(e.message); + if (e instanceof AppError.AppError) { + res.send(e.message); + } else { + next(e); + } }); - }); router.get('/tokens', function(req, res) { res.render('tokens', { title: '获取token' }); }); -router.get('/updateCheck', function(req, res){ +router.get('/updateCheck', function(req, res, next){ var deploymentKey = _.get(req, "query.deploymentKey"); var appVersion = _.get(req, "query.appVersion"); var label = _.get(req, "query.label"); @@ -41,7 +45,11 @@ router.get('/updateCheck', function(req, res){ res.send({"updateInfo":rs}); }) .catch(function (e) { - res.status(404).send(e.message); + if (e instanceof AppError.AppError) { + res.status(404).send(e.message); + } else { + next(e); + } }); }); @@ -51,8 +59,10 @@ router.post('/reportStatus/download', function(req, res){ var deploymentKey = _.get(req, "body.deploymentKey"); var clientManager = new ClientManager(); clientManager.reportStatusDownload(deploymentKey, label, clientUniqueId) - .catch(function (e) { - console.log(e); + .catch(function (err) { + if (!err instanceof AppError.AppError) { + console.error(err.stack) + } }); res.send('OK'); }); @@ -63,8 +73,10 @@ router.post('/reportStatus/deploy', function(req, res){ var deploymentKey = _.get(req, "body.deploymentKey"); var clientManager = new ClientManager(); clientManager.reportStatusDeploy(deploymentKey, label, clientUniqueId, req.body) - .catch(function (e) { - console.log(e); + .catch(function (err) { + if (!err instanceof AppError.AppError) { + console.error(err.stack) + } }); res.send('OK'); }); diff --git a/routes/sessions.js b/routes/sessions.js index 3c1f5927..b5862b54 100644 --- a/routes/sessions.js +++ b/routes/sessions.js @@ -3,16 +3,21 @@ var router = express.Router(); var _ = require('lodash'); var models = require('../models'); var middleware = require('../core/middleware'); +var AppError = require('../core/services/app-error'); -router.delete('/:machineName', middleware.checkToken, function(req, res){ +router.delete('/:machineName', middleware.checkToken, function(req, res, next){ var machineName = _.trim(decodeURI(req.params.machineName)); var uid = req.users.id; models.UserTokens.destroy({where: {created_by:machineName, uid: uid}}) .then(function(rowNum){ res.send(""); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch(e => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); From aa878bfa206b9c212ec198191a78f1481c9595c8 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 16:48:42 +0800 Subject: [PATCH 052/194] add define user error --- app.js | 35 ++- core/{services => }/app-error.js | 12 +- core/middleware.js | 49 ++-- core/services/account-manager.js | 79 +++--- core/services/app-manager.js | 3 +- core/services/client-manager.js | 2 +- core/services/collaborators.js | 5 +- core/services/datacenter-manager.js | 3 +- core/services/deployments.js | 9 +- core/services/email-manager.js | 2 +- core/services/package-manager.js | 39 +-- core/utils/common.js | 15 +- core/utils/security.js | 4 +- models/deployments.js | 3 +- routes/accessKeys.js | 63 +++-- routes/account.js | 2 +- routes/apps.js | 362 +++++++++++++++++----------- routes/auth.js | 23 +- routes/index.js | 26 +- routes/sessions.js | 6 +- routes/users.js | 70 ++++-- 21 files changed, 486 insertions(+), 326 deletions(-) rename core/{services => }/app-error.js (61%) diff --git a/app.js b/app.js index c1d1e2ce..2fc4f51c 100644 --- a/app.js +++ b/app.js @@ -16,7 +16,7 @@ var sessions = require('./routes/sessions'); var account = require('./routes/account'); var users = require('./routes/users'); var apps = require('./routes/apps'); -var AppError = require('./core/services/app-error'); +var AppError = require('./core/app-error'); var app = express(); app.use(helmet()); app.disable('x-powered-by'); @@ -70,16 +70,26 @@ app.use('/apps', apps); // will print stacktrace if (app.get('env') === 'development') { app.use(function(req, res, next) { - next(new AppError.NotFound()); - }); - app.use(function(err, req, res, next) { - res.status(err.status || 500); + var err = new AppError.NotFound(); + res.status(err.status || 404); res.render('error', { message: err.message, error: err }); console.error(err.stack); }); + app.use(function(err, req, res, next) { + if (err instanceof AppError.AppError) { + res.send(err); + } else { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + console.error(err.stack); + } + }); } else { app.use(function(req, res, next) { res.status(404).send(new AppError.NotFound()); @@ -87,12 +97,15 @@ if (app.get('env') === 'development') { // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { - var status = err.status || 500; - res.status(status); - var error = new AppError.AppError(`服务器繁忙,请稍后再试!`); - error.status = status; - res.status(status).send(error); - console.error(err.stack); + if (err instanceof AppError.AppError) { + res.send(err); + } else { + var status = err.status || 500; + var error = new AppError.AppError(`服务器繁忙,请稍后再试!`); + error.status = status; + res.status(status).send(error); + console.error(err.stack); + } }); } diff --git a/core/services/app-error.js b/core/app-error.js similarity index 61% rename from core/services/app-error.js rename to core/app-error.js index 6c9887de..acdb3b82 100644 --- a/core/services/app-error.js +++ b/core/app-error.js @@ -7,6 +7,7 @@ var AppError = function (msg, constr) { Error.captureStackTrace(this, constr || this) this.message = msg || 'Error' this.name = 'AppError' + this.status = 200 } util.inherits(AppError, Error) @@ -18,8 +19,17 @@ var NotFoundError = function(msg) { } util.inherits(NotFoundError, AppError) +var UnauthorizedError = function(msg) { + NotFoundError.super_.call(this, msg, this.constructor) + this.message = msg || `401 Unauthorized`; + this.name = 'UnauthorizedError' + this.status = 401 +} +util.inherits(UnauthorizedError, AppError) + module.exports = { AppError: AppError, - NotFound: NotFoundError + NotFound: NotFoundError, + Unauthorized: UnauthorizedError } diff --git a/core/middleware.js b/core/middleware.js index 48e79d1c..01a26d8b 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -4,38 +4,37 @@ var Promise = require('bluebird'); var security = require('../core/utils/security'); var models = require('../models'); var moment = require('moment'); +var AppError = require('./app-error') var middleware = module.exports -const UNAUTHORIZED_TEXT = `401 Unauthorized`; - var checkAuthToken = function (authToken) { var objToken = security.parseToken(authToken); return models.Users.findOne({ where: {identical: objToken.identical} }) - .then(function(users) { + .then((users) => { if (_.isEmpty(users)) { - throw new Error(UNAUTHORIZED_TEXT); + throw new AppError.Unauthorized(); } return models.UserTokens.findOne({ where: {tokens: authToken, uid: users.id, expires_at: { gt: moment().format('YYYY-MM-DD HH:mm:ss') }} }) - .then(function(tokenInfo){ + .then((tokenInfo) => { if (_.isEmpty(tokenInfo)){ - throw new Error(UNAUTHORIZED_TEXT) + throw new AppError.Unauthorized() } return users; }) - }).then(function (users) { + }).then((users) => { return users; }) } var checkAccessToken = function (accessToken) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { if (_.isEmpty(accessToken)) { - throw new Error(UNAUTHORIZED_TEXT); + throw new AppError.Unauthorized(); } var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); @@ -47,20 +46,20 @@ var checkAccessToken = function (accessToken) { return models.Users.findOne({ where: {id: uid} }) - .then(function(users) { + .then((users) => { if (_.isEmpty(users)) { - throw new Error(UNAUTHORIZED_TEXT); + throw new AppError.Unauthorized(); } if (!_.eq(hash, security.md5(users.get('ack_code')))){ - throw new Error(UNAUTHORIZED_TEXT); + throw new AppError.Unauthorized(); } resolve(users); }) - .catch(function (e) { + .catch((e) => { reject(e); }); } else { - throw new Error(UNAUTHORIZED_TEXT); + reject(new AppError.Unauthorized()); } }); } @@ -83,25 +82,33 @@ middleware.checkToken = function(req, res, next) { } if (authType == 1) { checkAuthToken(authToken) - .then(function(users) { + .then((users) => { req.users = users; next(); return users; }) - .catch(function (e) { - res.status(401).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(e.status || 404).send(e.message); + } else { + next(e); + } }); } else if (authType == 2) { checkAccessToken(authToken) - .then(function(users) { + .then((users) => { req.users = users; next(); return users; }) - .catch(function (e) { - res.status(401).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(e.status || 404).send(e.message); + } else { + next(e); + } }); } else { - res.status(401).send(UNAUTHORIZED_TEXT); + res.send(new AppError.Unauthorized(`Auth type not supported.`)); } }; diff --git a/core/services/account-manager.js b/core/services/account-manager.js index 4b12cd81..a3815e0f 100644 --- a/core/services/account-manager.js +++ b/core/services/account-manager.js @@ -8,6 +8,7 @@ var factory = require('../utils/factory'); var moment = require('moment'); var EmailManager = require('./email-manager'); var config = require('../config'); +var AppError = require('../app-error'); var proto = module.exports = function (){ function AccountManager() { @@ -19,9 +20,9 @@ var proto = module.exports = function (){ proto.collaboratorCan = function(uid, appName) { return this.getCollaborator(uid, appName) - .then(function (data) { + .then((data) => { if (!data) { - throw new Error(`App ${appName} not exists.`); + throw new AppError.AppError(`App ${appName} not exists.`); } return data; }); @@ -29,9 +30,9 @@ proto.collaboratorCan = function(uid, appName) { proto.ownerCan = function(uid, appName) { return this.getCollaborator(uid, appName) - .then(function (data) { + .then((data) => { if (!data || !_.eq(_.get(data,'roles'), 'Owner') ) { - throw new Error("Permission Deny!"); + throw new AppError.AppError("Permission Deny!"); } return data; }); @@ -43,9 +44,9 @@ proto.getCollaborator = function (uid, appName) { proto.findUserByEmail = function (email) { return models.Users.findOne({where: {email: email}}) - .then(function (data) { + .then((data) => { if (_.isEmpty(data)) { - throw new Error(email + " does not exist."); + throw new AppError.AppError(email + " does not exist."); } else { return data; } @@ -54,7 +55,7 @@ proto.findUserByEmail = function (email) { proto.getAllAccessKeyByUid = function (uid) { return models.UserTokens.findAll({where: {uid: uid}, order:[['id', 'DESC']]}) - .then(function (tokens) { + .then((tokens) => { return _.map(tokens, function(v){ return { id: v.id + "", @@ -93,10 +94,10 @@ const LOGIN_LIMIT_PRE = 'LOGIN_LIMIT_PRE_'; proto.login = function (account, password) { if (_.isEmpty(account)) { - return Promise.reject(new Error("请您输入邮箱地址")) + return Promise.reject(new AppError.AppError("请您输入邮箱地址")) } if (_.isEmpty(password)) { - return Promise.reject(new Error("请您输入密码")) + return Promise.reject(new AppError.AppError("请您输入密码")) } var where = {}; if (validator.isEmail(account)) { @@ -106,20 +107,20 @@ proto.login = function (account, password) { } var tryLoginTimes = _.get(config, 'common.tryLoginTimes', 0); return models.Users.findOne({where: where}) - .then(function(users) { + .then((users) => { if (_.isEmpty(users)) { - throw new Error("您输入的邮箱或密码有误"); + throw new AppError.AppError("您输入的邮箱或密码有误"); } return users; }) - .then(function (users) { + .then((users) => { if (tryLoginTimes > 0) { var loginKey = `${LOGIN_LIMIT_PRE}${users.id}`; var client = factory.getRedisClient("default"); return client.getAsync(loginKey) - .then(function (loginErrorTimes) { + .then((loginErrorTimes) => { if (loginErrorTimes > tryLoginTimes) { - throw new Error(`您输入密码错误次数超过限制,帐户已经锁定`); + throw new AppError.AppError(`您输入密码错误次数超过限制,帐户已经锁定`); } return users; }); @@ -127,24 +128,24 @@ proto.login = function (account, password) { return users; } }) - .then(function (users) { + .then((users) => { if (!security.passwordVerifySync(password, users.password)) { if (tryLoginTimes > 0) { var loginKey = `${LOGIN_LIMIT_PRE}${users.id}`; var client = factory.getRedisClient("default"); client.existsAsync(loginKey) - .then(function (isExists) { + .then((isExists) => { if (!isExists) { var expires = moment().endOf('day').format('X') - moment().format('X'); return client.setexAsync(loginKey, expires, 0); } return isExists; }) - .then(function () { + .then(() => { return client.incrAsync(loginKey); }); } - throw new Error("您输入的邮箱或密码有误"); + throw new AppError.AppError("您输入的邮箱或密码有误"); } else { return users; } @@ -157,23 +158,23 @@ const EXPIRED_SPEED = 10; proto.sendRegisterCode = function (email) { if (_.isEmpty(email)) { - return Promise.reject(new Error("请您输入邮箱地址")); + return Promise.reject(new AppError.AppError("请您输入邮箱地址")); } return models.Users.findOne({where: {email: email}}) - .then(function (u) { + .then((u) => { if (u) { - throw new Error(`"${email}" 已经注册过,请更换邮箱注册`); + throw new AppError.AppError(`"${email}" 已经注册过,请更换邮箱注册`); } }) - .then(function () { + .then(() => { //将token临时存储到redis var token = security.randToken(40); return factory.getRedisClient("default").setexAsync(`${REGISTER_CODE}${security.md5(email)}`, EXPIRED, token) - .then(function () { + .then(() => { return token; }); }) - .then(function (token) { + .then((token) => { //将token发送到用户邮箱 var emailManager = new EmailManager(); return emailManager.sendRegisterCode(email, token); @@ -182,28 +183,28 @@ proto.sendRegisterCode = function (email) { proto.checkRegisterCode = function (email, token) { return models.Users.findOne({where: {email: email}}) - .then(function (u) { + .then((u) => { if (u) { - throw new Error(`"${email}" 已经注册过,请更换邮箱注册`); + throw new AppError.AppError(`"${email}" 已经注册过,请更换邮箱注册`); } }) - .then(function () { + .then(() => { var registerKey = `${REGISTER_CODE}${security.md5(email)}`; var client = factory.getRedisClient("default"); return client.getAsync(registerKey) - .then(function (storageToken) { + .then((storageToken) => { if (_.isEmpty(storageToken)) { - throw new Error(`验证码已经失效,请您重新获取`); + throw new AppError.AppError(`验证码已经失效,请您重新获取`); } if (!_.eq(token, storageToken)) { client.ttlAsync(registerKey) - .then(function (ttl) { + .then((ttl) => { if (ttl > 0) { return client.expireAsync(registerKey, ttl - EXPIRED_SPEED); } return ttl; }) - throw new Error(`您输入的验证码不正确,请重新输入`); + throw new AppError.AppError(`您输入的验证码不正确,请重新输入`); } return storageToken; }) @@ -212,12 +213,12 @@ proto.checkRegisterCode = function (email, token) { proto.register = function (email, password) { return models.Users.findOne({where: {email: email}}) - .then(function (u) { + .then((u) => { if (u) { - throw new Error(`"${email}" 已经注册过,请更换邮箱注册`); + throw new AppError.AppError(`"${email}" 已经注册过,请更换邮箱注册`); } }) - .then(function () { + .then(() => { var identical = security.randToken(9); return models.Users.create({ email: email, @@ -229,19 +230,19 @@ proto.register = function (email, password) { proto.changePassword = function (uid, oldPassword, newPassword) { if (!_.isString(newPassword) || newPassword.length < 6) { - return Promise.reject(new Error("请您输入6~20位长度的新密码")); + return Promise.reject(new AppError.AppError("请您输入6~20位长度的新密码")); } return models.Users.findOne({where: {id: uid}}) - .then(function (u) { + .then((u) => { if (!u) { - throw new Error(`未找到用户信息`); + throw new AppError.AppError(`未找到用户信息`); } return u; }) - .then(function (u) { + .then((u) => { var isEq = security.passwordVerifySync(oldPassword, u.get('password')); if (!isEq) { - throw new Error(`您输入的旧密码不正确,请重新输入`); + throw new AppError.AppError(`您输入的旧密码不正确,请重新输入`); } u.set('password', security.passwordHashSync(newPassword)); u.set('ack_code', security.randToken(5)); diff --git a/core/services/app-manager.js b/core/services/app-manager.js index cceeda01..d0429d3f 100644 --- a/core/services/app-manager.js +++ b/core/services/app-manager.js @@ -3,6 +3,7 @@ var Promise = require('bluebird'); var models = require('../../models'); var _ = require('lodash'); var security = require('../../core/utils/security'); +var AppError = require('../app-error'); var proto = module.exports = function (){ function AppManager() { @@ -65,7 +66,7 @@ proto.modifyApp = function (appId, params) { return models.Apps.update(params, {where: {id:appId}}) .spread(function (affectedCount, affectedRows) { if (!_.gt(affectedCount, 0)) { - throw Error('modify errors'); + throw AppError.AppError('modify errors'); } return affectedCount; }); diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 30deac55..886d84e6 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -4,7 +4,7 @@ var models = require('../../models'); var _ = require('lodash'); var common = require('../utils/common'); var factory = require('../utils/factory'); -var AppError = require('./app-error'); +var AppError = require('../app-error'); var proto = module.exports = function (){ function ClientManager() { diff --git a/core/services/collaborators.js b/core/services/collaborators.js index 49d19300..da7f9b88 100644 --- a/core/services/collaborators.js +++ b/core/services/collaborators.js @@ -1,6 +1,7 @@ 'use strict'; var models = require('../../models'); var _ = require('lodash'); +var AppError = require('../app-error'); var proto = module.exports = function (){ function Collaborators() { @@ -44,7 +45,7 @@ proto.addCollaborator = function (appId, uid) { roles: "Collaborator" }); }else { - throw new Error('user already is Collaborator.'); + throw new AppError.AppError('user already is Collaborator.'); } }); }; @@ -53,7 +54,7 @@ proto.deleteCollaborator = function (appId, uid) { return models.Collaborators.findOne({where: {appid: appId, uid: uid}}) .then(function (data) { if (_.isEmpty(data)){ - throw new Error('user is not a Collaborator'); + throw new AppError.AppError('user is not a Collaborator'); }else { return models.Collaborators.destroy({where: {id: data.id}}); } diff --git a/core/services/datacenter-manager.js b/core/services/datacenter-manager.js index ab1309d5..be507be7 100644 --- a/core/services/datacenter-manager.js +++ b/core/services/datacenter-manager.js @@ -8,6 +8,7 @@ var security = require('../utils/security'); var common = require('../utils/common'); const MANIFEST_FILE_NAME = 'manifest.json'; const CONTENTS_NAME = 'contents'; +var AppError = require('../app-error'); var proto = module.exports = function (){ function DataCenterManager() { @@ -41,7 +42,7 @@ proto.getPackageInfo = function (packageHash) { var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; return this.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); } else { - throw new Error('can\'t get PackageInfo'); + throw new AppError.AppError('can\'t get PackageInfo'); } } diff --git a/core/services/deployments.js b/core/services/deployments.js index 570e605f..d2317244 100644 --- a/core/services/deployments.js +++ b/core/services/deployments.js @@ -6,6 +6,7 @@ var common = require('../../core/utils/common'); var PackageManager = require('./package-manager'); var _ = require('lodash'); var moment = require('moment'); +var AppError = require('../app-error'); var proto = module.exports = function (){ function Deployments() { @@ -23,7 +24,7 @@ proto.existDeloymentName = function (appId, name) { return models.Deployments.findOne({where: {appid: appId, name: name}}) .then(function (data) { if (!_.isEmpty(data)){ - throw new Error(name + " name does Exist!") + throw new AppError.AppError(name + " name does Exist!") } else { return data; } @@ -35,7 +36,7 @@ proto.addDeloyment = function (name, appId, uid) { return models.Users.findById(uid) .then(function (user) { if (_.isEmpty(user)) { - throw new Error('can\'t find user'); + throw new AppError.AppError('can\'t find user'); } return self.existDeloymentName(appId, name) .then(function () { @@ -63,7 +64,7 @@ proto.renameDeloymentByName = function (deploymentName, appId, newName) { if (_.gt(affectedCount, 0)) { return {name: newName}; } else { - throw new Error(`does not find the deployment "${deploymentName}"`); + throw new AppError.AppError(`does not find the deployment "${deploymentName}"`); } }); }); @@ -77,7 +78,7 @@ proto.deleteDeloymentByName = function (deploymentName, appId) { if (_.gt(rowNum, 0)) { return {name: `${deploymentName}`}; } else { - throw new Error(`does not find the deployment "${deploymentName}"`); + throw new AppError.AppError(`does not find the deployment "${deploymentName}"`); } }); }; diff --git a/core/services/email-manager.js b/core/services/email-manager.js index 1194f246..c3671c63 100644 --- a/core/services/email-manager.js +++ b/core/services/email-manager.js @@ -19,7 +19,7 @@ var proto = module.exports = function (){ proto.sendMail = function (options) { return new Promise(function (resolve, reject) { if(!_.get(options, 'to')) { - return reject(new Error("to是必传参数")); + return reject(new AppError.AppError("to是必传参数")); } var smtpConfig = _.get(config, 'smtpConfig'); if (!smtpConfig) { diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 9d492362..52cae3c3 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -11,6 +11,7 @@ var slash = require("slash"); var common = require('../utils/common'); var os = require('os'); var path = require('path'); +var AppError = require('../app-error'); var proto = module.exports = function (){ function PackageManager() { @@ -29,10 +30,10 @@ proto.parseReqFile = function (req) { var form = new formidable.IncomingForm(); form.parse(req, function(err, fields, files) { if (err) { - reject(new Error("upload error")); + reject(new AppError.AppError("upload error")); } else { if (_.isEmpty(fields.packageInfo) || _.isEmpty(files.package)) { - reject(new Error("upload info lack")); + reject(new AppError.AppError("upload info lack")); } else { resolve({packageInfo:JSON.parse(fields.packageInfo), package: files.package}); } @@ -231,7 +232,7 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { return models.Packages.findById(packageId) .then(function (originalPackage) { if (_.isEmpty(originalPackage)) { - throw Error('can\'t find Package'); + throw AppError.AppError('can\'t find Package'); } return Promise.all([ models.Packages.findAll({ @@ -260,7 +261,7 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { proto.createDiffPackages = function (originalPackage, destPackages) { if (!_.isArray(destPackages)) { - return Promise.reject(new Error('第二个参数必须是数组')); + return Promise.reject(new AppError.AppError('第二个参数必须是数组')); } if (destPackages.length <= 0) { return null; @@ -288,7 +289,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, var self = this; var appVersion = packageInfo.appVersion; if (!/^([0-9.]+)$/.test(appVersion)) { - return Promise.reject(new Error(`targetBinaryVersion ${appVersion} not support.`)) + return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) } var description = packageInfo.description; var isMandatory = packageInfo.isMandatory; @@ -300,7 +301,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, if (fileType == "application/zip") { return common.unzipFile(filePath, directoryPath) } else { - throw new Error("上传的文件格式不对"); + throw new AppError.AppError("上传的文件格式不对"); } }) ]) @@ -310,12 +311,12 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, if (type === 1) { //android if (pubType == 'ios' ) { - throw new Error("it must be publish it by ios type"); + throw new AppError.AppError("it must be publish it by ios type"); } } else if (type === 2) { //ios if (pubType == 'android'){ - throw new Error("it must be publish it by android type"); + throw new AppError.AppError("it must be publish it by android type"); } } else { //不验证 @@ -334,7 +335,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, return self.existPackageHashAndCreateVersions(deploymentId, appVersion, packageHash) .then(function (isExist) { if (isExist){ - throw new Error("The uploaded package is identical to the contents of the specified deployment's current release."); + throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); } return security.qetag(manifestFile); }) @@ -373,21 +374,21 @@ proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, package return models.DeploymentsVersions.findById(deploymentVersionId) .then(function(deploymentsVersions){ if (_.isBoolean(isDisabled)) { - throw new Error(`--disabled -x function is not implements`); + throw new AppError.AppError(`--disabled -x function is not implements`); } if (!appVersion) { if (!/^([0-9.]+)$/.test(appVersion)) { - return Promise.reject(new Error(`targetBinaryVersion ${appVersion} not support.`)) + return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) } return models.DeploymentsVersions.findOne({deployment_id: deploymentId, app_version: appVersion}) .then(function(d){ if (d) { - throw new Error(`version ${appVersion} already exist`); + throw new AppError.AppError(`version ${appVersion} already exist`); } }); } if(!deploymentsVersions) { - throw new Error(`packages were not found in db`); + throw new AppError.AppError(`packages were not found in db`); } }) .then(function(){ @@ -401,23 +402,23 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUi .then(function (sourceDeployment) { var lastDeploymentVersionId = _.get(sourceDeployment, 'last_deployment_version_id', 0); if (_.lte(lastDeploymentVersionId, 0)) { - throw new Error('does not exist last_deployment_version_id.'); + throw new AppError.AppError('does not exist last_deployment_version_id.'); } return models.DeploymentsVersions.findById(lastDeploymentVersionId) .then(function (deploymentsVersions) { var packageId = _.get(deploymentsVersions, 'current_package_id', 0); if (_.lte(packageId, 0)) { - throw new Error('does not exist packages.'); + throw new AppError.AppError('does not exist packages.'); } return models.Packages.findById(packageId) .then(function (packages) { if (!packages) { - throw new Error('does not exist packages.'); + throw new AppError.AppError('does not exist packages.'); } return self.existPackageHashAndCreateVersions(destDeploymentId, deploymentsVersions.app_version, packages.package_hash) .then(function (isExist) { if (isExist){ - throw new Error("The uploaded package is identical to the contents of the specified deployment's current release."); + throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); } }) .then(function () { @@ -445,7 +446,7 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) return models.DeploymentsVersions.findById(deploymentVersionId) .then(function(deploymentsVersions){ if (!deploymentsVersions) { - throw new Error("您之前还没有发布过版本"); + throw new AppError.AppError("您之前还没有发布过版本"); } return models.Packages.findById(deploymentsVersions.current_package_id) .then(function (currentPackageInfo){ @@ -469,7 +470,7 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) } } } - throw new Error("没有可供回滚的版本"); + throw new AppError.AppError("没有可供回滚的版本"); }) .then(function(rollbackPackage){ var params = { diff --git a/core/utils/common.js b/core/utils/common.js index be0daefa..8f849ca2 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -7,6 +7,7 @@ var config = require('../config'); var _ = require('lodash'); var qiniu = require("qiniu"); var common = {}; +var AppError = require('../app-error'); module.exports = common; common.createFileFromRequest = function (url, filePath) { @@ -87,7 +88,7 @@ common.unzipFile = function (zipFile, outputPath) { try { fs.exists(zipFile, function(exists){ if (!exists) { - reject(new Error("zipfile not found!")) + reject(new AppError.AppError("zipfile not found!")) } var readStream = fs.createReadStream(zipFile); var extract = unzip.Extract({ path: outputPath }); @@ -122,20 +123,20 @@ common.uploadFileToLocal = function (key, filePath) { return new Promise(function (resolve, reject) { var storageDir = _.get(config, 'local.storageDir'); if (!storageDir) { - throw new Error('please set config local storageDir'); + throw new AppError.AppError('please set config local storageDir'); } if (!fs.existsSync(storageDir)) { - throw new Error(`please create dir ${storageDir}`); + throw new AppError.AppError(`please create dir ${storageDir}`); } fs.accessSync(storageDir, fs.W_OK); var stats = fs.statSync(storageDir); if (!stats.isDirectory()) { - throw new Error(`${storageDir} must be directory`); + throw new AppError.AppError(`${storageDir} must be directory`); } fs.accessSync(filePath, fs.R_OK); stats = fs.statSync(filePath); if (!stats.isFile()) { - throw new Error(`${filePath} must be file`); + throw new AppError.AppError(`${filePath} must be file`); } fsextra.copy(filePath, `${storageDir}/${key}`, {clobber: true, limit: 16}, function (err) { if (err) { @@ -183,7 +184,7 @@ common.uploadFileToQiniu = function (key, filePath) { resolve(ret.hash); } else { // 上传失败, 处理返回代码 - reject(new Error(JSON.stringify(err))); + reject(new AppError.AppError(JSON.stringify(err))); } }); } @@ -208,7 +209,7 @@ common.uploadFileToS3 = function (key, filePath) { ACL:'public-read', }, function(err, response) { if(err) { - reject(new Error(JSON.stringify(err))); + reject(new AppError.AppError(JSON.stringify(err))); } else { resolve(response.ETag) } diff --git a/core/utils/security.js b/core/utils/security.js index edb3e730..3a9b45b9 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -111,7 +111,7 @@ security.isAndroidPackage = function (directoryPath) { reject(error); } else { if (files.length == 0) { - reject(new Error("empty files")); + reject(new AppError.AppError("empty files")); } else { const AREGEX=/android\.bundle/ const AREGEX_IOS=/main\.jsbundle/ @@ -143,7 +143,7 @@ security.calcAllFileSha256 = function (directoryPath) { reject(error); } else { if (files.length == 0) { - reject(new Error("empty files")); + reject(new AppError.AppError("empty files")); }else { security.sha256AllFiles(files) .then(function (results) { diff --git a/models/deployments.js b/models/deployments.js index 3726c27a..122b1b36 100644 --- a/models/deployments.js +++ b/models/deployments.js @@ -1,6 +1,7 @@ "use strict"; var _ = require('lodash'); +var AppError = require('../core/app-error'); module.exports = function(sequelize, DataTypes) { var Deployments = sequelize.define("Deployments", { @@ -28,7 +29,7 @@ module.exports = function(sequelize, DataTypes) { return sequelize.transaction(function (t) { return self.findById(deploymentId, {transaction: t,lock: t.LOCK.UPDATE}).then(function (data) { if (_.isEmpty(data)){ - throw new Error("does not find deployment"); + throw new AppError.AppError("does not find deployment"); } data.label_id = data.label_id + 1; return data.save({transaction: t}) diff --git a/routes/accessKeys.js b/routes/accessKeys.js index 66f9806c..c9ef8937 100644 --- a/routes/accessKeys.js +++ b/routes/accessKeys.js @@ -6,19 +6,24 @@ var security = require('../core/utils/security'); var models = require('../models'); var middleware = require('../core/middleware'); var accountManager = require('../core/services/account-manager')(); +var AppError = require('../core/app-error') -router.get('/', middleware.checkToken, function(req, res) { +router.get('/', middleware.checkToken, (req, res, next) => { var uid = req.users.id; accountManager.getAllAccessKeyByUid(uid) - .then(function(accessKeys){ + .then((accessKeys) => { res.send({accessKeys:accessKeys}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); -router.post('/', middleware.checkToken, function(req, res) { +router.post('/', middleware.checkToken, (req, res, next) => { var uid = req.users.id; var identical = req.users.identical; var createdBy = _.trim(req.body.createdBy); @@ -28,15 +33,15 @@ router.post('/', middleware.checkToken, function(req, res) { var description = _.trim(req.body.description); var newAccessKey = security.randToken(28).concat(identical); return accountManager.isExsitAccessKeyName(uid, friendlyName) - .then(function (data) { + .then((data) => { if (!_.isEmpty(data)) { - throw Error(`The access key "${friendlyName}" already exists.`); + throw new AppError.AppError(`The access key "${friendlyName}" already exists.`); } }) - .then(function () { + .then(() => { return accountManager.createAccessKey(uid, newAccessKey, isSession, ttl, friendlyName, createdBy, description); }) - .then(function(newToken){ + .then((newToken) => { var moment = require("moment"); var info = { name : newToken.tokens, @@ -49,24 +54,32 @@ router.post('/', middleware.checkToken, function(req, res) { }; res.send({accessKey:info}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); -router.delete('/:name', middleware.checkToken, function(req, res){ +router.delete('/:name', middleware.checkToken, (req, res, next) => { var name = _.trim(decodeURI(req.params.name)); var uid = req.users.id; return models.UserTokens.destroy({where: {name:name, uid: uid}}) - .then(function(rowNum){ + .then((rowNum) => { res.send({friendlyName:name}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); -router.patch('/:name', middleware.checkToken, function(req, res){ +router.patch('/:name', middleware.checkToken, (req, res, next) => { var name = _.trim(decodeURI(req.params.name)); var friendlyName = _.trim(req.body.friendlyName); var ttl = _.trim(req.body.ttl); @@ -75,16 +88,16 @@ router.patch('/:name', middleware.checkToken, function(req, res){ models.UserTokens.findOne({where: {name:name, uid: uid}}), accountManager.isExsitAccessKeyName(uid, friendlyName), ]) - .spread(function (token, token2) { + .spread((token, token2) => { if (_.isEmpty(token)) { - throw new Error(`The access key "${name}" does not exist.`); + throw new AppError.AppError(`The access key "${name}" does not exist.`); } if (!_.isEmpty(token2)) { - throw new Error(`The access key "${friendlyName}" already exists.`); + throw new AppError.AppError(`The access key "${friendlyName}" already exists.`); } return token; }) - .then(function (token) { + .then((token) => { var moment = require('moment'); if (ttl > 0 || ttl < 0) { var newExp = moment(token.get('expires_at')).add(ttl/1000, 'seconds').format('YYYY-MM-DD HH:mm:ss'); @@ -95,7 +108,7 @@ router.patch('/:name', middleware.checkToken, function(req, res){ } return token.save(); }) - .then(function (token) { + .then((token) => { var info = { name : '(hidden)', isSession: token.is_session == 1 ? true :false, @@ -108,8 +121,12 @@ router.patch('/:name', middleware.checkToken, function(req, res){ }; res.send({accessKey: info}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); diff --git a/routes/account.js b/routes/account.js index 93a333a6..c022af4d 100644 --- a/routes/account.js +++ b/routes/account.js @@ -5,7 +5,7 @@ var _ = require('lodash'); var security = require('../core/utils/security'); var middleware = require('../core/middleware'); -router.get('/', middleware.checkToken, function(req, res) { +router.get('/', middleware.checkToken, (req, res) => { var userInfo = { email:req.users.email, id:req.users.identical, diff --git a/routes/apps.js b/routes/apps.js index 4577599d..727dea4d 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -9,6 +9,7 @@ var Deployments = require('../core/services/deployments'); var Collaborators = require('../core/services/collaborators'); var AppManager = require('../core/services/app-manager'); var PackageManager = require('../core/services/package-manager'); +var AppError = require('../core/app-error'); var common = require('../core/utils/common'); var config = require('../core/config'); const REGEX = /^(\w+)(-android|-ios)$/; @@ -18,55 +19,67 @@ const OLD_REGEX_ANDROID = /^(android_)/; const OLD_REGEX_IOS = /^(ios_)/; router.get('/', - middleware.checkToken, function(req, res) { + middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appManager = new AppManager(); appManager.listApps(uid) - .then(function (data) { + .then((data) => { res.send({apps: data}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.get('/:appName/deployments', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appName = _.trim(req.params.appName); var deployments = new Deployments(); accountManager.collaboratorCan(uid, appName) - .then(function (col) { + .then((col) => { return deployments.listDeloyments(col.appid); }) - .then(function (data) { + .then((data) => { res.send({deployments: data}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.post('/:appName/deployments', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appName = _.trim(req.params.appName); var name = req.body.name; var deployments = new Deployments(); accountManager.ownerCan(uid, appName) - .then(function (col) { + .then((col) => { return deployments.addDeloyment(name, col.appid, uid); }) - .then(function (data) { + .then((data) => { res.send({deployment: {name: data.name, key: data.deployment_key}}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.get('/:appName/deployments/:deploymentName/metrics', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); @@ -74,22 +87,22 @@ router.get('/:appName/deployments/:deploymentName/metrics', var packageManager = new PackageManager(); accountManager.collaboratorCan(uid, appName) - .then(function(col) { + .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid) - .then(function (deploymentInfo) { + .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { - throw new Error("does not find the deployment"); + throw new AppError.AppError("does not find the deployment"); } return deploymentInfo; }) }) - .then(function(deploymentInfo) { + .then((deploymentInfo) => { return deployments.getAllPackageIdsByDeploymentsId(deploymentInfo.id); }) - .then(function(packagesInfos) { - return Promise.reduce(packagesInfos, function (result, v) { + .then((packagesInfos) => { + return Promise.reduce(packagesInfos, (result, v) => { return packageManager.getMetricsbyPackageId(v.get('id')) - .then(function (metrics) { + .then((metrics) => { if (metrics) { result[v.get('label')] = { active: metrics.get('active'), @@ -102,140 +115,160 @@ router.get('/:appName/deployments/:deploymentName/metrics', }); }, {}); }) - .then(function(rs) { + .then((rs) => { res.send({"metrics": rs}); }) - .catch(function(e){ - res.send({"metrics": null}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({"metrics": null}); + } else { + next(e); + } }); }); router.get('/:appName/deployments/:deploymentName/history', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var deployments = new Deployments(); accountManager.collaboratorCan(uid, appName) - .then(function(col){ + .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid) - .then(function (deploymentInfo) { + .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { - throw new Error("does not find the deployment"); + throw new AppError.AppError("does not find the deployment"); } return deploymentInfo; }); }) - .then(function(deploymentInfo) { + .then((deploymentInfo) => { return deployments.getDeploymentHistory(deploymentInfo.id); }) - .then(function (rs) { + .then((rs) => { res.send({history: rs}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.delete('/:appName/deployments/:deploymentName/history', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var deployments = new Deployments(); accountManager.ownerCan(uid, appName) - .then(function(col){ + .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid) - .then(function (deploymentInfo) { + .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { - throw new Error("does not find the deployment"); + throw new AppError.AppError("does not find the deployment"); } return deploymentInfo; }); }) - .then(function(deploymentInfo) { + .then((deploymentInfo) => { return deployments.deleteDeploymentHistory(deploymentInfo.id); }) - .then(function (rs) { + .then((rs) => { res.send("ok"); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.patch('/:appName/deployments/:deploymentName', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var name = req.body.name; var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var uid = req.users.id; var deployments = new Deployments(); accountManager.ownerCan(uid, appName) - .then(function (col) { + .then((col) => { return deployments.renameDeloymentByName(deploymentName, col.appid, name); }) - .then(function (data) { + .then((data) => { res.send({deployment: data}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.delete('/:appName/deployments/:deploymentName', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var uid = req.users.id; var deployments = new Deployments(); accountManager.ownerCan(uid, appName) - .then(function (col) { + .then((col) => { return deployments.deleteDeloymentByName(deploymentName, col.appid); }) - .then(function (data) { + .then((data) => { res.send({deployment: data}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.post('/:appName/deployments/:deploymentName/release', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var uid = req.users.id; var deployments = new Deployments(); var packageManager = new PackageManager(); accountManager.collaboratorCan(uid, appName) - .then(function (col) { + .then((col) => { var pubType = ''; if (REGEX_ANDROID.test(appName)) { pubType = 'android'; } else if (REGEX_IOS.test(appName)) { pubType = 'ios'; } else { - throw new Error(`you have to rename app name, eg. Demo-android Demo-ios`); + throw new AppError.AppError(`you have to rename app name, eg. Demo-android Demo-ios`); } return deployments.findDeloymentByName(deploymentName, col.appid) - .then(function (deploymentInfo) { + .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { - throw new Error("does not find the deployment"); + throw new AppError.AppError("does not find the deployment"); } return packageManager.parseReqFile(req) - .then(function (data) { + .then((data) => { return packageManager.releasePackage(deploymentInfo.id, data.packageInfo, data.package.type, data.package.path, uid, pubType) - .finally(function () { + .finally(() => { common.deleteFolderSync(data.package.path); }); }) - .then(function (packages) { + .then((packages) => { if (packages) { Promise.delay(2000) - .then(function () { + .then(() => { packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) - .catch(function(e){ + .catch((e) => { console.log(e); }); }); @@ -243,7 +276,7 @@ router.post('/:appName/deployments/:deploymentName/release', //clear cache if exists. if (_.get(config, 'common.updateCheckCache', false) !== false) { Promise.delay(2500) - .then(function () { + .then(() => { var ClientManager = require('../core/services/client-manager'); var clientManager = new ClientManager(); clientManager.clearUpdateCheckCache(deploymentInfo.deployment_key, '*', '*', '*'); @@ -253,16 +286,20 @@ router.post('/:appName/deployments/:deploymentName/release', }); }); }) - .then(function (data) { + .then((data) => { res.send(""); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.patch('/:appName/deployments/:deploymentName/release', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { return res.status(406).send('Not supported currently'); var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); @@ -270,26 +307,30 @@ router.patch('/:appName/deployments/:deploymentName/release', var deployments = new Deployments(); var packageManager = new PackageManager(); accountManager.collaboratorCan(uid, appName) - .then(function (col) { + .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid) - .then(function (deploymentInfo) { + .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { - throw new Error("does not find the deployment"); + throw new AppError.AppError("does not find the deployment"); } var label = deploymentInfo.label; var deploymentVersionId = deploymentInfo.last_deployment_version_id; return packageManager.modifyReleasePackage(deploymentInfo.id, deploymentVersionId, _.get(req, 'body.packageInfo')); }); - }).then(function (data) { + }).then((data) => { res.send(""); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeploymentName', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var sourceDeploymentName = _.trim(req.params.sourceDeploymentName); var destDeploymentName = _.trim(req.params.destDeploymentName); @@ -297,23 +338,23 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment var packageManager = new PackageManager(); var deployments = new Deployments(); accountManager.collaboratorCan(uid, appName) - .then(function (col) { + .then((col) => { var appId = col.appid; return Promise.all([ deployments.findDeloymentByName(sourceDeploymentName, appId), deployments.findDeloymentByName(destDeploymentName, appId) ]) - .spread(function (sourceDeploymentInfo, destDeploymentInfo) { + .spread((sourceDeploymentInfo, destDeploymentInfo) => { if (!sourceDeploymentInfo) { - throw new Error(`${sourceDeploymentName} does not exist.`); + throw new AppError.AppError(`${sourceDeploymentName} does not exist.`); } if (!destDeploymentInfo) { - throw new Error(`${destDeploymentName} does not exist.`); + throw new AppError.AppError(`${destDeploymentName} does not exist.`); } //clear cache if exists. if (_.get(config, 'common.updateCheckCache', false) !== false) { Promise.delay(2500) - .then(function () { + .then(() => { var ClientManager = require('../core/services/client-manager'); var clientManager = new ClientManager(); clientManager.clearUpdateCheckCache(destDeploymentInfo.deployment_key, '*', '*', '*'); @@ -321,31 +362,35 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment } return [sourceDeploymentInfo.id, destDeploymentInfo.id]; }) - .spread(function (sourceDeploymentId, destDeploymentId) { + .spread((sourceDeploymentId, destDeploymentId) => { return packageManager.promotePackage(sourceDeploymentId, destDeploymentId, uid); }); }) - .then(function (packages) { + .then((packages) => { if (packages) { Promise.delay(2000) - .then(function () { + .then(() => { packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) - .catch(function(e){ + .catch((e) => { console.log(e); }); }); } return null; }) - .then(function () { + .then(() => { res.send('ok'); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); -var rollbackCb = function (req, res) { +var rollbackCb = function (req, res, next) { var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var uid = req.users.id; @@ -353,14 +398,14 @@ var rollbackCb = function (req, res) { var deployments = new Deployments(); var packageManager = new PackageManager(); accountManager.collaboratorCan(uid, appName) - .then(function (col) { + .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid); }) - .then(function(dep){ + .then((dep) => { //clear cache if exists. if (_.get(config, 'common.updateCheckCache', false) !== false) { Promise.delay(2500) - .then(function () { + .then(() => { var ClientManager = require('../core/services/client-manager'); var clientManager = new ClientManager(); clientManager.clearUpdateCheckCache(dep.deployment_key, '*', '*', '*'); @@ -368,11 +413,15 @@ var rollbackCb = function (req, res) { } return packageManager.rollbackPackage(dep.last_deployment_version_id, targetLabel, uid); }) - .then(function () { + .then(() => { res.send('ok'); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }; @@ -383,15 +432,16 @@ router.post('/:appName/deployments/:deploymentName/rollback/:label', middleware.checkToken, rollbackCb); router.get('/:appName/collaborators', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var uid = req.users.id; var collaborators = new Collaborators(); - accountManager.collaboratorCan(uid, appName).then(function (col) { + accountManager.collaboratorCan(uid, appName) + .then((col) => { return collaborators.listCollaborators(col.appid); }) - .then(function (data) { - rs = _.reduce(data, function (result, value, key) { + .then((data) => { + rs = _.reduce(data, (result, value, key) => { if (_.eq(key, req.users.email)) { value.isCurrentAccount = true; }else { @@ -402,13 +452,17 @@ router.get('/:appName/collaborators', },{}); res.send({collaborators: rs}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.post('/:appName/collaborators/:email', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var email = _.trim(req.params.email); var uid = req.users.id; @@ -417,21 +471,26 @@ router.post('/:appName/collaborators/:email', } var collaborators = new Collaborators(); accountManager.ownerCan(uid, appName) - .then(function (col) { - return accountManager.findUserByEmail(email).then(function (data) { + .then((col) => { + return accountManager.findUserByEmail(email) + .then((data) => { return collaborators.addCollaborator(col.appid, data.id); }); }) - .then(function (data) { + .then((data) => { res.send(data); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.delete('/:appName/collaborators/:email', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var email = _.trim(decodeURI(req.params.email)); var uid = req.users.id; @@ -440,42 +499,51 @@ router.delete('/:appName/collaborators/:email', } var collaborators = new Collaborators(); accountManager.ownerCan(uid, appName) - .then(function (col) { - return accountManager.findUserByEmail(email).then(function (data) { + .then((col) => { + return accountManager.findUserByEmail(email) + .then((data) => { if (_.eq(data.id, uid)) { - throw new Error("can't delete yourself!"); + throw new AppError.AppError("can't delete yourself!"); } else { return collaborators.deleteCollaborator(col.appid, data.id); } }); }) - .then(function () { + .then(() => { res.send(""); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.delete('/:appName', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var uid = req.users.id; var appManager = new AppManager(); accountManager.ownerCan(uid, appName) - .then(function (col) { + .then((col) => { return appManager.deleteApp(col.appid); }) - .then(function (data) { + .then((data) => { res.send(data); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); router.patch('/:appName', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var newAppName = _.trim(req.body.name); var appName = _.trim(req.params.appName); var uid = req.users.id; @@ -484,37 +552,41 @@ router.patch('/:appName', } else { var appManager = new AppManager(); return accountManager.ownerCan(uid, appName) - .then(function (col) { + .then((col) => { if (REGEX_ANDROID.test(appName) || OLD_REGEX_ANDROID.test(appName)) { if (!REGEX_ANDROID.test(newAppName)) { - throw new Error(`new appName have to point -android suffix! eg. Demo-android`); + throw new AppError.AppError(`new appName have to point -android suffix! eg. Demo-android`); } } else if (REGEX_IOS.test(appName) || OLD_REGEX_IOS.test(appName)) { if (!REGEX_IOS.test(newAppName)) { - throw new Error(`new appName have to point -ios suffix! eg. Demo-ios`); + throw new AppError.AppError(`new appName have to point -ios suffix! eg. Demo-ios`); } } else { - throw new Error(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); + throw new AppError.AppError(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); } return appManager.findAppByName(uid, newAppName) - .then(function (appInfo) { + .then((appInfo) => { if (!_.isEmpty(appInfo)){ - throw new Error(newAppName + " Exist!"); + throw new AppError.AppError(newAppName + " Exist!"); } return appManager.modifyApp(col.appid, {name: newAppName}); }); }) - .then(function () { + .then(() => { res.send(""); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); } }); router.post('/:appName/transfer/:email', - middleware.checkToken, function (req, res) { + middleware.checkToken, (req, res, next) => { var appName = _.trim(req.params.appName); var email = _.trim(req.params.email); var uid = req.users.id; @@ -522,25 +594,29 @@ router.post('/:appName/transfer/:email', return res.status(406).send("Invalid Email!"); } return accountManager.ownerCan(uid, appName) - .then(function (col) { + .then((col) => { return accountManager.findUserByEmail(email) - .then(function (data) { + .then((data) => { if (_.eq(data.id, uid)) { - throw new Error("You can't transfer to yourself!"); + throw new AppError.AppError("You can't transfer to yourself!"); } var appManager = new AppManager(); return appManager.transferApp(col.appid, uid, data.id); }); }) - .then(function (data) { + .then((data) => { res.send(data); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); -router.post('/', middleware.checkToken, function (req, res) { +router.post('/', middleware.checkToken, (req, res, next) => { var appName = req.body.name; var uid = req.users.id; var appManager = new AppManager(); @@ -548,23 +624,27 @@ router.post('/', middleware.checkToken, function (req, res) { return res.status(406).send("Please input name!"); } appManager.findAppByName(uid, appName) - .then(function (appInfo) { + .then((appInfo) => { if (!_.isEmpty(appInfo)){ - throw new Error(appName + " Exist!"); + throw new AppError.AppError(appName + " Exist!"); } if (!REGEX.test(appName)) { - throw new Error(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); + throw new AppError.AppError(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); } return appManager.addApp(uid, appName, req.users.identical) - .then(function () { + .then(() => { return {name: appName, collaborators: {[req.users.email]: {permission: "Owner"}}}; }); }) - .then(function (data) { + .then((data) => { res.send({app: data}); }) - .catch(function (e) { - res.status(406).send(e.message); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } }); }); diff --git a/routes/auth.js b/routes/auth.js index 5f805b86..e9e0ccea 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -3,8 +3,9 @@ var router = express.Router(); var _ = require('lodash'); var security = require('../core/utils/security'); var accountManager = require('../core/services/account-manager')(); +var AppError = require('../core/app-error'); -router.get('/login', function(req, res) { +router.get('/login', (req, res) => { var config = require('../core/config'); var codePushWebUrl = _.get(config, 'common.codePushWebUrl'); var isRedirect = false; @@ -21,11 +22,11 @@ router.get('/login', function(req, res) { } }); -router.get('/link', function(req, res) { +router.get('/link', (req, res) => { res.redirect(`/auth/login`); }); -router.get('/register', function(req, res) { +router.get('/register', (req, res) => { var config = require('../core/config'); var codePushWebUrl = _.get(config, 'common.codePushWebUrl'); var isRedirect = false; @@ -42,25 +43,29 @@ router.get('/register', function(req, res) { } }); -router.post('/logout', function (req, res) { +router.post('/logout', (req, res) => { res.send("ok"); }); -router.post('/login', function(req, res) { +router.post('/login', (req, res, next) => { var account = _.trim(req.body.account); var password = _.trim(req.body.password); var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); accountManager.login(account, password) - .then(function (users) { + .then((users) => { var jwt = require('jsonwebtoken'); return jwt.sign({ uid: users.id, hash: security.md5(users.ack_code), expiredIn: 7200 }, tokenSecret); }) - .then(function (token) { + .then((token) => { res.send({status:'OK', results: {tokens: token}}); }) - .catch(function (e) { - res.send({status:'ERROR', errorMessage: e.message}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({status:'ERROR', errorMessage: e.message}); + } else { + next(e); + } }); }); diff --git a/routes/index.js b/routes/index.js index a08fdec9..9b1eb15c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,23 +1,23 @@ var express = require('express'); var router = express.Router(); var Promise = require('bluebird'); -var AppError = require('../core/services/app-error'); +var AppError = require('../core/app-error'); var middleware = require('../core/middleware'); var ClientManager = require('../core/services/client-manager'); var _ = require('lodash'); -router.get('/', function(req, res, next) { +router.get('/', (req, res, next) => { res.render('index', { title: 'CodePushServer' }); }); -router.get('/README.md', function(req, res, next) { +router.get('/README.md', (req, res, next) => { var MarkdownIt = require('markdown-it'); const path = require('path'); const fs = require('fs'); const readFile = Promise.promisify(fs.readFile); const README = path.join(__dirname, '../README.md'); readFile(README, { encoding: 'utf8' }) - .then(source=>{ + .then(source => { var md = new MarkdownIt(); res.send(md.render(source)); }) @@ -30,21 +30,21 @@ router.get('/README.md', function(req, res, next) { }); }); -router.get('/tokens', function(req, res) { +router.get('/tokens', (req, res) => { res.render('tokens', { title: '获取token' }); }); -router.get('/updateCheck', function(req, res, next){ +router.get('/updateCheck', (req, res, next) => { var deploymentKey = _.get(req, "query.deploymentKey"); var appVersion = _.get(req, "query.appVersion"); var label = _.get(req, "query.label"); var packageHash = _.get(req, "query.packageHash") var clientManager = new ClientManager(); clientManager.updateCheckFromCache(deploymentKey, appVersion, label, packageHash) - .then(function (rs) { + .then((rs) => { res.send({"updateInfo":rs}); }) - .catch(function (e) { + .catch((e) => { if (e instanceof AppError.AppError) { res.status(404).send(e.message); } else { @@ -53,13 +53,13 @@ router.get('/updateCheck', function(req, res, next){ }); }); -router.post('/reportStatus/download', function(req, res){ +router.post('/reportStatus/download', (req, res) => { var clientUniqueId = _.get(req, "body.clientUniqueId"); var label = _.get(req, "body.label"); var deploymentKey = _.get(req, "body.deploymentKey"); var clientManager = new ClientManager(); clientManager.reportStatusDownload(deploymentKey, label, clientUniqueId) - .catch(function (err) { + .catch((err) => { if (!err instanceof AppError.AppError) { console.error(err.stack) } @@ -67,13 +67,13 @@ router.post('/reportStatus/download', function(req, res){ res.send('OK'); }); -router.post('/reportStatus/deploy', function(req, res){ +router.post('/reportStatus/deploy', (req, res) => { var clientUniqueId = _.get(req, "body.clientUniqueId"); var label = _.get(req, "body.label"); var deploymentKey = _.get(req, "body.deploymentKey"); var clientManager = new ClientManager(); clientManager.reportStatusDeploy(deploymentKey, label, clientUniqueId, req.body) - .catch(function (err) { + .catch((err) => { if (!err instanceof AppError.AppError) { console.error(err.stack) } @@ -81,7 +81,7 @@ router.post('/reportStatus/deploy', function(req, res){ res.send('OK'); }); -router.get('/authenticated', middleware.checkToken, function (req, res) { +router.get('/authenticated', middleware.checkToken, (req, res) => { return res.send({authenticated: true}); }) diff --git a/routes/sessions.js b/routes/sessions.js index b5862b54..a7b4ce18 100644 --- a/routes/sessions.js +++ b/routes/sessions.js @@ -3,13 +3,13 @@ var router = express.Router(); var _ = require('lodash'); var models = require('../models'); var middleware = require('../core/middleware'); -var AppError = require('../core/services/app-error'); +var AppError = require('../core/app-error'); -router.delete('/:machineName', middleware.checkToken, function(req, res, next){ +router.delete('/:machineName', middleware.checkToken, (req, res, next) => { var machineName = _.trim(decodeURI(req.params.machineName)); var uid = req.users.id; models.UserTokens.destroy({where: {created_by:machineName, uid: uid}}) - .then(function(rowNum){ + .then((rowNum) => { res.send(""); }) .catch(e => { diff --git a/routes/users.js b/routes/users.js index b0dc7f3c..c4664f3f 100644 --- a/routes/users.js +++ b/routes/users.js @@ -5,83 +5,103 @@ var _ = require('lodash'); var models = require('../models'); var middleware = require('../core/middleware'); var AccountManager = require('../core/services/account-manager'); +var AppError = require('../core/app-error') -router.get('/', middleware.checkToken, function(req, res) { +router.get('/', middleware.checkToken, (req, res) => { res.send({ title: 'CodePushServer' }); }); -router.post('/', function (req, res) { +router.post('/', (req, res, next) => { var email = _.trim(_.get(req, 'body.email')); var token = _.trim(_.get(req, 'body.token')); var password = _.trim(_.get(req, 'body.password')); var accountManager = new AccountManager(); return accountManager.checkRegisterCode(email, token) - .then(function (u) { + .then((u) => { if (_.isString(password) && password.length < 6) { - throw new Error('请您输入6~20位长度的密码'); + throw new AppError.AppError('请您输入6~20位长度的密码'); } return accountManager.register(email, password); }) - .then(function () { + .then(() => { res.send({status: "OK"}); }) - .catch(function (e) { - res.send({status: "ERROR", message: e.message}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({status: "ERROR", message: e.message}); + } else { + next(e); + } }); - }); -router.get('/exists', function (req, res) { +router.get('/exists', (req, res, next) => { var email = _.trim(_.get(req, 'query.email')); models.Users.findOne({where: {email: email}}) - .then(function (u) { + .then((u) => { if (!email) { - throw new Error(`请您输入邮箱地址`); + throw new AppError.AppError(`请您输入邮箱地址`); } res.send({status: "OK", exists: u ? true : false}); }) - .catch(function (e) { - res.send({status: "ERROR", message: e.message}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({status: "ERROR", message: e.message}); + } else { + next(e); + } }); }); -router.post('/registerCode', function (req, res) { +router.post('/registerCode', (req, res, next) => { var email = _.get(req, 'body.email'); var accountManager = new AccountManager(); return accountManager.sendRegisterCode(email) - .then(function () { + .then(() => { res.send({status: "OK"}); }) - .catch(function (e) { - res.send({status: "ERROR", message: e.message}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({status: "ERROR", message: e.message}); + } else { + next(e); + } }); }); -router.get('/registerCode/exists', function (req, res) { +router.get('/registerCode/exists', (req, res, next) => { var email = _.trim(_.get(req, 'query.email')); var token = _.trim(_.get(req, 'query.token')); var accountManager = new AccountManager(); return accountManager.checkRegisterCode(email, token) - .then(function () { + .then(() => { res.send({status: "OK"}); }) - .catch(function (e) { - res.send({status: "ERROR", message: e.message}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({status: "ERROR", message: e.message}); + } else { + next(e); + } }); }); //修改密码 -router.patch('/password', middleware.checkToken, function(req, res) { +router.patch('/password', middleware.checkToken, (req, res, next) => { var oldPassword = _.trim(_.get(req, 'body.oldPassword')); var newPassword = _.trim(_.get(req, 'body.newPassword')); var uid = req.users.id; var accountManager = new AccountManager(); return accountManager.changePassword(uid, oldPassword, newPassword) - .then(function () { + .then(() => { res.send({status: "OK"}); }) - .catch(function (e) { - res.send({status: "ERROR", message: e.message}); + .catch((e) => { + if (e instanceof AppError.AppError) { + res.send({status: "ERROR", message: e.message}); + } else { + next(e); + } }); }); From 73783f7cdf40f476b5445bad4ec6d5ead083d407 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 17:26:58 +0800 Subject: [PATCH 053/194] function to ()=>{} --- core/services/app-manager.js | 28 +++--- core/services/client-manager.js | 28 +++--- core/services/collaborators.js | 10 +-- core/services/datacenter-manager.js | 8 +- core/services/deployments.js | 48 +++++----- core/services/email-manager.js | 2 +- core/services/package-manager.js | 135 ++++++++++++---------------- core/utils/common.js | 36 ++++---- core/utils/security.js | 34 +++---- 9 files changed, 156 insertions(+), 173 deletions(-) diff --git a/core/services/app-manager.js b/core/services/app-manager.js index d0429d3f..0d484b49 100644 --- a/core/services/app-manager.js +++ b/core/services/app-manager.js @@ -18,14 +18,14 @@ proto.findAppByName = function (uid, appName) { }; proto.addApp = function (uid, appName, identical) { - return models.sequelize.transaction(function (t) { + return models.sequelize.transaction((t) => { return models.Apps.create({ name: appName, uid: uid },{ transaction: t }) - .then(function (apps) { + .then((apps) => { var appId = apps.id; var deployments = []; var deploymentKey = security.randToken(28) + identical; @@ -53,7 +53,7 @@ proto.addApp = function (uid, appName, identical) { }; proto.deleteApp = function (appId) { - return models.sequelize.transaction(function (t) { + return models.sequelize.transaction((t) => { return Promise.all([ models.Apps.destroy({where: {id: appId}, transaction: t}), models.Collaborators.destroy({where: {appid: appId}, transaction: t}), @@ -64,7 +64,7 @@ proto.deleteApp = function (appId) { proto.modifyApp = function (appId, params) { return models.Apps.update(params, {where: {id:appId}}) - .spread(function (affectedCount, affectedRows) { + .spread((affectedCount, affectedRows) => { if (!_.gt(affectedCount, 0)) { throw AppError.AppError('modify errors'); } @@ -73,7 +73,7 @@ proto.modifyApp = function (appId, params) { }; proto.transferApp = function (appId, fromUid, toUid) { - return models.sequelize.transaction(function (t) { + return models.sequelize.transaction((t) => { return Promise.all([ models.Apps.update({uid: toUid}, {where: {id: appId}, transaction: t}), models.Collaborators.destroy({where: {appid: appId, uid: fromUid}, transaction: t}), @@ -86,18 +86,18 @@ proto.transferApp = function (appId, fromUid, toUid) { proto.listApps = function (uid) { const self = this; return models.Collaborators.findAll({where : {uid: uid}}) - .then(function(data){ + .then((data) => { if (_.isEmpty(data)){ return []; } else { - var appIds = _.map(data, function(v){ return v.appid }); + var appIds = _.map(data, (v) => { return v.appid }); return models.Apps.findAll({where: {id: {in: appIds}}}); } }) - .then(function (appInfos) { - var rs = Promise.map(_.values(appInfos), function(v){ + .then((appInfos) => { + var rs = Promise.map(_.values(appInfos), (v) => { return self.getAppDetailInfo(v, uid) - .then(function (info) { + .then((info) => { return info; }); }); @@ -111,11 +111,11 @@ proto.getAppDetailInfo = function (appInfo, currentUid) { models.Deployments.findAll({where: {appid: appId}}), models.Collaborators.findAll({where: {appid: appId}}), ]) - .spread(function (deploymentInfos, collaboratorInfos) { + .spread((deploymentInfos, collaboratorInfos) => { return Promise.props({ - collaborators: Promise.reduce(collaboratorInfos, function (allCol, collaborator) { + collaborators: Promise.reduce(collaboratorInfos, (allCol, collaborator) => { return models.Users.findOne({where: {id: collaborator.get('uid')}}) - .then(function (u) { + .then((u) => { var isCurrentAccount = false; if (_.eq(u.get('id'), currentUid)) { isCurrentAccount = true; @@ -125,7 +125,7 @@ proto.getAppDetailInfo = function (appInfo, currentUid) { }); }, {}), - deployments: _.map(deploymentInfos, function (item) { + deployments: _.map(deploymentInfos, (item) => { return _.get(item, 'name'); }), diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 886d84e6..da2dfdea 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -25,9 +25,9 @@ proto.clearUpdateCheckCache = function(deploymentKey, appVersion, label, package let redisCacheKey = this.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); var client = factory.getRedisClient("default"); return client.keysAsync(redisCacheKey) - .then(function(data) { + .then((data) => { if (_.isArray(data)) { - return Promise.map(data, function(key){ + return Promise.map(data, (key) => { return client.delAsync(key); }); } @@ -44,7 +44,7 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH let redisCacheKey = self.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); var client = factory.getRedisClient("default"); return client.getAsync(redisCacheKey) - .then(function(data){ + .then((data) => { if (data) { try { var obj = JSON.parse(data); @@ -53,7 +53,7 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH } } return self.updateCheck(deploymentKey, appVersion, label, packageHash) - .then(function(rs){ + .then((rs) => { try { var strRs = JSON.stringify(rs); client.setexAsync(redisCacheKey, EXPIRED, strRs); @@ -81,19 +81,19 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { return Promise.reject(new AppError.AppError("please input deploymentKey and appVersion")) } return models.Deployments.findOne({where: {deployment_key: deploymentKey}}) - .then(function (dep) { + .then((dep) => { if (_.isEmpty(dep)) { throw new AppError.AppError('does not found deployment'); } return models.DeploymentsVersions.findOne({where: {deployment_id: dep.id, app_version: appVersion}}); }) - .then(function (deploymentsVersions) { + .then((deploymentsVersions) => { var packageId = _.get(deploymentsVersions, 'current_package_id', 0); if (_.eq(packageId, 0) ) { return; } return models.Packages.findById(packageId) - .then(function (packages) { + .then((packages) => { if (packages && _.eq(packages.deployment_id, deploymentsVersions.deployment_id) && !_.eq(packages.package_hash, packageHash)) { @@ -110,11 +110,11 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { return packages; }) - .then(function (packages) { + .then((packages) => { //差异化更新 if (!_.isEmpty(packages) && !_.eq(_.get(packages, 'package_hash', ""), packageHash)) { return models.PackagesDiff.findOne({where: {package_id:packages.id, diff_against_package_hash: packageHash}}) - .then(function (diffPackage) { + .then((diffPackage) => { if (!_.isEmpty(diffPackage)) { rs.downloadURL = common.getBlobDownloadUrl(_.get(diffPackage, 'diff_blob_url')); rs.packageSize = _.get(diffPackage, 'diff_size', 0); @@ -126,7 +126,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { } }); }) - .then(function () { + .then(() => { return rs; }); }; @@ -136,13 +136,13 @@ proto.getPackagesInfo = function (deploymentKey, label) { return Promise.reject(new AppError.AppError("please input deploymentKey and label")) } return models.Deployments.findOne({where: {deployment_key: deploymentKey}}) - .then(function (dep) { + .then((dep) => { if (_.isEmpty(dep)) { throw new AppError.AppError('does not found deployment'); } return models.Packages.findOne({where: {deployment_id: dep.id, label: label}}); }) - .then(function (packages) { + .then((packages) => { if (_.isEmpty(packages)) { throw new AppError.AppError('does not found packages'); } @@ -152,14 +152,14 @@ proto.getPackagesInfo = function (deploymentKey, label) { proto.reportStatusDownload = function(deploymentKey, label, clientUniqueId) { return this.getPackagesInfo(deploymentKey, label) - .then(function (packages) { + .then((packages) => { return models.PackagesMetrics.addOneOnDownloadById(packages.id); }); }; proto.reportStatusDeploy = function (deploymentKey, label, clientUniqueId, others) { return this.getPackagesInfo(deploymentKey, label) - .then(function (packages) { + .then((packages) => { var status = _.get(others, "status"); var packageId = packages.id; if (_.eq(status, "DeploymentSucceeded")) { diff --git a/core/services/collaborators.js b/core/services/collaborators.js index da7f9b88..13241cca 100644 --- a/core/services/collaborators.js +++ b/core/services/collaborators.js @@ -13,16 +13,16 @@ var proto = module.exports = function (){ proto.listCollaborators = function (appId) { return models.Collaborators.findAll({where: {appid: appId}}) - .then(function (data) { + .then((data) => { return _.reduce(data, function(result, value, key) { (result['uids'] || (result['uids'] = [])).push(value.uid); result[value.uid] = value; return result; }, []); }) - .then(function (coInfo) { + .then((coInfo) => { return models.Users.findAll({where: {id: {in: coInfo.uids}}}) - .then(function (data2) { + .then((data2) => { return _.reduce(data2, function (result, value, key) { var permission = ""; if (!_.isEmpty(coInfo[value.id])) { @@ -37,7 +37,7 @@ proto.listCollaborators = function (appId) { proto.addCollaborator = function (appId, uid) { return models.Collaborators.findOne({where: {appid: appId, uid: uid}}) - .then(function (data) { + .then((data) => { if (_.isEmpty(data)){ return models.Collaborators.create({ appid: appId, @@ -52,7 +52,7 @@ proto.addCollaborator = function (appId, uid) { proto.deleteCollaborator = function (appId, uid) { return models.Collaborators.findOne({where: {appid: appId, uid: uid}}) - .then(function (data) { + .then((data) => { if (_.isEmpty(data)){ throw new AppError.AppError('user is not a Collaborator'); }else { diff --git a/core/services/datacenter-manager.js b/core/services/datacenter-manager.js index be507be7..6633acfe 100644 --- a/core/services/datacenter-manager.js +++ b/core/services/datacenter-manager.js @@ -64,7 +64,7 @@ proto.validateStore = function (providePackageHash) { return Promise.resolve(false); } return security.calcAllFileSha256(contentPath) - .then(function (manifestJson) { + .then((manifestJson) => { var packageHash = security.packageHashSync(manifestJson); try { var manifestJsonLocal = JSON.parse(fs.readFileSync(manifestFile)); @@ -85,7 +85,7 @@ proto.storePackage = function (sourceDst, force) { } var self = this; return security.calcAllFileSha256(sourceDst) - .then(function (manifestJson) { + .then((manifestJson) => { var packageHash = security.packageHashSync(manifestJson); var dataDir = self.getDataDir(); var packageHashPath = `${dataDir}/${packageHash}`; @@ -95,9 +95,9 @@ proto.storePackage = function (sourceDst, force) { return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); } else { return common.createEmptyFolder(packageHashPath) - .then(function(){ + .then(() => { return common.move(sourceDst, contentPath) - .then(function () { + .then(() => { var manifestString = JSON.stringify(manifestJson); fs.writeFileSync(manifestFile, manifestString); return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); diff --git a/core/services/deployments.js b/core/services/deployments.js index d2317244..be2ae0bf 100644 --- a/core/services/deployments.js +++ b/core/services/deployments.js @@ -22,7 +22,7 @@ proto.getAllPackageIdsByDeploymentsId = function(deploymentsId) { proto.existDeloymentName = function (appId, name) { return models.Deployments.findOne({where: {appid: appId, name: name}}) - .then(function (data) { + .then((data) => { if (!_.isEmpty(data)){ throw new AppError.AppError(name + " name does Exist!") } else { @@ -34,12 +34,12 @@ proto.existDeloymentName = function (appId, name) { proto.addDeloyment = function (name, appId, uid) { var self = this; return models.Users.findById(uid) - .then(function (user) { + .then((user) => { if (_.isEmpty(user)) { throw new AppError.AppError('can\'t find user'); } return self.existDeloymentName(appId, name) - .then(function () { + .then(() => { var identical = user.identical; var deploymentKey = security.randToken(28) + identical; return models.Deployments.create({ @@ -55,12 +55,12 @@ proto.addDeloyment = function (name, appId, uid) { proto.renameDeloymentByName = function (deploymentName, appId, newName) { return this.existDeloymentName(appId, newName) - .then(function () { + .then(() => { return models.Deployments.update( {name: newName}, {where: {name: deploymentName,appid: appId}} ) - .spread(function (affectedCount, affectedRow) { + .spread((affectedCount, affectedRow) => { if (_.gt(affectedCount, 0)) { return {name: newName}; } else { @@ -74,7 +74,7 @@ proto.deleteDeloymentByName = function (deploymentName, appId) { return models.Deployments.destroy({ where: {name: deploymentName, appid: appId} }) - .then(function (rowNum) { + .then((rowNum) => { if (_.gt(rowNum, 0)) { return {name: `${deploymentName}`}; } else { @@ -93,16 +93,16 @@ proto.findPackagesAndOtherInfos = function (packageId) { return models.Packages.findOne({ where: {id: packageId} }) - .then(function (packageInfo) { + .then((packageInfo) => { if (!packageInfo) { return null; } return Promise.props({ packageInfo: packageInfo, packageDiffMap: models.PackagesDiff.findAll({where: {package_id: packageId}}) - .then(function(diffs){ + .then((diffs) => { if (diffs.length > 0) { - return _.reduce(diffs, function(result, v){ + return _.reduce(diffs, (result, v) => { result[_.get(v, 'diff_against_package_hash')] = { size: _.get(v, 'diff_size'), url: common.getBlobDownloadUrl(_.get(v, 'diff_blob_url')), @@ -121,7 +121,7 @@ proto.findPackagesAndOtherInfos = function (packageId) { proto.findDeloymentsPackages = function (deploymentsVersionsId) { var self = this; return models.DeploymentsVersions.findOne({where: {id: deploymentsVersionsId}}) - .then(function(deploymentsVersionsInfo) { + .then((deploymentsVersionsInfo) => { if (deploymentsVersionsInfo) { return self.findPackagesAndOtherInfos(deploymentsVersionsInfo.current_package_id); } @@ -156,11 +156,11 @@ proto.formatPackage = function(packageVersion) { proto.listDeloyments = function (appId) { var self = this; return models.Deployments.findAll({where: {appid: appId}}) - .then(function(deploymentsInfos){ + .then((deploymentsInfos) => { if (_.isEmpty(deploymentsInfos)) { return []; } - return Promise.map(deploymentsInfos, function (v) { + return Promise.map(deploymentsInfos, (v) => { return Promise.props({ createdTime: parseInt(moment(v.created_at).format('x')), id: `${v.id}`, @@ -175,40 +175,40 @@ proto.listDeloyments = function (appId) { proto.getDeploymentHistory = function (deploymentId) { var self = this; return models.DeploymentsHistory.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 15}) - .then(function(history) { - return _.map(history, function(v){ return v.package_id}); + .then((history) => { + return _.map(history, (v) => { return v.package_id}); }) - .then(function(packageIds){ - return Promise.map(packageIds, function(v) { + .then((packageIds) => { + return Promise.map(packageIds, (v) => { return self.findPackagesAndOtherInfos(v).then(self.formatPackage); }); }); }; proto.deleteDeploymentHistory = function(deploymentId) { - return models.sequelize.transaction(function (t) { + return models.sequelize.transaction((t) => { return Promise.all([ models.Deployments.update( {last_deployment_version_id:0,label_id:0}, {where: {id: deploymentId},transaction: t} ), models.DeploymentsHistory.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 1000}) - .then(function(rs){ - return Promise.map(rs, function(v){ + .then((rs) => { + return Promise.map(rs, (v) => { return v.destroy({transaction: t}); }); }), models.DeploymentsVersions.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 1000}) - .then(function(rs) { - return Promise.map(rs, function(v){ + .then((rs) => { + return Promise.map(rs, (v) => { return v.destroy({transaction: t}); }); }), models.Packages.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 1000}) - .then(function(rs) { - return Promise.map(rs, function(v){ + .then((rs) => { + return Promise.map(rs, (v) => { return v.destroy({transaction: t}) - .then(function(){ + .then(() => { return Promise.all([ models.PackagesMetrics.destroy({where: {package_id: v.get('id')},transaction: t}), models.PackagesDiff.destroy({where: {package_id: v.get('id')},transaction: t}) diff --git a/core/services/email-manager.js b/core/services/email-manager.js index c3671c63..2ed3ef67 100644 --- a/core/services/email-manager.js +++ b/core/services/email-manager.js @@ -17,7 +17,7 @@ var proto = module.exports = function (){ }; proto.sendMail = function (options) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { if(!_.get(options, 'to')) { return reject(new AppError.AppError("to是必传参数")); } diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 52cae3c3..6bad795b 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -26,9 +26,9 @@ proto.getMetricsbyPackageId= function(packageId) { } proto.parseReqFile = function (req) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var form = new formidable.IncomingForm(); - form.parse(req, function(err, fields, files) { + form.parse(req, (err, fields, files) => { if (err) { reject(new AppError.AppError("upload error")); } else { @@ -50,26 +50,25 @@ proto.getDeploymentsVersions = function (deploymentId, appVersion) { proto.existPackageHashAndCreateVersions = function (deploymentId, appVersion, packageHash) { return this.getDeploymentsVersions(deploymentId, appVersion) - .then(function (data) { + .then((data) => { if (_.isEmpty(data)){ return models.DeploymentsVersions.create({ deployment_id: deploymentId, app_version: appVersion, - }).then(function () { - return false; - }); + }) + .then(() => false); } else { var packageId = data.current_package_id; if (_.gt(packageId, 0)) { return models.Packages.findById(packageId) - .then(function (data) { + .then((data) => { if (_.eq(_.get(data,"package_hash"), packageHash)){ return true; }else { return false; } }); - }else { + } else { return false } } @@ -85,10 +84,10 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH var originalLabel = params.originalLabel || ""; var originalDeployment = params.originalDeployment || ""; return models.Deployments.generateLabelId(deploymentId) - .then(function (labelId) { - return models.sequelize.transaction(function (t) { + .then((labelId) => { + return models.sequelize.transaction((t) => { return models.DeploymentsVersions.findOne({where: {deployment_id: deploymentId, app_version: appVersion}}) - .then(function (deploymentsVersions) { + .then((deploymentsVersions) => { if (!deploymentsVersions) { return models.DeploymentsVersions.create({ current_package_id: 0, @@ -98,7 +97,7 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH } return deploymentsVersions; }) - .then(function(deploymentsVersions) { + .then((deploymentsVersions) => { return models.Packages.create({ deployment_version_id: deploymentsVersions.id, deployment_id: deploymentId, @@ -114,7 +113,7 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH original_label: originalLabel, original_deployment: originalDeployment },{transaction: t}) - .then(function (packages) { + .then((packages) => { deploymentsVersions.set('current_package_id', packages.id); return Promise.all([ deploymentsVersions.save({transaction: t}), @@ -131,9 +130,7 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH {transaction: t} ) ]) - .then(function () { - return packages; - }); + .then(() => packages); }); }); }); @@ -143,15 +140,15 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH proto.downloadPackageAndExtract = function (workDirectoryPath, packageHash, blobHash) { var dataCenterManager = require('./datacenter-manager')(); return dataCenterManager.validateStore(packageHash) - .then(function (isValidate) { + .then((isValidate) => { if (isValidate) { return dataCenterManager.getPackageInfo(packageHash); } else { var downloadURL = common.getBlobDownloadUrl(blobHash); return common.createFileFromRequest(downloadURL, `${workDirectoryPath}/${blobHash}`) - .then(function (download) { + .then((download) => { return common.unzipFile(`${workDirectoryPath}/${blobHash}`, `${workDirectoryPath}/current`) - .then(function (outputPath) { + .then((outputPath) => { return dataCenterManager.storePackage(outputPath, true); }); }); @@ -160,17 +157,17 @@ proto.downloadPackageAndExtract = function (workDirectoryPath, packageHash, blob } proto.zipDiffPackage = function (fileName, files, baseDirectoryPath, hotCodePushFile) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var zipFile = new yazl.ZipFile(); var writeStream = fs.createWriteStream(fileName); - writeStream.on('error', function (error) { + writeStream.on('error', (error) => { reject(error); }) zipFile.outputStream.pipe(writeStream) - .on("error", function (error) { + .on("error", (error) => { reject(error); }) - .on("close", function () { + .on("close", () => { resolve({ isTemporary: true, path: fileName }); }); for (var i = 0; i < files.length; ++i) { @@ -190,13 +187,13 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente diff_against_package_hash: diffPackageHash } }) - .then(function (diffPackage) { + .then((diffPackage) => { if (!_.isEmpty(diffPackage)) { return; } var downloadURL = common.getBlobDownloadUrl(diffManifestBlobHash); return common.createFileFromRequest(downloadURL, `${workDirectoryPath}/${diffManifestBlobHash}`) - .then(function(){ + .then(() => { var originContentPath = dataCenter.contentPath; var originManifestJson = JSON.parse(fs.readFileSync(dataCenter.manifestFilePath, "utf8")) var diffManifestJson = JSON.parse(fs.readFileSync(`${workDirectoryPath}/${diffManifestBlobHash}`, "utf8")) @@ -208,11 +205,11 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente var fileName = `${workDirectoryPath}/${diffManifestBlobHash}.zip`; return self.zipDiffPackage(fileName, files, originContentPath, hotCodePushFile) - .then(function (data) { + .then((data) => { return security.qetag(data.path) - .then(function (diffHash) { + .then((diffHash) => { return common.uploadFileToStorage(diffHash, fileName) - .then(function () { + .then(() => { var stats = fs.statSync(fileName); return models.PackagesDiff.create({ package_id: packageId, @@ -230,7 +227,7 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente proto.createDiffPackagesByLastNums = function (packageId, num) { var self = this; return models.Packages.findById(packageId) - .then(function (originalPackage) { + .then((originalPackage) => { if (_.isEmpty(originalPackage)) { throw AppError.AppError('can\'t find Package'); } @@ -250,10 +247,10 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { limit: 2 }) ]) - .spread(function (lastNumsPackages, basePackages) { + .spread((lastNumsPackages, basePackages) => { return _.unionBy(lastNumsPackages, basePackages, 'id'); }) - .then(function(lastNumsPackages){ + .then((lastNumsPackages) => { return self.createDiffPackages(originalPackage, lastNumsPackages); }); }); @@ -272,17 +269,11 @@ proto.createDiffPackages = function (originalPackage, destPackages) { var blob_url = _.get(originalPackage, 'blob_url'); var workDirectoryPath = path.join(os.tmpdir(), 'codepush_' + security.randToken(32)); return common.createEmptyFolder(workDirectoryPath) - .then(function(){ - return self.downloadPackageAndExtract(workDirectoryPath, package_hash, blob_url) - }) - .then(function (dataCenter) { - return Promise.map(destPackages, function (v) { - return self.generateOneDiffPackage(workDirectoryPath, originalPackage.id, dataCenter, v.package_hash, v.manifest_blob_url); - }); - }) - .finally(function () { - common.deleteFolderSync(workDirectoryPath); - }); + .then(() => self.downloadPackageAndExtract(workDirectoryPath, package_hash, blob_url)) + .then((dataCenter) => Promise.map(destPackages, + (v) => self.generateOneDiffPackage(workDirectoryPath, originalPackage.id, dataCenter, v.package_hash, v.manifest_blob_url) + )) + .finally(() => common.deleteFolderSync(workDirectoryPath)); } proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, releaseUid, pubType) { @@ -297,7 +288,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, return Promise.all([ security.qetag(filePath), common.createEmptyFolder(directoryPath) - .then(function () { + .then(() => { if (fileType == "application/zip") { return common.unzipFile(filePath, directoryPath) } else { @@ -305,9 +296,9 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, } }) ]) - .spread(function(blobHash) { + .spread((blobHash) => { return security.isAndroidPackage(directoryPath) - .then(function (type) { + .then((type) => { if (type === 1) { //android if (pubType == 'ios' ) { @@ -322,35 +313,31 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, //不验证 } }) - .then(function(){ - return blobHash; - }) + .then(() => blobHash) }) - .then(function(blobHash) { + .then((blobHash) => { var dataCenterManager = require('./datacenter-manager')(); return dataCenterManager.storePackage(directoryPath) - .then(function (dataCenter) { + .then((dataCenter) => { var packageHash = dataCenter.packageHash; var manifestFile = dataCenter.manifestFilePath; return self.existPackageHashAndCreateVersions(deploymentId, appVersion, packageHash) - .then(function (isExist) { + .then((isExist) => { if (isExist){ throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); } return security.qetag(manifestFile); }) - .then(function (manifestHash) { + .then((manifestHash) => { return Promise.all([ common.uploadFileToStorage(manifestHash, manifestFile), common.uploadFileToStorage(blobHash, filePath) ]) - .then(function () { - return [packageHash, manifestHash, blobHash]; - }); + .then(() => [packageHash, manifestHash, blobHash]); }); }); }) - .spread(function (packageHash, manifestHash, blobHash) { + .spread((packageHash, manifestHash, blobHash) => { var stats = fs.statSync(filePath); var params = { releaseMethod: 'Upload', @@ -361,9 +348,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, } return self.createPackage(deploymentId, appVersion, packageHash, manifestHash, blobHash, params); }) - .finally(function () { - common.deleteFolderSync(directoryPath); - }) + .finally(() => common.deleteFolderSync(directoryPath)) }; proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, packageInfo) { @@ -372,7 +357,7 @@ proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, package var isMandatory = _.get(packageInfo, 'isMandatory'); var isDisabled = _.get(packageInfo, 'isDisabled'); return models.DeploymentsVersions.findById(deploymentVersionId) - .then(function(deploymentsVersions){ + .then((deploymentsVersions) => { if (_.isBoolean(isDisabled)) { throw new AppError.AppError(`--disabled -x function is not implements`); } @@ -381,7 +366,7 @@ proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, package return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) } return models.DeploymentsVersions.findOne({deployment_id: deploymentId, app_version: appVersion}) - .then(function(d){ + .then((d) => { if (d) { throw new AppError.AppError(`version ${appVersion} already exist`); } @@ -391,7 +376,7 @@ proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, package throw new AppError.AppError(`packages were not found in db`); } }) - .then(function(){ + .then(() => { }); }; @@ -399,35 +384,33 @@ proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, package proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUid) { var self = this; return models.Deployments.findById(sourceDeploymentId) - .then(function (sourceDeployment) { + .then((sourceDeployment) => { var lastDeploymentVersionId = _.get(sourceDeployment, 'last_deployment_version_id', 0); if (_.lte(lastDeploymentVersionId, 0)) { throw new AppError.AppError('does not exist last_deployment_version_id.'); } return models.DeploymentsVersions.findById(lastDeploymentVersionId) - .then(function (deploymentsVersions) { + .then((deploymentsVersions) => { var packageId = _.get(deploymentsVersions, 'current_package_id', 0); if (_.lte(packageId, 0)) { throw new AppError.AppError('does not exist packages.'); } return models.Packages.findById(packageId) - .then(function (packages) { + .then((packages) => { if (!packages) { throw new AppError.AppError('does not exist packages.'); } return self.existPackageHashAndCreateVersions(destDeploymentId, deploymentsVersions.app_version, packages.package_hash) - .then(function (isExist) { + .then((isExist) => { if (isExist){ throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); } }) - .then(function () { - return [sourceDeployment, deploymentsVersions, packages]; - }); + .then(() => [sourceDeployment, deploymentsVersions, packages]); }); }); }) - .spread(function (sourceDeployment, deploymentsVersions, packages) { + .spread((sourceDeployment, deploymentsVersions, packages) => { var params = { releaseMethod: 'Promote', releaseUid: promoteUid, @@ -444,25 +427,25 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUi proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) { var self = this; return models.DeploymentsVersions.findById(deploymentVersionId) - .then(function(deploymentsVersions){ + .then((deploymentsVersions) => { if (!deploymentsVersions) { throw new AppError.AppError("您之前还没有发布过版本"); } return models.Packages.findById(deploymentsVersions.current_package_id) - .then(function (currentPackageInfo){ + .then((currentPackageInfo) => { if (targetLabel) { return models.Packages.findAll({where: {deployment_version_id: deploymentVersionId, label: targetLabel}, limit: 1}) - .then(function(rollbackPackageInfos) { + .then((rollbackPackageInfos) => { return [currentPackageInfo, rollbackPackageInfos] }); } else { return self.getCanRollbackPackages(deploymentVersionId) - .then(function(rollbackPackageInfos) { + .then((rollbackPackageInfos) => { return [currentPackageInfo, rollbackPackageInfos] }); } }) - .spread(function (currentPackageInfo, rollbackPackageInfos){ + .spread((currentPackageInfo, rollbackPackageInfos) => { if (currentPackageInfo && rollbackPackageInfos.length > 0) { for (var i = rollbackPackageInfos.length - 1; i >= 0; i--) { if (rollbackPackageInfos[i].package_hash != currentPackageInfo.package_hash) { @@ -472,7 +455,7 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) } throw new AppError.AppError("没有可供回滚的版本"); }) - .then(function(rollbackPackage){ + .then((rollbackPackage) => { var params = { releaseMethod: 'Rollback', releaseUid: rollbackUid, diff --git a/core/utils/common.js b/core/utils/common.js index 8f849ca2..6d5c29dc 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -11,7 +11,7 @@ var AppError = require('../app-error'); module.exports = common; common.createFileFromRequest = function (url, filePath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { fs.exists(filePath, function (exists) { if (!exists) { var request = require('request'); @@ -40,7 +40,7 @@ common.createFileFromRequest = function (url, filePath) { } common.move = function (sourceDst, targertDst) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { fsextra.move(sourceDst, targertDst, {clobber: true, limit: 16}, function (err) { if (err) { return reject(err); @@ -51,7 +51,7 @@ common.move = function (sourceDst, targertDst) { }; common.deleteFolder = function (folderPath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { fsextra.remove(folderPath, function (err) { if (err) { reject(err); @@ -68,8 +68,8 @@ common.deleteFolderSync = function (folderPath) { common.createEmptyFolder = function (folderPath) { return common.deleteFolder(folderPath) - .then(function (data) { - fsextra.mkdirs(folderPath, function (err) { + .then((data) => { + fsextra.mkdirs(folderPath, (err) => { if (err) { throw err; } @@ -84,9 +84,9 @@ common.createEmptyFolderSync = function (folderPath) { }; common.unzipFile = function (zipFile, outputPath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { try { - fs.exists(zipFile, function(exists){ + fs.exists(zipFile, (exists) => { if (!exists) { reject(new AppError.AppError("zipfile not found!")) } @@ -120,7 +120,7 @@ common.uploadFileToStorage = function (key, filePath) { }; common.uploadFileToLocal = function (key, filePath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var storageDir = _.get(config, 'local.storageDir'); if (!storageDir) { throw new AppError.AppError('please set config local storageDir'); @@ -138,7 +138,7 @@ common.uploadFileToLocal = function (key, filePath) { if (!stats.isFile()) { throw new AppError.AppError(`${filePath} must be file`); } - fsextra.copy(filePath, `${storageDir}/${key}`, {clobber: true, limit: 16}, function (err) { + fsextra.copy(filePath, `${storageDir}/${key}`, {clobber: true, limit: 16}, (err) => { if (err) { return reject(err); } @@ -163,12 +163,12 @@ common.getBlobDownloadUrl = function (blobUrl) { }; common.uploadFileToQiniu = function (key, filePath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { qiniu.conf.ACCESS_KEY = _.get(config, "qiniu.accessKey"); qiniu.conf.SECRET_KEY = _.get(config, "qiniu.secretKey"); var bucket = _.get(config, "qiniu.bucketName", "jukang"); var client = new qiniu.rs.Client(); - client.stat(bucket, key, function(err, ret) { + client.stat(bucket, key, (err, ret) => { if (!err) { resolve(ret.hash); } else { @@ -178,7 +178,7 @@ common.uploadFileToQiniu = function (key, filePath) { reject(e); } var extra = new qiniu.io.PutExtra(); - qiniu.io.putFile(uptoken, key, filePath, extra, function(err, ret) { + qiniu.io.putFile(uptoken, key, filePath, extra, (err, ret) => { if(!err) { // 上传成功, 处理返回值 resolve(ret.hash); @@ -195,19 +195,19 @@ common.uploadFileToQiniu = function (key, filePath) { common.uploadFileToS3 = function (key, filePath) { var AWS = require('aws-sdk'); return ( - new Promise(function(resolve, reject) { + new Promise((resolve, reject) => { AWS.config.update({ region: _.get(config, 's3.region') }); var s3 = new AWS.S3({ params: {Bucket: _.get(config, 's3.bucketName')} }); - fs.readFile(filePath, function(err, data) { + fs.readFile(filePath, (err, data) => { s3.upload({ Key: key, Body: data, ACL:'public-read', - }, function(err, response) { + }, (err, response) => { if(err) { reject(new AppError.AppError(JSON.stringify(err))); } else { @@ -232,12 +232,12 @@ common.uploadFileToOSS = function (key, filePath) { Key: `${_.get(config, 'oss.prefix')}/${key}`, }); - return new Promise(function (resolve, reject) { - upload.on('error', function (error) { + return new Promise((resolve, reject) => { + upload.on('error', (error) => { reject(error); }); - upload.on('uploaded', function (details) { + upload.on('uploaded', (details) => { resolve(details.ETag); }); fs.createReadStream(filePath).pipe(upload); diff --git a/core/utils/security.js b/core/utils/security.js index 3a9b45b9..f8604809 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -37,14 +37,14 @@ security.parseToken = function(token) { } security.fileSha256 = function (file) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var rs = fs.createReadStream(file); var hash = crypto.createHash('sha256'); rs.on('data', hash.update.bind(hash)); - rs.on('error', function(e){ + rs.on('error', (e) => { reject(e); }); - rs.on('end', function () { + rs.on('end', () => { resolve(hash.digest('hex')); }); }); @@ -58,7 +58,7 @@ security.stringSha256Sync = function (contents) { security.packageHashSync = function (jsonData) { var sortedArr = security.sortJsonToArr(jsonData); - var manifestData = _.map(sortedArr, function(v){ + var manifestData = _.map(sortedArr, (v) => { return v.path + ':' + v.hash; }); var manifestString = JSON.stringify(manifestData.sort()); @@ -68,13 +68,13 @@ security.packageHashSync = function (jsonData) { //参数为buffer或者readableStream或者文件路径 security.qetag = function (buffer) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { qetag(buffer, resolve); }); } security.qetagString = function (contents) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var Readable = require('stream').Readable var buffer = new Readable buffer.push(contents) @@ -84,13 +84,13 @@ security.qetagString = function (contents) { } security.sha256AllFiles = function (files) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var results = {}; var length = files.length; var count = 0; - files.forEach(function (file) { + files.forEach((file) => { security.fileSha256(file) - .then(function (hash) { + .then((hash) => { results[file] = hash; count++; if (count == length) { @@ -102,11 +102,11 @@ security.sha256AllFiles = function (files) { } security.isAndroidPackage = function (directoryPath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var recursiveFs = require("recursive-fs"); var path = require('path'); var slash = require("slash"); - recursiveFs.readdirr(directoryPath, function (error, directories, files) { + recursiveFs.readdirr(directoryPath, (error, directories, files) => { if (error) { reject(error); } else { @@ -134,11 +134,11 @@ security.isAndroidPackage = function (directoryPath) { } security.calcAllFileSha256 = function (directoryPath) { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { var recursiveFs = require("recursive-fs"); var path = require('path'); var slash = require("slash"); - recursiveFs.readdirr(directoryPath, function (error, directories, files) { + recursiveFs.readdirr(directoryPath, (error, directories, files) => { if (error) { reject(error); } else { @@ -146,9 +146,9 @@ security.calcAllFileSha256 = function (directoryPath) { reject(new AppError.AppError("empty files")); }else { security.sha256AllFiles(files) - .then(function (results) { + .then((results) => { var data = {}; - _.forIn(results, function (value, key) { + _.forIn(results, (value, key) => { var relativePath = path.relative(directoryPath, key); relativePath = slash(relativePath); data[relativePath] = value; @@ -163,8 +163,8 @@ security.calcAllFileSha256 = function (directoryPath) { security.sortJsonToArr = function (json) { var rs = []; - _.forIn(json, function (value, key) { + _.forIn(json, (value, key) => { rs.push({path:key, hash: value}) }); - return _.sortBy(rs, function(o) { return o.path; }); + return _.sortBy(rs, (o) => o.path); } From 7e84567ab3523d6e2842ca64fb65e44d8e4de07f Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 18:10:28 +0800 Subject: [PATCH 054/194] add readme notes --- README.md | 1 + docs/react-native-code-push.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 9b4cd3ac..a1f9b7a8 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in - react-native 不同平台bundle包不一样,在使用code-push-server的时候必须创建不同的应用来区分(eg. CodePushDemo-ios 和 CodePushDemo-android) - react-native-code-push只更新资源文件,不会更新java和Objective C,所以npm升级依赖包版本的时候,如果依赖包使用的本地化实现, 这时候必须更改应用版本号(ios修改Info.plist中的CFBundleShortVersionString, android修改build.gradle中的versionName), 然后重新编译app发布到应用商店。 - 推荐使用code-push release-react 命令发布应用,该命令合并了打包和发布命令(eg. code-push release-react CodePushDemo-ios ios -d Production) +- 每次向App Store提交新的版本时,也应该基于该提交版本同时向code-push-server发布一个初始版本。(因为后面每次向code-push-server发布版本时,code-puse-server都会和初始版本比较,生成补丁版本) ## EXAMPLE codepush.19910225.com 只是一个测试server,不要将自己生产环境的项目放在上面,服务器的宽带只有1M,而且服务没有做负载均衡和监控,稳定性不能保证,烦请大家自己搭建自己的服务。 diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index e2008ae8..3dce5fe1 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -170,6 +170,7 @@ $ code-push release-react CodePushDemo-android android -d Production #android版 - react-native 不同平台bundle包不一样,在使用code-push-server的时候必须创建不同的应用来区分(eg. CodePushDemo-ios 和 CodePushDemo-android) - react-native-code-push只更新资源文件,不会更新java和Objective C,所以npm升级依赖包版本的时候,如果依赖包使用的本地化实现, 这时候必须更改应用版本号(ios修改Info.plist中的CFBundleShortVersionString, android修改build.gradle中的versionName), 然后重新编译app发布到应用商店。 - 推荐使用code-push release-react 命令发布应用,该命令合并了打包和发布命令(eg. code-push release-react CodePushDemo-ios ios -d Production) +- 每次向App Store提交新的版本时,也应该基于该提交版本同时向code-push-server发布一个初始版本。(因为后面每次向code-push-server发布版本时,code-puse-server都会和初始版本比较,生成补丁版本) ## 例子 From 8e56b4ef9eb2aa9d7dd66106812d0c4d5ecca46e Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Feb 2017 21:34:40 +0800 Subject: [PATCH 055/194] fix error --- app.js | 1 - bin/www | 2 +- config/config.js | 3 ++- config/config.test.js | 3 ++- config/config.testwin.js | 3 ++- core/services/account-manager.js | 7 +++++-- package.json | 2 ++ routes/apps.js | 2 +- 8 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app.js b/app.js index 2fc4f51c..06c68056 100644 --- a/app.js +++ b/app.js @@ -20,7 +20,6 @@ var AppError = require('./core/app-error'); var app = express(); app.use(helmet()); app.disable('x-powered-by'); - // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); diff --git a/bin/www b/bin/www index 8203dcb6..d39896eb 100755 --- a/bin/www +++ b/bin/www @@ -5,7 +5,7 @@ */ var app = require('../app'); -var debug = require('debug')('codepush:server'); +var debug = require('debug')('code-push-server:server'); var http = require('http'); var validator = require('validator') var _ = require('lodash') diff --git a/config/config.js b/config/config.js index 75254bc7..3029c7f2 100644 --- a/config/config.js +++ b/config/config.js @@ -7,7 +7,8 @@ config.development = { database: process.env.DATA_BASE || "codepush", host: process.env.RDS_HOST || "127.0.0.1", port: process.env.RDS_PORT || 3306, - dialect: "mysql" + dialect: "mysql", + logging: false }, // Config for qiniu (http://www.qiniu.com/) cloud storage when storageType value is "qiniu". qiniu: { diff --git a/config/config.test.js b/config/config.test.js index 4e0722be..61b588eb 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -8,7 +8,8 @@ config.test = { database: "codepush_test", host: "127.0.0.1", port: 3306, - dialect: "mysql" + dialect: "mysql", + logging: false }, local: { storageDir: os.tmpdir(), diff --git a/config/config.testwin.js b/config/config.testwin.js index 24d017cd..edd87fb1 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -8,7 +8,8 @@ config.test = { database: "codepush_test", host: "127.0.0.1", port: 3306, - dialect: "mysql" + dialect: "mysql", + logging: false }, local: { storageDir: os.tmpdir(), diff --git a/core/services/account-manager.js b/core/services/account-manager.js index a3815e0f..0a07f63a 100644 --- a/core/services/account-manager.js +++ b/core/services/account-manager.js @@ -31,8 +31,11 @@ proto.collaboratorCan = function(uid, appName) { proto.ownerCan = function(uid, appName) { return this.getCollaborator(uid, appName) .then((data) => { - if (!data || !_.eq(_.get(data,'roles'), 'Owner') ) { - throw new AppError.AppError("Permission Deny!"); + if (!data) { + throw new AppError.AppError(`App ${appName} not exists.`); + } + if (!_.eq(_.get(data,'roles'), 'Owner') ) { + throw new AppError.AppError("Permission Deny, You are not owner!"); } return data; }); diff --git a/package.json b/package.json index 6a1deb0c..6d7d20d5 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,10 @@ "formidable": "^1.0.17", "fs-extra": "^1.0.0", "helmet": "^3.1.0", + "i18n": "^0.8.3", "jsonwebtoken": "^7.1.7", "lodash": "^4.5.1", + "log4js": "^1.1.0", "markdown-it": "^8.0.1", "moment": "^2.14.1", "morgan": "^1.7.0", diff --git a/routes/apps.js b/routes/apps.js index 727dea4d..ba323243 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -269,7 +269,7 @@ router.post('/:appName/deployments/:deploymentName/release', .then(() => { packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch((e) => { - console.log(e); + console.error(e); }); }); } From b076e280dfafce65506d124bc69c2ca69f546e51 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 13 Feb 2017 13:36:10 +0800 Subject: [PATCH 056/194] add app debug --- app.js | 56 ++++++++++++++++++++++++++-------------- bin/www | 29 +++++++++++++++------ config/config.js | 11 ++++++++ config/config.test.js | 9 +++++++ config/config.testwin.js | 9 +++++++ docs/process.yml | 2 ++ 6 files changed, 89 insertions(+), 27 deletions(-) diff --git a/app.js b/app.js index 06c68056..5318d01b 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,6 @@ var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); -var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var helmet = require('helmet'); @@ -17,6 +16,8 @@ var account = require('./routes/account'); var users = require('./routes/users'); var apps = require('./routes/apps'); var AppError = require('./core/app-error'); +var log4js = require('log4js'); +var log = log4js.getLogger("app"); var app = express(); app.use(helmet()); app.disable('x-powered-by'); @@ -24,13 +25,7 @@ app.disable('x-powered-by'); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); -// uncomment after placing your favicon in /public -//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); -if (app.get('env') === 'development') { - app.use(logger('dev')); -} else if (app.get('env') === 'production'){ - app.use(logger('combined',{skip: function (req, res) { return res.statusCode < 400 }})); -} +app.use(log4js.connectLogger(log4js.getLogger("http"), {level: log4js.levels.INFO})); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); @@ -39,22 +34,42 @@ app.use(express.static(path.join(__dirname, 'public'))); //use nginx in production if (app.get('env') === 'development') { + log.debug("set Access-Control Header"); app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,PATCH,DELETE,OPTIONS"); + log.debug("use set Access-Control Header"); next(); }); } -if (_.get(config, 'common.storageType') === 'local' - && _.get(config, 'local.storageDir') - ) { - if (!fs.existsSync(_.get(config, 'local.storageDir'))) { - var dir = _.get(config, 'local.storageDir'); - throw new Error(`Please create dir ${dir}`); +log.debug("config common.storageType value: " + _.get(config, 'common.storageType')); + +if (_.get(config, 'common.storageType') === 'local') { + var localStorageDir = _.get(config, 'local.storageDir'); + if (localStorageDir) { + + log.debug("config common.storageDir value: " + localStorageDir); + + if (!fs.existsSync(localStorageDir)) { + var e = new Error(`Please create dir ${localStorageDir}`); + log.error(e); + throw e; + } + try { + log.debug('checking storageDir fs.W_OK | fs.R_OK'); + fs.accessSync(localStorageDir, fs.W_OK | fs.R_OK); + log.debug('storageDir fs.W_OK | fs.R_OK is ok'); + } catch (e) { + log.error(e); + throw e; + } + log.debug("static download uri value: " + _.get(config, 'local.public', '/download')); + app.use(_.get(config, 'local.public', '/download'), express.static(localStorageDir)); + } else { + log.error('please config local storageDir'); } - app.use(_.get(config, 'local.public', '/download'), express.static(_.get(config, 'local.storageDir'))); } app.use('/', routes); @@ -75,23 +90,26 @@ if (app.get('env') === 'development') { message: err.message, error: err }); - console.error(err.stack); + log.error(err); }); app.use(function(err, req, res, next) { if (err instanceof AppError.AppError) { res.send(err); + log.debug(err); } else { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); - console.error(err.stack); + log.error(err); } }); } else { app.use(function(req, res, next) { - res.status(404).send(new AppError.NotFound()); + var e = new AppError.NotFound(); + res.status(404).send(e); + log.debug(e); }); // production error handler // no stacktraces leaked to user @@ -103,7 +121,7 @@ if (app.get('env') === 'development') { var error = new AppError.AppError(`服务器繁忙,请稍后再试!`); error.status = status; res.status(status).send(error); - console.error(err.stack); + log.error(err); } }); } diff --git a/bin/www b/bin/www index d39896eb..6514e541 100755 --- a/bin/www +++ b/bin/www @@ -5,18 +5,31 @@ */ var app = require('../app'); -var debug = require('debug')('code-push-server:server'); +var log4js = require('log4js'); var http = require('http'); var validator = require('validator') var _ = require('lodash') +var config = require('../core/config'); + +log4js.configure(_.get(config, 'log4js', {appenders: [{ type: 'console'}], levels : {"[all]": "ERROR", http: "ERROR"} })); +var log = log4js.getLogger("startup") + /** * Get port from environment and store in Express. */ var port = normalizePort(process.env.PORT || '3000'); +log.debug('port '+ port); + var host = null; -if (process.env.HOST && validator.isIP(process.env.HOST)) { - host = process.env.HOST; +if (process.env.HOST) { + log.debug('process.env.HOST '+ process.env.HOST); + if (validator.isIP(process.env.HOST)) { + log.trace(process.env.HOST + ' valid'); + host = process.env.HOST; + } else { + log.warn('process.env.HOST '+ process.env.HOST + ' invalid, use 0.0.0.0 instead'); + } } app.set('port', port); @@ -42,9 +55,9 @@ models.Versions.findOne({where:{type:1}}) }) .catch(function(e){ if (_.startsWith(e.message, 'ER_NO_SUCH_TABLE')) { - console.error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); + log.error(new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`)); } else { - console.error(e); + log.error(e); } process.exit(1); }); @@ -85,11 +98,11 @@ function onError(error) { // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': - console.error(bind + ' requires elevated privileges'); + log.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': - console.error(bind + ' is already in use'); + log.error(bind + ' is already in use'); process.exit(1); break; default: @@ -106,5 +119,5 @@ function onListening() { var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; - debug('Listening on ' + bind); + log.debug('Listening on ' + bind); } diff --git a/config/config.js b/config/config.js index 3029c7f2..29ebd866 100644 --- a/config/config.js +++ b/config/config.js @@ -98,5 +98,16 @@ config.development = { } } } + +config.development.log4js = { + appenders: [ + { type: 'console'} + ], + levels : { + "[all]": "ERROR", + "http" : "INFO" + } +} + config.production = Object.assign({}, config.development); module.exports = config; diff --git a/config/config.test.js b/config/config.test.js index 61b588eb..92025598 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -46,4 +46,13 @@ config.test = { } } } +config.test.log4js = { + appenders: [ + { type: 'console'} + ], + levels : { + "[all]": "ERROR", + "http" : "INFO" + } +} module.exports = config; diff --git a/config/config.testwin.js b/config/config.testwin.js index edd87fb1..07f344c3 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -47,4 +47,13 @@ config.test = { } } } +config.test.log4js = { + appenders: [ + { type: 'console'} + ], + levels : { + "[all]": "ERROR", + "http" : "INFO" + } +} module.exports = config; diff --git a/docs/process.yml b/docs/process.yml index 045427b5..b2251f36 100644 --- a/docs/process.yml +++ b/docs/process.yml @@ -1,6 +1,8 @@ apps: - script : /path/to/code-push-server/bin/www name : code-push-server + instances : "max" #开启实例数量,max为cpu核数 + exec_mode : "cluster" #集群模式,最大提升网站并发 watch : false env : NODE_ENV: production From b74b583213af31a7e937b7266b016ac27960c14c Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 14 Feb 2017 20:14:51 +0800 Subject: [PATCH 057/194] add log4js --- README.md | 24 +++++++++++++++++++++--- app.js | 4 ++-- bin/www | 4 ++-- core/config.js | 11 +++++++---- core/services/account-manager.js | 6 ++++++ core/services/deployments.js | 3 +++ core/services/package-manager.js | 12 +++++++++++- docs/process.json | 16 ++++++++++++++++ docs/process.yml => process.yml | 3 +-- routes/accessKeys.js | 7 ++++++- routes/apps.js | 7 ++++++- 11 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 docs/process.json rename docs/process.yml => process.yml (71%) diff --git a/README.md b/README.md index a1f9b7a8..ffb30051 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,24 @@ $ ./bin/db init --dbhost localhost --dbuser root --dbpassword #初始化mysql数 $ ./bin/www #启动服务 浏览器中打开 http://127.0.0.1:3000 ``` +## UPGRADE + +*from source code* + +```shell +$ cd /path/to/code-push-server +$ git pull --rebase origin master +$ ./bin/db upgrade --dbhost localhost --dbuser root --dbpassword #升级codepush数据库 +$ #restart code-push-server +``` + +*from npm package* + +```shell +$ code-push-server-db upgrade --dbhost localhost --dbuser root --dbpassword #升级codepush数据库 +$ #restart code-push-server +``` + ## CONFIG ```shell $ vim config/config.js @@ -219,9 +237,9 @@ use [pm2](http://pm2.keymetrics.io/) to manage process. $ npm install pm2 -g $ cp config/config.js /path/to/production/config.js $ vim /path/to/production/config.js #configure your env. -$ cp docs/process.yml /path/to/production/process.yml -$ vim /path/to/production/process.yml #configure your env. -$ pm2 start /path/to/production/process.yml +$ cp docs/process.json /path/to/production/process.json +$ vim /path/to/production/process.json #configure your env. +$ pm2 start /path/to/production/process.json ``` ## Use [CodePush Web](https://github.com/lisong/code-push-web) manage apps diff --git a/app.js b/app.js index 5318d01b..172965ab 100644 --- a/app.js +++ b/app.js @@ -17,7 +17,7 @@ var users = require('./routes/users'); var apps = require('./routes/apps'); var AppError = require('./core/app-error'); var log4js = require('log4js'); -var log = log4js.getLogger("app"); +var log = log4js.getLogger("cps:app"); var app = express(); app.use(helmet()); app.disable('x-powered-by'); @@ -25,7 +25,7 @@ app.disable('x-powered-by'); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); -app.use(log4js.connectLogger(log4js.getLogger("http"), {level: log4js.levels.INFO})); +app.use(log4js.connectLogger(log4js.getLogger("http"), {level: log4js.levels.INFO, nolog:'\\.gif|\\.jpg|\\.js|\\.css$' })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); diff --git a/bin/www b/bin/www index 6514e541..729e1936 100755 --- a/bin/www +++ b/bin/www @@ -4,16 +4,16 @@ * Module dependencies. */ -var app = require('../app'); var log4js = require('log4js'); var http = require('http'); var validator = require('validator') var _ = require('lodash') var config = require('../core/config'); - log4js.configure(_.get(config, 'log4js', {appenders: [{ type: 'console'}], levels : {"[all]": "ERROR", http: "ERROR"} })); var log = log4js.getLogger("startup") +var app = require('../app'); + /** * Get port from environment and store in Express. */ diff --git a/core/config.js b/core/config.js index ca9f46f5..a1057a98 100644 --- a/core/config.js +++ b/core/config.js @@ -2,10 +2,13 @@ var env = process.env.NODE_ENV || 'development'; var _ = require('lodash'); var path = require('path'); var config = {}; +var log4js = require('log4js'); +var log = log4js.getLogger("cps:config"); +var CONFIG_PATH = path.join(__dirname, '../config/config.js'); if (process.env.CONFIG_FILE) { - var CONFIG_PATH = path.join(__dirname, path.relative(__dirname, process.env.CONFIG_FILE)); - config = _.get(require(CONFIG_PATH), env); -} else { - config = _.get(require('../config/config.js'), env); + CONFIG_PATH = path.join(__dirname, path.relative(__dirname, process.env.CONFIG_FILE)); + log.info(`process.env.CONFIG_FILE value: ` +process.env.CONFIG_FILE) } +log.info(`use config file ${CONFIG_PATH}`) +config = _.get(require(CONFIG_PATH), env); module.exports = config; diff --git a/core/services/account-manager.js b/core/services/account-manager.js index 0a07f63a..dd4a06ef 100644 --- a/core/services/account-manager.js +++ b/core/services/account-manager.js @@ -9,6 +9,8 @@ var moment = require('moment'); var EmailManager = require('./email-manager'); var config = require('../config'); var AppError = require('../app-error'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:AccountManager"); var proto = module.exports = function (){ function AccountManager() { @@ -22,8 +24,10 @@ proto.collaboratorCan = function(uid, appName) { return this.getCollaborator(uid, appName) .then((data) => { if (!data) { + log.debug(`collaboratorCan App ${appName} not exists.`); throw new AppError.AppError(`App ${appName} not exists.`); } + log.debug('collaboratorCan yes'); return data; }); }; @@ -32,9 +36,11 @@ proto.ownerCan = function(uid, appName) { return this.getCollaborator(uid, appName) .then((data) => { if (!data) { + log.debug(`ownerCan App ${appName} not exists.`); throw new AppError.AppError(`App ${appName} not exists.`); } if (!_.eq(_.get(data,'roles'), 'Owner') ) { + log.debug(`ownerCan Permission Deny, You are not owner!`); throw new AppError.AppError("Permission Deny, You are not owner!"); } return data; diff --git a/core/services/deployments.js b/core/services/deployments.js index be2ae0bf..db30e8a7 100644 --- a/core/services/deployments.js +++ b/core/services/deployments.js @@ -7,6 +7,8 @@ var PackageManager = require('./package-manager'); var _ = require('lodash'); var moment = require('moment'); var AppError = require('../app-error'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:deployments"); var proto = module.exports = function (){ function Deployments() { @@ -84,6 +86,7 @@ proto.deleteDeloymentByName = function (deploymentName, appId) { }; proto.findDeloymentByName = function (deploymentName, appId) { + log.debug(`findDeloymentByName name:${deploymentName},appId: ${appId}`); return models.Deployments.findOne({ where: {name: deploymentName, appid: appId} }); diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 6bad795b..8f0fe47b 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -12,6 +12,8 @@ var common = require('../utils/common'); var os = require('os'); var path = require('path'); var AppError = require('../app-error'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:PackageManager"); var proto = module.exports = function (){ function PackageManager() { @@ -26,15 +28,21 @@ proto.getMetricsbyPackageId= function(packageId) { } proto.parseReqFile = function (req) { + log.debug('parseReqFile'); return new Promise((resolve, reject) => { var form = new formidable.IncomingForm(); form.parse(req, (err, fields, files) => { if (err) { + log.debug('parseReqFile:', err); reject(new AppError.AppError("upload error")); } else { - if (_.isEmpty(fields.packageInfo) || _.isEmpty(files.package)) { + log.debug('parseReqFile fields:', fields); + log.debug('parseReqFile file location:', _.get(files,'package.path')); + if (_.isEmpty(fields.packageInfo) || _.isEmpty(_.get(files,'package'))) { + log.debug('parseReqFile upload info lack'); reject(new AppError.AppError("upload info lack")); } else { + log.debug('parseReqFile is ok'); resolve({packageInfo:JSON.parse(fields.packageInfo), package: files.package}); } } @@ -280,11 +288,13 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, var self = this; var appVersion = packageInfo.appVersion; if (!/^([0-9.]+)$/.test(appVersion)) { + log.debug(`releasePackage targetBinaryVersion ${appVersion} not support.`); return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) } var description = packageInfo.description; var isMandatory = packageInfo.isMandatory; var directoryPath = path.join(os.tmpdir(), 'codepush_' + security.randToken(32)); + log.debug(`releasePackage generate an random dir path: ${directoryPath}`); return Promise.all([ security.qetag(filePath), common.createEmptyFolder(directoryPath) diff --git a/docs/process.json b/docs/process.json new file mode 100644 index 00000000..37c5a5a7 --- /dev/null +++ b/docs/process.json @@ -0,0 +1,16 @@ +{ + "apps" : [ + { + "name" : "code-push-server", + "max_memory_restart" : "300M", + "script" : "/path/to/code-push-server/bin/www", + "instances" : "max", //开启实例数量,max为cpu核数 + "exec_mode" : "cluster", //集群模式,最大提升网站并发 + "env" : { + "NODE_ENV" : "production", + "PORT" : 3001, + "CONFIG_FILE" : "/path/to/production/config.js" + } + } + ] +} \ No newline at end of file diff --git a/docs/process.yml b/process.yml similarity index 71% rename from docs/process.yml rename to process.yml index b2251f36..67e3f0ee 100644 --- a/docs/process.yml +++ b/process.yml @@ -1,5 +1,5 @@ apps: - - script : /path/to/code-push-server/bin/www + - script : /Users/tablee/workspaces/code-push-server/bin/www name : code-push-server instances : "max" #开启实例数量,max为cpu核数 exec_mode : "cluster" #集群模式,最大提升网站并发 @@ -7,4 +7,3 @@ apps: env : NODE_ENV: production PORT: 3001 - CONFIG_FILE: /path/to/production/config.js \ No newline at end of file diff --git a/routes/accessKeys.js b/routes/accessKeys.js index c9ef8937..835ac8ff 100644 --- a/routes/accessKeys.js +++ b/routes/accessKeys.js @@ -7,15 +7,20 @@ var models = require('../models'); var middleware = require('../core/middleware'); var accountManager = require('../core/services/account-manager')(); var AppError = require('../core/app-error') +var log4js = require('log4js'); +var log = log4js.getLogger("cps:accessKey"); router.get('/', middleware.checkToken, (req, res, next) => { + log.debug('request get acceesKeys') var uid = req.users.id; accountManager.getAllAccessKeyByUid(uid) .then((accessKeys) => { - res.send({accessKeys:accessKeys}); + log.debug('acceesKeys:', accessKeys) + res.send({accessKeys: accessKeys}); }) .catch((e) => { if (e instanceof AppError.AppError) { + log.debug('request get acceesKeys AppError', e) res.status(406).send(e.message); } else { next(e); diff --git a/routes/apps.js b/routes/apps.js index ba323243..1e8f81c1 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -17,6 +17,8 @@ const REGEX_ANDROID = /^(\w+)(-android)$/; const REGEX_IOS = /^(\w+)(-ios)$/; const OLD_REGEX_ANDROID = /^(android_)/; const OLD_REGEX_IOS = /^(ios_)/; +var log4js = require('log4js'); +var log = log4js.getLogger("cps:apps"); router.get('/', middleware.checkToken, (req, res, next) => { @@ -85,7 +87,6 @@ router.get('/:appName/deployments/:deploymentName/metrics', var deploymentName = _.trim(req.params.deploymentName); var deployments = new Deployments(); var packageManager = new PackageManager(); - accountManager.collaboratorCan(uid, appName) .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid) @@ -244,16 +245,20 @@ router.post('/:appName/deployments/:deploymentName/release', accountManager.collaboratorCan(uid, appName) .then((col) => { var pubType = ''; + log.debug(`check publish type`); if (REGEX_ANDROID.test(appName)) { pubType = 'android'; } else if (REGEX_IOS.test(appName)) { pubType = 'ios'; } else { + log.debug(`you have to rename app name, eg. Demo-android Demo-ios`); throw new AppError.AppError(`you have to rename app name, eg. Demo-android Demo-ios`); } + log.debug(`publish type is ${pubType}`); return deployments.findDeloymentByName(deploymentName, col.appid) .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { + log.debug(`does not find the deployment`); throw new AppError.AppError("does not find the deployment"); } return packageManager.parseReqFile(req) From 7f37a58edb770803ad1b1e0500c59a327c11bd56 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 14 Feb 2017 23:26:05 +0800 Subject: [PATCH 058/194] use extract-zip replase unzip-2 --- core/services/package-manager.js | 5 +-- core/utils/common.js | 56 +++++++++++++++++++------------- core/utils/security.js | 29 ++++++++++------- package.json | 2 +- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 8f0fe47b..a6943fad 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -43,7 +43,7 @@ proto.parseReqFile = function (req) { reject(new AppError.AppError("upload info lack")); } else { log.debug('parseReqFile is ok'); - resolve({packageInfo:JSON.parse(fields.packageInfo), package: files.package}); + resolve({packageInfo: JSON.parse(fields.packageInfo), package: files.package}); } } }); @@ -293,7 +293,8 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, } var description = packageInfo.description; var isMandatory = packageInfo.isMandatory; - var directoryPath = path.join(os.tmpdir(), 'codepush_' + security.randToken(32)); + var tmpDir = os.tmpdir(); + var directoryPath = path.join(tmpDir, 'codepush_' + security.randToken(32)); log.debug(`releasePackage generate an random dir path: ${directoryPath}`); return Promise.all([ security.qetag(filePath), diff --git a/core/utils/common.js b/core/utils/common.js index 6d5c29dc..4429e68b 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -2,12 +2,14 @@ var Promise = require('bluebird'); var fs = require("fs"); var fsextra = require("fs-extra"); -var unzip = require('node-unzip-2'); +var extract = require('extract-zip') var config = require('../config'); var _ = require('lodash'); var qiniu = require("qiniu"); var common = {}; var AppError = require('../app-error'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:utils:common"); module.exports = common; common.createFileFromRequest = function (url, filePath) { @@ -43,9 +45,10 @@ common.move = function (sourceDst, targertDst) { return new Promise((resolve, reject) => { fsextra.move(sourceDst, targertDst, {clobber: true, limit: 16}, function (err) { if (err) { - return reject(err); + reject(err); + } else { + resolve(); } - resolve(); }); }); }; @@ -67,13 +70,18 @@ common.deleteFolderSync = function (folderPath) { }; common.createEmptyFolder = function (folderPath) { - return common.deleteFolder(folderPath) - .then((data) => { - fsextra.mkdirs(folderPath, (err) => { - if (err) { - throw err; - } - return folderPath; + return new Promise((resolve, reject) => { + log.debug(`createEmptyFolder Create dir ${folderPath}`); + return common.deleteFolder(folderPath) + .then((data) => { + fsextra.mkdirs(folderPath, (err) => { + if (err) { + log.error(err); + reject(new AppError.AppError(err.message)); + } else { + resolve(folderPath); + } + }); }); }); }; @@ -86,20 +94,22 @@ common.createEmptyFolderSync = function (folderPath) { common.unzipFile = function (zipFile, outputPath) { return new Promise((resolve, reject) => { try { - fs.exists(zipFile, (exists) => { - if (!exists) { - reject(new AppError.AppError("zipfile not found!")) - } - var readStream = fs.createReadStream(zipFile); - var extract = unzip.Extract({ path: outputPath }); - readStream.pipe(extract); - extract.on("close", function () { - resolve(outputPath); - }); - }) + log.debug(`unzipFile check zipFile ${zipFile} fs.R_OK`); + fs.accessSync(zipFile, fs.R_OK); + log.debug(`Pass unzipFile file ${zipFile}`); } catch (e) { - reject(e) + log.error(e); + return reject(new AppError.AppError(e.message)) } + extract(zipFile, {dir: outputPath}, function(err){ + if (err) { + log.error(err); + reject(new AppError.AppError(`it's not a zipFile`)) + } else { + log.debug(`unzipFile success`); + resolve(outputPath); + } + }); }); }; @@ -175,7 +185,7 @@ common.uploadFileToQiniu = function (key, filePath) { try { var uptoken = common.uptoken(bucket, key); } catch (e) { - reject(e); + return reject(e); } var extra = new qiniu.io.PutExtra(); qiniu.io.putFile(uptoken, key, filePath, extra, (err, ret) => { diff --git a/core/utils/security.js b/core/utils/security.js index f8604809..b06f4040 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -5,6 +5,9 @@ var fs = require('fs'); var Promise = require('bluebird'); var qetag = require('../utils/qetag'); var _ = require('lodash'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:utils:security"); +var AppError = require('../app-error'); var randToken = require('rand-token').generator({ chars: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', @@ -68,18 +71,22 @@ security.packageHashSync = function (jsonData) { //参数为buffer或者readableStream或者文件路径 security.qetag = function (buffer) { + if (typeof buffer === 'string') { + try { + log.debug(`Check upload file ${buffer} fs.R_OK`); + fs.accessSync(buffer, fs.R_OK); + log.debug(`Pass upload file ${buffer}`); + } catch (e) { + log.error(e); + return Promise.reject(new AppError.AppError(e.message)) + } + } + log.debug(`generate file identical`) return new Promise((resolve, reject) => { - qetag(buffer, resolve); - }); -} - -security.qetagString = function (contents) { - return new Promise((resolve, reject) => { - var Readable = require('stream').Readable - var buffer = new Readable - buffer.push(contents) - buffer.push(null) - qetag(buffer, resolve); + qetag(buffer, (data)=>{ + log.debug('identical:', data); + resolve(data) + }); }); } diff --git a/package.json b/package.json index 6d7d20d5..e1f0a770 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "cookie-parser": "^1.4.3", "debug": "^2.3.3", "express": "^4.14.0", + "extract-zip": "^1.6.0", "formidable": "^1.0.17", "fs-extra": "^1.0.0", "helmet": "^3.1.0", @@ -55,7 +56,6 @@ "moment": "^2.14.1", "morgan": "^1.7.0", "mysql": "^2.10.2", - "node-unzip-2": "^0.2.1", "nodemailer": "^2.5.0", "pug": "^2.0.0-beta6", "qiniu": "^6.1.10", From 1e38ffcd09c7bab943c7e0aaa35b1e952b1ea0e5 Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 14 Feb 2017 17:21:35 -0600 Subject: [PATCH 059/194] delete process yml --- process.yml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 process.yml diff --git a/process.yml b/process.yml deleted file mode 100644 index 67e3f0ee..00000000 --- a/process.yml +++ /dev/null @@ -1,9 +0,0 @@ -apps: - - script : /Users/tablee/workspaces/code-push-server/bin/www - name : code-push-server - instances : "max" #开启实例数量,max为cpu核数 - exec_mode : "cluster" #集群模式,最大提升网站并发 - watch : false - env : - NODE_ENV: production - PORT: 3001 From 21d4e7207a8271f2a33e1b855c4c40866d9c9b4e Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 14 Feb 2017 23:37:27 +0800 Subject: [PATCH 060/194] 0.2.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1f0a770..1b028d72 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.15", + "version": "0.2.16", "license": "MIT", "repository": { "type": "git", From 531ae96478b6f3a046b88434c23304d14d8b41d3 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 18 Feb 2017 15:12:12 +0800 Subject: [PATCH 061/194] add debug log --- bin/www | 2 +- config/config.js | 1 + config/config.test.js | 1 + config/config.testwin.js | 1 + core/services/datacenter-manager.js | 36 +++++++---- core/services/package-manager.js | 96 +++++++++++++++-------------- core/utils/common.js | 38 +++++++++--- core/utils/security.js | 24 +++++--- 8 files changed, 126 insertions(+), 73 deletions(-) diff --git a/bin/www b/bin/www index 729e1936..a34f74be 100755 --- a/bin/www +++ b/bin/www @@ -119,5 +119,5 @@ function onListening() { var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; - log.debug('Listening on ' + bind); + log.info('Listening on ' + bind); } diff --git a/config/config.js b/config/config.js index 29ebd866..1444def6 100644 --- a/config/config.js +++ b/config/config.js @@ -105,6 +105,7 @@ config.development.log4js = { ], levels : { "[all]": "ERROR", + "startup": "INFO", "http" : "INFO" } } diff --git a/config/config.test.js b/config/config.test.js index 92025598..fbfd4cd5 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -52,6 +52,7 @@ config.test.log4js = { ], levels : { "[all]": "ERROR", + "startup": "INFO", "http" : "INFO" } } diff --git a/config/config.testwin.js b/config/config.testwin.js index 07f344c3..2f6b1f82 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -53,6 +53,7 @@ config.test.log4js = { ], levels : { "[all]": "ERROR", + "startup": "INFO", "http" : "INFO" } } diff --git a/core/services/datacenter-manager.js b/core/services/datacenter-manager.js index 6633acfe..1193d2ea 100644 --- a/core/services/datacenter-manager.js +++ b/core/services/datacenter-manager.js @@ -9,6 +9,8 @@ var common = require('../utils/common'); const MANIFEST_FILE_NAME = 'manifest.json'; const CONTENTS_NAME = 'contents'; var AppError = require('../app-error'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:DataCenterManager"); var proto = module.exports = function (){ function DataCenterManager() { @@ -61,25 +63,32 @@ proto.validateStore = function (providePackageHash) { var manifestFile = `${packageHashPath}/${MANIFEST_FILE_NAME}`; var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; if (!this.hasPackageStoreSync(providePackageHash)) { + log.debug(`validateStore providePackageHash not exist`); return Promise.resolve(false); } return security.calcAllFileSha256(contentPath) .then((manifestJson) => { var packageHash = security.packageHashSync(manifestJson); + log.debug(`validateStore packageHash:`, packageHash); try { var manifestJsonLocal = JSON.parse(fs.readFileSync(manifestFile)); }catch(e) { + log.debug(`validateStore manifestFile contents invilad`); return false; } var packageHashLocal = security.packageHashSync(manifestJsonLocal); + log.debug(`validateStore packageHashLocal:`, packageHashLocal); if (_.eq(providePackageHash, packageHash) && _.eq(providePackageHash, packageHashLocal)) { + log.debug(`validateStore store files is ok`); return true; } + log.debug(`validateStore store files broken`); return false; }); } proto.storePackage = function (sourceDst, force) { + log.debug(`storePackage sourceDst:`, sourceDst); if (_.isEmpty(force)){ force = false; } @@ -87,22 +96,27 @@ proto.storePackage = function (sourceDst, force) { return security.calcAllFileSha256(sourceDst) .then((manifestJson) => { var packageHash = security.packageHashSync(manifestJson); + log.debug('storePackage manifestJson packageHash:', packageHash); var dataDir = self.getDataDir(); var packageHashPath = `${dataDir}/${packageHash}`; var manifestFile = `${packageHashPath}/${MANIFEST_FILE_NAME}`; var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; - if (!force && self.hasPackageStoreSync(packageHash)) { - return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); - } else { - return common.createEmptyFolder(packageHashPath) - .then(() => { - return common.move(sourceDst, contentPath) + return self.validateStore(packageHash) + .then((isValidate) => { + if (!force && isValidate) { + return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); + } else { + log.debug(`storePackage cover from sourceDst:`, sourceDst); + return common.createEmptyFolder(packageHashPath) .then(() => { - var manifestString = JSON.stringify(manifestJson); - fs.writeFileSync(manifestFile, manifestString); - return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); + return common.move(sourceDst, contentPath) + .then(() => { + var manifestString = JSON.stringify(manifestJson); + fs.writeFileSync(manifestFile, manifestString); + return self.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); + }); }); - }); - } + } + }); }); } diff --git a/core/services/package-manager.js b/core/services/package-manager.js index a6943fad..6d68cda7 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -50,35 +50,35 @@ proto.parseReqFile = function (req) { }); }; -proto.getDeploymentsVersions = function (deploymentId, appVersion) { - return models.DeploymentsVersions.findOne({ - where: {deployment_id: deploymentId, app_version: appVersion} +proto.createDeploymentsVersionIfNotExist = function (deploymentId, appVersion, t) { + return models.DeploymentsVersions.findOrCreate({ + where: {deployment_id: deploymentId, app_version: appVersion}, + defaults: {current_package_id: 0}, + transaction: t + }) + .spread((data, created)=>{ + if (created) { + log.debug(`createDeploymentsVersionIfNotExist findOrCreate version ${appVersion}`); + } + log.debug(`createDeploymentsVersionIfNotExist version data:`, data.get()); + return data; }); }; -proto.existPackageHashAndCreateVersions = function (deploymentId, appVersion, packageHash) { - return this.getDeploymentsVersions(deploymentId, appVersion) +proto.isMatchPackageHash = function (packageId, packageHash) { + if (_.lt(packageId, 0)) { + log.debug(`isMatchPackageHash packageId is 0`); + return Promise.resolve(false); + } + return models.Packages.findById(packageId) .then((data) => { - if (_.isEmpty(data)){ - return models.DeploymentsVersions.create({ - deployment_id: deploymentId, - app_version: appVersion, - }) - .then(() => false); - } else { - var packageId = data.current_package_id; - if (_.gt(packageId, 0)) { - return models.Packages.findById(packageId) - .then((data) => { - if (_.eq(_.get(data,"package_hash"), packageHash)){ - return true; - }else { - return false; - } - }); - } else { - return false - } + if (data && _.eq(data.get('package_hash'), packageHash)){ + log.debug(`isMatchPackageHash data:`, data.get()); + log.debug(`isMatchPackageHash packageHash exist`); + return true; + }else { + log.debug(`isMatchPackageHash package is null`); + return false; } }); }; @@ -91,20 +91,11 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH var description = params.description || ""; var originalLabel = params.originalLabel || ""; var originalDeployment = params.originalDeployment || ""; + var self = this; return models.Deployments.generateLabelId(deploymentId) .then((labelId) => { return models.sequelize.transaction((t) => { - return models.DeploymentsVersions.findOne({where: {deployment_id: deploymentId, app_version: appVersion}}) - .then((deploymentsVersions) => { - if (!deploymentsVersions) { - return models.DeploymentsVersions.create({ - current_package_id: 0, - deployment_id: deploymentId, - app_version: appVersion - },{transaction: t}); - } - return deploymentsVersions; - }) + return self.createDeploymentsVersionIfNotExist(deploymentId, appVersion, t) .then((deploymentsVersions) => { return models.Packages.create({ deployment_version_id: deploymentsVersions.id, @@ -216,6 +207,7 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente .then((data) => { return security.qetag(data.path) .then((diffHash) => { + log.debug('diff'); return common.uploadFileToStorage(diffHash, fileName) .then(() => { var stats = fs.statSync(fileName); @@ -303,28 +295,34 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, if (fileType == "application/zip") { return common.unzipFile(filePath, directoryPath) } else { + log.debug(`上传的文件格式不对`); throw new AppError.AppError("上传的文件格式不对"); } }) ]) .spread((blobHash) => { - return security.isAndroidPackage(directoryPath) + return security.uploadPackageType(directoryPath) .then((type) => { if (type === 1) { //android if (pubType == 'ios' ) { - throw new AppError.AppError("it must be publish it by ios type"); + var e = new AppError.AppError("it must be publish it by ios type"); + log.debug(e); + throw e; } } else if (type === 2) { //ios if (pubType == 'android'){ - throw new AppError.AppError("it must be publish it by android type"); + var e = new AppError.AppError("it must be publish it by android type"); + log.debug(e); + throw e; } } else { //不验证 + log.debug(`Unknown package type`); } - }) - .then(() => blobHash) + return blobHash; + }); }) .then((blobHash) => { var dataCenterManager = require('./datacenter-manager')(); @@ -332,10 +330,15 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, .then((dataCenter) => { var packageHash = dataCenter.packageHash; var manifestFile = dataCenter.manifestFilePath; - return self.existPackageHashAndCreateVersions(deploymentId, appVersion, packageHash) + return self.createDeploymentsVersionIfNotExist(deploymentId, appVersion) + .then((deploymentsVersions) => { + return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packageHash); + }) .then((isExist) => { if (isExist){ - throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); + var e = new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); + log.debug(e.message); + throw e; } return security.qetag(manifestFile); }) @@ -345,7 +348,7 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, common.uploadFileToStorage(blobHash, filePath) ]) .then(() => [packageHash, manifestHash, blobHash]); - }); + }) }); }) .spread((packageHash, manifestHash, blobHash) => { @@ -411,7 +414,10 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUi if (!packages) { throw new AppError.AppError('does not exist packages.'); } - return self.existPackageHashAndCreateVersions(destDeploymentId, deploymentsVersions.app_version, packages.package_hash) + return self.createDeploymentsVersionIfNotExist(destDeploymentId, deploymentsVersions.app_version) + .then((deploymentsVersions) => { + return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packages.package_hash); + }) .then((isExist) => { if (isExist){ throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); diff --git a/core/utils/common.js b/core/utils/common.js index 4429e68b..4c268ff8 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -45,8 +45,10 @@ common.move = function (sourceDst, targertDst) { return new Promise((resolve, reject) => { fsextra.move(sourceDst, targertDst, {clobber: true, limit: 16}, function (err) { if (err) { + log.error(err); reject(err); } else { + log.debug(`move success sourceDst:${sourceDst} targertDst:${targertDst}`); resolve(); } }); @@ -57,8 +59,10 @@ common.deleteFolder = function (folderPath) { return new Promise((resolve, reject) => { fsextra.remove(folderPath, function (err) { if (err) { + log.error(err); reject(err); }else { + log.debug(`deleteFolder delete ${folderPath} success.`); resolve(null); } }); @@ -135,23 +139,41 @@ common.uploadFileToLocal = function (key, filePath) { if (!storageDir) { throw new AppError.AppError('please set config local storageDir'); } - if (!fs.existsSync(storageDir)) { - throw new AppError.AppError(`please create dir ${storageDir}`); + try { + log.debug(`uploadFileToLocal check directory ${storageDir} fs.R_OK`); + fs.accessSync(storageDir, fs.W_OK); + log.debug(`uploadFileToLocal directory ${storageDir} fs.R_OK is ok`); + } catch (e) { + log.error(e); + throw new AppError.AppError(e.message); + } + if (fs.existsSync(`${storageDir}/${key}`)) { + return resolve(key); } - fs.accessSync(storageDir, fs.W_OK); var stats = fs.statSync(storageDir); if (!stats.isDirectory()) { - throw new AppError.AppError(`${storageDir} must be directory`); + var e = new AppError.AppError(`${storageDir} must be directory`); + log.error(e); + throw e; + } + try { + fs.accessSync(filePath, fs.R_OK); + } catch (e) { + log.error(e); + throw new AppError.AppError(e.message); } - fs.accessSync(filePath, fs.R_OK); stats = fs.statSync(filePath); if (!stats.isFile()) { - throw new AppError.AppError(`${filePath} must be file`); + var e = new AppError.AppError(`${filePath} must be file`); + log.debug(e); + throw e; } - fsextra.copy(filePath, `${storageDir}/${key}`, {clobber: true, limit: 16}, (err) => { + fsextra.copy(filePath, `${storageDir}/${key}`,(err) => { if (err) { - return reject(err); + log.error(new AppError.AppError(err.message)); + return reject(new AppError.AppError(err.message)); } + log.debug(`uploadFileToLocal copy file ${key} success.`); resolve(key); }); }); diff --git a/core/utils/security.js b/core/utils/security.js index b06f4040..401fd040 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -64,8 +64,10 @@ security.packageHashSync = function (jsonData) { var manifestData = _.map(sortedArr, (v) => { return v.path + ':' + v.hash; }); + log.debug('packageHashSync manifestData:', manifestData); var manifestString = JSON.stringify(manifestData.sort()); manifestString = _.replace(manifestString, /\\\//g, '/'); + log.debug('packageHashSync manifestString:', manifestData); return security.stringSha256Sync(manifestString); } @@ -108,32 +110,35 @@ security.sha256AllFiles = function (files) { }); } -security.isAndroidPackage = function (directoryPath) { +security.uploadPackageType = function (directoryPath) { return new Promise((resolve, reject) => { var recursiveFs = require("recursive-fs"); var path = require('path'); var slash = require("slash"); - recursiveFs.readdirr(directoryPath, (error, directories, files) => { - if (error) { - reject(error); + recursiveFs.readdirr(directoryPath, (err, directories, files) => { + if (err) { + log.error(new AppError.AppError(err.message)); + reject(err); } else { if (files.length == 0) { + log.debug(`uploadPackageType empty files`); reject(new AppError.AppError("empty files")); } else { const AREGEX=/android\.bundle/ const AREGEX_IOS=/main\.jsbundle/ - var isAndroid = 0; + var packageType = 0; _.forIn(files, function (value) { if (AREGEX.test(value)) { - isAndroid = 1; + packageType = 1; return false; } if (AREGEX_IOS.test(value)) { - isAndroid = 2; + packageType = 2; return false; } }); - resolve(isAndroid); + log.debug(`uploadPackageType packageType: ${packageType}`); + resolve(packageType); } } }); @@ -147,9 +152,11 @@ security.calcAllFileSha256 = function (directoryPath) { var slash = require("slash"); recursiveFs.readdirr(directoryPath, (error, directories, files) => { if (error) { + log.error(error); reject(error); } else { if (files.length == 0) { + log.debug(`calcAllFileSha256 empty files in directoryPath:`, directoryPath); reject(new AppError.AppError("empty files")); }else { security.sha256AllFiles(files) @@ -160,6 +167,7 @@ security.calcAllFileSha256 = function (directoryPath) { relativePath = slash(relativePath); data[relativePath] = value; }); + log.debug(`calcAllFileSha256 files:`, data); resolve(data); }); } From 4a4030945e6bb1cfe38cfff4b69741f8ce8021e3 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 18 Feb 2017 16:49:46 +0800 Subject: [PATCH 062/194] update dep --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 1b028d72..e7e5ded2 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "express": "^4.14.0", "extract-zip": "^1.6.0", "formidable": "^1.0.17", - "fs-extra": "^1.0.0", + "fs-extra": "^2.0.0", "helmet": "^3.1.0", "i18n": "^0.8.3", "jsonwebtoken": "^7.1.7", @@ -56,10 +56,10 @@ "moment": "^2.14.1", "morgan": "^1.7.0", "mysql": "^2.10.2", - "nodemailer": "^2.5.0", + "nodemailer": "^3.1.3", "pug": "^2.0.0-beta6", "qiniu": "^6.1.10", - "rand-token": "^0.2.1", + "rand-token": "^0.3.0", "recursive-fs": "^1.0.0", "redis": "^2.6.2", "request": "^2.72.0", @@ -72,9 +72,9 @@ }, "devDependencies": { "istanbul": "^0.4.5", - "mocha": "^3.0.2", - "should": "^11.1.0", - "supertest": "^2.0.0" + "mocha": "^3.2.0", + "should": "^11.2.0", + "supertest": "^3.0.0" }, "files": [ "bin", From ced0c490c0d984d76f28f521517174f5b2fb62cd Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 18 Feb 2017 18:23:31 +0800 Subject: [PATCH 063/194] node >= 6.0 --- .travis.yml | 18 +++++------------- appveyor.yml | 6 ++++-- package.json | 2 +- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 79a4ea4f..0d59c5dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,20 +13,12 @@ services: - mysql node_js: - - "6" + - "7.5" + - "7" + - "6.9.5" - "6.1" - - "5" - - "5.11" - - "5.10" - - "5.9" - - "5.8" - - "5.7" - - "5.6" - - "5.5" - - "5.4" - - "5.3" - - "5.2" - - "5.1" + - "6" + cache: directories: - node_modules diff --git a/appveyor.yml b/appveyor.yml index 8f45ad6b..3fca1216 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,9 +3,11 @@ init: environment: matrix: - - nodejs_version: "6" + - nodejs_version: "7.5" + - nodejs_version: "7" + - nodejs_version: "6.9.5" - nodejs_version: "6.1" - - nodejs_version: "5" + - nodejs_version: "6" services: - mysql diff --git a/package.json b/package.json index e7e5ded2..28a1ca04 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "code-push-server-db": "./bin/db" }, "engines": { - "node": ">= 5.0", + "node": ">= 6.0", "npm": ">= 3.10.8" }, "scripts": { From d62b786f79c4e6afbb4cbd78e9a5ad3361efd383 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 18 Feb 2017 19:07:18 +0800 Subject: [PATCH 064/194] dev bin --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 28a1ca04..d051c29c 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ }, "scripts": { "start": "node ./bin/www", + "dev": "supervisor ./bin/www", "test": "make test", "test-win": "mocha test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000", "coverage": "make coverage" @@ -74,7 +75,8 @@ "istanbul": "^0.4.5", "mocha": "^3.2.0", "should": "^11.2.0", - "supertest": "^3.0.0" + "supertest": "^3.0.0", + "supervisor": "^0.12.0" }, "files": [ "bin", From ba6e919e163107b9d188d4baf9d512984f670613 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 18 Feb 2017 19:14:12 +0800 Subject: [PATCH 065/194] add init/upgrade to package.json --- bin/db | 2 +- package.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/db b/bin/db index 3e916651..53411b18 100755 --- a/bin/db +++ b/bin/db @@ -88,7 +88,7 @@ if (command === 'init') { } if (version_no == '0.2.15') { console.log('Everything up-to-date.'); - process.exit(1); + process.exit(0); } var allSqlFile = [ {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14.sql')}, diff --git a/package.json b/package.json index d051c29c..76e5f908 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,10 @@ "npm": ">= 3.10.8" }, "scripts": { - "start": "node ./bin/www", "dev": "supervisor ./bin/www", + "start": "node ./bin/www", + "init": "node ./bin/db init", + "upgrade": "node ./bin/db upgrade", "test": "make test", "test-win": "mocha test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000", "coverage": "make coverage" From c1a35f1692287412a66b023db8850baf43e6bb3d Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 21 Feb 2017 16:36:42 +0800 Subject: [PATCH 066/194] fixport --- docs/process.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/process.json b/docs/process.json index 37c5a5a7..de88022b 100644 --- a/docs/process.json +++ b/docs/process.json @@ -8,7 +8,7 @@ "exec_mode" : "cluster", //集群模式,最大提升网站并发 "env" : { "NODE_ENV" : "production", - "PORT" : 3001, + "PORT" : 3000, "CONFIG_FILE" : "/path/to/production/config.js" } } From 61d4c7aa7e127450be281f190ce357d0c4c50497 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 21 Feb 2017 16:39:23 +0800 Subject: [PATCH 067/194] 0.2.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76e5f908..f636dba4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.16", + "version": "0.2.17", "license": "MIT", "repository": { "type": "git", From cd944354e90c44bf23b715fc5fd348c4050a4b58 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 22 Feb 2017 12:08:12 +0800 Subject: [PATCH 068/194] fix oss prefix --- core/utils/common.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/utils/common.js b/core/utils/common.js index 4c268ff8..a144a250 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -259,9 +259,12 @@ common.uploadFileToOSS = function (key, filePath) { endpoint: _.get(config, 'oss.endpoint'), apiVersion: '2013-10-15', })); + if (!_.isEmpty(_.get(config, 'oss.prefix', ""))) { + key = `${_.get(config, 'oss.prefix')}/${key}`; + } var upload = ossStream.upload({ Bucket: _.get(config, 'oss.bucketName'), - Key: `${_.get(config, 'oss.prefix')}/${key}`, + Key: key, }); return new Promise((resolve, reject) => { From 72243e63cc75546c123c5d608a702646f399ae72 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 22 Feb 2017 13:39:33 +0800 Subject: [PATCH 069/194] update s3 --- config/config.js | 2 ++ core/utils/common.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/config/config.js b/config/config.js index 1444def6..80bfbed9 100644 --- a/config/config.js +++ b/config/config.js @@ -19,6 +19,8 @@ config.development = { }, // Config for Amazon s3 (https://aws.amazon.com/cn/s3/) storage when storageType value is "s3". s3: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, bucketName: process.env.BUCKET_NAME, region: process.env.REGION, downloadUrl: process.env.DOWNLOAD_URL, // binary files download host address. diff --git a/core/utils/common.js b/core/utils/common.js index a144a250..06225f27 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -229,6 +229,8 @@ common.uploadFileToS3 = function (key, filePath) { return ( new Promise((resolve, reject) => { AWS.config.update({ + accessKeyId: _.get(config, 's3.accessKeyId'), + secretAccessKey: _.get(config, 's3.secretAccessKey'), region: _.get(config, 's3.region') }); var s3 = new AWS.S3({ From 3c069edfb14d6a938bbdbb2ef0a6516dcf00ec9a Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 22 Feb 2017 13:44:46 +0800 Subject: [PATCH 070/194] update s3 token (optional) --- config/config.js | 1 + core/utils/common.js | 1 + 2 files changed, 2 insertions(+) diff --git a/config/config.js b/config/config.js index 80bfbed9..79c4638b 100644 --- a/config/config.js +++ b/config/config.js @@ -21,6 +21,7 @@ config.development = { s3: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + sessionToken: process.env.AWS_SESSION_TOKEN, //(optional) bucketName: process.env.BUCKET_NAME, region: process.env.REGION, downloadUrl: process.env.DOWNLOAD_URL, // binary files download host address. diff --git a/core/utils/common.js b/core/utils/common.js index 06225f27..ca328c18 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -231,6 +231,7 @@ common.uploadFileToS3 = function (key, filePath) { AWS.config.update({ accessKeyId: _.get(config, 's3.accessKeyId'), secretAccessKey: _.get(config, 's3.secretAccessKey'), + sessionToken: _.get(config, 's3.sessionToken'), region: _.get(config, 's3.region') }); var s3 = new AWS.S3({ From 6175ee796e4541faadb838549802c809b925fa7a Mon Sep 17 00:00:00 2001 From: kimown Date: Thu, 23 Feb 2017 17:32:18 +0800 Subject: [PATCH 071/194] mysql db init check dbpassword (#55) * Update db fix: https://github.com/lisong/code-push-server/issues/54 * Update db fix: not use default password * Update db fix: same as upgrade command --- bin/db | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/bin/db b/bin/db index 53411b18..1f54b864 100755 --- a/bin/db +++ b/bin/db @@ -10,8 +10,18 @@ var mysql = require('mysql'); var Promise = require("bluebird"); var yargs = require('yargs') .usage('Usage: $0 [options]') - .command('init', '初始化数据库') - .command('upgrade', '升级数据库') + .command('init', '初始化数据库', { + dbpassword: { + alias: 'dbpassword', + type: 'string' + } + }) + .command('upgrade', '升级数据库', { + dbpassword: { + alias: 'dbpassword', + type: 'string' + } + }) .example('$0 init --dbname codepush --dbhost localhost --dbuser root --dbpassword 123456 --dbport 3306 --force', '初始化code-push-server数据库') .example('$0 upgrade --dbname codepush --dbhost localhost --dbuser root --dbpassword 123456 --dbport 3306', '升级code-push-server数据库') .default({dbname: 'codepush', dbhost: 'localhost', dbuser: 'root', dbpassword: null}) @@ -24,9 +34,6 @@ var dbhost = argv.dbhost ? argv.dbhost : 'localhost'; var dbuser = argv.dbuser ? argv.dbuser : 'root'; var dbport = argv.dbport ? argv.dbport : 3306; var dbpassword = null; -if (_.isString(argv.dbpassword) || _.isNumber(argv.dbpassword)) { - dbpassword = argv.dbpassword; -} if (command === 'init') { var connection2; From 49837030515dc29b6b8adc433b950bd95ab108a0 Mon Sep 17 00:00:00 2001 From: kimown Date: Sun, 26 Feb 2017 13:17:02 +0800 Subject: [PATCH 072/194] fix: dbpassword shouldn't null (#57) --- bin/db | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/db b/bin/db index 1f54b864..a856921f 100755 --- a/bin/db +++ b/bin/db @@ -33,7 +33,7 @@ var dbname = argv.dbname ? argv.dbname : 'codepush'; var dbhost = argv.dbhost ? argv.dbhost : 'localhost'; var dbuser = argv.dbuser ? argv.dbuser : 'root'; var dbport = argv.dbport ? argv.dbport : 3306; -var dbpassword = null; +var dbpassword = argv.dbpassword; if (command === 'init') { var connection2; From d7ca87382f4a0c8b3cc6b0ab2abdb384eb2ee222 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Feb 2017 21:06:39 +0800 Subject: [PATCH 073/194] 0.2.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f636dba4..87819f35 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.17", + "version": "0.2.18", "license": "MIT", "repository": { "type": "git", From 95839aad4652e3286ecefd44ccf2da2da9998247 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Feb 2017 21:53:50 +0800 Subject: [PATCH 074/194] update dependencies --- core/config.js | 1 + package.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/config.js b/core/config.js index a1057a98..6c8f71a7 100644 --- a/core/config.js +++ b/core/config.js @@ -10,5 +10,6 @@ if (process.env.CONFIG_FILE) { log.info(`process.env.CONFIG_FILE value: ` +process.env.CONFIG_FILE) } log.info(`use config file ${CONFIG_PATH}`) +log.info(`use env ${env}`) config = _.get(require(CONFIG_PATH), env); module.exports = config; diff --git a/package.json b/package.json index 87819f35..8603dbeb 100644 --- a/package.json +++ b/package.json @@ -67,9 +67,9 @@ "redis": "^2.6.2", "request": "^2.72.0", "sequelize": "^3.24.5", - "serve-favicon": "~2.3.0", + "serve-favicon": "^2.4.0", "slash": "^1.0.0", - "validator": "^6.1.0", + "validator": "^7.0.0", "yargs": "^6.2.0", "yazl": "^2.3.0" }, From ecd514005bfd3a0738c5194ebe8449bbc1626888 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 4 Mar 2017 21:19:15 +0800 Subject: [PATCH 075/194] fix jwt --- core/middleware.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/middleware.js b/core/middleware.js index 01a26d8b..da4676a2 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -39,7 +39,11 @@ var checkAccessToken = function (accessToken) { var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); var jwt = require('jsonwebtoken'); - var authData = jwt.verify(accessToken, tokenSecret); + try { + var authData = jwt.verify(accessToken, tokenSecret); + } catch (e) { + reject(new AppError.Unauthorized()); + } var uid = _.get(authData, 'uid', null); var hash = _.get(authData, 'hash', null); if (parseInt(uid) > 0) { From ad703f83cec92fbcf7dcfc019f5d4156d6be833f Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 4 Mar 2017 23:00:06 +0800 Subject: [PATCH 076/194] add deployinfo adaptor code-push-cli@1.12.8-beta --- core/app-error.js | 2 +- core/services/deployments.js | 19 ++++++++++++------- routes/apps.js | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/core/app-error.js b/core/app-error.js index acdb3b82..178a573b 100644 --- a/core/app-error.js +++ b/core/app-error.js @@ -20,7 +20,7 @@ var NotFoundError = function(msg) { util.inherits(NotFoundError, AppError) var UnauthorizedError = function(msg) { - NotFoundError.super_.call(this, msg, this.constructor) + UnauthorizedError.super_.call(this, msg, this.constructor) this.message = msg || `401 Unauthorized`; this.name = 'UnauthorizedError' this.status = 401 diff --git a/core/services/deployments.js b/core/services/deployments.js index db30e8a7..6e0b19ea 100644 --- a/core/services/deployments.js +++ b/core/services/deployments.js @@ -164,17 +164,22 @@ proto.listDeloyments = function (appId) { return []; } return Promise.map(deploymentsInfos, (v) => { - return Promise.props({ - createdTime: parseInt(moment(v.created_at).format('x')), - id: `${v.id}`, - key: v.deployment_key, - name: v.name, - package: self.findDeloymentsPackages([v.last_deployment_version_id]).then(self.formatPackage) - }); + return self.listDeloyment(v); }) }); }; +proto.listDeloyment = function (deploymentInfo) { + const self = this; + return Promise.props({ + createdTime: parseInt(moment(deploymentInfo.created_at).format('x')), + id: `${deploymentInfo.id}`, + key: deploymentInfo.deployment_key, + name: deploymentInfo.name, + package: self.findDeloymentsPackages([deploymentInfo.last_deployment_version_id]).then(self.formatPackage) + }); +} + proto.getDeploymentHistory = function (deploymentId) { var self = this; return models.DeploymentsHistory.findAll({where: {deployment_id: deploymentId}, order: [['id','desc']], limit: 15}) diff --git a/routes/apps.js b/routes/apps.js index 1e8f81c1..8f634bec 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -58,6 +58,31 @@ router.get('/:appName/deployments', }); }); +router.get('/:appName/deployments/:deploymentName', + middleware.checkToken, (req, res, next) => { + var uid = req.users.id; + var appName = _.trim(req.params.appName); + var deploymentName = _.trim(req.params.deploymentName); + var deployments = new Deployments(); + accountManager.collaboratorCan(uid, appName) + .then((col) => { + return deployments.findDeloymentByName(deploymentName, col.appid) + }) + .then((deploymentInfo) => { + if (_.isEmpty(deploymentInfo)) { + throw new AppError.AppError("does not find the deployment"); + } + res.send({deployment: deployments.listDeloyment(deploymentInfo)}); + }) + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(406).send(e.message); + } else { + next(e); + } + }); +}); + router.post('/:appName/deployments', middleware.checkToken, (req, res, next) => { var uid = req.users.id; From bfd3de72f0f332915df30470684e1c8aaff9d3c4 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 4 Mar 2017 23:01:11 +0800 Subject: [PATCH 077/194] 0.2.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8603dbeb..d1b0605d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.18", + "version": "0.2.19", "license": "MIT", "repository": { "type": "git", From 63f33b81e707a328535b1392a9fb776da512c8f4 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 5 Mar 2017 17:10:42 +0800 Subject: [PATCH 078/194] change domain --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ffb30051..86972353 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in - 每次向App Store提交新的版本时,也应该基于该提交版本同时向code-push-server发布一个初始版本。(因为后面每次向code-push-server发布版本时,code-puse-server都会和初始版本比较,生成补丁版本) ## EXAMPLE -codepush.19910225.com 只是一个测试server,不要将自己生产环境的项目放在上面,服务器的宽带只有1M,而且服务没有做负载均衡和监控,稳定性不能保证,烦请大家自己搭建自己的服务。 +api.code-push.com 只是一个测试server,不要将自己生产环境的项目放在上面,服务器的宽带只有1M,而且服务没有做负载均衡和监控,稳定性不能保证,烦请大家自己搭建自己的服务。 ### shell命令行端 ```shell -$ code-push login http://codepush.19910225.com:8080 #登录 +$ code-push login http://api.code-push.com:8080 #登录 ``` -### [web](http://codepush-managerment.19910225.com:8080) +### [web](http://www.code-push.com:8080) -访问:http://codepush-managerment.19910225.com:8080 +访问:http://www.code-push.com:8080 ### 客户端eg. @@ -222,11 +222,11 @@ edit config.xml. add code below. ```xml - + - + ``` From a4516ee80b31086d7ea06f9a26abcb18640f60a6 Mon Sep 17 00:00:00 2001 From: lisong Date: Sat, 24 Jun 2017 19:19:47 +0800 Subject: [PATCH 079/194] compate react-native-code-push 2.1 compate react-native-code-push 2.1 --- core/services/client-manager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index da2dfdea..dc59f1c5 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -67,6 +67,7 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { var rs = { downloadURL: "", + downloadUrl: "", description: "", isAvailable: false, isMandatory: false, @@ -98,6 +99,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { && _.eq(packages.deployment_id, deploymentsVersions.deployment_id) && !_.eq(packages.package_hash, packageHash)) { rs.downloadURL = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); + rs.downloadUrl = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); rs.description = _.get(packages, 'description', ''); rs.isAvailable = true; rs.isMandatory = _.eq(packages.is_mandatory, 1) ? true : false; From 082f7a9c70debb287b80de86db6892615ef40aec Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sat, 1 Jul 2017 05:00:19 +0300 Subject: [PATCH 080/194] fix: package.json & .snyk to reduce vulnerabilities (#66) The following vulnerabilities are fixed with a Snyk patch: - https://snyk.io/vuln/npm:ms:20170412 Latest report for lisong/code-push-server: https://snyk.io/test/github/lisong/code-push-server --- .snyk | 10 ++++++++++ package.json | 10 +++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 .snyk diff --git a/.snyk b/.snyk new file mode 100644 index 00000000..f79d2591 --- /dev/null +++ b/.snyk @@ -0,0 +1,10 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.7.0 +ignore: {} +# patches apply the minimum changes required to fix a vulnerability +patch: + 'npm:ms:20170412': + - extract-zip > debug > ms: + patched: '2017-05-23T03:00:06.406Z' + - morgan > debug > ms: + patched: '2017-05-23T03:00:06.406Z' diff --git a/package.json b/package.json index d1b0605d..9b17a5e5 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@ "upgrade": "node ./bin/db upgrade", "test": "make test", "test-win": "mocha test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000", - "coverage": "make coverage" + "coverage": "make coverage", + "snyk-protect": "snyk protect", + "prepublish": "npm run snyk-protect" }, "dependencies": { "aliyun-oss-upload-stream": "^1.3.0", @@ -71,7 +73,8 @@ "slash": "^1.0.0", "validator": "^7.0.0", "yargs": "^6.2.0", - "yazl": "^2.3.0" + "yazl": "^2.3.0", + "snyk": "^1.30.1" }, "devDependencies": { "istanbul": "^0.4.5", @@ -93,5 +96,6 @@ "app.js", "README.md", "LICENSE" - ] + ], + "snyk": true } From 8d46af6ac6f47441e2c9f65c4db4307829de9e1e Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Jul 2017 09:59:42 +0800 Subject: [PATCH 081/194] redis client quit bug --- core/services/account-manager.js | 13 +++++++++---- core/services/client-manager.js | 4 +++- test/api/users/users.test.js | 6 ++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/core/services/account-manager.js b/core/services/account-manager.js index dd4a06ef..74f6e180 100644 --- a/core/services/account-manager.js +++ b/core/services/account-manager.js @@ -132,7 +132,8 @@ proto.login = function (account, password) { throw new AppError.AppError(`您输入密码错误次数超过限制,帐户已经锁定`); } return users; - }); + }) + .finally(() => client.quit()); } else { return users; } @@ -152,7 +153,8 @@ proto.login = function (account, password) { }) .then(() => { return client.incrAsync(loginKey); - }); + }) + .finally(() => client.quit()); } throw new AppError.AppError("您输入的邮箱或密码有误"); } else { @@ -178,10 +180,12 @@ proto.sendRegisterCode = function (email) { .then(() => { //将token临时存储到redis var token = security.randToken(40); - return factory.getRedisClient("default").setexAsync(`${REGISTER_CODE}${security.md5(email)}`, EXPIRED, token) + var client = factory.getRedisClient("default"); + return client.setexAsync(`${REGISTER_CODE}${security.md5(email)}`, EXPIRED, token) .then(() => { return token; - }); + }) + .finally(() => client.quit()); }) .then((token) => { //将token发送到用户邮箱 @@ -213,6 +217,7 @@ proto.checkRegisterCode = function (email, token) { } return ttl; }) + .finally(() => client.quit()); throw new AppError.AppError(`您输入的验证码不正确,请重新输入`); } return storageToken; diff --git a/core/services/client-manager.js b/core/services/client-manager.js index dc59f1c5..8697ddea 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -32,7 +32,8 @@ proto.clearUpdateCheckCache = function(deploymentKey, appVersion, label, package }); } return null; - }); + }) + .finally(() => client.quit()); } proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageHash) { @@ -62,6 +63,7 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH return rs; }); }) + .finally(() => client.quit()); } proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { diff --git a/test/api/users/users.test.js b/test/api/users/users.test.js index 57d87109..abced1b2 100644 --- a/test/api/users/users.test.js +++ b/test/api/users/users.test.js @@ -78,7 +78,8 @@ describe('api/users/users.test.js', function() { .then(function (t) { storageToken = t; done(); - }); + }) + .finally(() => client.quit()); }); it('should not check register code successful when email already exists', function(done) { @@ -131,7 +132,8 @@ describe('api/users/users.test.js', function() { .then(function (t) { storageToken = t; done(); - }); + }) + .finally(() => client.quit()); }); it('should not sign up successful when password length invalid', function(done) { From 4cf42aab2dafd220f361568c04a0e29d8de6c750 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Jul 2017 10:55:23 +0800 Subject: [PATCH 082/194] upgrade dep package --- bin/db | 2 +- models/collaborators.js | 19 +++++----- models/deployments.js | 35 +++++++++--------- models/packages_metrics.js | 74 ++++++++++++++++++++------------------ package.json | 18 +++++----- 5 files changed, 74 insertions(+), 74 deletions(-) diff --git a/bin/db b/bin/db index a856921f..660914d9 100755 --- a/bin/db +++ b/bin/db @@ -6,7 +6,7 @@ var fs = require('fs'); var path = require('path'); var _ = require('lodash'); -var mysql = require('mysql'); +var mysql = require('mysql2'); var Promise = require("bluebird"); var yargs = require('yargs') .usage('Usage: $0 [options]') diff --git a/models/collaborators.js b/models/collaborators.js index 6440b358..c5f8d268 100644 --- a/models/collaborators.js +++ b/models/collaborators.js @@ -16,17 +16,14 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'collaborators', underscored: true, - paranoid: true, - classMethods: { - findByAppNameAndUid: function(uid, appName) { - var sql = "SELECT b.* FROM `apps` as a left join `collaborators` as b on (a.id = b.appid) where a.name= :appName and b.uid = :uid and a.`deleted_at` IS NULL and b.`deleted_at` IS NULL limit 0,1"; - return sequelize.query(sql, { replacements: { appName: appName, uid: uid }, model: Collaborators}) - .then(function(data) { - return data.pop(); - }); - } - } - + paranoid: true }); + Collaborators.findByAppNameAndUid = function (uid, appName) { + var sql = "SELECT b.* FROM `apps` as a left join `collaborators` as b on (a.id = b.appid) where a.name= :appName and b.uid = :uid and a.`deleted_at` IS NULL and b.`deleted_at` IS NULL limit 0,1"; + return sequelize.query(sql, { replacements: { appName: appName, uid: uid }, model: Collaborators}) + .then(function(data) { + return data.pop(); + }); + }; return Collaborators; }; diff --git a/models/deployments.js b/models/deployments.js index 122b1b36..fade4b93 100644 --- a/models/deployments.js +++ b/models/deployments.js @@ -22,25 +22,24 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'deployments', underscored: true, - paranoid: true, - classMethods: { - generateLabelId: function(deploymentId) { - var self = this; - return sequelize.transaction(function (t) { - return self.findById(deploymentId, {transaction: t,lock: t.LOCK.UPDATE}).then(function (data) { - if (_.isEmpty(data)){ - throw new AppError.AppError("does not find deployment"); - } - data.label_id = data.label_id + 1; - return data.save({transaction: t}) - .then(function (data) { - return data.label_id; - }); - }); - }); - } - } + paranoid: true }); + Deployments.generateLabelId = function(deploymentId) { + var self = this; + return sequelize.transaction(function (t) { + return self.findById(deploymentId, {transaction: t,lock: t.LOCK.UPDATE}).then(function (data) { + if (_.isEmpty(data)){ + throw new AppError.AppError("does not find deployment"); + } + data.label_id = data.label_id + 1; + return data.save({transaction: t}) + .then(function (data) { + return data.label_id; + }); + }); + }); + }; + return Deployments; }; diff --git a/models/packages_metrics.js b/models/packages_metrics.js index 86a1acff..3ee99887 100644 --- a/models/packages_metrics.js +++ b/models/packages_metrics.js @@ -20,41 +20,45 @@ module.exports = function(sequelize, DataTypes) { }, { tableName: 'packages_metrics', underscored: true, - paranoid: true, - classMethods: { - addOne : function (packageId, fieldName) { - var self = this; - var sql = 'UPDATE packages_metrics SET `' + fieldName + '`=`' + fieldName + '` + 1 WHERE package_id = :package_id'; - return sequelize.query(sql, { replacements: { package_id: packageId}}) - .spread(function(results, metadata) { - if (_.eq(results.affectedRows, 0)) { - var params = { - package_id: packageId, - active: 0, - downloaded: 0, - failed: 0, - installed: 0, - }; - params[fieldName] = 1; - return self.create(params); - }else { - return true; - } - }); - }, - addOneOnDownloadById: function (packageId) { - return this.addOne(packageId, 'downloaded'); - }, - addOneOnFailedById: function (packageId) { - return this.addOne(packageId, 'failed'); - }, - addOneOnInstalledById: function (packageId) { - return this.addOne(packageId, 'installed'); - }, - addOneOnActiveById: function (packageId) { - return this.addOne(packageId, 'active'); - }, - } + paranoid: true }); + + PackagesMetrics.addOne = function (packageId, fieldName) { + var self = this; + var sql = 'UPDATE packages_metrics SET `' + fieldName + '`=`' + fieldName + '` + 1 WHERE package_id = :package_id'; + return sequelize.query(sql, { replacements: { package_id: packageId}}) + .spread(function(results, metadata) { + if (_.eq(results.affectedRows, 0)) { + var params = { + package_id: packageId, + active: 0, + downloaded: 0, + failed: 0, + installed: 0, + }; + params[fieldName] = 1; + return self.create(params); + }else { + return true; + } + }); + }; + + PackagesMetrics.addOneOnDownloadById = function (packageId) { + return this.addOne(packageId, 'downloaded'); + }; + + PackagesMetrics.addOneOnFailedById = function (packageId) { + return this.addOne(packageId, 'failed'); + }; + + PackagesMetrics.addOneOnInstalledById = function (packageId) { + return this.addOne(packageId, 'installed'); + }; + + PackagesMetrics.addOneOnActiveById = function (packageId) { + return this.addOne(packageId, 'active'); + }; + return PackagesMetrics; }; diff --git a/package.json b/package.json index 9b17a5e5..2f84d392 100644 --- a/package.json +++ b/package.json @@ -47,11 +47,11 @@ "bluebird": "^3.4.1", "body-parser": "^1.15.2", "cookie-parser": "^1.4.3", - "debug": "^2.3.3", + "debug": "^2.6.8", "express": "^4.14.0", "extract-zip": "^1.6.0", "formidable": "^1.0.17", - "fs-extra": "^2.0.0", + "fs-extra": "^3.0.1", "helmet": "^3.1.0", "i18n": "^0.8.3", "jsonwebtoken": "^7.1.7", @@ -60,21 +60,21 @@ "markdown-it": "^8.0.1", "moment": "^2.14.1", "morgan": "^1.7.0", - "mysql": "^2.10.2", - "nodemailer": "^3.1.3", + "mysql2": "^1.3.5", + "nodemailer": "^4.0.1", "pug": "^2.0.0-beta6", - "qiniu": "^6.1.10", + "qiniu": "^7.0.4", "rand-token": "^0.3.0", "recursive-fs": "^1.0.0", "redis": "^2.6.2", "request": "^2.72.0", - "sequelize": "^3.24.5", + "sequelize": "^4.2.1", "serve-favicon": "^2.4.0", "slash": "^1.0.0", + "snyk": "^1.30.1", "validator": "^7.0.0", - "yargs": "^6.2.0", - "yazl": "^2.3.0", - "snyk": "^1.30.1" + "yargs": "^8.0.2", + "yazl": "^2.3.0" }, "devDependencies": { "istanbul": "^0.4.5", From ead87cbb598911c37cb8b5abff8e84ae5d0e48f7 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 11 Mar 2017 22:47:28 +0800 Subject: [PATCH 083/194] local storage split dir --- core/utils/common.js | 34 ++++++++++++++++++++++------------ routes/apps.js | 1 + 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/core/utils/common.js b/core/utils/common.js index ca328c18..777c0c1a 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -139,6 +139,10 @@ common.uploadFileToLocal = function (key, filePath) { if (!storageDir) { throw new AppError.AppError('please set config local storageDir'); } + if (key.length < 3) { + log.error(`generate key is too short, key value:${key}`); + throw new AppError.AppError('generate key is too short.'); + } try { log.debug(`uploadFileToLocal check directory ${storageDir} fs.R_OK`); fs.accessSync(storageDir, fs.W_OK); @@ -147,7 +151,10 @@ common.uploadFileToLocal = function (key, filePath) { log.error(e); throw new AppError.AppError(e.message); } - if (fs.existsSync(`${storageDir}/${key}`)) { + var subDir = key.substr(0, 2).toLowerCase(); + var finalDir = `${storageDir}/${subDir}`; + var fileName = `${finalDir}/${key}`; + if (fs.existsSync(fileName)) { return resolve(key); } var stats = fs.statSync(storageDir); @@ -156,6 +163,10 @@ common.uploadFileToLocal = function (key, filePath) { log.error(e); throw e; } + if (!fs.existsSync(`${finalDir}`)) { + fs.mkdirSync(`${finalDir}`); + log.debug(`uploadFileToLocal mkdir:${finalDir}`); + } try { fs.accessSync(filePath, fs.R_OK); } catch (e) { @@ -168,7 +179,7 @@ common.uploadFileToLocal = function (key, filePath) { log.debug(e); throw e; } - fsextra.copy(filePath, `${storageDir}/${key}`,(err) => { + fsextra.copy(filePath, fileName,(err) => { if (err) { log.error(new AppError.AppError(err.message)); return reject(new AppError.AppError(err.message)); @@ -179,26 +190,25 @@ common.uploadFileToLocal = function (key, filePath) { }); }; -common.getDownloadUrl = function () { +common.getBlobDownloadUrl = function (blobUrl) { + var downloadUrl = ''; + var fileName = blobUrl; if (_.get(config, 'common.storageType') === 'local') { - return _.get(config, 'local.downloadUrl'); + downloadUrl = _.get(config, 'local.downloadUrl'); + fileName = blobUrl.substr(0, 2).toLowerCase() + '/' + blobUrl; } else if (_.get(config, 'common.storageType') === 's3') { - return _.get(config, 's3.downloadUrl'); + downloadUrl = _.get(config, 's3.downloadUrl'); } else if (_.get(config, 'common.storageType') === 'oss') { - return _.get(config, 'oss.downloadUrl'); + downloadUrl = _.get(config, 'oss.downloadUrl'); } - return _.get(config, 'qiniu.downloadUrl'); -} - -common.getBlobDownloadUrl = function (blobUrl) { - return `${common.getDownloadUrl()}/${blobUrl}` + return `${downloadUrl}/${fileName}` }; common.uploadFileToQiniu = function (key, filePath) { return new Promise((resolve, reject) => { qiniu.conf.ACCESS_KEY = _.get(config, "qiniu.accessKey"); qiniu.conf.SECRET_KEY = _.get(config, "qiniu.secretKey"); - var bucket = _.get(config, "qiniu.bucketName", "jukang"); + var bucket = _.get(config, "qiniu.bucketName", ""); var client = new qiniu.rs.Client(); client.stat(bucket, key, (err, ret) => { if (!err) { diff --git a/routes/apps.js b/routes/apps.js index 8f634bec..a608a6a8 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -73,6 +73,7 @@ router.get('/:appName/deployments/:deploymentName', throw new AppError.AppError("does not find the deployment"); } res.send({deployment: deployments.listDeloyment(deploymentInfo)}); + return true; }) .catch((e) => { if (e instanceof AppError.AppError) { From 9c537fd1c2b1ddbb6aa78103612d5b31c0b91df5 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 12 Mar 2017 15:15:50 +0800 Subject: [PATCH 084/194] use recursive-readdir --- core/utils/security.js | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/utils/security.js b/core/utils/security.js index 401fd040..3307018b 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -112,13 +112,13 @@ security.sha256AllFiles = function (files) { security.uploadPackageType = function (directoryPath) { return new Promise((resolve, reject) => { - var recursiveFs = require("recursive-fs"); + var recursive = require("recursive-readdir"); var path = require('path'); var slash = require("slash"); - recursiveFs.readdirr(directoryPath, (err, directories, files) => { + recursive(directoryPath, (err, files) => { if (err) { log.error(new AppError.AppError(err.message)); - reject(err); + reject(new AppError.AppError(err.message)); } else { if (files.length == 0) { log.debug(`uploadPackageType empty files`); @@ -147,13 +147,13 @@ security.uploadPackageType = function (directoryPath) { security.calcAllFileSha256 = function (directoryPath) { return new Promise((resolve, reject) => { - var recursiveFs = require("recursive-fs"); + var recursive = require("recursive-readdir"); var path = require('path'); var slash = require("slash"); - recursiveFs.readdirr(directoryPath, (error, directories, files) => { + recursive(directoryPath, (error, files) => { if (error) { log.error(error); - reject(error); + reject(new AppError.AppError(error.message)); } else { if (files.length == 0) { log.debug(`calcAllFileSha256 empty files in directoryPath:`, directoryPath); diff --git a/package.json b/package.json index 2f84d392..6bee0e75 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "pug": "^2.0.0-beta6", "qiniu": "^7.0.4", "rand-token": "^0.3.0", - "recursive-fs": "^1.0.0", + "recursive-readdir": "^2.1.1", "redis": "^2.6.2", "request": "^2.72.0", "sequelize": "^4.2.1", From 01fd7fa8d78a0814f4f7a3c934f5fa3233614ac5 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Jul 2017 11:22:45 +0800 Subject: [PATCH 085/194] use mysql2 --- test/api/init/database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/api/init/database.js b/test/api/init/database.js index 90b7238e..83232b59 100644 --- a/test/api/init/database.js +++ b/test/api/init/database.js @@ -1,5 +1,5 @@ var config = require('../../../core/config'); -var mysql = require('mysql'); +var mysql = require('mysql2'); var redis = require('redis'); var should = require('should'); var fs = require('fs'); From 4121d3bc03417f27692ea976d753c02139ab8820 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 9 Aug 2017 19:44:39 +0800 Subject: [PATCH 086/194] rm snyk --- .snyk | 10 ---------- package.json | 7 ++----- 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 .snyk diff --git a/.snyk b/.snyk deleted file mode 100644 index f79d2591..00000000 --- a/.snyk +++ /dev/null @@ -1,10 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.7.0 -ignore: {} -# patches apply the minimum changes required to fix a vulnerability -patch: - 'npm:ms:20170412': - - extract-zip > debug > ms: - patched: '2017-05-23T03:00:06.406Z' - - morgan > debug > ms: - patched: '2017-05-23T03:00:06.406Z' diff --git a/package.json b/package.json index 6bee0e75..41fb38bf 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,7 @@ "upgrade": "node ./bin/db upgrade", "test": "make test", "test-win": "mocha test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000", - "coverage": "make coverage", - "snyk-protect": "snyk protect", - "prepublish": "npm run snyk-protect" + "coverage": "make coverage" }, "dependencies": { "aliyun-oss-upload-stream": "^1.3.0", @@ -96,6 +94,5 @@ "app.js", "README.md", "LICENSE" - ], - "snyk": true + ] } From ff07696826cb75c4dd9795cf1038e3c1293014f1 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 9 Aug 2017 22:15:29 +0800 Subject: [PATCH 087/194] add download stat --- CHANGELOG.md | 1 + README.md | 2 ++ config/config.js | 2 +- core/services/app-manager.js | 3 ++- 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..ce8ae7ed --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +# Changelog for code-push-server \ No newline at end of file diff --git a/README.md b/README.md index 86972353..e5b08d36 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # CodePush Server [source](https://github.com/lisong/code-push-server) +[![NPM](https://nodei.co/npm/code-push-server.svg?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/code-push-server/) + [![NPM Version](https://img.shields.io/npm/v/code-push-server.svg)](https://npmjs.org/package/code-push-server) [![Node.js Version](https://img.shields.io/node/v/code-push-server.svg)](https://nodejs.org/en/download/) [![Linux Status](https://img.shields.io/travis/lisong/code-push-server/master.svg?label=linux)](https://travis-ci.org/lisong/code-push-server) diff --git a/config/config.js b/config/config.js index 79c4638b..ecdc3e3c 100644 --- a/config/config.js +++ b/config/config.js @@ -69,7 +69,7 @@ config.development = { }, // Config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer smtpConfig:{ - host: "smtp.mxhichina.com", + host: "smtp.aliyun.com", port: 465, secure: true, auth: { diff --git a/core/services/app-manager.js b/core/services/app-manager.js index 0d484b49..d180d0d3 100644 --- a/core/services/app-manager.js +++ b/core/services/app-manager.js @@ -129,7 +129,8 @@ proto.getAppDetailInfo = function (appInfo, currentUid) { return _.get(item, 'name'); }), - name: appInfo.get('name') + name: appInfo.get('name'), + id: appInfo.get('id') }); }); }; From e882ad5c6814676823e4dc0372434f6048aee8a5 Mon Sep 17 00:00:00 2001 From: Rain Cheung Date: Thu, 24 Aug 2017 20:21:00 +0800 Subject: [PATCH 088/194] =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=B8=83=E7=89=9B=E4=B8=8B=E8=BD=BD=E5=9C=B0=E5=9D=80=20(#89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加七牛下载链接获取 --- core/utils/common.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/utils/common.js b/core/utils/common.js index 777c0c1a..2359425c 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -200,6 +200,8 @@ common.getBlobDownloadUrl = function (blobUrl) { downloadUrl = _.get(config, 's3.downloadUrl'); } else if (_.get(config, 'common.storageType') === 'oss') { downloadUrl = _.get(config, 'oss.downloadUrl'); + }else if (_.get(config, 'common.storageType') === 'qiniu') { + downloadUrl = _.get(config, 'qiniu.downloadUrl'); } return `${downloadUrl}/${fileName}` }; From 21063a650d1eaa502224489aadaf47a758845b3d Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 24 Aug 2017 23:41:37 +0800 Subject: [PATCH 089/194] fix --- core/utils/common.js | 1 + docs/react-native-code-push.md | 2 +- package.json | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/utils/common.js b/core/utils/common.js index 2359425c..68a4948c 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -206,6 +206,7 @@ common.getBlobDownloadUrl = function (blobUrl) { return `${downloadUrl}/${fileName}` }; + common.uploadFileToQiniu = function (key, filePath) { return new Promise((resolve, reject) => { qiniu.conf.ACCESS_KEY = _.get(config, "qiniu.accessKey"); diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index 3dce5fe1..c27e8413 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -36,7 +36,7 @@ $ npm install code-push-cli@latest -g ```shell $ react-native init CodePushDemo #初始化一个react-native项目 $ cd CodePushDemo -$ npm install --save react-native-code-push #安装react-native-code-push +$ npm install --save react-native-code-push@latest #安装react-native-code-push $ react-native link react-native-code-push #连接到项目中,提示输入配置可以先行忽略 ``` diff --git a/package.json b/package.json index 41fb38bf..0e760010 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,6 @@ "sequelize": "^4.2.1", "serve-favicon": "^2.4.0", "slash": "^1.0.0", - "snyk": "^1.30.1", "validator": "^7.0.0", "yargs": "^8.0.2", "yazl": "^2.3.0" From 47ff7f958e40792cea7508de1b932f7c608f0938 Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 25 Aug 2017 01:13:09 +0800 Subject: [PATCH 090/194] fix qiniu upload bug --- core/utils/common.js | 55 +++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/core/utils/common.js b/core/utils/common.js index 68a4948c..88b613c0 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -117,9 +117,12 @@ common.unzipFile = function (zipFile, outputPath) { }); }; -common.uptoken = function (bucket, key) { - var putPolicy = new qiniu.rs.PutPolicy(bucket+":"+key); - return putPolicy.token(); +common.getUploadTokenQiniu = function (mac, bucket, key) { + var options = { + scope: bucket + ":" + key + } + var putPolicy = new qiniu.rs.PutPolicy(options); + return putPolicy.uploadToken(mac); }; common.uploadFileToStorage = function (key, filePath) { @@ -209,27 +212,43 @@ common.getBlobDownloadUrl = function (blobUrl) { common.uploadFileToQiniu = function (key, filePath) { return new Promise((resolve, reject) => { - qiniu.conf.ACCESS_KEY = _.get(config, "qiniu.accessKey"); - qiniu.conf.SECRET_KEY = _.get(config, "qiniu.secretKey"); + var accessKey = _.get(config, "qiniu.accessKey"); + var secretKey = _.get(config, "qiniu.secretKey"); var bucket = _.get(config, "qiniu.bucketName", ""); - var client = new qiniu.rs.Client(); - client.stat(bucket, key, (err, ret) => { - if (!err) { - resolve(ret.hash); + var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); + var conf = new qiniu.conf.Config(); + var bucketManager = new qiniu.rs.BucketManager(mac, conf); + bucketManager.stat(bucket, key, (respErr, respBody, respInfo) => { + if (respErr) { + log.debug('uploadFileToQiniu file stat:', respErr); + return reject(new AppError.AppError(respErr.message)); + } + log.debug('uploadFileToQiniu file stat respBody:', respBody); + log.debug('uploadFileToQiniu file stat respInfo:', respInfo); + if (respInfo.statusCode == 200) { + resolve(respBody.hash); } else { try { - var uptoken = common.uptoken(bucket, key); + var uploadToken = common.getUploadTokenQiniu(mac, bucket, key); } catch (e) { - return reject(e); + return reject(new AppError.AppError(e.message)); } - var extra = new qiniu.io.PutExtra(); - qiniu.io.putFile(uptoken, key, filePath, extra, (err, ret) => { - if(!err) { - // 上传成功, 处理返回值 - resolve(ret.hash); - } else { + var formUploader = new qiniu.form_up.FormUploader(conf); + var putExtra = new qiniu.form_up.PutExtra(); + formUploader.putFile(uploadToken, key, filePath, putExtra, (respErr, respBody, respInfo) => { + if(respErr) { + log.error('uploadFileToQiniu putFile:', respErr); // 上传失败, 处理返回代码 - reject(new AppError.AppError(JSON.stringify(err))); + return reject(new AppError.AppError(JSON.stringify(respErr))); + } else { + log.debug('uploadFileToQiniu putFile respBody:', respBody); + log.debug('uploadFileToQiniu putFile respInfo:', respInfo); + // 上传成功, 处理返回值 + if (respInfo.statusCode == 200) { + return resolve(respBody.hash); + } else { + return reject(new AppError.AppError(respBody.error)); + } } }); } From 9a1aa5f2881494ccac791e6f9a33edb333a07d5d Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 14 Sep 2017 22:57:59 +0800 Subject: [PATCH 091/194] fix readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e5b08d36..a62e9ced 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,12 @@ api.code-push.com 只是一个测试server,不要将自己生产环境的项 ### shell命令行端 ```shell -$ code-push login http://api.code-push.com:8080 #登录 +$ code-push login http://api.code-push.com #登录 ``` -### [web](http://www.code-push.com:8080) +### [web](http://www.code-push.com) -访问:http://www.code-push.com:8080 +访问:http://www.code-push.com ### 客户端eg. @@ -224,11 +224,11 @@ edit config.xml. add code below. ```xml - + - + ``` From 326ffe0d1d916683c87c3e1c3113e1927c6f5367 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 14 Sep 2017 23:59:50 +0800 Subject: [PATCH 092/194] fix android download --- core/services/client-manager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 8697ddea..8516e2ab 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -121,6 +121,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { .then((diffPackage) => { if (!_.isEmpty(diffPackage)) { rs.downloadURL = common.getBlobDownloadUrl(_.get(diffPackage, 'diff_blob_url')); + rs.downloadUrl = common.getBlobDownloadUrl(_.get(diffPackage, 'diff_blob_url')); rs.packageSize = _.get(diffPackage, 'diff_size', 0); } return; From 020a35014d7c202d87f92a601b96f661380c6a80 Mon Sep 17 00:00:00 2001 From: Ian Zhong Date: Fri, 2 Mar 2018 20:36:19 +0800 Subject: [PATCH 093/194] fix issue 103: https://github.com/lisong/code-push-server/issues/103 (#113) thanks ! --- routes/apps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/apps.js b/routes/apps.js index a608a6a8..317dc37c 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -318,7 +318,7 @@ router.post('/:appName/deployments/:deploymentName/release', }); }) .then((data) => { - res.send(""); + res.send('{"msg": "succeed"}'); }) .catch((e) => { if (e instanceof AppError.AppError) { From 69823f314601012e0f0e55394f7f1db4addd2578 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 18 Mar 2018 12:38:49 +0800 Subject: [PATCH 094/194] update dep package version --- bin/www | 5 ++++- config/config.js | 16 +++++++--------- config/config.test.js | 14 ++++++-------- config/config.testwin.js | 14 ++++++-------- core/utils/common.js | 21 +++++++++++---------- package.json | 16 ++++++++-------- test/api/auth/auth.test.js | 4 ++-- 7 files changed, 44 insertions(+), 46 deletions(-) diff --git a/bin/www b/bin/www index a34f74be..3fb0c6ec 100755 --- a/bin/www +++ b/bin/www @@ -9,7 +9,10 @@ var http = require('http'); var validator = require('validator') var _ = require('lodash') var config = require('../core/config'); -log4js.configure(_.get(config, 'log4js', {appenders: [{ type: 'console'}], levels : {"[all]": "ERROR", http: "ERROR"} })); +log4js.configure(_.get(config, 'log4js', { + appenders: {console: { type: 'console'}}, + categories : { default: { appenders: ['console'], level: 'info' }} +})); var log = log4js.getLogger("startup") var app = require('../app'); diff --git a/config/config.js b/config/config.js index ecdc3e3c..b4641694 100644 --- a/config/config.js +++ b/config/config.js @@ -40,7 +40,7 @@ config.development = { // Binary files storage dir, Do not use tmpdir and it's public download dir. storageDir: process.env.STORAGE_DIR || "/Users/tablee/workspaces/storage", // Binary files download host address which Code Push Server listen to. the files storage in storageDir. - downloadUrl: process.env.LOCAL_DOWNLOAD_URL || "http://localhost:3000/download", + downloadUrl: process.env.LOCAL_DOWNLOAD_URL || "http://127.0.0.1:3000/download", // public static download spacename. public: process.env.PUBLIC || '/download' }, @@ -57,7 +57,7 @@ config.development = { */ tryLoginTimes: 0, // CodePush Web(https://github.com/lisong/code-push-web) login address. - //codePushWebUrl: "http://localhost:3001/login", + //codePushWebUrl: "http://127.0.0.1:3001/login", // create patch updates's number. default value is 3 diffNums: 3, // data dir for caclulate diff files. it's optimization. @@ -103,13 +103,11 @@ config.development = { } config.development.log4js = { - appenders: [ - { type: 'console'} - ], - levels : { - "[all]": "ERROR", - "startup": "INFO", - "http" : "INFO" + appenders: {console: { type: 'console'}}, + categories : { + "default": { appenders: ['console'], level:'error'}, + "startup": { appenders: ['console'], level:'info'}, + "http": { appenders: ['console'], level:'info'} } } diff --git a/config/config.test.js b/config/config.test.js index fbfd4cd5..7b53588b 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -13,7 +13,7 @@ config.test = { }, local: { storageDir: os.tmpdir(), - downloadUrl: "http://localhost:3000/download", + downloadUrl: "http://127.0.0.1:3000/download", public: '/download' }, jwt: { @@ -47,13 +47,11 @@ config.test = { } } config.test.log4js = { - appenders: [ - { type: 'console'} - ], - levels : { - "[all]": "ERROR", - "startup": "INFO", - "http" : "INFO" + appenders: {console: { type: 'console'}}, + categories : { + "default": { appenders: ['console'], level:'error'}, + "startup": { appenders: ['console'], level:'info'}, + "http": { appenders: ['console'], level:'info'} } } module.exports = config; diff --git a/config/config.testwin.js b/config/config.testwin.js index 2f6b1f82..b98cedd0 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -13,7 +13,7 @@ config.test = { }, local: { storageDir: os.tmpdir(), - downloadUrl: "http://localhost:3000/download", + downloadUrl: "http://127.0.0.1:3000/download", public: '/download' }, jwt: { @@ -48,13 +48,11 @@ config.test = { } } config.test.log4js = { - appenders: [ - { type: 'console'} - ], - levels : { - "[all]": "ERROR", - "startup": "INFO", - "http" : "INFO" + appenders: {console: { type: 'console'}}, + categories : { + "default": { appenders: ['console'], level:'error'}, + "startup": { appenders: ['console'], level:'info'}, + "http": { appenders: ['console'], level:'info'} } } module.exports = config; diff --git a/core/utils/common.js b/core/utils/common.js index 88b613c0..863478ad 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -5,6 +5,7 @@ var fsextra = require("fs-extra"); var extract = require('extract-zip') var config = require('../config'); var _ = require('lodash'); +var validator = require('validator'); var qiniu = require("qiniu"); var common = {}; var AppError = require('../app-error'); @@ -17,6 +18,7 @@ common.createFileFromRequest = function (url, filePath) { fs.exists(filePath, function (exists) { if (!exists) { var request = require('request'); + log.debug(`createFileFromRequest url:${url}`) request(url).on('error', function (error) { reject(error); }) @@ -179,7 +181,7 @@ common.uploadFileToLocal = function (key, filePath) { stats = fs.statSync(filePath); if (!stats.isFile()) { var e = new AppError.AppError(`${filePath} must be file`); - log.debug(e); + log.error(e); throw e; } fsextra.copy(filePath, fileName,(err) => { @@ -194,17 +196,16 @@ common.uploadFileToLocal = function (key, filePath) { }; common.getBlobDownloadUrl = function (blobUrl) { - var downloadUrl = ''; var fileName = blobUrl; - if (_.get(config, 'common.storageType') === 'local') { - downloadUrl = _.get(config, 'local.downloadUrl'); + var storageType = _.get(config, 'common.storageType'); + var downloadUrl = _.get(config, `${storageType}.downloadUrl`); + if ( storageType === 'local') { fileName = blobUrl.substr(0, 2).toLowerCase() + '/' + blobUrl; - } else if (_.get(config, 'common.storageType') === 's3') { - downloadUrl = _.get(config, 's3.downloadUrl'); - } else if (_.get(config, 'common.storageType') === 'oss') { - downloadUrl = _.get(config, 'oss.downloadUrl'); - }else if (_.get(config, 'common.storageType') === 'qiniu') { - downloadUrl = _.get(config, 'qiniu.downloadUrl'); + } + if (!validator.isURL(downloadUrl)) { + var e = new AppError.AppError(`Please config ${storageType}.downloadUrl in config.js`); + log.error(e); + throw e; } return `${downloadUrl}/${fileName}` }; diff --git a/package.json b/package.json index 0e760010..a561976d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "aliyun-oss-upload-stream": "^1.3.0", - "aliyun-sdk": "^1.9.17", + "aliyun-sdk": "^1.11.5", "aws-sdk": "^2.7.0", "bcryptjs": "^2.3.0", "bluebird": "^3.4.1", @@ -52,24 +52,24 @@ "fs-extra": "^3.0.1", "helmet": "^3.1.0", "i18n": "^0.8.3", - "jsonwebtoken": "^7.1.7", - "lodash": "^4.5.1", - "log4js": "^1.1.0", + "jsonwebtoken": "^8.2.0", + "lodash": "^4.17.5", + "log4js": "^2.5.3", "markdown-it": "^8.0.1", "moment": "^2.14.1", "morgan": "^1.7.0", "mysql2": "^1.3.5", "nodemailer": "^4.0.1", - "pug": "^2.0.0-beta6", - "qiniu": "^7.0.4", + "pug": "^2.0.1", + "qiniu": "^7.1.3", "rand-token": "^0.3.0", "recursive-readdir": "^2.1.1", "redis": "^2.6.2", "request": "^2.72.0", - "sequelize": "^4.2.1", + "sequelize": "^4.37.1", "serve-favicon": "^2.4.0", "slash": "^1.0.0", - "validator": "^7.0.0", + "validator": "^9.4.1", "yargs": "^8.0.2", "yazl": "^2.3.0" }, diff --git a/test/api/auth/auth.test.js b/test/api/auth/auth.test.js index 06311a30..0263639a 100644 --- a/test/api/auth/auth.test.js +++ b/test/api/auth/auth.test.js @@ -10,7 +10,7 @@ describe('api/auth/test.js', function() { describe('sign in view', function(done) { it('should show sign in redirect view successful', function(done) { - _.set(config, 'common.codePushWebUrl', 'http://localhost:3001') + _.set(config, 'common.codePushWebUrl', 'http://127.0.0.1:3001') request.get('/auth/login') .send() .end(function(err, res) { @@ -34,7 +34,7 @@ describe('api/auth/test.js', function() { describe('sign up view', function(done) { it('should show sign up redirect view successful', function(done) { - _.set(config, 'common.codePushWebUrl', 'http://localhost:3001') + _.set(config, 'common.codePushWebUrl', 'http://127.0.0.1:3001') request.get('/auth/register') .send() .end(function(err, res) { From 7e7181eb9d0ba39a848cd5b358f121e9513eef06 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 18 Mar 2018 12:56:11 +0800 Subject: [PATCH 095/194] 0.2.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a561976d..3a3031d9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.19", + "version": "0.2.20", "license": "MIT", "repository": { "type": "git", From 695c72eb4c938ac942081b78b4c2dd1fbb357f7f Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 18 Mar 2018 15:09:16 +0800 Subject: [PATCH 096/194] add package-lock.json --- .travis.yml | 3 +- appveyor.yml | 3 +- package-lock.json | 4607 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 4611 insertions(+), 2 deletions(-) create mode 100644 package-lock.json diff --git a/.travis.yml b/.travis.yml index 0d59c5dd..3a0d6580 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ services: - mysql node_js: + - "8.10.0" - "7.5" - "7" - "6.9.5" @@ -27,4 +28,4 @@ before_install: - "test ! -d node_modules || npm prune" - "test ! -d node_modules || npm rebuild" script: "npm run-script coverage" -after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" \ No newline at end of file +after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" diff --git a/appveyor.yml b/appveyor.yml index 3fca1216..7833713b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,7 @@ init: environment: matrix: + - nodejs_version: "8.10.0" - nodejs_version: "7.5" - nodejs_version: "7" - nodejs_version: "6.9.5" @@ -27,4 +28,4 @@ test_script: - set CONFIG_FILE=config/config.testwin.js - node_modules\.bin\npm run test-win build: off -version: "{build}" \ No newline at end of file +version: "{build}" diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..ce2ce991 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4607 @@ +{ + "name": "code-push-server", + "version": "0.2.20", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/babel-types": { + "version": "7.0.1", + "resolved": "http://registry.npm.taobao.org/@types/babel-types/download/@types/babel-types-7.0.1.tgz", + "integrity": "sha1-FAXlOWloxDAplLAWHOQFtyuHQlc=" + }, + "@types/babylon": { + "version": "6.16.2", + "resolved": "http://registry.npm.taobao.org/@types/babylon/download/@types/babylon-6.16.2.tgz", + "integrity": "sha1-BizmO2k9mvHCRvWu35KLycMFicg=", + "requires": { + "@types/babel-types": "7.0.1" + } + }, + "@types/geojson": { + "version": "1.0.6", + "resolved": "http://registry.npm.taobao.org/@types/geojson/download/@types/geojson-1.0.6.tgz", + "integrity": "sha1-PgKXJyjGkkjCrwjWCkjLuGgP/98=" + }, + "@types/node": { + "version": "9.4.7", + "resolved": "http://registry.npm.taobao.org/@types/node/download/@types/node-9.4.7.tgz", + "integrity": "sha1-V9gc2YcZ3yyd4Rjy1fOxEg3NcnU=" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/abbrev/download/abbrev-1.1.1.tgz", + "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + }, + "accepts": { + "version": "1.3.5", + "resolved": "http://registry.npm.taobao.org/accepts/download/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "3.3.0", + "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + }, + "acorn-globals": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/acorn-globals/download/acorn-globals-3.1.0.tgz", + "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + } + } + }, + "address": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/address/download/address-1.0.3.tgz", + "integrity": "sha1-tfUGMfjWzsi9IMljljr7VeBsvOk=" + }, + "addressparser": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/addressparser/download/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "optional": true + }, + "agent-base": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/agent-base/download/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "http://registry.npm.taobao.org/semver/download/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" + } + } + }, + "agentkeepalive": { + "version": "3.3.0", + "resolved": "http://registry.npm.taobao.org/agentkeepalive/download/agentkeepalive-3.3.0.tgz", + "integrity": "sha1-bV3lgpr9O+JxIgGjknX9EcZRhXw=", + "requires": { + "humanize-ms": "1.2.1" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "http://registry.npm.taobao.org/align-text/download/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "aliyun-oss-upload-stream": { + "version": "1.3.0", + "resolved": "http://registry.npm.taobao.org/aliyun-oss-upload-stream/download/aliyun-oss-upload-stream-1.3.0.tgz", + "integrity": "sha1-ODAbGfA0QGhDjrY5d6DNldYEcMA=" + }, + "aliyun-sdk": { + "version": "1.11.5", + "resolved": "http://registry.npm.taobao.org/aliyun-sdk/download/aliyun-sdk-1.11.5.tgz", + "integrity": "sha1-kwWBkrN0Wn+AbLJW+L+oEBb2dy0=", + "requires": { + "node_memcached": "1.1.3", + "pomelo-protobuf": "0.4.0", + "protobufjs": "4.1.3", + "xml2js": "0.4.4", + "xmlbuilder": "2.6.5" + } + }, + "ambi": { + "version": "2.5.0", + "resolved": "http://registry.npm.taobao.org/ambi/download/ambi-2.5.0.tgz", + "integrity": "sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA=", + "requires": { + "editions": "1.3.4", + "typechecker": "4.5.0" + }, + "dependencies": { + "typechecker": { + "version": "4.5.0", + "resolved": "http://registry.npm.taobao.org/typechecker/download/typechecker-4.5.0.tgz", + "integrity": "sha1-w4KSAJeBI2S7r0WVsKtliCRBF6Y=", + "requires": { + "editions": "1.3.4" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "amqplib": { + "version": "0.5.2", + "resolved": "http://registry.npm.taobao.org/amqplib/download/amqplib-0.5.2.tgz", + "integrity": "sha1-0tcxPH/6pNELzx5iUt5FkbbMe2M=", + "optional": true, + "requires": { + "bitsyntax": "0.0.4", + "bluebird": "3.5.1", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.1.14", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "optional": true + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "optional": true + }, + "ansicolors": { + "version": "0.2.1", + "resolved": "http://registry.npm.taobao.org/ansicolors/download/ansicolors-0.2.1.tgz", + "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "http://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "argparse": { + "version": "1.0.10", + "resolved": "http://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz", + "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "requires": { + "sprintf-js": "1.0.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + } + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asap": { + "version": "2.0.6", + "resolved": "http://registry.npm.taobao.org/asap/download/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "ascli": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/ascli/download/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "0.7.1", + "optjs": "3.2.2" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "ast-types": { + "version": "0.11.3", + "resolved": "http://registry.npm.taobao.org/ast-types/download/ast-types-0.11.3.tgz", + "integrity": "sha1-wgdX/nLucSeOoP89h+XCyjDZ7fg=", + "optional": true + }, + "async": { + "version": "1.5.2", + "resolved": "http://registry.npm.taobao.org/async/download/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sdk": { + "version": "2.211.0", + "resolved": "http://registry.npm.taobao.org/aws-sdk/download/aws-sdk-2.211.0.tgz", + "integrity": "sha1-kCt1Jedv+fpyzQOLc7ikfIxnGmI=", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.1.0", + "xml2js": "0.4.17", + "xmlbuilder": "4.2.1" + }, + "dependencies": { + "sax": { + "version": "1.2.1", + "resolved": "http://registry.npm.taobao.org/sax/download/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "xml2js": { + "version": "0.4.17", + "resolved": "http://registry.npm.taobao.org/xml2js/download/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "requires": { + "sax": "1.2.1", + "xmlbuilder": "4.2.1" + } + }, + "xmlbuilder": { + "version": "4.2.1", + "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "requires": { + "lodash": "4.17.5" + } + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/aws4/download/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "axios": { + "version": "0.15.3", + "resolved": "http://registry.npm.taobao.org/axios/download/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "optional": true, + "requires": { + "follow-redirects": "1.0.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "http://registry.npm.taobao.org/babel-types/download/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "http://registry.npm.taobao.org/babylon/download/babylon-6.18.0.tgz", + "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.2.3", + "resolved": "http://registry.npm.taobao.org/base64-js/download/base64-js-1.2.3.tgz", + "integrity": "sha1-+xNmgjPZYUz1+0vOlam6QJbN+AE=" + }, + "base64url": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/base64url/download/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" + }, + "basic-auth": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/basic-auth/download/basic-auth-2.0.0.tgz", + "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "http://registry.npm.taobao.org/bcryptjs/download/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "http://registry.npm.taobao.org/bitsyntax/download/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "optional": true, + "requires": { + "buffer-more-ints": "0.0.2" + } + }, + "bl": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/bl/download/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "optional": true, + "requires": { + "readable-stream": "2.0.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "optional": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "optional": true + } + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "http://registry.npm.taobao.org/bluebird/download/bluebird-3.5.1.tgz", + "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=" + }, + "body-parser": { + "version": "1.18.2", + "resolved": "http://registry.npm.taobao.org/body-parser/download/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "http://registry.npm.taobao.org/boom/download/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "http://registry.npm.taobao.org/browser-stdout/download/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "buffer": { + "version": "4.9.1", + "resolved": "http://registry.npm.taobao.org/buffer/download/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "1.2.3", + "ieee754": "1.1.10", + "isarray": "1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "http://registry.npm.taobao.org/buffer-crc32/download/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/buffer-equal-constant-time/download/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "http://registry.npm.taobao.org/buffer-more-ints/download/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=" + }, + "bufferview": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/bufferview/download/bufferview-1.0.1.tgz", + "integrity": "sha1-ev10pF+Tf6QiodM4wIu/3HbNcl0=" + }, + "buildmail": { + "version": "4.0.1", + "resolved": "http://registry.npm.taobao.org/buildmail/download/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "optional": true + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/builtin-modules/download/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytebuffer": { + "version": "4.1.0", + "resolved": "http://registry.npm.taobao.org/bytebuffer/download/bytebuffer-4.1.0.tgz", + "integrity": "sha1-TFgmngUqseSx9/82T9+zzogpBqo=", + "requires": { + "bufferview": "1.0.1", + "long": "2.4.0" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelize": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/camelize/download/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "cardinal": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/cardinal/download/cardinal-1.0.0.tgz", + "integrity": "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=", + "requires": { + "ansicolors": "0.2.1", + "redeyed": "1.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "http://registry.npm.taobao.org/center-align/download/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "optional": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "character-parser": { + "version": "2.2.0", + "resolved": "http://registry.npm.taobao.org/character-parser/download/character-parser-2.2.0.tgz", + "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", + "requires": { + "is-regex": "1.0.4" + } + }, + "circular-json": { + "version": "0.5.1", + "resolved": "http://registry.npm.taobao.org/circular-json/download/circular-json-0.5.1.tgz", + "integrity": "sha1-uJQqCeU1hj3CGwRBepGXHh2c2R8=" + }, + "clean-css": { + "version": "3.4.28", + "resolved": "http://registry.npm.taobao.org/clean-css/download/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "requires": { + "commander": "2.8.1", + "source-map": "0.4.4" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "cls-bluebird": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/cls-bluebird/download/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "requires": { + "is-bluebird": "1.0.2", + "shimmer": "1.2.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "http://registry.npm.taobao.org/co/download/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "http://registry.npm.taobao.org/coffee-script/download/coffee-script-1.12.7.tgz", + "integrity": "sha1-wF2uDLeVkdBbMHCoQzqYyaiczFM=" + }, + "colour": { + "version": "0.7.1", + "resolved": "http://registry.npm.taobao.org/colour/download/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.15.0", + "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.15.0.tgz", + "integrity": "sha1-rSojocOwNuOSRpuAEs7GsztMEyI=", + "optional": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "http://registry.npm.taobao.org/component-emitter/download/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "http://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" + } + }, + "constantinople": { + "version": "3.1.2", + "resolved": "http://registry.npm.taobao.org/constantinople/download/constantinople-3.1.2.tgz", + "integrity": "sha1-1F7XJPV9PRBQABen06iJwTga5kc=", + "requires": { + "@types/babel-types": "7.0.1", + "@types/babylon": "6.16.2", + "babel-types": "6.26.0", + "babylon": "6.18.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "http://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-security-policy-builder": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/content-security-policy-builder/download/content-security-policy-builder-2.0.0.tgz", + "integrity": "sha1-h0mh1UL8voIjcoHqn3Fs5os5TdI=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "http://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "http://registry.npm.taobao.org/cookie/download/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-parser": { + "version": "1.4.3", + "resolved": "http://registry.npm.taobao.org/cookie-parser/download/cookie-parser-1.4.3.tgz", + "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "http://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/cookiejar/download/cookiejar-2.1.1.tgz", + "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc32": { + "version": "0.2.2", + "resolved": "http://registry.npm.taobao.org/crc32/download/crc32-0.2.2.tgz", + "integrity": "sha1-etIg1v/c0Rn5/BJ6d3LKzqOQpLo=" + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.2", + "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.2.tgz", + "integrity": "sha1-RSNLLm4vKzPaElYkxGZJKaAiTD8=", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "http://registry.npm.taobao.org/boom/download/boom-5.2.0.tgz", + "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "csextends": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/csextends/download/csextends-1.1.1.tgz", + "integrity": "sha1-zFPBNJ+vfwrmzfb2xKTZFW08TsE=", + "requires": { + "coffee-script": "1.12.7" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "dasherize": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/dasherize/download/dasherize-2.0.0.tgz", + "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/data-uri-to-buffer/download/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", + "optional": true + }, + "date-format": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/date-format/download/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=" + }, + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "http://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "default-user-agent": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/default-user-agent/download/default-user-agent-1.0.0.tgz", + "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", + "requires": { + "os-name": "1.0.3" + } + }, + "degenerator": { + "version": "1.0.4", + "resolved": "http://registry.npm.taobao.org/degenerator/download/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "optional": true, + "requires": { + "ast-types": "0.11.3", + "escodegen": "1.9.1", + "esprima": "3.1.3" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "denque": { + "version": "1.2.3", + "resolved": "http://registry.npm.taobao.org/denque/download/denque-1.2.3.tgz", + "integrity": "sha1-mMUMjdjN+uMYzFhZzI7j2g+bDMI=" + }, + "depd": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "http://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "diff": { + "version": "3.2.0", + "resolved": "http://registry.npm.taobao.org/diff/download/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "digest-header": { + "version": "0.0.1", + "resolved": "http://registry.npm.taobao.org/digest-header/download/digest-header-0.0.1.tgz", + "integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=", + "requires": { + "utility": "0.1.11" + } + }, + "dns-prefetch-control": { + "version": "0.1.0", + "resolved": "http://registry.npm.taobao.org/dns-prefetch-control/download/dns-prefetch-control-0.1.0.tgz", + "integrity": "sha1-YN20V3dOF48flBXwyrsOhbCzALI=" + }, + "doctypes": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/doctypes/download/doctypes-1.1.0.tgz", + "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/dont-sniff-mimetype/download/dont-sniff-mimetype-1.0.0.tgz", + "integrity": "sha1-WTKJDcn04vGeXrAqIAJuXl78j1g=" + }, + "dottie": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/dottie/download/dottie-2.0.0.tgz", + "integrity": "sha1-2hkZgci41xPKARXViYzzl8Lw3dA=" + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "http://registry.npm.taobao.org/double-ended-queue/download/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, + "eachr": { + "version": "2.0.4", + "resolved": "http://registry.npm.taobao.org/eachr/download/eachr-2.0.4.tgz", + "integrity": "sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8=", + "requires": { + "typechecker": "2.1.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "http://registry.npm.taobao.org/ecdsa-sig-formatter/download/ecdsa-sig-formatter-1.0.9.tgz", + "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "requires": { + "base64url": "2.0.0", + "safe-buffer": "5.1.1" + } + }, + "editions": { + "version": "1.3.4", + "resolved": "http://registry.npm.taobao.org/editions/download/editions-1.3.4.tgz", + "integrity": "sha1-NmLLWSNHwxaOuOSYoP9zJx1n9Qs=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "entities": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/entities/download/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + }, + "error-ex": { + "version": "1.3.1", + "resolved": "http://registry.npm.taobao.org/error-ex/download/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "http://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.9.1", + "resolved": "http://registry.npm.taobao.org/escodegen/download/escodegen-1.9.1.tgz", + "integrity": "sha1-264X75bI5L7bE1b0UE+kzC98t+I=", + "optional": true, + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "http://registry.npm.taobao.org/esprima/download/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "http://registry.npm.taobao.org/estraverse/download/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "optional": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "http://registry.npm.taobao.org/esutils/download/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "http://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "events": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/events/download/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "0.7.0", + "resolved": "http://registry.npm.taobao.org/execa/download/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expect-ct": { + "version": "0.1.0", + "resolved": "http://registry.npm.taobao.org/expect-ct/download/expect-ct-0.1.0.tgz", + "integrity": "sha1-UnNWeN4YUwiQ2Ne5XwrGNkCVgJQ=" + }, + "express": { + "version": "4.16.3", + "resolved": "http://registry.npm.taobao.org/express/download/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "setprototypeof": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=" + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "http://registry.npm.taobao.org/extend/download/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extendr": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/extendr/download/extendr-2.1.0.tgz", + "integrity": "sha1-MBqgu+pWX00tyPVw8qImEahSe1Y=", + "requires": { + "typechecker": "2.0.8" + }, + "dependencies": { + "typechecker": { + "version": "2.0.8", + "resolved": "http://registry.npm.taobao.org/typechecker/download/typechecker-2.0.8.tgz", + "integrity": "sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4=" + } + } + }, + "extract-opts": { + "version": "2.2.0", + "resolved": "http://registry.npm.taobao.org/extract-opts/download/extract-opts-2.2.0.tgz", + "integrity": "sha1-H6KOunNSxttID4hc63GkaBC+bX0=", + "requires": { + "typechecker": "2.0.8" + }, + "dependencies": { + "typechecker": { + "version": "2.0.8", + "resolved": "http://registry.npm.taobao.org/typechecker/download/typechecker-2.0.8.tgz", + "integrity": "sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4=" + } + } + }, + "extract-zip": { + "version": "1.6.6", + "resolved": "http://registry.npm.taobao.org/extract-zip/download/extract-zip-1.6.6.tgz", + "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "requires": { + "concat-stream": "1.6.0", + "debug": "2.6.9", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "http://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "requires": { + "pend": "1.2.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz", + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", + "optional": true + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.1.tgz", + "integrity": "sha1-7r9O2EAHnIP0JJA4ydcDAIMBsQU=", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "optional": true, + "requires": { + "debug": "2.6.9" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "formidable": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/formidable/download/formidable-1.2.0.tgz", + "integrity": "sha1-zikb/sZ8F24oL4keziw33gyDroQ=" + }, + "formstream": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/formstream/download/formstream-1.1.0.tgz", + "integrity": "sha1-UfOXDyYTbrCtRDBN5M67UCB7RHk=", + "requires": { + "destroy": "1.0.4", + "mime": "1.4.1", + "pause-stream": "0.0.11" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "http://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "frameguard": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/frameguard/download/frameguard-3.0.0.tgz", + "integrity": "sha1-e8rUae57lukdEs6zlZx4I1qScuk=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "http://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "http://registry.npm.taobao.org/fs-extra/download/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "3.0.1", + "universalify": "0.1.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "ftp": { + "version": "0.3.10", + "resolved": "http://registry.npm.taobao.org/ftp/download/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "optional": true, + "requires": { + "readable-stream": "1.1.14", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + }, + "generate-function": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/generate-function/download/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/generate-object-property/download/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "optional": true, + "requires": { + "is-property": "1.0.2" + } + }, + "generic-pool": { + "version": "3.4.2", + "resolved": "http://registry.npm.taobao.org/generic-pool/download/generic-pool-3.4.2.tgz", + "integrity": "sha1-kv9xllINZwg5pnMICSoSqt8valk=" + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/get-caller-file/download/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-uri": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/get-uri/download/get-uri-2.0.1.tgz", + "integrity": "sha1-29ysrNjGCKODFoaTaBF2l6FjHFk=", + "optional": true, + "requires": { + "data-uri-to-buffer": "1.2.0", + "debug": "2.6.9", + "extend": "3.0.1", + "file-uri-to-path": "1.0.0", + "ftp": "0.3.10", + "readable-stream": "2.3.5" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "http://registry.npm.taobao.org/glob/download/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/graceful-readlink/download/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.9.2", + "resolved": "http://registry.npm.taobao.org/growl/download/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "resolved": "http://registry.npm.taobao.org/handlebars/download/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/has/download/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "optional": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "hawk": { + "version": "6.0.2", + "resolved": "http://registry.npm.taobao.org/hawk/download/hawk-6.0.2.tgz", + "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/he/download/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "helmet": { + "version": "3.12.0", + "resolved": "http://registry.npm.taobao.org/helmet/download/helmet-3.12.0.tgz", + "integrity": "sha1-IJjjXPTlHGTC8dOGcLfTgqN32Sw=", + "requires": { + "dns-prefetch-control": "0.1.0", + "dont-sniff-mimetype": "1.0.0", + "expect-ct": "0.1.0", + "frameguard": "3.0.0", + "helmet-csp": "2.7.0", + "hide-powered-by": "1.0.0", + "hpkp": "2.0.0", + "hsts": "2.1.0", + "ienoopen": "1.0.0", + "nocache": "2.0.0", + "referrer-policy": "1.1.0", + "x-xss-protection": "1.1.0" + } + }, + "helmet-csp": { + "version": "2.7.0", + "resolved": "http://registry.npm.taobao.org/helmet-csp/download/helmet-csp-2.7.0.tgz", + "integrity": "sha1-eTQJRhfR/re7LcQ7t9nogw93RxY=", + "requires": { + "camelize": "1.0.0", + "content-security-policy-builder": "2.0.0", + "dasherize": "2.0.0", + "lodash.reduce": "4.6.0", + "platform": "1.3.5" + } + }, + "hide-powered-by": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/hide-powered-by/download/hide-powered-by-1.0.0.tgz", + "integrity": "sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=" + }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/hipchat-notifier/download/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "optional": true, + "requires": { + "lodash": "4.17.5", + "request": "2.85.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-4.2.1.tgz", + "integrity": "sha1-ljRQKqEsRF3Vp8VzS1cruHOKrLs=" + }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "http://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.6.0.tgz", + "integrity": "sha1-IyNbKasjDFdqqw1PE/wEawsDgiI=" + }, + "hpkp": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/hpkp/download/hpkp-2.0.0.tgz", + "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=" + }, + "hsts": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/hsts/download/hsts-2.1.0.tgz", + "integrity": "sha1-y9bJGKI4X+4d1WgL+ys6GUwBIcw=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "http://registry.npm.taobao.org/http-errors/download/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + } + } + }, + "http-proxy-agent": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/http-proxy-agent/download/http-proxy-agent-1.0.0.tgz", + "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "http://registry.npm.taobao.org/httpntlm/download/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "requires": { + "httpreq": "0.4.24", + "underscore": "1.7.0" + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "http://registry.npm.taobao.org/httpreq/download/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=" + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/https-proxy-agent/download/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "http://registry.npm.taobao.org/humanize-ms/download/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "2.0.0" + } + }, + "i18n": { + "version": "0.8.3", + "resolved": "http://registry.npm.taobao.org/i18n/download/i18n-0.8.3.tgz", + "integrity": "sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4=", + "requires": { + "debug": "2.6.9", + "make-plural": "3.0.6", + "math-interval-parser": "1.1.0", + "messageformat": "0.3.1", + "mustache": "2.3.0", + "sprintf-js": "1.1.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + }, + "ieee754": { + "version": "1.1.10", + "resolved": "http://registry.npm.taobao.org/ieee754/download/ieee754-1.1.10.tgz", + "integrity": "sha1-cZpvewJoMeZL24OLDeG7ACm79xY=" + }, + "ienoopen": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/ienoopen/download/ienoopen-1.0.0.tgz", + "integrity": "sha1-NGpCj0dKrI9QzzeE6i0PFvYr2ms=" + }, + "ignorefs": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/ignorefs/download/ignorefs-1.2.0.tgz", + "integrity": "sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y=", + "requires": { + "editions": "1.3.4", + "ignorepatterns": "1.1.0" + } + }, + "ignorepatterns": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/ignorepatterns/download/ignorepatterns-1.1.0.tgz", + "integrity": "sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4=" + }, + "inflection": { + "version": "1.10.0", + "resolved": "http://registry.npm.taobao.org/inflection/download/inflection-1.10.0.tgz", + "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/invert-kv/download/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.0.1.tgz", + "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", + "optional": true + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "http://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-bluebird": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/is-bluebird/download/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/is-builtin-module/download/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-expression": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/is-expression/download/is-expression-3.0.0.tgz", + "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", + "requires": { + "acorn": "4.0.13", + "object-assign": "4.1.1" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" + } + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/is-my-ip-valid/download/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha1-ezUbjo7dTTmV1NBmaA5mTZRpaCQ=", + "optional": true + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "http://registry.npm.taobao.org/is-my-json-valid/download/is-my-json-valid-2.17.2.tgz", + "integrity": "sha1-ayEDoojpTvPeXPFdKd2F/Et41lw=", + "optional": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/is-promise/download/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/is-property/download/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "optional": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "http://registry.npm.taobao.org/is-regex/download/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul": { + "version": "0.4.5", + "resolved": "http://registry.npm.taobao.org/istanbul/download/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.11.0", + "mkdirp": "0.5.0", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "http://registry.npm.taobao.org/abbrev/download/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "http://registry.npm.taobao.org/escodegen/download/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "http://registry.npm.taobao.org/esprima/download/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "http://registry.npm.taobao.org/estraverse/download/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "http://registry.npm.taobao.org/resolve/download/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "jmespath": { + "version": "0.15.0", + "resolved": "http://registry.npm.taobao.org/jmespath/download/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "js-stringify": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/js-stringify/download/js-stringify-1.0.2.tgz", + "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" + }, + "js-yaml": { + "version": "3.11.0", + "resolved": "http://registry.npm.taobao.org/js-yaml/download/js-yaml-3.11.0.tgz", + "integrity": "sha1-WXwai9VxUvJtYizkEXhRpR9euu8=", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "http://registry.npm.taobao.org/esprima/download/esprima-4.0.0.tgz", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json3": { + "version": "3.3.2", + "resolved": "http://registry.npm.taobao.org/json3/download/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "http://registry.npm.taobao.org/jsonpointer/download/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "optional": true + }, + "jsonwebtoken": { + "version": "8.2.0", + "resolved": "http://registry.npm.taobao.org/jsonwebtoken/download/jsonwebtoken-8.2.0.tgz", + "integrity": "sha1-aQ7DqefpXiiENHzj6eudOJqlmLM=", + "requires": { + "jws": "3.1.4", + "lodash.includes": "4.3.0", + "lodash.isboolean": "3.0.3", + "lodash.isinteger": "4.0.4", + "lodash.isnumber": "3.0.3", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.once": "4.1.1", + "ms": "2.1.1", + "xtend": "4.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz", + "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstransformer": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/jstransformer/download/jstransformer-1.0.0.tgz", + "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", + "requires": { + "is-promise": "2.1.0", + "promise": "7.3.1" + } + }, + "jwa": { + "version": "1.1.5", + "resolved": "http://registry.npm.taobao.org/jwa/download/jwa-1.1.5.tgz", + "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "requires": { + "base64url": "2.0.0", + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.9", + "safe-buffer": "5.1.1" + } + }, + "jws": { + "version": "3.1.4", + "resolved": "http://registry.npm.taobao.org/jws/download/jws-3.1.4.tgz", + "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "requires": { + "base64url": "2.0.0", + "jwa": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "http://registry.npm.taobao.org/lazy-cache/download/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/lcid/download/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "http://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "http://registry.npm.taobao.org/libbase64/download/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=" + }, + "libmime": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/libmime/download/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/libqp/download/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" + }, + "linkify-it": { + "version": "2.0.3", + "resolved": "http://registry.npm.taobao.org/linkify-it/download/linkify-it-2.0.3.tgz", + "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", + "requires": { + "uc.micro": "1.0.5" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-4.17.5.tgz", + "integrity": "sha1-maktZcAnLevoyWtgV7yPv6O+1RE=" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "http://registry.npm.taobao.org/lodash._baseassign/download/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "http://registry.npm.taobao.org/lodash._basecopy/download/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "http://registry.npm.taobao.org/lodash._basecreate/download/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "http://registry.npm.taobao.org/lodash._getnative/download/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "http://registry.npm.taobao.org/lodash._isiterateecall/download/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "http://registry.npm.taobao.org/lodash.create/download/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "http://registry.npm.taobao.org/lodash.includes/download/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/lodash.isarguments/download/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "http://registry.npm.taobao.org/lodash.isarray/download/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "http://registry.npm.taobao.org/lodash.isboolean/download/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "http://registry.npm.taobao.org/lodash.isinteger/download/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "http://registry.npm.taobao.org/lodash.isnumber/download/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "http://registry.npm.taobao.org/lodash.isplainobject/download/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "http://registry.npm.taobao.org/lodash.isstring/download/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "http://registry.npm.taobao.org/lodash.keys/download/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "http://registry.npm.taobao.org/lodash.once/download/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "http://registry.npm.taobao.org/lodash.reduce/download/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "log4js": { + "version": "2.5.3", + "resolved": "http://registry.npm.taobao.org/log4js/download/log4js-2.5.3.tgz", + "integrity": "sha1-OLt73l6cHBgb116LwSjFzQQJyvE=", + "requires": { + "amqplib": "0.5.2", + "axios": "0.15.3", + "circular-json": "0.5.1", + "date-format": "1.2.0", + "debug": "3.1.0", + "hipchat-notifier": "1.1.0", + "loggly": "1.1.1", + "mailgun-js": "0.7.15", + "nodemailer": "2.7.2", + "redis": "2.8.0", + "semver": "5.5.0", + "slack-node": "0.2.0", + "streamroller": "0.7.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "requires": { + "ms": "2.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "optional": true + }, + "nodemailer": { + "version": "2.7.2", + "resolved": "http://registry.npm.taobao.org/nodemailer/download/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + } + }, + "socks": { + "version": "1.1.9", + "resolved": "http://registry.npm.taobao.org/socks/download/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "optional": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + } + } + }, + "loggly": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/loggly/download/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "optional": true, + "requires": { + "json-stringify-safe": "5.0.1", + "request": "2.75.0", + "timespan": "2.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "0.2.0", + "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "optional": true + }, + "boom": { + "version": "2.10.1", + "resolved": "http://registry.npm.taobao.org/boom/download/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "optional": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "form-data": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "optional": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.15.0", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "http://registry.npm.taobao.org/hawk/download/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "http://registry.npm.taobao.org/node-uuid/download/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "http://registry.npm.taobao.org/qs/download/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "optional": true + }, + "request": { + "version": "2.75.0", + "resolved": "http://registry.npm.taobao.org/request/download/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "bl": "1.1.2", + "caseless": "0.11.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.0.0", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "6.2.3", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.4.3" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "optional": true + } + } + }, + "long": { + "version": "2.4.0", + "resolved": "http://registry.npm.taobao.org/long/download/long-2.4.0.tgz", + "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" + }, + "longest": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lru-cache": { + "version": "2.6.5", + "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-2.6.5.tgz", + "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", + "optional": true + }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "http://registry.npm.taobao.org/mailcomposer/download/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } + }, + "mailgun-js": { + "version": "0.7.15", + "resolved": "http://registry.npm.taobao.org/mailgun-js/download/mailgun-js-0.7.15.tgz", + "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", + "optional": true, + "requires": { + "async": "2.1.5", + "debug": "2.2.0", + "form-data": "2.1.4", + "inflection": "1.10.0", + "is-stream": "1.1.0", + "path-proxy": "1.0.0", + "proxy-agent": "2.0.0", + "q": "1.4.1", + "tsscmp": "1.0.5" + }, + "dependencies": { + "async": { + "version": "2.1.5", + "resolved": "http://registry.npm.taobao.org/async/download/async-2.1.5.tgz", + "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", + "optional": true, + "requires": { + "lodash": "4.17.5" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "optional": true, + "requires": { + "ms": "0.7.1" + } + }, + "form-data": { + "version": "2.1.4", + "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "optional": true + } + } + }, + "make-plural": { + "version": "3.0.6", + "resolved": "http://registry.npm.taobao.org/make-plural/download/make-plural-3.0.6.tgz", + "integrity": "sha1-IDOgO6wpC487uRJY9lud9+iwHKc=", + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, + "markdown-it": { + "version": "8.4.1", + "resolved": "http://registry.npm.taobao.org/markdown-it/download/markdown-it-8.4.1.tgz", + "integrity": "sha1-IG/lmw5OG3inxzJQr5s0pK0Kr0Q=", + "requires": { + "argparse": "1.0.10", + "entities": "1.1.1", + "linkify-it": "2.0.3", + "mdurl": "1.0.1", + "uc.micro": "1.0.5" + } + }, + "math-interval-parser": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/math-interval-parser/download/math-interval-parser-1.1.0.tgz", + "integrity": "sha1-2+2lsGsySZc8bfYXD94jhvCv2JM=", + "requires": { + "xregexp": "2.0.0" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/mdurl/download/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "http://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/mem/download/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "1.2.0" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "messageformat": { + "version": "0.3.1", + "resolved": "http://registry.npm.taobao.org/messageformat/download/messageformat-0.3.1.tgz", + "integrity": "sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI=", + "requires": { + "async": "1.5.2", + "glob": "6.0.4", + "make-plural": "3.0.6", + "nopt": "3.0.6", + "watchr": "2.4.13" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "http://registry.npm.taobao.org/glob/download/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.4.1.tgz", + "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "http://registry.npm.taobao.org/mime-db/download/mime-db-1.33.0.tgz", + "integrity": "sha1-o0kgUKXLm2NFBUHjnZeI0icng9s=" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.18.tgz", + "integrity": "sha1-bzI/YKg9ERRvgx/xH9ZuL+VQO7g=", + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz", + "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "http://registry.npm.taobao.org/mocha/download/mocha-3.5.3.tgz", + "integrity": "sha1-HgSA/jbS2lhY0etqzDhBiybqog0=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "http://registry.npm.taobao.org/glob/download/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "moment": { + "version": "2.21.0", + "resolved": "http://registry.npm.taobao.org/moment/download/moment-2.21.0.tgz", + "integrity": "sha1-KhFLUdKm7J5tg8+AP4OKh42KAjo=" + }, + "moment-timezone": { + "version": "0.5.14", + "resolved": "http://registry.npm.taobao.org/moment-timezone/download/moment-timezone-0.5.14.tgz", + "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", + "requires": { + "moment": "2.21.0" + } + }, + "morgan": { + "version": "1.9.0", + "resolved": "http://registry.npm.taobao.org/morgan/download/morgan-1.9.0.tgz", + "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", + "requires": { + "basic-auth": "2.0.0", + "debug": "2.6.9", + "depd": "1.1.2", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mustache": { + "version": "2.3.0", + "resolved": "http://registry.npm.taobao.org/mustache/download/mustache-2.3.0.tgz", + "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=" + }, + "mysql2": { + "version": "1.5.2", + "resolved": "http://registry.npm.taobao.org/mysql2/download/mysql2-1.5.2.tgz", + "integrity": "sha1-5OBzg5uxCXJmmyQOx3Bh1/9Vz1k=", + "requires": { + "cardinal": "1.0.0", + "denque": "1.2.3", + "generate-function": "2.0.0", + "iconv-lite": "0.4.19", + "long": "4.0.0", + "lru-cache": "4.1.2", + "named-placeholders": "1.1.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.2", + "safe-buffer": "5.1.1", + "seq-queue": "0.0.5", + "sqlstring": "2.3.1" + }, + "dependencies": { + "long": { + "version": "4.0.0", + "resolved": "http://registry.npm.taobao.org/long/download/long-4.0.0.tgz", + "integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=" + }, + "lru-cache": { + "version": "4.1.2", + "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.2.tgz", + "integrity": "sha1-RSNLLm4vKzPaElYkxGZJKaAiTD8=", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "readable-stream": { + "version": "2.3.2", + "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.2.tgz", + "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "named-placeholders": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/named-placeholders/download/named-placeholders-1.1.1.tgz", + "integrity": "sha1-O3oNJiA910s6nfTJz7gnsvuQfmQ=", + "requires": { + "lru-cache": "2.5.0" + }, + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-2.5.0.tgz", + "integrity": "sha1-2COIrpyWC+y+oMc7uet5tsbOmus=" + } + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "netmask": { + "version": "1.0.6", + "resolved": "http://registry.npm.taobao.org/netmask/download/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "optional": true + }, + "nocache": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/nocache/download/nocache-2.0.0.tgz", + "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" + }, + "node_memcached": { + "version": "1.1.3", + "resolved": "http://registry.npm.taobao.org/node_memcached/download/node_memcached-1.1.3.tgz", + "integrity": "sha1-icFSr4itKIF/ANiRyZBFHV1xLqg=", + "requires": { + "debug": "2.6.9" + } + }, + "nodemailer": { + "version": "4.6.3", + "resolved": "http://registry.npm.taobao.org/nodemailer/download/nodemailer-4.6.3.tgz", + "integrity": "sha1-w7fpf7cvRtSkdcQGoV7SOkXbzdw=" + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "http://registry.npm.taobao.org/nodemailer-direct-transport/download/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/nodemailer-fetch/download/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=" + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/nodemailer-shared/download/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "http://registry.npm.taobao.org/nodemailer-smtp-pool/download/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "http://registry.npm.taobao.org/nodemailer-smtp-transport/download/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "http://registry.npm.taobao.org/nodemailer-wellknown/download/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "http://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "http://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/on-headers/download/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/optimist/download/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "http://registry.npm.taobao.org/optjs/download/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-name": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "requires": { + "osx-release": "1.1.0", + "win-release": "1.1.1" + } + }, + "osx-release": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-1.2.0.tgz", + "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pac-proxy-agent": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/pac-proxy-agent/download/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha1-NKOF399h0vDsrOCIWMdF0+eR/U0=", + "optional": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "get-uri": "2.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "pac-resolver": "2.0.0", + "raw-body": "2.3.2", + "socks-proxy-agent": "2.1.1" + } + }, + "pac-resolver": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/pac-resolver/download/pac-resolver-2.0.0.tgz", + "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", + "optional": true, + "requires": { + "co": "3.0.6", + "degenerator": "1.0.4", + "ip": "1.0.1", + "netmask": "1.0.6", + "thunkify": "2.1.2" + }, + "dependencies": { + "co": { + "version": "3.0.6", + "resolved": "http://registry.npm.taobao.org/co/download/co-3.0.6.tgz", + "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", + "optional": true + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "http://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "http://registry.npm.taobao.org/parseurl/download/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/path-proxy/download/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "optional": true, + "requires": { + "inflection": "1.3.8" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "http://registry.npm.taobao.org/inflection/download/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "optional": true + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "2.3.0" + } + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "2.3.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "optional": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "optional": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "platform": { + "version": "1.3.5", + "resolved": "http://registry.npm.taobao.org/platform/download/platform-1.3.5.tgz", + "integrity": "sha1-+2lYxpbgfikY0u7aDwvJRI1zNEQ=" + }, + "pomelo-protobuf": { + "version": "0.4.0", + "resolved": "http://registry.npm.taobao.org/pomelo-protobuf/download/pomelo-protobuf-0.4.0.tgz", + "integrity": "sha1-5F6aCkRusYZn4MbhPutT1Hrdvag=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz", + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + }, + "promise": { + "version": "7.3.1", + "resolved": "http://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "requires": { + "asap": "2.0.6" + } + }, + "protobufjs": { + "version": "4.1.3", + "resolved": "http://registry.npm.taobao.org/protobufjs/download/protobufjs-4.1.3.tgz", + "integrity": "sha1-jjbRsCJsu2jWR+S0TCoUTzfyd54=", + "requires": { + "ascli": "1.0.1", + "bytebuffer": "4.1.0", + "glob": "5.0.15", + "yargs": "3.32.0" + }, + "dependencies": { + "yargs": { + "version": "3.32.0", + "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.3.tgz", + "integrity": "sha1-NV8mJQWmIWRrMTCnKOtkfiIFU0E=", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "proxy-agent": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/proxy-agent/download/proxy-agent-2.0.0.tgz", + "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", + "optional": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "lru-cache": "2.6.5", + "pac-proxy-agent": "1.1.0", + "socks-proxy-agent": "2.1.1" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pug": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/pug/download/pug-2.0.1.tgz", + "integrity": "sha1-J8FRYStT1ymr6OgoWqxryJNFtdA=", + "requires": { + "pug-code-gen": "2.0.1", + "pug-filters": "3.0.1", + "pug-lexer": "4.0.0", + "pug-linker": "3.0.5", + "pug-load": "2.0.11", + "pug-parser": "5.0.0", + "pug-runtime": "2.0.4", + "pug-strip-comments": "1.0.3" + } + }, + "pug-attrs": { + "version": "2.0.3", + "resolved": "http://registry.npm.taobao.org/pug-attrs/download/pug-attrs-2.0.3.tgz", + "integrity": "sha1-owlflw5kFR972tlX7vVftdeQXRU=", + "requires": { + "constantinople": "3.1.2", + "js-stringify": "1.0.2", + "pug-runtime": "2.0.4" + } + }, + "pug-code-gen": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/pug-code-gen/download/pug-code-gen-2.0.1.tgz", + "integrity": "sha1-CVHsgyJddNjPxHan+Zolm199BQw=", + "requires": { + "constantinople": "3.1.2", + "doctypes": "1.1.0", + "js-stringify": "1.0.2", + "pug-attrs": "2.0.3", + "pug-error": "1.3.2", + "pug-runtime": "2.0.4", + "void-elements": "2.0.1", + "with": "5.1.1" + } + }, + "pug-error": { + "version": "1.3.2", + "resolved": "http://registry.npm.taobao.org/pug-error/download/pug-error-1.3.2.tgz", + "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY=" + }, + "pug-filters": { + "version": "3.0.1", + "resolved": "http://registry.npm.taobao.org/pug-filters/download/pug-filters-3.0.1.tgz", + "integrity": "sha1-Fj73O/ux8VRNAysrQPRRMOtS3Ms=", + "requires": { + "clean-css": "3.4.28", + "constantinople": "3.1.2", + "jstransformer": "1.0.0", + "pug-error": "1.3.2", + "pug-walk": "1.1.7", + "resolve": "1.5.0", + "uglify-js": "2.8.29" + } + }, + "pug-lexer": { + "version": "4.0.0", + "resolved": "http://registry.npm.taobao.org/pug-lexer/download/pug-lexer-4.0.0.tgz", + "integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=", + "requires": { + "character-parser": "2.2.0", + "is-expression": "3.0.0", + "pug-error": "1.3.2" + } + }, + "pug-linker": { + "version": "3.0.5", + "resolved": "http://registry.npm.taobao.org/pug-linker/download/pug-linker-3.0.5.tgz", + "integrity": "sha1-npp65ABWgtAn3uuWsAD4juuDoC8=", + "requires": { + "pug-error": "1.3.2", + "pug-walk": "1.1.7" + } + }, + "pug-load": { + "version": "2.0.11", + "resolved": "http://registry.npm.taobao.org/pug-load/download/pug-load-2.0.11.tgz", + "integrity": "sha1-5kjlftET/iwfRdV4WOorrWvAFSc=", + "requires": { + "object-assign": "4.1.1", + "pug-walk": "1.1.7" + } + }, + "pug-parser": { + "version": "5.0.0", + "resolved": "http://registry.npm.taobao.org/pug-parser/download/pug-parser-5.0.0.tgz", + "integrity": "sha1-45Stmz/KkxI5QK/4hcBuRKt+aOQ=", + "requires": { + "pug-error": "1.3.2", + "token-stream": "0.0.1" + } + }, + "pug-runtime": { + "version": "2.0.4", + "resolved": "http://registry.npm.taobao.org/pug-runtime/download/pug-runtime-2.0.4.tgz", + "integrity": "sha1-4XjhvaaKsujArPybztLFT9iM61g=" + }, + "pug-strip-comments": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/pug-strip-comments/download/pug-strip-comments-1.0.3.tgz", + "integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=", + "requires": { + "pug-error": "1.3.2" + } + }, + "pug-walk": { + "version": "1.1.7", + "resolved": "http://registry.npm.taobao.org/pug-walk/download/pug-walk-1.1.7.tgz", + "integrity": "sha1-wA1cUSi6xYBr7BXSt+fNq+QlMfM=" + }, + "punycode": { + "version": "1.3.2", + "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "q": { + "version": "1.4.1", + "resolved": "http://registry.npm.taobao.org/q/download/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "optional": true + }, + "qiniu": { + "version": "7.1.3", + "resolved": "http://registry.npm.taobao.org/qiniu/download/qiniu-7.1.3.tgz", + "integrity": "sha1-Zk2FDSvmndSMEldV2O1XTUh/kzI=", + "requires": { + "agentkeepalive": "3.3.0", + "crc32": "0.2.2", + "encodeurl": "1.0.2", + "formstream": "1.1.0", + "mime": "1.3.6", + "tunnel-agent": "0.6.0", + "urllib": "2.22.0" + }, + "dependencies": { + "mime": { + "version": "1.3.6", + "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.3.6.tgz", + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=" + } + } + }, + "qs": { + "version": "6.5.1", + "resolved": "http://registry.npm.taobao.org/qs/download/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" + }, + "querystring": { + "version": "0.2.0", + "resolved": "http://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "rand-token": { + "version": "0.3.0", + "resolved": "http://registry.npm.taobao.org/rand-token/download/rand-token-0.3.0.tgz", + "integrity": "sha1-MsDmciAIZ3ZqE2AaIc75isZ0eMc=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/range-parser/download/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "http://registry.npm.taobao.org/raw-body/download/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz", + "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "recursive-readdir": { + "version": "2.2.2", + "resolved": "http://registry.npm.taobao.org/recursive-readdir/download/recursive-readdir-2.2.2.tgz", + "integrity": "sha1-mUb7MnThYo3m42svZxSVO0hFCU8=", + "requires": { + "minimatch": "3.0.4" + } + }, + "redeyed": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/redeyed/download/redeyed-1.0.1.tgz", + "integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=", + "requires": { + "esprima": "3.0.0" + }, + "dependencies": { + "esprima": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/esprima/download/esprima-3.0.0.tgz", + "integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=" + } + } + }, + "redis": { + "version": "2.8.0", + "resolved": "http://registry.npm.taobao.org/redis/download/redis-2.8.0.tgz", + "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", + "requires": { + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.5", + "redis-parser": "2.6.0" + } + }, + "redis-commands": { + "version": "1.3.5", + "resolved": "http://registry.npm.taobao.org/redis-commands/download/redis-commands-1.3.5.tgz", + "integrity": "sha1-RJWIlBTx6IYmEYCxRC5ylWAtg6I=" + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "http://registry.npm.taobao.org/redis-parser/download/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" + }, + "referrer-policy": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/referrer-policy/download/referrer-policy-1.1.0.tgz", + "integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "http://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz", + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "http://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.85.0", + "resolved": "http://registry.npm.taobao.org/request/download/request-2.85.0.tgz", + "integrity": "sha1-WgNhWkfGFCCz65m326IE+DYD4fo=", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "requestretry": { + "version": "1.13.0", + "resolved": "http://registry.npm.taobao.org/requestretry/download/requestretry-1.13.0.tgz", + "integrity": "sha1-IT7BAG7rdQ6LjOVBdig9FajVXZQ=", + "optional": true, + "requires": { + "extend": "3.0.1", + "lodash": "4.17.5", + "request": "2.85.0", + "when": "3.7.8" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/require-main-filename/download/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.5.0", + "resolved": "http://registry.npm.taobao.org/resolve/download/resolve-1.5.0.tgz", + "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", + "requires": { + "path-parse": "1.0.5" + } + }, + "retry-as-promised": { + "version": "2.3.2", + "resolved": "http://registry.npm.taobao.org/retry-as-promised/download/retry-as-promised-2.3.2.tgz", + "integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=", + "requires": { + "bluebird": "3.5.1", + "debug": "2.6.9" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "http://registry.npm.taobao.org/right-align/download/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + }, + "safefs": { + "version": "3.2.2", + "resolved": "http://registry.npm.taobao.org/safefs/download/safefs-3.2.2.tgz", + "integrity": "sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "sax": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/sax/download/sax-0.6.1.tgz", + "integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=" + }, + "scandirectory": { + "version": "2.5.0", + "resolved": "http://registry.npm.taobao.org/scandirectory/download/scandirectory-2.5.0.tgz", + "integrity": "sha1-bOA/VKCQtmjjy+2/IO354xBZPnI=", + "requires": { + "ignorefs": "1.2.0", + "safefs": "3.2.2", + "taskgroup": "4.3.1" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "http://registry.npm.taobao.org/semver/download/semver-5.5.0.tgz", + "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=" + }, + "send": { + "version": "0.16.2", + "resolved": "http://registry.npm.taobao.org/send/download/send-0.16.2.tgz", + "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" + } + }, + "seq-queue": { + "version": "0.0.5", + "resolved": "http://registry.npm.taobao.org/seq-queue/download/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "sequelize": { + "version": "4.37.1", + "resolved": "http://registry.npm.taobao.org/sequelize/download/sequelize-4.37.1.tgz", + "integrity": "sha1-F6qX8mm3YhAVxz53qmshNPRdp9c=", + "requires": { + "bluebird": "3.5.1", + "cls-bluebird": "2.1.0", + "debug": "3.1.0", + "depd": "1.1.2", + "dottie": "2.0.0", + "generic-pool": "3.4.2", + "inflection": "1.12.0", + "lodash": "4.17.5", + "moment": "2.21.0", + "moment-timezone": "0.5.14", + "retry-as-promised": "2.3.2", + "semver": "5.5.0", + "terraformer-wkt-parser": "1.1.2", + "toposort-class": "1.0.1", + "uuid": "3.2.1", + "validator": "9.4.1", + "wkx": "0.4.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "requires": { + "ms": "2.0.0" + } + }, + "inflection": { + "version": "1.12.0", + "resolved": "http://registry.npm.taobao.org/inflection/download/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.2.1.tgz", + "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=" + } + } + }, + "serve-favicon": { + "version": "2.4.5", + "resolved": "http://registry.npm.taobao.org/serve-favicon/download/serve-favicon-2.4.5.tgz", + "integrity": "sha1-SdmkaGMVOpJAaRyJPSsOfYXW1DY=", + "requires": { + "etag": "1.8.1", + "fresh": "0.5.2", + "ms": "2.0.0", + "parseurl": "1.3.2", + "safe-buffer": "5.1.1" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "http://registry.npm.taobao.org/serve-static/download/serve-static-1.13.2.tgz", + "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shimmer": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/shimmer/download/shimmer-1.2.0.tgz", + "integrity": "sha1-+Wb3VVeJdj502IQRk2haXnhzZmU=" + }, + "should": { + "version": "11.2.1", + "resolved": "http://registry.npm.taobao.org/should/download/should-11.2.1.tgz", + "integrity": "sha1-kPVRRVUtAc/CAGZuToGKHJZw7aI=", + "dev": true, + "requires": { + "should-equal": "1.0.1", + "should-format": "3.0.3", + "should-type": "1.4.0", + "should-type-adaptors": "1.1.0", + "should-util": "1.0.0" + } + }, + "should-equal": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/should-equal/download/should-equal-1.0.1.tgz", + "integrity": "sha1-C26VFvJgGp+wuy3MNpr6HH4gCvc=", + "dev": true, + "requires": { + "should-type": "1.4.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "http://registry.npm.taobao.org/should-format/download/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "requires": { + "should-type": "1.4.0", + "should-type-adaptors": "1.1.0" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/should-type/download/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/should-type-adaptors/download/should-type-adaptors-1.1.0.tgz", + "integrity": "sha1-QB5/M7VTMDOUTVzYvytlAneS4no=", + "dev": true, + "requires": { + "should-type": "1.4.0", + "should-util": "1.0.0" + } + }, + "should-util": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/should-util/download/should-util-1.0.0.tgz", + "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slack-node": { + "version": "0.2.0", + "resolved": "http://registry.npm.taobao.org/slack-node/download/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "optional": true, + "requires": { + "requestretry": "1.13.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "http://registry.npm.taobao.org/smart-buffer/download/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=" + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "http://registry.npm.taobao.org/smtp-connection/download/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-2.1.0.tgz", + "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "requires": { + "hoek": "4.2.1" + } + }, + "socks": { + "version": "1.1.10", + "resolved": "http://registry.npm.taobao.org/socks/download/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + }, + "dependencies": { + "ip": { + "version": "1.1.5", + "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + } + } + }, + "socks-proxy-agent": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/socks-proxy-agent/download/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha1-huuwcZMlhjeHDhO3vZnybGY989M=", + "requires": { + "agent-base": "2.1.1", + "extend": "3.0.1", + "socks": "1.1.10" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "optional": true + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.0.0.tgz", + "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.1.0.tgz", + "integrity": "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k=" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.0.tgz", + "integrity": "sha1-enzShHDMbToc/m1miG9rxDDTrIc=" + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "http://registry.npm.taobao.org/sqlstring/download/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, + "sshpk": { + "version": "1.14.1", + "resolved": "http://registry.npm.taobao.org/sshpk/download/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/statuses/download/statuses-1.4.0.tgz", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" + }, + "streamroller": { + "version": "0.7.0", + "resolved": "http://registry.npm.taobao.org/streamroller/download/streamroller-0.7.0.tgz", + "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", + "requires": { + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.5" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "requires": { + "ms": "2.0.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "http://registry.npm.taobao.org/stringstream/download/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "superagent": { + "version": "3.8.2", + "resolved": "http://registry.npm.taobao.org/superagent/download/superagent-3.8.2.tgz", + "integrity": "sha1-5KEbnQR/fT7+s7vlNtnsACHRZAM=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.1", + "debug": "3.1.0", + "extend": "3.0.1", + "form-data": "2.3.2", + "formidable": "1.2.0", + "methods": "1.1.2", + "mime": "1.4.1", + "qs": "6.5.1", + "readable-stream": "2.3.5" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "supertest": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/supertest/download/supertest-3.0.0.tgz", + "integrity": "sha1-jUu2j9GDDuBwM7HFpamkAhyWUpY=", + "dev": true, + "requires": { + "methods": "1.1.2", + "superagent": "3.8.2" + } + }, + "supervisor": { + "version": "0.12.0", + "resolved": "http://registry.npm.taobao.org/supervisor/download/supervisor-0.12.0.tgz", + "integrity": "sha1-3n5jNwFbKRhRwQ81OMSn8EkX7ME=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "optional": true + }, + "taskgroup": { + "version": "4.3.1", + "resolved": "http://registry.npm.taobao.org/taskgroup/download/taskgroup-4.3.1.tgz", + "integrity": "sha1-feGT/r12gnPEV3MElwJNUSwnkVo=", + "requires": { + "ambi": "2.5.0", + "csextends": "1.1.1" + } + }, + "terraformer": { + "version": "1.0.8", + "resolved": "http://registry.npm.taobao.org/terraformer/download/terraformer-1.0.8.tgz", + "integrity": "sha1-UeCtiXRvzyFh3G9lqnDkI3fItZM=", + "requires": { + "@types/geojson": "1.0.6" + } + }, + "terraformer-wkt-parser": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/terraformer-wkt-parser/download/terraformer-wkt-parser-1.1.2.tgz", + "integrity": "sha1-M2oMj8gglKWv+DKI9prt7NNpvww=", + "requires": { + "terraformer": "1.0.8" + } + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "thunkify": { + "version": "2.1.2", + "resolved": "http://registry.npm.taobao.org/thunkify/download/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "optional": true + }, + "timespan": { + "version": "2.3.0", + "resolved": "http://registry.npm.taobao.org/timespan/download/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "optional": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "token-stream": { + "version": "0.0.1", + "resolved": "http://registry.npm.taobao.org/token-stream/download/token-stream-0.0.1.tgz", + "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/toposort-class/download/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.3.4.tgz", + "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", + "requires": { + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "http://registry.npm.taobao.org/tsscmp/download/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "optional": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "http://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "http://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "http://registry.npm.taobao.org/type-is/download/type-is-1.6.16.tgz", + "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "typechecker": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/typechecker/download/typechecker-2.1.0.tgz", + "integrity": "sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M=" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "http://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "uc.micro": { + "version": "1.0.5", + "resolved": "http://registry.npm.taobao.org/uc.micro/download/uc.micro-1.0.5.tgz", + "integrity": "sha1-DGXxX4FaoItWCmHOi023/8P0U3Y=" + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "http://registry.npm.taobao.org/uglify-js/download/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "http://registry.npm.taobao.org/window-size/download/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/uglify-to-browserify/download/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "http://registry.npm.taobao.org/underscore/download/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + }, + "universalify": { + "version": "0.1.1", + "resolved": "http://registry.npm.taobao.org/universalify/download/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "url": { + "version": "0.10.3", + "resolved": "http://registry.npm.taobao.org/url/download/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "urllib": { + "version": "2.22.0", + "resolved": "http://registry.npm.taobao.org/urllib/download/urllib-2.22.0.tgz", + "integrity": "sha1-KWXcSuEnpvtpW32yfTGE8X2Cy0I=", + "requires": { + "any-promise": "1.3.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "default-user-agent": "1.0.0", + "digest-header": "0.0.1", + "ee-first": "1.1.1", + "humanize-ms": "1.2.1", + "iconv-lite": "0.4.19", + "qs": "6.5.1", + "statuses": "1.4.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utility": { + "version": "0.1.11", + "resolved": "http://registry.npm.taobao.org/utility/download/utility-0.1.11.tgz", + "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", + "requires": { + "address": "1.0.3" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.1.0.tgz", + "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "http://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "validator": { + "version": "9.4.1", + "resolved": "http://registry.npm.taobao.org/validator/download/validator-9.4.1.tgz", + "integrity": "sha1-q/Rm05i1Yc0kMFARLG/x3mzBJmM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/void-elements/download/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, + "watchr": { + "version": "2.4.13", + "resolved": "http://registry.npm.taobao.org/watchr/download/watchr-2.4.13.tgz", + "integrity": "sha1-10hHu01vkPYf4sdPn2hmKqDgdgE=", + "requires": { + "eachr": "2.0.4", + "extendr": "2.1.0", + "extract-opts": "2.2.0", + "ignorefs": "1.2.0", + "safefs": "3.2.2", + "scandirectory": "2.5.0", + "taskgroup": "4.3.1", + "typechecker": "2.1.0" + } + }, + "when": { + "version": "3.7.8", + "resolved": "http://registry.npm.taobao.org/when/download/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "optional": true + }, + "which": { + "version": "1.3.0", + "resolved": "http://registry.npm.taobao.org/which/download/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "win-release": { + "version": "1.1.1", + "resolved": "http://registry.npm.taobao.org/win-release/download/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "requires": { + "semver": "5.5.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "http://registry.npm.taobao.org/window-size/download/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "with": { + "version": "5.1.1", + "resolved": "http://registry.npm.taobao.org/with/download/with-5.1.1.tgz", + "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", + "requires": { + "acorn": "3.3.0", + "acorn-globals": "3.1.0" + } + }, + "wkx": { + "version": "0.4.4", + "resolved": "http://registry.npm.taobao.org/wkx/download/wkx-0.4.4.tgz", + "integrity": "sha1-z3UbZy5LReFi+f0wEkh45z2WybI=", + "requires": { + "@types/node": "9.4.7" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "x-xss-protection": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/x-xss-protection/download/x-xss-protection-1.1.0.tgz", + "integrity": "sha1-TxiYwzLesefyvhKA77PixT1pwac=" + }, + "xml2js": { + "version": "0.4.4", + "resolved": "http://registry.npm.taobao.org/xml2js/download/xml2js-0.4.4.tgz", + "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=", + "requires": { + "sax": "0.6.1", + "xmlbuilder": "2.6.5" + } + }, + "xmlbuilder": { + "version": "2.6.5", + "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-2.6.5.tgz", + "integrity": "sha1-b/etYPty0idk8AehZLd/K/FABSY=", + "requires": { + "lodash": "3.10.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "xregexp": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/xregexp/download/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "http://registry.npm.taobao.org/xtend/download/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "http://registry.npm.taobao.org/y18n/download/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "8.0.2", + "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-2.1.0.tgz", + "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "http://registry.npm.taobao.org/yauzl/download/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "requires": { + "fd-slicer": "1.0.1" + } + }, + "yazl": { + "version": "2.4.3", + "resolved": "http://registry.npm.taobao.org/yazl/download/yazl-2.4.3.tgz", + "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", + "requires": { + "buffer-crc32": "0.2.13" + } + } + } +} From 205fc93d44a53049ec8b4e391d6dcc5c1462b3c7 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 18 Mar 2018 15:33:33 +0800 Subject: [PATCH 097/194] fix Makefile --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0ef8c45e..b27b2477 100644 --- a/Makefile +++ b/Makefile @@ -8,18 +8,20 @@ test: test-integration test-integration: @echo "\nRunning integration tests..." + @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init & @NODE_ENV=test PORT=3000 HOST=127.0.0.1 CONFIG_FILE=${ROOT}/config/config.test.js node bin/www & @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha \ - test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000 + test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000 coverage: @echo "\n\nRunning coverage report..." rm -rf coverage # @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js cover --report lcovonly --dir coverage/core ./node_modules/.bin/_mocha \ # test/unit -- -R spec --recursive --timeout 15000 + @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init & @NODE_ENV=test PORT=3000 HOST=127.0.0.1 CONFIG_FILE=${ROOT}/config/config.test.js node bin/www & @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js cover --report lcovonly --dir coverage/api ./node_modules/.bin/_mocha \ - test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index -- -R spec --recursive --timeout 15000 + test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index -- -R spec --recursive --timeout 15000 @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js report .PHONY: coverage \ No newline at end of file From 36af161b81dd9079433373c88a5e7d2bd01276b4 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 18 Mar 2018 15:44:25 +0800 Subject: [PATCH 098/194] appveyor --- appveyor.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7833713b..977b5a1e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,11 +4,6 @@ init: environment: matrix: - nodejs_version: "8.10.0" - - nodejs_version: "7.5" - - nodejs_version: "7" - - nodejs_version: "6.9.5" - - nodejs_version: "6.1" - - nodejs_version: "6" services: - mysql From a26a4408d96bf7697fdaa52f5591cb9409071d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E9=B9=8F=E7=BF=94?= Date: Mon, 21 May 2018 17:10:40 +0800 Subject: [PATCH 099/194] =?UTF-8?q?=E5=A2=9E=E5=8A=A0maxFilesSize=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=20(#125)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 增加maxFilesSize属性 增加maxFilesSize属性, 避免bundle资源过大, 导致的upload error * Update package-manager.js 拼写错误! --- core/services/package-manager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 6d68cda7..872641ac 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -31,6 +31,7 @@ proto.parseReqFile = function (req) { log.debug('parseReqFile'); return new Promise((resolve, reject) => { var form = new formidable.IncomingForm(); + form.maxFieldsSize = 200 * 1024 * 1024; form.parse(req, (err, fields, files) => { if (err) { log.debug('parseReqFile:', err); From f89c817572b2e4cffe808b62a84ed7e2e6aa91d1 Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 22 May 2018 09:59:42 +0800 Subject: [PATCH 100/194] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a62e9ced..d5737c2a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use local storage, just modify config.js file, it's simple configure. -## qq交流群 535491067 +## qq交流群 +- 628921445 +- 535491067 ## 正确使用code-push热更新 From 87f39648ee9ab4f20469c01aa78194acdf592cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E9=B9=8F=E7=BF=94?= Date: Thu, 31 May 2018 23:52:02 +0800 Subject: [PATCH 101/194] =?UTF-8?q?=E5=8D=87=E7=BA=A7formidable=20(#124)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 升级formidable至1.2.1(最低1.1.1), 增加maxFilesSize选项, 避免bundle资源过大出现的upload error --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a3031d9..b1d31b87 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "debug": "^2.6.8", "express": "^4.14.0", "extract-zip": "^1.6.0", - "formidable": "^1.0.17", + "formidable": "^1.2.1", "fs-extra": "^3.0.1", "helmet": "^3.1.0", "i18n": "^0.8.3", From 777ee7592e0e9434a25fa4e12834bf96bc715a26 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 18 Mar 2018 17:11:35 +0800 Subject: [PATCH 102/194] deprecated operatorsAliases --- config/config.js | 3 ++- config/config.test.js | 3 ++- config/config.testwin.js | 3 ++- core/middleware.js | 3 ++- core/services/app-manager.js | 3 ++- core/services/collaborators.js | 3 ++- core/services/package-manager.js | 8 +++++--- 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/config/config.js b/config/config.js index b4641694..a7a7c3d1 100644 --- a/config/config.js +++ b/config/config.js @@ -8,7 +8,8 @@ config.development = { host: process.env.RDS_HOST || "127.0.0.1", port: process.env.RDS_PORT || 3306, dialect: "mysql", - logging: false + logging: false, + operatorsAliases: false, }, // Config for qiniu (http://www.qiniu.com/) cloud storage when storageType value is "qiniu". qiniu: { diff --git a/config/config.test.js b/config/config.test.js index 7b53588b..ad45309a 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -9,7 +9,8 @@ config.test = { host: "127.0.0.1", port: 3306, dialect: "mysql", - logging: false + logging: false, + operatorsAliases: false, }, local: { storageDir: os.tmpdir(), diff --git a/config/config.testwin.js b/config/config.testwin.js index b98cedd0..1fbc730a 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -9,7 +9,8 @@ config.test = { host: "127.0.0.1", port: 3306, dialect: "mysql", - logging: false + logging: false, + operatorsAliases: false, }, local: { storageDir: os.tmpdir(), diff --git a/core/middleware.js b/core/middleware.js index da4676a2..28bd0f80 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -17,8 +17,9 @@ var checkAuthToken = function (authToken) { if (_.isEmpty(users)) { throw new AppError.Unauthorized(); } + var Sequelize = require('sequelize'); return models.UserTokens.findOne({ - where: {tokens: authToken, uid: users.id, expires_at: { gt: moment().format('YYYY-MM-DD HH:mm:ss') }} + where: {tokens: authToken, uid: users.id, expires_at: { [Sequelize.Op.gt]: moment().format('YYYY-MM-DD HH:mm:ss') }} }) .then((tokenInfo) => { if (_.isEmpty(tokenInfo)){ diff --git a/core/services/app-manager.js b/core/services/app-manager.js index d180d0d3..60600fe1 100644 --- a/core/services/app-manager.js +++ b/core/services/app-manager.js @@ -91,7 +91,8 @@ proto.listApps = function (uid) { return []; } else { var appIds = _.map(data, (v) => { return v.appid }); - return models.Apps.findAll({where: {id: {in: appIds}}}); + var Sequelize = require('sequelize'); + return models.Apps.findAll({where: {id: {[Sequelize.Op.in]: appIds}}}); } }) .then((appInfos) => { diff --git a/core/services/collaborators.js b/core/services/collaborators.js index 13241cca..b2371103 100644 --- a/core/services/collaborators.js +++ b/core/services/collaborators.js @@ -21,7 +21,8 @@ proto.listCollaborators = function (appId) { }, []); }) .then((coInfo) => { - return models.Users.findAll({where: {id: {in: coInfo.uids}}}) + var Sequelize = require('sequelize'); + return models.Users.findAll({where: {id: {[Sequelize.Op.in]: coInfo.uids}}}) .then((data2) => { return _.reduce(data2, function (result, value, key) { var permission = ""; diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 872641ac..7574e1ca 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -232,18 +232,19 @@ proto.createDiffPackagesByLastNums = function (packageId, num) { if (_.isEmpty(originalPackage)) { throw AppError.AppError('can\'t find Package'); } + var Sequelize = require('sequelize'); return Promise.all([ models.Packages.findAll({ where:{ deployment_version_id: originalPackage.deployment_version_id, - id: {$lt: packageId}}, + id: {[Sequelize.Op.lt]: packageId}}, order: [['id','desc']], limit: num }), models.Packages.findAll({ where:{ deployment_version_id: originalPackage.deployment_version_id, - id: {$lt: packageId}}, + id: {[Sequelize.Op.lt]: packageId}}, order: [['id','asc']], limit: 2 }) @@ -495,7 +496,8 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) } proto.getCanRollbackPackages = function (deploymentVersionId) { + var Sequelize = require('sequelize'); return models.Packages.findAll({ - where: {deployment_version_id: deploymentVersionId, release_method: {$in: ['Upload', 'Promote'] }}, order: [['id','desc']], limit: 2 + where: {deployment_version_id: deploymentVersionId, release_method: {[Sequelize.Op.in]: ['Upload', 'Promote'] }}, order: [['id','desc']], limit: 2 }); } From dc20e0e6499020053c97d303c90812595479b2ba Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 24 Mar 2018 17:56:25 +0800 Subject: [PATCH 103/194] accesskey --- app.js | 29 +++++--------- config/config.js | 2 +- core/config.js | 10 +++-- core/services/account-manager.js | 5 +-- routes/accessKeys.js | 68 ++++---------------------------- routes/sessions.js | 24 ----------- 6 files changed, 25 insertions(+), 113 deletions(-) delete mode 100644 routes/sessions.js diff --git a/app.js b/app.js index 172965ab..cb2110b9 100644 --- a/app.js +++ b/app.js @@ -11,7 +11,6 @@ var fs = require('fs'); var routes = require('./routes/index'); var auth = require('./routes/auth'); var accessKeys = require('./routes/accessKeys'); -var sessions = require('./routes/sessions'); var account = require('./routes/account'); var users = require('./routes/users'); var apps = require('./routes/apps'); @@ -75,7 +74,6 @@ if (_.get(config, 'common.storageType') === 'local') { app.use('/', routes); app.use('/auth', auth); app.use('/accessKeys', accessKeys); -app.use('/sessions', sessions); app.use('/account', account); app.use('/users', users); app.use('/apps', apps); @@ -93,34 +91,27 @@ if (app.get('env') === 'development') { log.error(err); }); app.use(function(err, req, res, next) { - if (err instanceof AppError.AppError) { - res.send(err); - log.debug(err); - } else { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: err - }); - log.error(err); - } + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + log.error(err); }); } else { app.use(function(req, res, next) { var e = new AppError.NotFound(); - res.status(404).send(e); + res.status(404).send(e.message); log.debug(e); }); // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { if (err instanceof AppError.AppError) { - res.send(err); + res.send(err.message); + log.debug(err); } else { - var status = err.status || 500; - var error = new AppError.AppError(`服务器繁忙,请稍后再试!`); - error.status = status; - res.status(status).send(error); + res.status(err.status || 500).send(`服务器繁忙,请稍后再试!`); log.error(err); } }); diff --git a/config/config.js b/config/config.js index a7a7c3d1..45bd2076 100644 --- a/config/config.js +++ b/config/config.js @@ -62,7 +62,7 @@ config.development = { // create patch updates's number. default value is 3 diffNums: 3, // data dir for caclulate diff files. it's optimization. - dataDir: process.env.DATA_DIR || "/Users/tablee/workspaces/data", + dataDir: process.env.DATA_DIR || os.tmpdir(), // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") storageType: process.env.STORAGE_TYPE || "local", // options value is (true | false), when it's true, it will cache updateCheck results in redis. diff --git a/core/config.js b/core/config.js index 6c8f71a7..a67eae86 100644 --- a/core/config.js +++ b/core/config.js @@ -1,15 +1,17 @@ -var env = process.env.NODE_ENV || 'development'; +var env = process.env.NODE_ENV || 'development'; var _ = require('lodash'); var path = require('path'); -var config = {}; var log4js = require('log4js'); var log = log4js.getLogger("cps:config"); var CONFIG_PATH = path.join(__dirname, '../config/config.js'); if (process.env.CONFIG_FILE) { CONFIG_PATH = path.join(__dirname, path.relative(__dirname, process.env.CONFIG_FILE)); - log.info(`process.env.CONFIG_FILE value: ` +process.env.CONFIG_FILE) + log.info(`process.env.CONFIG_FILE value: ${process.env.CONFIG_FILE}`) } log.info(`use config file ${CONFIG_PATH}`) log.info(`use env ${env}`) -config = _.get(require(CONFIG_PATH), env); +var config = _.get(require(CONFIG_PATH), env); +if (_.isEmpty(config)) { + throw new Error(`config is {}, check the env and config`); +} module.exports = config; diff --git a/core/services/account-manager.js b/core/services/account-manager.js index 74f6e180..0eae4a9e 100644 --- a/core/services/account-manager.js +++ b/core/services/account-manager.js @@ -67,13 +67,11 @@ proto.getAllAccessKeyByUid = function (uid) { .then((tokens) => { return _.map(tokens, function(v){ return { - id: v.id + "", name: '(hidden)', createdTime: parseInt(moment(v.created_at).format('x')), createdBy: v.created_by, expires: parseInt(moment(v.expires_at).format('x')), friendlyName: v.name, - isSession: v.is_session == 0 ? false : true, description: v.description, }; }); @@ -86,13 +84,12 @@ proto.isExsitAccessKeyName = function (uid, friendlyName) { }); }; -proto.createAccessKey = function (uid, newAccessKey, isSession, ttl, friendlyName, createdBy, description) { +proto.createAccessKey = function (uid, newAccessKey, ttl, friendlyName, createdBy, description) { return models.UserTokens.create({ uid: uid, name: friendlyName, tokens: newAccessKey, description: description, - is_session: isSession ? 1 : 0, created_by: createdBy, expires_at: moment().add(ttl/1000, 'seconds').format('YYYY-MM-DD HH:mm:ss'), created_at: moment().format('YYYY-MM-DD HH:mm:ss'), diff --git a/routes/accessKeys.js b/routes/accessKeys.js index 835ac8ff..b7239b41 100644 --- a/routes/accessKeys.js +++ b/routes/accessKeys.js @@ -19,12 +19,7 @@ router.get('/', middleware.checkToken, (req, res, next) => { res.send({accessKeys: accessKeys}); }) .catch((e) => { - if (e instanceof AppError.AppError) { - log.debug('request get acceesKeys AppError', e) - res.status(406).send(e.message); - } else { - next(e); - } + next(e); }); }); @@ -33,9 +28,9 @@ router.post('/', middleware.checkToken, (req, res, next) => { var identical = req.users.identical; var createdBy = _.trim(req.body.createdBy); var friendlyName = _.trim(req.body.friendlyName); - var isSession = req.body.isSession; var ttl = parseInt(req.body.ttl); var description = _.trim(req.body.description); + log.debug(req.body) var newAccessKey = security.randToken(28).concat(identical); return accountManager.isExsitAccessKeyName(uid, friendlyName) .then((data) => { @@ -44,7 +39,7 @@ router.post('/', middleware.checkToken, (req, res, next) => { } }) .then(() => { - return accountManager.createAccessKey(uid, newAccessKey, isSession, ttl, friendlyName, createdBy, description); + return accountManager.createAccessKey(uid, newAccessKey, ttl, friendlyName, createdBy, description); }) .then((newToken) => { var moment = require("moment"); @@ -53,14 +48,15 @@ router.post('/', middleware.checkToken, (req, res, next) => { createdTime : parseInt(moment(newToken.created_at).format('x')), createdBy : newToken.created_by, expires : parseInt(moment(newToken.expires_at).format('x')), - isSession: newToken.is_session == 1 ? true :false, description : newToken.description, friendlyName: newToken.name, }; + log.debug(info); res.send({accessKey:info}); }) .catch((e) => { if (e instanceof AppError.AppError) { + log.debug(e) res.status(406).send(e.message); } else { next(e); @@ -73,66 +69,16 @@ router.delete('/:name', middleware.checkToken, (req, res, next) => { var uid = req.users.id; return models.UserTokens.destroy({where: {name:name, uid: uid}}) .then((rowNum) => { + log.debug('delete acceesKey:', name) res.send({friendlyName:name}); }) .catch((e) => { if (e instanceof AppError.AppError) { + log.debug(e) res.status(406).send(e.message); } else { next(e); } }); }); - -router.patch('/:name', middleware.checkToken, (req, res, next) => { - var name = _.trim(decodeURI(req.params.name)); - var friendlyName = _.trim(req.body.friendlyName); - var ttl = _.trim(req.body.ttl); - var uid = req.users.id; - return Promise.all([ - models.UserTokens.findOne({where: {name:name, uid: uid}}), - accountManager.isExsitAccessKeyName(uid, friendlyName), - ]) - .spread((token, token2) => { - if (_.isEmpty(token)) { - throw new AppError.AppError(`The access key "${name}" does not exist.`); - } - if (!_.isEmpty(token2)) { - throw new AppError.AppError(`The access key "${friendlyName}" already exists.`); - } - return token; - }) - .then((token) => { - var moment = require('moment'); - if (ttl > 0 || ttl < 0) { - var newExp = moment(token.get('expires_at')).add(ttl/1000, 'seconds').format('YYYY-MM-DD HH:mm:ss'); - token.set('expires_at', newExp); - } - if (friendlyName.length > 0) { - token.set('name', friendlyName); - } - return token.save(); - }) - .then((token) => { - var info = { - name : '(hidden)', - isSession: token.is_session == 1 ? true :false, - createdTime : token.created_at, - createdBy : token.created_by, - description : token.description, - expires : token.expires_at, - friendlyName: token.name, - id: token.id + "" - }; - res.send({accessKey: info}); - }) - .catch((e) => { - if (e instanceof AppError.AppError) { - res.status(406).send(e.message); - } else { - next(e); - } - }); -}); - module.exports = router; diff --git a/routes/sessions.js b/routes/sessions.js deleted file mode 100644 index a7b4ce18..00000000 --- a/routes/sessions.js +++ /dev/null @@ -1,24 +0,0 @@ -var express = require('express'); -var router = express.Router(); -var _ = require('lodash'); -var models = require('../models'); -var middleware = require('../core/middleware'); -var AppError = require('../core/app-error'); - -router.delete('/:machineName', middleware.checkToken, (req, res, next) => { - var machineName = _.trim(decodeURI(req.params.machineName)); - var uid = req.users.id; - models.UserTokens.destroy({where: {created_by:machineName, uid: uid}}) - .then((rowNum) => { - res.send(""); - }) - .catch(e => { - if (e instanceof AppError.AppError) { - res.status(406).send(e.message); - } else { - next(e); - } - }); -}); - -module.exports = router; From c7a74349c0a0b7bd5283865c2c680940462a1444 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 18 Aug 2018 09:56:24 +0800 Subject: [PATCH 104/194] delete session --- Makefile | 4 +- package.json | 2 +- routes/account.js | 4 +- routes/apps.js | 14 ++--- routes/auth.js | 35 +++++------- test/api/accessKeys/accessKeys.test.js | 79 ++------------------------ test/api/account/account.test.js | 2 +- test/api/apps/apps.test.js | 4 +- test/api/apps/release.test.js | 4 +- test/api/sessions/sessions.test.js | 58 ------------------- 10 files changed, 33 insertions(+), 173 deletions(-) delete mode 100644 test/api/sessions/sessions.test.js diff --git a/Makefile b/Makefile index b27b2477..6ffcf5ba 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ test-integration: @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init & @NODE_ENV=test PORT=3000 HOST=127.0.0.1 CONFIG_FILE=${ROOT}/config/config.test.js node bin/www & @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha \ - test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000 + test/api/users test/api/auth test/api/account test/api/accessKeys test/api/apps test/api/index --recursive --timeout 15000 coverage: @echo "\n\nRunning coverage report..." @@ -21,7 +21,7 @@ coverage: @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init & @NODE_ENV=test PORT=3000 HOST=127.0.0.1 CONFIG_FILE=${ROOT}/config/config.test.js node bin/www & @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js cover --report lcovonly --dir coverage/api ./node_modules/.bin/_mocha \ - test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index -- -R spec --recursive --timeout 15000 + test/api/users test/api/auth test/api/account test/api/accessKeys test/api/apps test/api/index -- -R spec --recursive --timeout 15000 @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js report .PHONY: coverage \ No newline at end of file diff --git a/package.json b/package.json index b1d31b87..0d173b8f 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "init": "node ./bin/db init", "upgrade": "node ./bin/db upgrade", "test": "make test", - "test-win": "mocha test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/sessions test/api/apps test/api/index --recursive --timeout 15000", + "test-win": "mocha test/api/init test/api/users test/api/auth test/api/account test/api/accessKeys test/api/apps test/api/index --recursive --timeout 15000", "coverage": "make coverage" }, "dependencies": { diff --git a/routes/account.js b/routes/account.js index c022af4d..edae56f1 100644 --- a/routes/account.js +++ b/routes/account.js @@ -4,14 +4,16 @@ var models = require('../models'); var _ = require('lodash'); var security = require('../core/utils/security'); var middleware = require('../core/middleware'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:account"); router.get('/', middleware.checkToken, (req, res) => { var userInfo = { email:req.users.email, - id:req.users.identical, linkedProviders: [], name:req.users.username, }; + log.debug(userInfo); res.send({account:userInfo}); }); diff --git a/routes/apps.js b/routes/apps.js index 317dc37c..be5d414a 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -15,8 +15,6 @@ var config = require('../core/config'); const REGEX = /^(\w+)(-android|-ios)$/; const REGEX_ANDROID = /^(\w+)(-android)$/; const REGEX_IOS = /^(\w+)(-ios)$/; -const OLD_REGEX_ANDROID = /^(android_)/; -const OLD_REGEX_IOS = /^(ios_)/; var log4js = require('log4js'); var log = log4js.getLogger("cps:apps"); @@ -584,14 +582,10 @@ router.patch('/:appName', var appManager = new AppManager(); return accountManager.ownerCan(uid, appName) .then((col) => { - if (REGEX_ANDROID.test(appName) || OLD_REGEX_ANDROID.test(appName)) { - if (!REGEX_ANDROID.test(newAppName)) { - throw new AppError.AppError(`new appName have to point -android suffix! eg. Demo-android`); - } - } else if (REGEX_IOS.test(appName) || OLD_REGEX_IOS.test(appName)) { - if (!REGEX_IOS.test(newAppName)) { - throw new AppError.AppError(`new appName have to point -ios suffix! eg. Demo-ios`); - } + if (REGEX_ANDROID.test(appName) && !REGEX_ANDROID.test(newAppName)) { + throw new AppError.AppError(`new appName have to point -android suffix! eg. Demo-android`); + } else if (REGEX_IOS.test(appName) && !REGEX_IOS.test(newAppName)) { + throw new AppError.AppError(`new appName have to point -ios suffix! eg. Demo-ios`); } else { throw new AppError.AppError(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); } diff --git a/routes/auth.js b/routes/auth.js index e9e0ccea..2db402e9 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -1,21 +1,15 @@ var express = require('express'); var router = express.Router(); var _ = require('lodash'); -var security = require('../core/utils/security'); -var accountManager = require('../core/services/account-manager')(); -var AppError = require('../core/app-error'); +var config = require('../core/config'); +var validator = require('validator'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:auth"); router.get('/login', (req, res) => { - var config = require('../core/config'); var codePushWebUrl = _.get(config, 'common.codePushWebUrl'); - var isRedirect = false; - if (codePushWebUrl) { - var validator = require('validator'); - if (validator.isURL(codePushWebUrl)){ - isRedirect = true; - } - } - if (isRedirect) { + if (codePushWebUrl && validator.isURL(codePushWebUrl)) { + log.debug(`login redirect:${codePushWebUrl}`); res.redirect(`${codePushWebUrl}/login`); } else { res.render('auth/login', { title: 'CodePushServer' }); @@ -27,16 +21,10 @@ router.get('/link', (req, res) => { }); router.get('/register', (req, res) => { - var config = require('../core/config'); var codePushWebUrl = _.get(config, 'common.codePushWebUrl'); var isRedirect = false; - if (codePushWebUrl) { - var validator = require('validator'); - if (validator.isURL(codePushWebUrl)){ - isRedirect = true; - } - } - if (isRedirect) { + if (codePushWebUrl && validator.isURL(codePushWebUrl)) { + log.debug(`register redirect:${codePushWebUrl}`); res.redirect(`${codePushWebUrl}/register`); } else { res.render('auth/login', { title: 'CodePushServer' }); @@ -48,20 +36,25 @@ router.post('/logout', (req, res) => { }); router.post('/login', (req, res, next) => { + var AppError = require('../core/app-error'); + var accountManager = require('../core/services/account-manager')(); + var security = require('../core/utils/security'); var account = _.trim(req.body.account); var password = _.trim(req.body.password); - var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); + log.debug(`login:${account}`); accountManager.login(account, password) .then((users) => { var jwt = require('jsonwebtoken'); return jwt.sign({ uid: users.id, hash: security.md5(users.ack_code), expiredIn: 7200 }, tokenSecret); }) .then((token) => { + log.debug(token); res.send({status:'OK', results: {tokens: token}}); }) .catch((e) => { if (e instanceof AppError.AppError) { + log.debug(e); res.send({status:'ERROR', errorMessage: e.message}); } else { next(e); diff --git a/test/api/accessKeys/accessKeys.test.js b/test/api/accessKeys/accessKeys.test.js index 83122f8d..69dc2fd6 100644 --- a/test/api/accessKeys/accessKeys.test.js +++ b/test/api/accessKeys/accessKeys.test.js @@ -30,14 +30,14 @@ describe('api/accessKeys/accessKeys.test.js', function() { it('should create accessKeys successful', function(done) { request.post(`/accessKeys`) .set('Authorization', `Basic ${authToken}`) - .send({createdBy: 'tablee', friendlyName: friendlyName, isSession: false, ttl: 30*24*60*60}) + .send({createdBy: 'tablee', friendlyName: friendlyName, ttl: 30*24*60*60}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(200); var rs = JSON.parse(res.text); rs.should.have.properties('accessKey'); rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); + 'expires', 'description', 'friendlyName']); done(); }); }); @@ -45,7 +45,7 @@ describe('api/accessKeys/accessKeys.test.js', function() { it('should not create accessKeys successful when friendlyName exist', function(done) { request.post(`/accessKeys`) .set('Authorization', `Basic ${authToken}`) - .send({createdBy: 'tablee', friendlyName: friendlyName, isSession: true, ttl: 30*24*60*60}) + .send({createdBy: 'tablee', friendlyName: friendlyName, ttl: 30*24*60*60}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(406); @@ -68,84 +68,13 @@ describe('api/accessKeys/accessKeys.test.js', function() { rs.accessKeys.should.be.an.instanceOf(Array); rs.accessKeys.should.matchEach(function(it) { return it.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); + 'expires', 'description', 'friendlyName']); }); done(); }); }); }); - describe('modify accessKeys', function(done) { - it('should modify accessKeys add ttl successful', function(done) { - request.patch(`/accessKeys/${encodeURI(friendlyName)}`) - .set('Authorization', `Basic ${authToken}`) - .send({ttl: 7*24*60*60*1000}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(200); - var rs = JSON.parse(res.text); - rs.should.have.properties('accessKey'); - rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); - done(); - }); - }); - - it('should modify accessKeys substact ttl successful', function(done) { - request.patch(`/accessKeys/${encodeURI(friendlyName)}`) - .set('Authorization', `Basic ${authToken}`) - .send({ttl: -7*24*60*60*1000}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(200); - var rs = JSON.parse(res.text); - rs.should.have.properties('accessKey'); - rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); - done(); - }); - }); - - it('should not modify accessKeys friendlyName successful when friendlyName exists', function(done) { - request.patch(`/accessKeys/${encodeURI(friendlyName)}`) - .set('Authorization', `Basic ${authToken}`) - .send({friendlyName: friendlyName}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(406); - res.text.should.equal(`The access key "${friendlyName}" already exists.`); - done(); - }); - }); - - it('should not modify accessKeys friendlyName successful when friendlyName invalid', function(done) { - request.patch(`/accessKeys/${encodeURI(newFriendlyName)}`) - .set('Authorization', `Basic ${authToken}`) - .send({friendlyName: newFriendlyName}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(406); - res.text.should.equal(`The access key "${newFriendlyName}" does not exist.`); - done(); - }); - }); - - it('should modify accessKeys friendlyName successful', function(done) { - request.patch(`/accessKeys/${encodeURI(friendlyName)}`) - .set('Authorization', `Basic ${authToken}`) - .send({friendlyName: newFriendlyName}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(200); - var rs = JSON.parse(res.text); - rs.should.have.properties('accessKey'); - rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); - done(); - }); - }); - }); - describe('delete accessKeys', function(done) { it('should delete accessKeys successful', function(done) { request.delete(`/accessKeys/${encodeURI(newFriendlyName)}`) diff --git a/test/api/account/account.test.js b/test/api/account/account.test.js index 83ebb2ce..62e262a3 100644 --- a/test/api/account/account.test.js +++ b/test/api/account/account.test.js @@ -35,7 +35,7 @@ describe('api/account/account.test.js', function() { res.status.should.equal(200); var rs = JSON.parse(res.text); rs.should.have.properties('account'); - rs.account.should.have.properties(['email', 'id', 'linkedProviders', 'name']); + rs.account.should.have.properties(['email', 'linkedProviders', 'name']); done(); }); }); diff --git a/test/api/apps/apps.test.js b/test/api/apps/apps.test.js index 4628b7a9..261c536f 100644 --- a/test/api/apps/apps.test.js +++ b/test/api/apps/apps.test.js @@ -38,14 +38,14 @@ describe('api/apps/apps.test.js', function() { it('should create accessKeys successful', function(done) { request.post(`/accessKeys`) .set('Authorization', `Basic ${authToken}`) - .send({createdBy: machineName, friendlyName: friendlyName, isSession: true, ttl: 30*24*60*60}) + .send({createdBy: machineName, friendlyName: friendlyName, ttl: 30*24*60*60}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(200); var rs = JSON.parse(res.text); rs.should.have.properties('accessKey'); rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); + 'expires', 'description', 'friendlyName']); bearerToken = _.get(rs, 'accessKey.name'); done(); }); diff --git a/test/api/apps/release.test.js b/test/api/apps/release.test.js index dd6bdd9c..d845dee2 100644 --- a/test/api/apps/release.test.js +++ b/test/api/apps/release.test.js @@ -35,14 +35,14 @@ describe('api/apps/release.test.js', function() { it('should create accessKeys successful', function(done) { request.post(`/accessKeys`) .set('Authorization', `Basic ${authToken}`) - .send({createdBy: machineName, friendlyName: friendlyName, isSession: true, ttl: 30*24*60*60}) + .send({createdBy: machineName, friendlyName: friendlyName, ttl: 30*24*60*60}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(200); var rs = JSON.parse(res.text); rs.should.have.properties('accessKey'); rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); + 'expires', 'description', 'friendlyName']); bearerToken = _.get(rs, 'accessKey.name'); done(); }); diff --git a/test/api/sessions/sessions.test.js b/test/api/sessions/sessions.test.js deleted file mode 100644 index 3e7821a6..00000000 --- a/test/api/sessions/sessions.test.js +++ /dev/null @@ -1,58 +0,0 @@ -var app = require('../../../app'); -var request = require('supertest')(app); -var should = require("should"); -var security = require('../../../core/utils/security'); -var factory = require('../../../core/utils/factory'); -var _ = require('lodash'); - -describe('api/sessions/sessions.test.js', function() { - var account = '522539441@qq.com'; - var password = '123456'; - var authToken; - var friendlyName = 'sessions'; - var machineName = 'tablee.hosts'; - before(function(done){ - request.post('/auth/login') - .send({ - account: account, - password: password - }) - .end(function(err, res) { - should.not.exist(err); - var rs = JSON.parse(res.text); - rs.should.containEql({status:"OK"}); - authToken = (new Buffer(`auth:${_.get(rs, 'results.tokens')}`)).toString('base64'); - done(); - }); - }); - - describe('create accessKeys', function() { - it('should create accessKeys successful', function(done) { - request.post(`/accessKeys`) - .set('Authorization', `Basic ${authToken}`) - .send({createdBy: machineName, friendlyName: friendlyName, isSession: true, ttl: 30*24*60*60}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(200); - var rs = JSON.parse(res.text); - rs.should.have.properties('accessKey'); - rs.accessKey.should.have.properties(['name', 'createdTime', 'createdBy', - 'expires', 'isSession', 'description', 'friendlyName']); - done(); - }); - }); - }); - - describe('delete sessions', function() { - it('should delete sessions successful', function(done) { - request.delete(`/sessions/${encodeURI(machineName)}`) - .set('Authorization', `Basic ${authToken}`) - .send() - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(200); - done(); - }); - }); - }); -}); From ca0e63b89ed247a606f37cd9ab66d76b8bb7e490 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 19 Aug 2018 00:12:19 +0800 Subject: [PATCH 105/194] add pacth,support rollout --- core/const.js | 38 + core/services/app-manager.js | 27 +- core/services/client-manager.js | 1 + core/services/package-manager.js | 197 +++-- core/utils/security.js | 5 +- models/apps.js | 2 + models/packages.js | 2 + package-lock.json | 1379 +++++------------------------- package.json | 14 +- routes/apps.js | 104 ++- 10 files changed, 464 insertions(+), 1305 deletions(-) create mode 100644 core/const.js diff --git a/core/const.js b/core/const.js new file mode 100644 index 00000000..20306b66 --- /dev/null +++ b/core/const.js @@ -0,0 +1,38 @@ +function define(name, value) { + Object.defineProperty(exports, name, { + value: value, + enumerable: true + }); +} + +//定义支持的平台 +define("IOS", 1); +define("IOS_NAME", 'iOS'); +define("ANDROID", 2); +define("ANDROID_NAME", 'Android'); +define("WINDOWS", 3); +define("WINDOWS_NAME", 'Windows'); + +//定义支持的应用类型 +define("REACT_NATIVE", 1); +define("REACT_NATIVE_NAME", 'React-Native'); +define("CORDOVA", 2); +define("CORDOVA_NAME", 'Cordova'); + +define("PRODUCTION", 'Production'); +define("STAGING", 'Staging'); + + +define("IS_MANDATORY_YES", 1); +define("IS_MANDATORY_NO", 0); + + +define("IS_DISABLED_YES", 1); +define("IS_DISABLED_NO", 0); + + +define("RELEAS_EMETHOD_PROMOTE", 'Promote'); +define("RELEAS_EMETHOD_UPLOAD", 'Upload'); + + + diff --git a/core/services/app-manager.js b/core/services/app-manager.js index 60600fe1..b3a56811 100644 --- a/core/services/app-manager.js +++ b/core/services/app-manager.js @@ -17,21 +17,24 @@ proto.findAppByName = function (uid, appName) { return models.Apps.findOne({where: {name: appName, uid: uid}}); }; -proto.addApp = function (uid, appName, identical) { +proto.addApp = function (uid, appName, os, platform, identical) { return models.sequelize.transaction((t) => { return models.Apps.create({ name: appName, - uid: uid + uid: uid, + os: os, + platform: platform },{ transaction: t }) .then((apps) => { + var constName = require('../const'); var appId = apps.id; var deployments = []; var deploymentKey = security.randToken(28) + identical; deployments.push({ appid: appId, - name: 'Production', + name: constName.PRODUCTION, last_deployment_version_id: 0, label_id: 0, deployment_key: deploymentKey @@ -39,7 +42,7 @@ proto.addApp = function (uid, appName, identical) { deploymentKey = security.randToken(28) + identical; deployments.push({ appid: appId, - name: 'Staging', + name: constName.STAGING, last_deployment_version_id: 0, label_id: 0, deployment_key: deploymentKey @@ -99,6 +102,19 @@ proto.listApps = function (uid) { var rs = Promise.map(_.values(appInfos), (v) => { return self.getAppDetailInfo(v, uid) .then((info) => { + var constName = require('../const'); + if (info.os == constName.IOS) { + info.os = constName.IOS_NAME; + } else if (info.os == constName.ANDROID) { + info.os = constName.ANDROID_NAME; + } else if (info.os == constName.WINDOWS) { + info.os = constName.WINDOWS_NAME; + } + if (info.platform == constName.REACT_NATIVE) { + info.platform = constName.REACT_NATIVE_NAME; + } else if (info.platform == constName.CORDOVA) { + info.platform = constName.CORDOVA_NAME; + } return info; }); }); @@ -129,7 +145,8 @@ proto.getAppDetailInfo = function (appInfo, currentUid) { deployments: _.map(deploymentInfos, (item) => { return _.get(item, 'name'); }), - + os: appInfo.get('os'), + platform: appInfo.get('platform'), name: appInfo.get('name'), id: appInfo.get('id') }); diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 8516e2ab..560602e8 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -22,6 +22,7 @@ proto.getUpdateCheckCacheKey = function(deploymentKey, appVersion, label, packag } proto.clearUpdateCheckCache = function(deploymentKey, appVersion, label, packageHash) { + log.debug('clear cache Deployments key:', deploymentKey); let redisCacheKey = this.getUpdateCheckCacheKey(deploymentKey, appVersion, label, packageHash); var client = factory.getRedisClient("default"); return client.keysAsync(redisCacheKey) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 7574e1ca..ebc9000d 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -13,6 +13,7 @@ var os = require('os'); var path = require('path'); var AppError = require('../app-error'); var log4js = require('log4js'); +var constConfig = require('../const'); var log = log4js.getLogger("cps:PackageManager"); var proto = module.exports = function (){ @@ -23,10 +24,26 @@ var proto = module.exports = function (){ return PackageManager; }; -proto.getMetricsbyPackageId= function(packageId) { +proto.getMetricsbyPackageId = function(packageId) { return models.PackagesMetrics.findOne({where: {package_id: packageId}}); } +proto.findPackageInfoByDeploymentIdAndLabel = function (deploymentId, label) { + return models.Packages.findOne({where: {deployment_id: deploymentId, label:label}}); +} + +proto.findLatestPackageInfoByDeployVersion = function (deploymentsVersionsId) { + return models.DeploymentsVersions.findById(deploymentsVersionsId) + .then((deploymentsVersions)=>{ + if (!deploymentsVersions || deploymentsVersions.current_package_id < 0) { + var e = new AppError.AppError("not found last packages"); + log.debug(e); + throw e; + } + return models.Packages.findById(deploymentsVersions.current_package_id); + }); +} + proto.parseReqFile = function (req) { log.debug('parseReqFile'); return new Promise((resolve, reject) => { @@ -85,12 +102,14 @@ proto.isMatchPackageHash = function (packageId, packageHash) { }; proto.createPackage = function (deploymentId, appVersion, packageHash, manifestHash, blobHash, params) { - var releaseMethod = params.releaseMethod || 'Upload'; + var releaseMethod = params.releaseMethod || constConfig.RELEAS_EMETHOD_UPLOAD; var releaseUid = params.releaseUid || 0; - var isMandatory = params.isMandatory ? 1 : 0; + var isMandatory = params.isMandatory || 0; var size = params.size || 0; + var rollout = params.rollout || 100; var description = params.description || ""; var originalLabel = params.originalLabel || ""; + var isDisabled = params.isDisabled || 0; var originalDeployment = params.originalDeployment || ""; var self = this; return models.Deployments.generateLabelId(deploymentId) @@ -110,6 +129,8 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH label: "v" + labelId, released_by: releaseUid, is_mandatory: isMandatory, + is_disabled: isDisabled, + rollout: rollout, original_label: originalLabel, original_deployment: originalDeployment },{transaction: t}) @@ -278,15 +299,17 @@ proto.createDiffPackages = function (originalPackage, destPackages) { .finally(() => common.deleteFolderSync(workDirectoryPath)); } -proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, releaseUid, pubType) { +proto.releasePackage = function (appId, deploymentId, packageInfo, filePath, releaseUid) { var self = this; var appVersion = packageInfo.appVersion; if (!/^([0-9.]+)$/.test(appVersion)) { log.debug(`releasePackage targetBinaryVersion ${appVersion} not support.`); return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) } - var description = packageInfo.description; - var isMandatory = packageInfo.isMandatory; + var description = packageInfo.description; //描述 + var isDisabled = packageInfo.isDisabled; //是否立刻下载 + var rollout = packageInfo.rollout; //灰度百分比 + var isMandatory = packageInfo.isMandatory; //是否强制更新,无法跳过 var tmpDir = os.tmpdir(); var directoryPath = path.join(tmpDir, 'codepush_' + security.randToken(32)); log.debug(`releasePackage generate an random dir path: ${directoryPath}`); @@ -294,36 +317,23 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, security.qetag(filePath), common.createEmptyFolder(directoryPath) .then(() => { - if (fileType == "application/zip") { - return common.unzipFile(filePath, directoryPath) - } else { - log.debug(`上传的文件格式不对`); - throw new AppError.AppError("上传的文件格式不对"); - } + return common.unzipFile(filePath, directoryPath) }) ]) .spread((blobHash) => { return security.uploadPackageType(directoryPath) .then((type) => { - if (type === 1) { - //android - if (pubType == 'ios' ) { - var e = new AppError.AppError("it must be publish it by ios type"); - log.debug(e); - throw e; - } - } else if (type === 2) { - //ios - if (pubType == 'android'){ - var e = new AppError.AppError("it must be publish it by android type"); - log.debug(e); - throw e; + return models.Apps.findById(appId).then((appInfo)=>{ + if (type > 0 && appInfo.os > 0 && appInfo.os != type) { + var e = new AppError.AppError("it must be publish it by ios type"); + log.debug(e); + throw e; + } else { + //不验证 + log.debug(`Unknown package type:`, type, ',db os:', appInfo.os); } - } else { - //不验证 - log.debug(`Unknown package type`); - } - return blobHash; + return blobHash; + }); }); }) .then((blobHash) => { @@ -356,9 +366,11 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, .spread((packageHash, manifestHash, blobHash) => { var stats = fs.statSync(filePath); var params = { - releaseMethod: 'Upload', + releaseMethod: constConfig.RELEAS_EMETHOD_UPLOAD, releaseUid: releaseUid, - isMandatory: isMandatory, + isMandatory: isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO, + isDisabled: isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO, + rollout: rollout, size: stats.size, description: description } @@ -367,79 +379,83 @@ proto.releasePackage = function (deploymentId, packageInfo, fileType, filePath, .finally(() => common.deleteFolderSync(directoryPath)) }; -proto.modifyReleasePackage = function(deploymentId, deploymentVersionId, packageInfo) { - var appVersion = _.get(packageInfo, 'appVersion'); - var description = _.get(packageInfo, 'description'); - var isMandatory = _.get(packageInfo, 'isMandatory'); - var isDisabled = _.get(packageInfo, 'isDisabled'); - return models.DeploymentsVersions.findById(deploymentVersionId) - .then((deploymentsVersions) => { - if (_.isBoolean(isDisabled)) { - throw new AppError.AppError(`--disabled -x function is not implements`); - } - if (!appVersion) { - if (!/^([0-9.]+)$/.test(appVersion)) { - return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) - } - return models.DeploymentsVersions.findOne({deployment_id: deploymentId, app_version: appVersion}) - .then((d) => { - if (d) { - throw new AppError.AppError(`version ${appVersion} already exist`); - } - }); - } - if(!deploymentsVersions) { - throw new AppError.AppError(`packages were not found in db`); +proto.modifyReleasePackage = function(packageId, params) { + var appVersion = _.get(params, 'appVersion'); + var description = _.get(params, 'description'); + var isMandatory = _.get(params, 'isMandatory'); + var isDisabled = _.get(params, 'isDisabled'); + var rollout = _.get(params, 'rollout'); + return models.Packages.findById(packageId) + .then((packageInfo) => { + if (!packageInfo) { + throw new AppError.AppError(`packageInfo not found`); } - }) - .then(() => { - + var new_params = { + description: description || packageInfo.description, + is_mandatory: isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO, + is_disabled: isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO, + rollout: rollout || 100 + }; + return models.Packages.update(new_params,{where: {id: packageId}}); }); }; -proto.promotePackage = function (sourceDeploymentId, destDeploymentId, promoteUid) { +proto.promotePackage = function (sourceDeploymentId, destDeploymentId, params) { var self = this; + var appVersion = params.appVersion; return models.Deployments.findById(sourceDeploymentId) .then((sourceDeployment) => { - var lastDeploymentVersionId = _.get(sourceDeployment, 'last_deployment_version_id', 0); - if (_.lte(lastDeploymentVersionId, 0)) { - throw new AppError.AppError('does not exist last_deployment_version_id.'); + if (appVersion) { + return models.DeploymentsVersions.findOne({where: {deployment_id: sourceDeploymentId, app_version:appVersion}}) + .then((deploymentsVersions)=>{return [sourceDeployment, deploymentsVersions]}); + } else { + var lastDeploymentVersionId = _.get(sourceDeployment, 'last_deployment_version_id', 0); + if (_.lte(lastDeploymentVersionId, 0)) { + throw new AppError.AppError('does not exist last_deployment_version_id.'); + } + return models.DeploymentsVersions.findById(lastDeploymentVersionId) + .then((deploymentsVersions)=>{return [sourceDeployment, deploymentsVersions]}); + } + }) + .spread((sourceDeployment, deploymentsVersions) => { + if (!deploymentsVersions) { + throw new AppError.AppError('does not exist deployment_version.'); + } + log.debug('deploymentsVersions',deploymentsVersions); + var packageId = _.get(deploymentsVersions, 'current_package_id', 0); + if (_.lte(packageId, 0)) { + throw new AppError.AppError('does not exist packages.'); } - return models.DeploymentsVersions.findById(lastDeploymentVersionId) - .then((deploymentsVersions) => { - var packageId = _.get(deploymentsVersions, 'current_package_id', 0); - if (_.lte(packageId, 0)) { + return models.Packages.findById(packageId) + .then((packages) => { + if (!packages) { throw new AppError.AppError('does not exist packages.'); } - return models.Packages.findById(packageId) - .then((packages) => { - if (!packages) { - throw new AppError.AppError('does not exist packages.'); + return self.createDeploymentsVersionIfNotExist(destDeploymentId, deploymentsVersions.app_version) + .then((deploymentsVersions) => { + return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packages.package_hash); + }) + .then((isExist) => { + if (isExist){ + throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); } - return self.createDeploymentsVersionIfNotExist(destDeploymentId, deploymentsVersions.app_version) - .then((deploymentsVersions) => { - return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packages.package_hash); - }) - .then((isExist) => { - if (isExist){ - throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); - } - }) - .then(() => [sourceDeployment, deploymentsVersions, packages]); - }); + }) + .then(() => [sourceDeployment, deploymentsVersions, packages]); }); }) .spread((sourceDeployment, deploymentsVersions, packages) => { - var params = { - releaseMethod: 'Promote', - releaseUid: promoteUid, - isMandatory: packages.is_mandatory == 1 ? true : false, + var create_params = { + releaseMethod: constConfig.RELEAS_EMETHOD_PROMOTE, + releaseUid: params.promoteUid || 0, + isMandatory: params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO, + isDisabled: params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO, + rollout: params.rollout || packages.rollout, size: packages.size, description: packages.description, originalLabel: packages.label, originalDeployment: sourceDeployment.name }; - return self.createPackage(destDeploymentId, deploymentsVersions.app_version, packages.package_hash, packages.manifest_blob_url, packages.blob_url, params); + return self.createPackage(destDeploymentId, deploymentsVersions.app_version, packages.package_hash, packages.manifest_blob_url, packages.blob_url, create_params); }); }; @@ -478,7 +494,9 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) var params = { releaseMethod: 'Rollback', releaseUid: rollbackUid, - isMandatory: rollbackPackage.is_mandatory == 1 ? true : false, + isMandatory: rollbackPackage.is_mandatory, + isDisabled: packages.is_disabled, + rollout: packages.rollout, size: rollbackPackage.size, description: rollbackPackage.description, originalLabel: rollbackPackage.label, @@ -498,6 +516,9 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) proto.getCanRollbackPackages = function (deploymentVersionId) { var Sequelize = require('sequelize'); return models.Packages.findAll({ - where: {deployment_version_id: deploymentVersionId, release_method: {[Sequelize.Op.in]: ['Upload', 'Promote'] }}, order: [['id','desc']], limit: 2 + where: { + deployment_version_id: deploymentVersionId, + release_method: {[Sequelize.Op.in]: [constConfig.RELEAS_EMETHOD_UPLOAD, constConfig.RELEAS_EMETHOD_PROMOTE] } + }, order: [['id','desc']], limit: 2 }); } diff --git a/core/utils/security.js b/core/utils/security.js index 3307018b..4bbc7095 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -124,16 +124,17 @@ security.uploadPackageType = function (directoryPath) { log.debug(`uploadPackageType empty files`); reject(new AppError.AppError("empty files")); } else { + var constName = require('../const'); const AREGEX=/android\.bundle/ const AREGEX_IOS=/main\.jsbundle/ var packageType = 0; _.forIn(files, function (value) { if (AREGEX.test(value)) { - packageType = 1; + packageType = constName.ANDROID; return false; } if (AREGEX_IOS.test(value)) { - packageType = 2; + packageType = constName.IOS; return false; } }); diff --git a/models/apps.js b/models/apps.js index 3261bc6e..a34425a7 100644 --- a/models/apps.js +++ b/models/apps.js @@ -10,6 +10,8 @@ module.exports = function(sequelize, DataTypes) { }, name: DataTypes.STRING, uid: DataTypes.BIGINT(20), + os: DataTypes.INTEGER(3), + platform: DataTypes.INTEGER(3), created_at: DataTypes.DATE, updated_at: DataTypes.DATE, }, { diff --git a/models/packages.js b/models/packages.js index 6ec423db..989eb32a 100644 --- a/models/packages.js +++ b/models/packages.js @@ -21,6 +21,8 @@ module.exports = function(sequelize, DataTypes) { original_deployment: DataTypes.STRING, released_by: DataTypes.STRING, is_mandatory: DataTypes.INTEGER(3), + is_disabled: DataTypes.INTEGER(3), + rollout: DataTypes.INTEGER(3), created_at: DataTypes.DATE, updated_at: DataTypes.DATE, }, { diff --git a/package-lock.json b/package-lock.json index ce2ce991..68e19da1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,28 +66,6 @@ "resolved": "http://registry.npm.taobao.org/address/download/address-1.0.3.tgz", "integrity": "sha1-tfUGMfjWzsi9IMljljr7VeBsvOk=" }, - "addressparser": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/addressparser/download/addressparser-1.0.1.tgz", - "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", - "optional": true - }, - "agent-base": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/agent-base/download/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "requires": { - "extend": "3.0.1", - "semver": "5.0.3" - }, - "dependencies": { - "semver": { - "version": "5.0.3", - "resolved": "http://registry.npm.taobao.org/semver/download/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" - } - } - }, "agentkeepalive": { "version": "3.3.0", "resolved": "http://registry.npm.taobao.org/agentkeepalive/download/agentkeepalive-3.3.0.tgz", @@ -158,56 +136,11 @@ "resolved": "http://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, - "amqplib": { - "version": "0.5.2", - "resolved": "http://registry.npm.taobao.org/amqplib/download/amqplib-0.5.2.tgz", - "integrity": "sha1-0tcxPH/6pNELzx5iUt5FkbbMe2M=", - "optional": true, - "requires": { - "bitsyntax": "0.0.4", - "bluebird": "3.5.1", - "buffer-more-ints": "0.0.2", - "readable-stream": "1.1.14", - "safe-buffer": "5.1.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "optional": true - } - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "optional": true - }, "ansicolors": { "version": "0.2.1", "resolved": "http://registry.npm.taobao.org/ansicolors/download/ansicolors-0.2.1.tgz", @@ -262,12 +195,6 @@ "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, - "ast-types": { - "version": "0.11.3", - "resolved": "http://registry.npm.taobao.org/ast-types/download/ast-types-0.11.3.tgz", - "integrity": "sha1-wgdX/nLucSeOoP89h+XCyjDZ7fg=", - "optional": true - }, "async": { "version": "1.5.2", "resolved": "http://registry.npm.taobao.org/async/download/async-1.5.2.tgz", @@ -328,15 +255,6 @@ "resolved": "http://registry.npm.taobao.org/aws4/download/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, - "axios": { - "version": "0.15.3", - "resolved": "http://registry.npm.taobao.org/axios/download/axios-0.15.3.tgz", - "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", - "optional": true, - "requires": { - "follow-redirects": "1.0.0" - } - }, "babel-runtime": { "version": "6.26.0", "resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", @@ -399,52 +317,6 @@ "resolved": "http://registry.npm.taobao.org/bcryptjs/download/bcryptjs-2.4.3.tgz", "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" }, - "bitsyntax": { - "version": "0.0.4", - "resolved": "http://registry.npm.taobao.org/bitsyntax/download/bitsyntax-0.0.4.tgz", - "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", - "optional": true, - "requires": { - "buffer-more-ints": "0.0.2" - } - }, - "bl": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/bl/download/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", - "optional": true, - "requires": { - "readable-stream": "2.0.6" - }, - "dependencies": { - "process-nextick-args": { - "version": "1.0.7", - "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "optional": true - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "optional": true - } - } - }, "bluebird": { "version": "3.5.1", "resolved": "http://registry.npm.taobao.org/bluebird/download/bluebird-3.5.1.tgz", @@ -465,6 +337,16 @@ "qs": "6.5.1", "raw-body": "2.3.2", "type-is": "1.6.16" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "boom": { @@ -510,44 +392,11 @@ "resolved": "http://registry.npm.taobao.org/buffer-equal-constant-time/download/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, - "buffer-more-ints": { - "version": "0.0.2", - "resolved": "http://registry.npm.taobao.org/buffer-more-ints/download/buffer-more-ints-0.0.2.tgz", - "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=" - }, "bufferview": { "version": "1.0.1", "resolved": "http://registry.npm.taobao.org/bufferview/download/bufferview-1.0.1.tgz", "integrity": "sha1-ev10pF+Tf6QiodM4wIu/3HbNcl0=" }, - "buildmail": { - "version": "4.0.1", - "resolved": "http://registry.npm.taobao.org/buildmail/download/buildmail-4.0.1.tgz", - "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", - "optional": true, - "requires": { - "addressparser": "1.0.1", - "libbase64": "0.1.0", - "libmime": "3.0.0", - "libqp": "1.1.0", - "nodemailer-fetch": "1.6.0", - "nodemailer-shared": "1.1.0", - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "optional": true - } - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/builtin-modules/download/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, "bytebuffer": { "version": "4.1.0", "resolved": "http://registry.npm.taobao.org/bytebuffer/download/bytebuffer-4.1.0.tgz", @@ -595,19 +444,6 @@ "lazy-cache": "1.0.4" } }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "optional": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, "character-parser": { "version": "2.2.0", "resolved": "http://registry.npm.taobao.org/character-parser/download/character-parser-2.2.0.tgz", @@ -617,9 +453,9 @@ } }, "circular-json": { - "version": "0.5.1", - "resolved": "http://registry.npm.taobao.org/circular-json/download/circular-json-0.5.1.tgz", - "integrity": "sha1-uJQqCeU1hj3CGwRBepGXHh2c2R8=" + "version": "0.5.5", + "resolved": "http://registry.npm.taobao.org/circular-json/download/circular-json-0.5.5.tgz", + "integrity": "sha1-ZBgu81kELTfNjnZ/yd6Hix6UR9M=" }, "clean-css": { "version": "3.4.28", @@ -695,12 +531,6 @@ "delayed-stream": "1.0.0" } }, - "commander": { - "version": "2.15.0", - "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.15.0.tgz", - "integrity": "sha1-rSojocOwNuOSRpuAEs7GsztMEyI=", - "optional": true - }, "component-emitter": { "version": "1.2.1", "resolved": "http://registry.npm.taobao.org/component-emitter/download/component-emitter-1.2.1.tgz", @@ -793,20 +623,9 @@ "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "requires": { - "lru-cache": "4.1.2", + "lru-cache": "4.1.3", "shebang-command": "1.2.0", "which": "1.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.2", - "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.2.tgz", - "integrity": "sha1-RSNLLm4vKzPaElYkxGZJKaAiTD8=", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - } } }, "cryptiles": { @@ -848,21 +667,15 @@ "resolved": "http://registry.npm.taobao.org/dasherize/download/dasherize-2.0.0.tgz", "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/data-uri-to-buffer/download/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha1-dxY+qcINhkG0cH6PGKvfmnjzSDU=", - "optional": true - }, "date-format": { "version": "1.2.0", "resolved": "http://registry.npm.taobao.org/date-format/download/date-format-1.2.0.tgz", "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=" }, "debug": { - "version": "2.6.9", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "version": "3.1.0", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "requires": { "ms": "2.0.0" } @@ -875,7 +688,8 @@ "deep-is": { "version": "0.1.3", "resolved": "http://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "default-user-agent": { "version": "1.0.0", @@ -885,17 +699,6 @@ "os-name": "1.0.3" } }, - "degenerator": { - "version": "1.0.4", - "resolved": "http://registry.npm.taobao.org/degenerator/download/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "optional": true, - "requires": { - "ast-types": "0.11.3", - "escodegen": "1.9.1", - "esprima": "3.1.3" - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", @@ -1001,14 +804,6 @@ "resolved": "http://registry.npm.taobao.org/entities/download/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, - "error-ex": { - "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/error-ex/download/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "requires": { - "is-arrayish": "0.2.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", @@ -1017,31 +812,8 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "http://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "escodegen": { - "version": "1.9.1", - "resolved": "http://registry.npm.taobao.org/escodegen/download/escodegen-1.9.1.tgz", - "integrity": "sha1-264X75bI5L7bE1b0UE+kzC98t+I=", - "optional": true, - "requires": { - "esprima": "3.1.3", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.6.1" - } - }, - "esprima": { - "version": "3.1.3", - "resolved": "http://registry.npm.taobao.org/esprima/download/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - }, - "estraverse": { - "version": "4.2.0", - "resolved": "http://registry.npm.taobao.org/estraverse/download/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "optional": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "esutils": { "version": "2.0.2", @@ -1114,6 +886,14 @@ "vary": "1.1.2" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, "setprototypeof": { "version": "1.1.0", "resolved": "http://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz", @@ -1165,6 +945,16 @@ "debug": "2.6.9", "mkdirp": "0.5.0", "yauzl": "2.4.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "extsprintf": { @@ -1185,7 +975,8 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "http://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fd-slicer": { "version": "1.0.1", @@ -1195,12 +986,6 @@ "pend": "1.2.0" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz", - "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", - "optional": true - }, "finalhandler": { "version": "1.1.1", "resolved": "http://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.1.tgz", @@ -1213,23 +998,24 @@ "parseurl": "1.3.2", "statuses": "1.4.0", "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "find-up": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.0.0.tgz", - "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", - "optional": true, + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", "requires": { - "debug": "2.6.9" + "locate-path": "3.0.0" } }, "forever-agent": { @@ -1278,13 +1064,13 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "fs-extra": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/fs-extra/download/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "version": "7.0.0", + "resolved": "http://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.0.tgz", + "integrity": "sha1-jMP0fOB+97NZOhG5+yRffjTAQdY=", "requires": { "graceful-fs": "4.1.11", - "jsonfile": "3.0.1", - "universalify": "0.1.1" + "jsonfile": "4.0.0", + "universalify": "0.1.2" } }, "fs.realpath": { @@ -1293,42 +1079,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "ftp": { - "version": "0.3.10", - "resolved": "http://registry.npm.taobao.org/ftp/download/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "optional": true, - "requires": { - "readable-stream": "1.1.14", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "optional": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "optional": true - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "http://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", @@ -1339,44 +1089,21 @@ "resolved": "http://registry.npm.taobao.org/generate-function/download/generate-function-2.0.0.tgz", "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/generate-object-property/download/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "optional": true, - "requires": { - "is-property": "1.0.2" - } - }, "generic-pool": { "version": "3.4.2", "resolved": "http://registry.npm.taobao.org/generic-pool/download/generic-pool-3.4.2.tgz", "integrity": "sha1-kv9xllINZwg5pnMICSoSqt8valk=" }, "get-caller-file": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/get-caller-file/download/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/get-caller-file/download/get-caller-file-1.0.3.tgz", + "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=" }, "get-stream": { "version": "3.0.0", "resolved": "http://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, - "get-uri": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/get-uri/download/get-uri-2.0.1.tgz", - "integrity": "sha1-29ysrNjGCKODFoaTaBF2l6FjHFk=", - "optional": true, - "requires": { - "data-uri-to-buffer": "1.2.0", - "debug": "2.6.9", - "extend": "3.0.1", - "file-uri-to-path": "1.0.0", - "ftp": "0.3.10", - "readable-stream": "2.3.5" - } - }, "getpass": { "version": "0.1.7", "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", @@ -1458,15 +1185,6 @@ "function-bind": "1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "optional": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, "has-flag": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-1.0.0.tgz", @@ -1526,26 +1244,11 @@ "resolved": "http://registry.npm.taobao.org/hide-powered-by/download/hide-powered-by-1.0.0.tgz", "integrity": "sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=" }, - "hipchat-notifier": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/hipchat-notifier/download/hipchat-notifier-1.1.0.tgz", - "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", - "optional": true, - "requires": { - "lodash": "4.17.5", - "request": "2.85.0" - } - }, "hoek": { "version": "4.2.1", "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-4.2.1.tgz", "integrity": "sha1-ljRQKqEsRF3Vp8VzS1cruHOKrLs=" }, - "hosted-git-info": { - "version": "2.6.0", - "resolved": "http://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.6.0.tgz", - "integrity": "sha1-IyNbKasjDFdqqw1PE/wEawsDgiI=" - }, "hpkp": { "version": "2.0.0", "resolved": "http://registry.npm.taobao.org/hpkp/download/hpkp-2.0.0.tgz", @@ -1574,16 +1277,6 @@ } } }, - "http-proxy-agent": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/http-proxy-agent/download/http-proxy-agent-1.0.0.tgz", - "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, "http-signature": { "version": "1.2.0", "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", @@ -1594,30 +1287,6 @@ "sshpk": "1.14.1" } }, - "httpntlm": { - "version": "1.6.1", - "resolved": "http://registry.npm.taobao.org/httpntlm/download/httpntlm-1.6.1.tgz", - "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", - "requires": { - "httpreq": "0.4.24", - "underscore": "1.7.0" - } - }, - "httpreq": { - "version": "0.4.24", - "resolved": "http://registry.npm.taobao.org/httpreq/download/httpreq-0.4.24.tgz", - "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=" - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/https-proxy-agent/download/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, "humanize-ms": { "version": "1.2.1", "resolved": "http://registry.npm.taobao.org/humanize-ms/download/humanize-ms-1.2.1.tgz", @@ -1631,7 +1300,7 @@ "resolved": "http://registry.npm.taobao.org/i18n/download/i18n-0.8.3.tgz", "integrity": "sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4=", "requires": { - "debug": "2.6.9", + "debug": "3.1.0", "make-plural": "3.0.6", "math-interval-parser": "1.1.0", "messageformat": "0.3.1", @@ -1668,12 +1337,6 @@ "resolved": "http://registry.npm.taobao.org/ignorepatterns/download/ignorepatterns-1.1.0.tgz", "integrity": "sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4=" }, - "inflection": { - "version": "1.10.0", - "resolved": "http://registry.npm.taobao.org/inflection/download/inflection-1.10.0.tgz", - "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", - "optional": true - }, "inflight": { "version": "1.0.6", "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", @@ -1693,22 +1356,11 @@ "resolved": "http://registry.npm.taobao.org/invert-kv/download/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, - "ip": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.0.1.tgz", - "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", - "optional": true - }, "ipaddr.js": { "version": "1.6.0", "resolved": "http://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.6.0.tgz", "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "http://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, "is-bluebird": { "version": "1.0.2", "resolved": "http://registry.npm.taobao.org/is-bluebird/download/is-bluebird-1.0.2.tgz", @@ -1719,14 +1371,6 @@ "resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-builtin-module/download/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "requires": { - "builtin-modules": "1.1.1" - } - }, "is-expression": { "version": "3.0.0", "resolved": "http://registry.npm.taobao.org/is-expression/download/is-expression-3.0.0.tgz", @@ -1751,36 +1395,11 @@ "number-is-nan": "1.0.1" } }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-my-ip-valid/download/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha1-ezUbjo7dTTmV1NBmaA5mTZRpaCQ=", - "optional": true - }, - "is-my-json-valid": { - "version": "2.17.2", - "resolved": "http://registry.npm.taobao.org/is-my-json-valid/download/is-my-json-valid-2.17.2.tgz", - "integrity": "sha1-ayEDoojpTvPeXPFdKd2F/Et41lw=", - "optional": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "is-my-ip-valid": "1.0.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, "is-promise": { "version": "2.1.0", "resolved": "http://registry.npm.taobao.org/is-promise/download/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, - "is-property": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/is-property/download/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "optional": true - }, "is-regex": { "version": "1.0.4", "resolved": "http://registry.npm.taobao.org/is-regex/download/is-regex-1.0.4.tgz", @@ -1950,19 +1569,13 @@ "dev": true }, "jsonfile": { - "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "version": "4.0.0", + "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { "graceful-fs": "4.1.11" } }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "http://registry.npm.taobao.org/jsonpointer/download/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "optional": true - }, "jsonwebtoken": { "version": "8.2.0", "resolved": "http://registry.npm.taobao.org/jsonwebtoken/download/jsonwebtoken-8.2.0.tgz", @@ -2053,38 +1666,12 @@ "version": "0.3.0", "resolved": "http://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" } }, - "libbase64": { - "version": "0.1.0", - "resolved": "http://registry.npm.taobao.org/libbase64/download/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=" - }, - "libmime": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/libmime/download/libmime-3.0.0.tgz", - "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", - "requires": { - "iconv-lite": "0.4.15", - "libbase64": "0.1.0", - "libqp": "1.1.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.15", - "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" - } - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/libqp/download/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" - }, "linkify-it": { "version": "2.0.3", "resolved": "http://registry.npm.taobao.org/linkify-it/download/linkify-it-2.0.3.tgz", @@ -2093,23 +1680,12 @@ "uc.micro": "1.0.5" } }, - "load-json-file": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" - } - }, "locate-path": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", "requires": { - "p-locate": "2.0.0", + "p-locate": "3.0.0", "path-exists": "3.0.0" } }, @@ -2227,299 +1803,34 @@ "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" }, "log4js": { - "version": "2.5.3", - "resolved": "http://registry.npm.taobao.org/log4js/download/log4js-2.5.3.tgz", - "integrity": "sha1-OLt73l6cHBgb116LwSjFzQQJyvE=", + "version": "3.0.5", + "resolved": "http://registry.npm.taobao.org/log4js/download/log4js-3.0.5.tgz", + "integrity": "sha1-uAFGv+utaLQw1PNWlVbYpu3+8wM=", "requires": { - "amqplib": "0.5.2", - "axios": "0.15.3", - "circular-json": "0.5.1", + "circular-json": "0.5.5", "date-format": "1.2.0", "debug": "3.1.0", - "hipchat-notifier": "1.1.0", - "loggly": "1.1.1", - "mailgun-js": "0.7.15", - "nodemailer": "2.7.2", - "redis": "2.8.0", - "semver": "5.5.0", - "slack-node": "0.2.0", + "rfdc": "1.1.2", "streamroller": "0.7.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "requires": { - "ms": "2.0.0" - } - }, - "ip": { - "version": "1.1.5", - "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "optional": true - }, - "nodemailer": { - "version": "2.7.2", - "resolved": "http://registry.npm.taobao.org/nodemailer/download/nodemailer-2.7.2.tgz", - "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", - "optional": true, - "requires": { - "libmime": "3.0.0", - "mailcomposer": "4.0.1", - "nodemailer-direct-transport": "3.3.2", - "nodemailer-shared": "1.1.0", - "nodemailer-smtp-pool": "2.8.2", - "nodemailer-smtp-transport": "2.7.2", - "socks": "1.1.9" - } - }, - "socks": { - "version": "1.1.9", - "resolved": "http://registry.npm.taobao.org/socks/download/socks-1.1.9.tgz", - "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", - "optional": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - } - } - } - }, - "loggly": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/loggly/download/loggly-1.1.1.tgz", - "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", - "optional": true, - "requires": { - "json-stringify-safe": "5.0.1", - "request": "2.75.0", - "timespan": "2.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "optional": true - }, - "boom": { - "version": "2.10.1", - "resolved": "http://registry.npm.taobao.org/boom/download/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "requires": { - "hoek": "2.16.3" - } - }, - "caseless": { - "version": "0.11.0", - "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "optional": true - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "optional": true, - "requires": { - "boom": "2.10.1" - } - }, - "form-data": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.0.0.tgz", - "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "optional": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.15.0", - "is-my-json-valid": "2.17.2", - "pinkie-promise": "2.0.1" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "http://registry.npm.taobao.org/hawk/download/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "optional": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - }, - "http-signature": { - "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" - } - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "http://registry.npm.taobao.org/node-uuid/download/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "optional": true - }, - "qs": { - "version": "6.2.3", - "resolved": "http://registry.npm.taobao.org/qs/download/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "optional": true - }, - "request": { - "version": "2.75.0", - "resolved": "http://registry.npm.taobao.org/request/download/request-2.75.0.tgz", - "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "bl": "1.1.2", - "caseless": "0.11.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.0.0", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "node-uuid": "1.4.8", - "oauth-sign": "0.8.2", - "qs": "6.2.3", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.4.3" - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "optional": true, - "requires": { - "hoek": "2.16.3" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "optional": true - } } }, "long": { "version": "2.4.0", "resolved": "http://registry.npm.taobao.org/long/download/long-2.4.0.tgz", - "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" - }, - "longest": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" - }, - "lru-cache": { - "version": "2.6.5", - "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-2.6.5.tgz", - "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", - "optional": true - }, - "mailcomposer": { - "version": "4.0.1", - "resolved": "http://registry.npm.taobao.org/mailcomposer/download/mailcomposer-4.0.1.tgz", - "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", - "optional": true, - "requires": { - "buildmail": "4.0.1", - "libmime": "3.0.0" - } + "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" }, - "mailgun-js": { - "version": "0.7.15", - "resolved": "http://registry.npm.taobao.org/mailgun-js/download/mailgun-js-0.7.15.tgz", - "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", - "optional": true, + "longest": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.3.tgz", + "integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=", "requires": { - "async": "2.1.5", - "debug": "2.2.0", - "form-data": "2.1.4", - "inflection": "1.10.0", - "is-stream": "1.1.0", - "path-proxy": "1.0.0", - "proxy-agent": "2.0.0", - "q": "1.4.1", - "tsscmp": "1.0.5" - }, - "dependencies": { - "async": { - "version": "2.1.5", - "resolved": "http://registry.npm.taobao.org/async/download/async-2.1.5.tgz", - "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", - "optional": true, - "requires": { - "lodash": "4.17.5" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "optional": true, - "requires": { - "ms": "0.7.1" - } - }, - "form-data": { - "version": "2.1.4", - "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "optional": true - } + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "make-plural": { @@ -2751,6 +2062,16 @@ "depd": "1.1.2", "on-finished": "2.3.0", "on-headers": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "ms": { @@ -2837,12 +2158,6 @@ "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, - "netmask": { - "version": "1.0.6", - "resolved": "http://registry.npm.taobao.org/netmask/download/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "optional": true - }, "nocache": { "version": "2.0.0", "resolved": "http://registry.npm.taobao.org/nocache/download/nocache-2.0.0.tgz", @@ -2854,6 +2169,16 @@ "integrity": "sha1-icFSr4itKIF/ANiRyZBFHV1xLqg=", "requires": { "debug": "2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "nodemailer": { @@ -2861,56 +2186,6 @@ "resolved": "http://registry.npm.taobao.org/nodemailer/download/nodemailer-4.6.3.tgz", "integrity": "sha1-w7fpf7cvRtSkdcQGoV7SOkXbzdw=" }, - "nodemailer-direct-transport": { - "version": "3.3.2", - "resolved": "http://registry.npm.taobao.org/nodemailer-direct-transport/download/nodemailer-direct-transport-3.3.2.tgz", - "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-fetch": { - "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/nodemailer-fetch/download/nodemailer-fetch-1.6.0.tgz", - "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=" - }, - "nodemailer-shared": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/nodemailer-shared/download/nodemailer-shared-1.1.0.tgz", - "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", - "requires": { - "nodemailer-fetch": "1.6.0" - } - }, - "nodemailer-smtp-pool": { - "version": "2.8.2", - "resolved": "http://registry.npm.taobao.org/nodemailer-smtp-pool/download/nodemailer-smtp-pool-2.8.2.tgz", - "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "http://registry.npm.taobao.org/nodemailer-smtp-transport/download/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", - "optional": true, - "requires": { - "nodemailer-shared": "1.1.0", - "nodemailer-wellknown": "0.1.10", - "smtp-connection": "2.12.0" - } - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "resolved": "http://registry.npm.taobao.org/nodemailer-wellknown/download/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=" - }, "nopt": { "version": "3.0.6", "resolved": "http://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz", @@ -2919,17 +2194,6 @@ "abbrev": "1.1.1" } }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", - "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.3" - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", @@ -2996,6 +2260,7 @@ "version": "0.8.2", "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -3048,71 +2313,25 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-1.2.0.tgz", - "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-2.0.0.tgz", + "integrity": "sha1-5iTtVO6MRgp3izyfNnBJb/ileuw=", "requires": { - "p-try": "1.0.0" + "p-try": "2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", "requires": { - "p-limit": "1.2.0" + "p-limit": "2.0.0" } }, "p-try": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "pac-proxy-agent": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/pac-proxy-agent/download/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha1-NKOF399h0vDsrOCIWMdF0+eR/U0=", - "optional": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1", - "get-uri": "2.0.1", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "1.0.0", - "pac-resolver": "2.0.0", - "raw-body": "2.3.2", - "socks-proxy-agent": "2.1.1" - } - }, - "pac-resolver": { "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/pac-resolver/download/pac-resolver-2.0.0.tgz", - "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", - "optional": true, - "requires": { - "co": "3.0.6", - "degenerator": "1.0.4", - "ip": "1.0.1", - "netmask": "1.0.6", - "thunkify": "2.1.2" - }, - "dependencies": { - "co": { - "version": "3.0.6", - "resolved": "http://registry.npm.taobao.org/co/download/co-3.0.6.tgz", - "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", - "optional": true - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } + "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-2.0.0.tgz", + "integrity": "sha1-hQgLuHxkaI+keZb+j3376CEXYLE=" }, "parseurl": { "version": "1.3.2", @@ -3139,36 +2358,11 @@ "resolved": "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, - "path-proxy": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/path-proxy/download/path-proxy-1.0.0.tgz", - "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", - "optional": true, - "requires": { - "inflection": "1.3.8" - }, - "dependencies": { - "inflection": { - "version": "1.3.8", - "resolved": "http://registry.npm.taobao.org/inflection/download/inflection-1.3.8.tgz", - "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", - "optional": true - } - } - }, "path-to-regexp": { "version": "0.1.7", "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "path-type": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "requires": { - "pify": "2.3.0" - } - }, "pause-stream": { "version": "0.0.11", "resolved": "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz", @@ -3187,26 +2381,6 @@ "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, - "pify": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "optional": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "optional": true, - "requires": { - "pinkie": "2.0.4" - } - }, "platform": { "version": "1.3.5", "resolved": "http://registry.npm.taobao.org/platform/download/platform-1.3.5.tgz", @@ -3220,7 +2394,8 @@ "prelude-ls": { "version": "1.1.2", "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, "process-nextick-args": { "version": "2.0.0", @@ -3271,22 +2446,6 @@ "ipaddr.js": "1.6.0" } }, - "proxy-agent": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/proxy-agent/download/proxy-agent-2.0.0.tgz", - "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", - "optional": true, - "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "1.0.0", - "lru-cache": "2.6.5", - "pac-proxy-agent": "1.1.0", - "socks-proxy-agent": "2.1.1" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz", @@ -3411,12 +2570,6 @@ "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" }, - "q": { - "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/q/download/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "optional": true - }, "qiniu": { "version": "7.1.3", "resolved": "http://registry.npm.taobao.org/qiniu/download/qiniu-7.1.3.tgz", @@ -3449,9 +2602,9 @@ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, "rand-token": { - "version": "0.3.0", - "resolved": "http://registry.npm.taobao.org/rand-token/download/rand-token-0.3.0.tgz", - "integrity": "sha1-MsDmciAIZ3ZqE2AaIc75isZ0eMc=" + "version": "0.4.0", + "resolved": "http://registry.npm.taobao.org/rand-token/download/rand-token-0.4.0.tgz", + "integrity": "sha1-GlZbatEtkt1LMMTE5ZReiqJKWzs=" }, "range-parser": { "version": "1.2.0", @@ -3469,25 +2622,6 @@ "unpipe": "1.0.0" } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" - } - }, "readable-stream": { "version": "2.3.5", "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz", @@ -3589,18 +2723,6 @@ "uuid": "3.1.0" } }, - "requestretry": { - "version": "1.13.0", - "resolved": "http://registry.npm.taobao.org/requestretry/download/requestretry-1.13.0.tgz", - "integrity": "sha1-IT7BAG7rdQ6LjOVBdig9FajVXZQ=", - "optional": true, - "requires": { - "extend": "3.0.1", - "lodash": "4.17.5", - "request": "2.85.0", - "when": "3.7.8" - } - }, "require-directory": { "version": "2.1.1", "resolved": "http://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", @@ -3626,8 +2748,23 @@ "requires": { "bluebird": "3.5.1", "debug": "2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, + "rfdc": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/rfdc/download/rfdc-1.1.2.tgz", + "integrity": "sha1-5uctdPXcOd6PU49l4Aw2wYAY40k=" + }, "right-align": { "version": "0.1.3", "resolved": "http://registry.npm.taobao.org/right-align/download/right-align-0.1.3.tgz", @@ -3687,6 +2824,16 @@ "on-finished": "2.3.0", "range-parser": "1.2.0", "statuses": "1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "seq-queue": { @@ -3735,6 +2882,11 @@ "version": "3.2.1", "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.2.1.tgz", "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=" + }, + "validator": { + "version": "9.4.1", + "resolved": "http://registry.npm.taobao.org/validator/download/validator-9.4.1.tgz", + "integrity": "sha1-q/Rm05i1Yc0kMFARLG/x3mzBJmM=" } } }, @@ -3848,33 +3000,10 @@ "resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, - "slack-node": { - "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/slack-node/download/slack-node-0.2.0.tgz", - "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", - "optional": true, - "requires": { - "requestretry": "1.13.0" - } - }, "slash": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "http://registry.npm.taobao.org/smart-buffer/download/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=" - }, - "smtp-connection": { - "version": "2.12.0", - "resolved": "http://registry.npm.taobao.org/smtp-connection/download/smtp-connection-2.12.0.tgz", - "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", - "requires": { - "httpntlm": "1.6.1", - "nodemailer-shared": "1.1.0" - } + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz", + "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=" }, "sntp": { "version": "2.1.0", @@ -3884,66 +3013,6 @@ "hoek": "4.2.1" } }, - "socks": { - "version": "1.1.10", - "resolved": "http://registry.npm.taobao.org/socks/download/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - } - } - }, - "socks-proxy-agent": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/socks-proxy-agent/download/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha1-huuwcZMlhjeHDhO3vZnybGY989M=", - "requires": { - "agent-base": "2.1.1", - "extend": "3.0.1", - "socks": "1.1.10" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "optional": true - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.0.0.tgz", - "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", - "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.1.0.tgz", - "integrity": "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k=" - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", - "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.0.tgz", - "integrity": "sha1-enzShHDMbToc/m1miG9rxDDTrIc=" - }, "sprintf-js": { "version": "1.1.1", "resolved": "http://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.1.1.tgz", @@ -3985,14 +3054,6 @@ "readable-stream": "2.3.5" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", - "requires": { - "ms": "2.0.0" - } - }, "mkdirp": { "version": "0.5.1", "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz", @@ -4034,11 +3095,6 @@ "ansi-regex": "2.1.1" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - }, "strip-eof": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", @@ -4089,12 +3145,6 @@ "integrity": "sha1-3n5jNwFbKRhRwQ81OMSn8EkX7ME=", "dev": true }, - "supports-color": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "optional": true - }, "taskgroup": { "version": "4.3.1", "resolved": "http://registry.npm.taobao.org/taskgroup/download/taskgroup-4.3.1.tgz", @@ -4125,18 +3175,6 @@ "resolved": "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, - "thunkify": { - "version": "2.1.2", - "resolved": "http://registry.npm.taobao.org/thunkify/download/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "optional": true - }, - "timespan": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/timespan/download/timespan-2.3.0.tgz", - "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", - "optional": true - }, "to-fast-properties": { "version": "1.0.3", "resolved": "http://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-1.0.3.tgz", @@ -4167,12 +3205,6 @@ } } }, - "tsscmp": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/tsscmp/download/tsscmp-1.0.5.tgz", - "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", - "optional": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", @@ -4191,6 +3223,7 @@ "version": "0.3.2", "resolved": "http://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, "requires": { "prelude-ls": "1.1.2" } @@ -4278,15 +3311,10 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, - "underscore": { - "version": "1.7.0", - "resolved": "http://registry.npm.taobao.org/underscore/download/underscore-1.7.0.tgz", - "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" - }, "universalify": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/universalify/download/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + "version": "0.1.2", + "resolved": "http://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" }, "unpipe": { "version": "1.0.0", @@ -4317,6 +3345,16 @@ "iconv-lite": "0.4.19", "qs": "6.5.1", "statuses": "1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } } }, "util-deprecate": { @@ -4342,19 +3380,10 @@ "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.1.0.tgz", "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" }, - "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "http://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", - "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" - } - }, "validator": { - "version": "9.4.1", - "resolved": "http://registry.npm.taobao.org/validator/download/validator-9.4.1.tgz", - "integrity": "sha1-q/Rm05i1Yc0kMFARLG/x3mzBJmM=" + "version": "10.6.0", + "resolved": "http://registry.npm.taobao.org/validator/download/validator-10.6.0.tgz", + "integrity": "sha1-qb3OaFs8PoSA5+u7nrlcVM2XM7A=" }, "vary": { "version": "1.1.2", @@ -4391,12 +3420,6 @@ "typechecker": "2.1.0" } }, - "when": { - "version": "3.7.8", - "resolved": "http://registry.npm.taobao.org/when/download/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "optional": true - }, "which": { "version": "1.3.0", "resolved": "http://registry.npm.taobao.org/which/download/which-1.3.0.tgz", @@ -4443,7 +3466,8 @@ "wordwrap": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true }, "wrap-ansi": { "version": "2.1.0", @@ -4509,23 +3533,22 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { - "version": "8.0.2", - "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", - "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", + "version": "12.0.1", + "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-12.0.1.tgz", + "integrity": "sha1-ZDLlYSO7Tnw1YhFUAemDdAYCYcI=", + "requires": { + "cliui": "4.1.0", + "decamelize": "2.0.0", + "find-up": "3.0.0", + "get-caller-file": "1.0.3", "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", "require-directory": "2.1.1", "require-main-filename": "1.0.1", "set-blocking": "2.0.0", "string-width": "2.1.1", "which-module": "2.0.0", "y18n": "3.2.1", - "yargs-parser": "7.0.0" + "yargs-parser": "10.1.0" }, "dependencies": { "ansi-regex": { @@ -4533,10 +3556,23 @@ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, - "camelcase": { + "cliui": { "version": "4.1.0", - "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz", + "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/decamelize/download/decamelize-2.0.0.tgz", + "integrity": "sha1-ZW17vICUxMeI6lPFhAkIycfQY8c=", + "requires": { + "xregexp": "4.0.0" + } }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -4569,13 +3605,18 @@ "requires": { "ansi-regex": "3.0.0" } + }, + "xregexp": { + "version": "4.0.0", + "resolved": "http://registry.npm.taobao.org/xregexp/download/xregexp-4.0.0.tgz", + "integrity": "sha1-5pgYneSd0qGMxWh7BeF8jkOUMCA=" } } }, "yargs-parser": { - "version": "7.0.0", - "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "version": "10.1.0", + "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-10.1.0.tgz", + "integrity": "sha1-cgImW4n36eny5XZeD+c1qQXtuqg=", "requires": { "camelcase": "4.1.0" }, diff --git a/package.json b/package.json index 0d173b8f..43b12f39 100644 --- a/package.json +++ b/package.json @@ -45,16 +45,16 @@ "bluebird": "^3.4.1", "body-parser": "^1.15.2", "cookie-parser": "^1.4.3", - "debug": "^2.6.8", + "debug": "^3.1.0", "express": "^4.14.0", "extract-zip": "^1.6.0", "formidable": "^1.2.1", - "fs-extra": "^3.0.1", + "fs-extra": "^7.0.0", "helmet": "^3.1.0", "i18n": "^0.8.3", "jsonwebtoken": "^8.2.0", "lodash": "^4.17.5", - "log4js": "^2.5.3", + "log4js": "^3.0.5", "markdown-it": "^8.0.1", "moment": "^2.14.1", "morgan": "^1.7.0", @@ -62,15 +62,15 @@ "nodemailer": "^4.0.1", "pug": "^2.0.1", "qiniu": "^7.1.3", - "rand-token": "^0.3.0", + "rand-token": "^0.4.0", "recursive-readdir": "^2.1.1", "redis": "^2.6.2", "request": "^2.72.0", "sequelize": "^4.37.1", "serve-favicon": "^2.4.0", - "slash": "^1.0.0", - "validator": "^9.4.1", - "yargs": "^8.0.2", + "slash": "^2.0.0", + "validator": "^10.6.0", + "yargs": "^12.0.1", "yazl": "^2.3.0" }, "devDependencies": { diff --git a/routes/apps.js b/routes/apps.js index be5d414a..991d6152 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -18,8 +18,7 @@ const REGEX_IOS = /^(\w+)(-ios)$/; var log4js = require('log4js'); var log = log4js.getLogger("cps:apps"); -router.get('/', - middleware.checkToken, (req, res, next) => { +router.get('/', middleware.checkToken, (req, res, next) => { var uid = req.users.id; var appManager = new AppManager(); appManager.listApps(uid) @@ -268,17 +267,7 @@ router.post('/:appName/deployments/:deploymentName/release', var packageManager = new PackageManager(); accountManager.collaboratorCan(uid, appName) .then((col) => { - var pubType = ''; - log.debug(`check publish type`); - if (REGEX_ANDROID.test(appName)) { - pubType = 'android'; - } else if (REGEX_IOS.test(appName)) { - pubType = 'ios'; - } else { - log.debug(`you have to rename app name, eg. Demo-android Demo-ios`); - throw new AppError.AppError(`you have to rename app name, eg. Demo-android Demo-ios`); - } - log.debug(`publish type is ${pubType}`); + log.debug(col); return deployments.findDeloymentByName(deploymentName, col.appid) .then((deploymentInfo) => { if (_.isEmpty(deploymentInfo)) { @@ -287,7 +276,12 @@ router.post('/:appName/deployments/:deploymentName/release', } return packageManager.parseReqFile(req) .then((data) => { - return packageManager.releasePackage(deploymentInfo.id, data.packageInfo, data.package.type, data.package.path, uid, pubType) + if (data.package.type != "application/zip") { + log.debug(`upload file type is invlidate`, data.package); + throw new AppError.AppError("upload file type is invalidate"); + } + log.debug('packageInfo:', data.packageInfo); + return packageManager.releasePackage(deploymentInfo.appid, deploymentInfo.id, data.packageInfo, data.package.path, uid) .finally(() => { common.deleteFolderSync(data.package.path); }); @@ -315,7 +309,7 @@ router.post('/:appName/deployments/:deploymentName/release', }); }); }) - .then((data) => { + .then(() => { res.send('{"msg": "succeed"}'); }) .catch((e) => { @@ -329,12 +323,13 @@ router.post('/:appName/deployments/:deploymentName/release', router.patch('/:appName/deployments/:deploymentName/release', middleware.checkToken, (req, res, next) => { - return res.status(406).send('Not supported currently'); + log.debug('req.body', req.body); var appName = _.trim(req.params.appName); var deploymentName = _.trim(req.params.deploymentName); var uid = req.users.id; var deployments = new Deployments(); var packageManager = new PackageManager(); + var label = _.get(req, 'body.packageInfo.label'); accountManager.collaboratorCan(uid, appName) .then((col) => { return deployments.findDeloymentByName(deploymentName, col.appid) @@ -342,9 +337,35 @@ router.patch('/:appName/deployments/:deploymentName/release', if (_.isEmpty(deploymentInfo)) { throw new AppError.AppError("does not find the deployment"); } - var label = deploymentInfo.label; - var deploymentVersionId = deploymentInfo.last_deployment_version_id; - return packageManager.modifyReleasePackage(deploymentInfo.id, deploymentVersionId, _.get(req, 'body.packageInfo')); + if (label) { + return packageManager.findPackageInfoByDeploymentIdAndLabel(deploymentInfo.id, label) + .then((data)=>{ + return [deploymentInfo, data]; + }); + } else { + var deploymentVersionId = deploymentInfo.last_deployment_version_id; + return packageManager.findLatestPackageInfoByDeployVersion(deploymentVersionId) + .then((data)=>{ + return [deploymentInfo, data]; + });; + } + }) + .spread((deploymentInfo, packageInfo)=>{ + if (!packageInfo) { + throw new AppError.AppError("does not find the packageInfo"); + } + return packageManager.modifyReleasePackage(packageInfo.id, _.get(req, 'body.packageInfo')) + .then(()=>{ + //clear cache if exists. + if (_.get(config, 'common.updateCheckCache', false) !== false) { + Promise.delay(2500) + .then(() => { + var ClientManager = require('../core/services/client-manager'); + var clientManager = new ClientManager(); + clientManager.clearUpdateCheckCache(deploymentInfo.deployment_key, '*', '*', '*'); + }); + } + }); }); }).then((data) => { res.send(""); @@ -358,8 +379,10 @@ router.patch('/:appName/deployments/:deploymentName/release', }); }); + router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeploymentName', middleware.checkToken, (req, res, next) => { + log.debug('promote:', req.body); var appName = _.trim(req.params.appName); var sourceDeploymentName = _.trim(req.params.sourceDeploymentName); var destDeploymentName = _.trim(req.params.destDeploymentName); @@ -392,7 +415,7 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment return [sourceDeploymentInfo.id, destDeploymentInfo.id]; }) .spread((sourceDeploymentId, destDeploymentId) => { - return packageManager.promotePackage(sourceDeploymentId, destDeploymentId, uid); + return packageManager.promotePackage(sourceDeploymentId, destDeploymentId, req.body); }); }) .then((packages) => { @@ -405,10 +428,10 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment }); }); } - return null; + return packages; }) - .then(() => { - res.send('ok'); + .then((packages) => { + res.send({package:packages}); }) .catch((e) => { if (e instanceof AppError.AppError) { @@ -582,13 +605,6 @@ router.patch('/:appName', var appManager = new AppManager(); return accountManager.ownerCan(uid, appName) .then((col) => { - if (REGEX_ANDROID.test(appName) && !REGEX_ANDROID.test(newAppName)) { - throw new AppError.AppError(`new appName have to point -android suffix! eg. Demo-android`); - } else if (REGEX_IOS.test(appName) && !REGEX_IOS.test(newAppName)) { - throw new AppError.AppError(`new appName have to point -ios suffix! eg. Demo-ios`); - } else { - throw new AppError.AppError(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); - } return appManager.findAppByName(uid, newAppName) .then((appInfo) => { if (!_.isEmpty(appInfo)){ @@ -642,7 +658,30 @@ router.post('/:appName/transfer/:email', }); router.post('/', middleware.checkToken, (req, res, next) => { + log.debug("addApp params:",req.body); + var constName = require('../core/const'); var appName = req.body.name; + var osName = _.toLower(req.body.os); + var os; + if (osName == _.toLower(constName.IOS_NAME)) { + os = constName.IOS; + } else if (osName == _.toLower(constName.ANDROID_NAME)) { + os = constName.ANDROID; + } else if (osName == _.toLower(constName.WINDOWS_NAME)) { + os = constName.WINDOWS; + } else { + return res.status(406).send("Please input os [iOS|Android|Windows]!"); + } + var platformName = _.toLower(req.body.platform); + var platform; + if (platformName == _.toLower(constName.REACT_NATIVE_NAME)) { + platform = constName.REACT_NATIVE; + } else if (platformName == _.toLower(constName.CORDOVA_NAME)) { + platform = constName.CORDOVA; + } else { + return res.status(406).send("Please input platform [React-Native|Cordova]!"); + } + var manuallyProvisionDeployments = req.body.manuallyProvisionDeployments; var uid = req.users.id; var appManager = new AppManager(); if (_.isEmpty(appName)) { @@ -653,10 +692,7 @@ router.post('/', middleware.checkToken, (req, res, next) => { if (!_.isEmpty(appInfo)){ throw new AppError.AppError(appName + " Exist!"); } - if (!REGEX.test(appName)) { - throw new AppError.AppError(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); - } - return appManager.addApp(uid, appName, req.users.identical) + return appManager.addApp(uid, appName, os, platform, req.users.identical) .then(() => { return {name: appName, collaborators: {[req.users.email]: {permission: "Owner"}}}; }); From 13b2a62b514ee1eb1e32c6dc157a22fd24009d77 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 19 Aug 2018 00:32:20 +0800 Subject: [PATCH 106/194] fix default value --- core/services/package-manager.js | 28 +++++++++++++++++++++------- package-lock.json | 8 ++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index ebc9000d..218a734a 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -392,10 +392,16 @@ proto.modifyReleasePackage = function(packageId, params) { } var new_params = { description: description || packageInfo.description, - is_mandatory: isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO, - is_disabled: isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO, - rollout: rollout || 100 }; + if (_.isInteger(rollout)) { + new_params.rollout = rollout; + } + if (_.isBoolean(isMandatory)) { + new_params.is_mandatory = isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO; + } + if (_.isBoolean(isDisabled)) { + new_params.is_disabled = isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; + } return models.Packages.update(new_params,{where: {id: packageId}}); }); }; @@ -447,14 +453,22 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, params) { var create_params = { releaseMethod: constConfig.RELEAS_EMETHOD_PROMOTE, releaseUid: params.promoteUid || 0, - isMandatory: params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO, - isDisabled: params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO, - rollout: params.rollout || packages.rollout, + rollout: params.rollout || 100, size: packages.size, - description: packages.description, + description: params.description || packages.description, originalLabel: packages.label, originalDeployment: sourceDeployment.name }; + if (_.isBoolean(isMandatory)) { + create_params.is_mandatory = params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO; + } else { + create_params.is_mandatory = packages.is_mandatory + } + if (_.isBoolean(isDisabled)) { + create_params.is_disabled = params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; + } else { + create_params.is_disabled = packages.is_disabled + } return self.createPackage(destDeploymentId, deploymentsVersions.app_version, packages.package_hash, packages.manifest_blob_url, packages.blob_url, create_params); }); }; diff --git a/package-lock.json b/package-lock.json index 68e19da1..96936a75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1034,9 +1034,9 @@ } }, "formidable": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/formidable/download/formidable-1.2.0.tgz", - "integrity": "sha1-zikb/sZ8F24oL4keziw33gyDroQ=" + "version": "1.2.1", + "resolved": "http://registry.npm.taobao.org/formidable/download/formidable-1.2.1.tgz", + "integrity": "sha1-cPt8oCkO5v+WEJBBX0s989IIJlk=" }, "formstream": { "version": "1.1.0", @@ -3111,7 +3111,7 @@ "debug": "3.1.0", "extend": "3.0.1", "form-data": "2.3.2", - "formidable": "1.2.0", + "formidable": "1.2.1", "methods": "1.1.2", "mime": "1.4.1", "qs": "6.5.1", From cf92c00eb91234e25d046c8e52f2f8967e61c618 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 19 Aug 2018 15:19:31 +0800 Subject: [PATCH 107/194] fix --- CHANGELOG.md | 13 +- README.md | 2 +- app.js | 2 +- bin/db | 7 +- config/config.js | 4 +- config/config.test.js | 3 +- config/config.testwin.js | 3 +- core/const.js | 3 + core/services/client-manager.js | 99 ++++++++++-- core/services/package-manager.js | 18 +-- models/log_report_deploy.js | 24 +++ models/log_report_download.js | 21 +++ package.json | 2 +- routes/apps.js | 9 +- routes/index.js | 20 ++- sql/codepush-all.sql | 33 +++- sql/codepush-v0.0.1.sql | 153 ------------------ ...v0.2.14.sql => codepush-v0.2.14-patch.sql} | 0 ...v0.2.15.sql => codepush-v0.2.15-patch.sql} | 0 sql/codepush-v0.3.0-patch.sql | 26 +++ test/api/apps/apps.test.js | 34 +--- test/api/apps/release.test.js | 3 +- test/api/index/index.test.js | 2 +- 23 files changed, 253 insertions(+), 228 deletions(-) create mode 100644 models/log_report_deploy.js create mode 100644 models/log_report_download.js delete mode 100644 sql/codepush-v0.0.1.sql rename sql/{codepush-v0.2.14.sql => codepush-v0.2.14-patch.sql} (100%) rename sql/{codepush-v0.2.15.sql => codepush-v0.2.15-patch.sql} (100%) create mode 100644 sql/codepush-v0.3.0-patch.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index ce8ae7ed..c1776d06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,12 @@ -# Changelog for code-push-server \ No newline at end of file +# Changelog for code-push-server + +## 0.3.0 + +- 支持灰度发布 +- 适配`code-push app add` 命令,应用不在以名字区分平台,而是以类型区分平台 + - 数据库表apps新增字段`os`,`platform` +- 完善`code-push release/release-react/release-cordova` 命令 + - 数据库表packages新增`is_disabled`,`rollout`字段 +- 适配`code-push patch`命令 +- 新增`log_report_download`,`log_report_deploy`日志表 +- 升级npm依赖包 \ No newline at end of file diff --git a/README.md b/README.md index d5737c2a..bc9613d1 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in ## 正确使用code-push热更新 -- 苹果允许使用热更新[Apple's developer agreement](https://developer.apple.com/programs/ios/information/iOS_Program_Information_4_3_15.pdf), 但是规定不能弹框提示用户更新,影响用户体验。 而Google Play恰好相反,必须弹框告知用户更新。然而中国的android市场都必须关闭更新弹框,否则会在审核应用时以“请上传最新版本的二进制应用包”驳回应用。 +- 苹果App允许使用热更新[Apple's developer agreement](https://developer.apple.com/programs/ios/information/iOS_Program_Information_4_3_15.pdf), 为了不影响用户体验,规定必须使用静默更新。 Google Play不能使用静默更新,必须弹框告知用户App有更新。中国的android市场必须采用静默更新(如果弹框提示,App会被“请上传最新版本的二进制应用包”原因驳回)。 - react-native 不同平台bundle包不一样,在使用code-push-server的时候必须创建不同的应用来区分(eg. CodePushDemo-ios 和 CodePushDemo-android) - react-native-code-push只更新资源文件,不会更新java和Objective C,所以npm升级依赖包版本的时候,如果依赖包使用的本地化实现, 这时候必须更改应用版本号(ios修改Info.plist中的CFBundleShortVersionString, android修改build.gradle中的versionName), 然后重新编译app发布到应用商店。 - 推荐使用code-push release-react 命令发布应用,该命令合并了打包和发布命令(eg. code-push release-react CodePushDemo-ios ios -d Production) diff --git a/app.js b/app.js index cb2110b9..cfc415a3 100644 --- a/app.js +++ b/app.js @@ -111,7 +111,7 @@ if (app.get('env') === 'development') { res.send(err.message); log.debug(err); } else { - res.status(err.status || 500).send(`服务器繁忙,请稍后再试!`); + res.status(err.status || 500).send(err.message); log.error(err); } }); diff --git a/bin/db b/bin/db index 660914d9..4a61541e 100755 --- a/bin/db +++ b/bin/db @@ -93,13 +93,14 @@ if (command === 'init') { version_no = _.get(rs,'0.version', '0.0.1'); } catch (e) { } - if (version_no == '0.2.15') { + if (version_no == '0.3.0') { console.log('Everything up-to-date.'); process.exit(0); } var allSqlFile = [ - {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14.sql')}, - {version:'0.2.15', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.15.sql')} + {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14-patch.sql')}, + {version:'0.2.15', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.15-patch.sql')}, + {version:'0.3.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.3.0-patch.sql')} ]; for (var i = 0; i < allSqlFile.length; i++) { if(!_.gt(allSqlFile[i]['version'], version_no)) { diff --git a/config/config.js b/config/config.js index 45bd2076..f0884b79 100644 --- a/config/config.js +++ b/config/config.js @@ -66,7 +66,9 @@ config.development = { // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") storageType: process.env.STORAGE_TYPE || "local", // options value is (true | false), when it's true, it will cache updateCheck results in redis. - updateCheckCache: false + updateCheckCache: false, + // options value is (true | false), when it's true, it will cache rollout results in redis + rolloutClientUniqueIdCache: false, }, // Config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer smtpConfig:{ diff --git a/config/config.test.js b/config/config.test.js index ad45309a..22990cff 100644 --- a/config/config.test.js +++ b/config/config.test.js @@ -25,7 +25,8 @@ config.test = { diffNums: 3, dataDir: os.tmpdir(), storageType: "local", - updateCheckCache: true + updateCheckCache: true, + rolloutClientUniqueIdCache: false, }, smtpConfig: false, redis: { diff --git a/config/config.testwin.js b/config/config.testwin.js index 1fbc730a..2f5fa96d 100644 --- a/config/config.testwin.js +++ b/config/config.testwin.js @@ -25,7 +25,8 @@ config.test = { diffNums: 3, dataDir: os.tmpdir(), storageType: "local", - updateCheckCache: true + updateCheckCache: true, + rolloutClientUniqueIdCache: false, }, smtpConfig: false, redis: { diff --git a/core/const.js b/core/const.js index 20306b66..c224b64e 100644 --- a/core/const.js +++ b/core/const.js @@ -34,5 +34,8 @@ define("IS_DISABLED_NO", 0); define("RELEAS_EMETHOD_PROMOTE", 'Promote'); define("RELEAS_EMETHOD_UPLOAD", 'Upload'); +define("DEPLOYMENT_SUCCEEDED", 1); +define("DEPLOYMENT_FAILED", 2); + diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 560602e8..f0c75bd2 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -5,6 +5,9 @@ var _ = require('lodash'); var common = require('../utils/common'); var factory = require('../utils/factory'); var AppError = require('../app-error'); +var config = require('../config'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:ClientManager"); var proto = module.exports = function (){ function ClientManager() { @@ -15,6 +18,7 @@ var proto = module.exports = function (){ }; const UPDATE_CHECK = "UPDATE_CHECK"; +const CHOSEN_MAN = "CHOSEN_MAN"; const EXPIRED = 600; proto.getUpdateCheckCacheKey = function(deploymentKey, appVersion, label, packageHash) { @@ -37,9 +41,9 @@ proto.clearUpdateCheckCache = function(deploymentKey, appVersion, label, package .finally(() => client.quit()); } -proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageHash) { +proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageHash, clientUniqueId) { const self = this; - var updateCheckCache = _.get(require('../config'), 'common.updateCheckCache', false); + var updateCheckCache = _.get(config, 'common.updateCheckCache', false); if (updateCheckCache === false) { return self.updateCheck(deploymentKey, appVersion, label, packageHash); } @@ -49,14 +53,16 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH .then((data) => { if (data) { try { + log.debug('updateCheckFromCache read from catch'); var obj = JSON.parse(data); return obj; } catch (e) { } } - return self.updateCheck(deploymentKey, appVersion, label, packageHash) + return self.updateCheck(deploymentKey, appVersion, label, packageHash, clientUniqueId) .then((rs) => { try { + log.debug('updateCheckFromCache read from db'); var strRs = JSON.stringify(rs); client.setexAsync(redisCacheKey, EXPIRED, strRs); } catch (e) { @@ -67,7 +73,51 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH .finally(() => client.quit()); } -proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { +proto.getChosenManCacheKey = function(deploymentKey, appVersion, clientUniqueId, rollout) { + return [CHOSEN_MAN, deploymentKey, appVersion, clientUniqueId, rollout].join(':'); +} + +proto.random = function(rollout) { + var r = Math.ceil(Math.random()*10000); + if (r < rollout * 100) { + return Promise.resolve(true); + } else { + return Promise.resolve(false); + } +} + +proto.chosenMan = function (rollout, deploymentKey, appVersion, clientUniqueId) { + var self = this; + if (rollout >= 100) { + return Promise.resolve(true); + } + var rolloutClientUniqueIdCache = _.get(config, 'common.rolloutClientUniqueIdCache', false); + if (rolloutClientUniqueIdCache === false) { + return self.random(rollout); + } else { + var client = factory.getRedisClient("default"); + var redisCacheKey = self.getChosenManCacheKey(deploymentKey, appVersion, clientUniqueId, rollout); + return client.getAsync(redisCacheKey) + .then((data) => { + if (data == 1) { + return true; + } else if (data == 2) { + return false; + } else { + return self.random(rollout) + .then((r)=>{ + return client.setexAsync(redisCacheKey, 60*60*24*7, r ? 1:2) + .then(()=>{ + return r; + }); + }); + } + }) + .finally(() => client.quit()); + } +} + +proto.updateCheck = function(deploymentKey, appVersion, label, packageHash, clientUniqueId) { var rs = { downloadURL: "", downloadUrl: "", @@ -79,15 +129,17 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { label: "", packageSize: 0, updateAppVersion: false, - shouldRunBinaryVersion: false + shouldRunBinaryVersion: false, + rollout: 100 }; + var self = this; if (_.isEmpty(deploymentKey) || _.isEmpty(appVersion)) { return Promise.reject(new AppError.AppError("please input deploymentKey and appVersion")) } return models.Deployments.findOne({where: {deployment_key: deploymentKey}}) .then((dep) => { if (_.isEmpty(dep)) { - throw new AppError.AppError('does not found deployment'); + throw new AppError.AppError('Not found deployment, check deployment key is right.'); } return models.DeploymentsVersions.findOne({where: {deployment_id: dep.id, app_version: appVersion}}); }) @@ -101,22 +153,20 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash) { if (packages && _.eq(packages.deployment_id, deploymentsVersions.deployment_id) && !_.eq(packages.package_hash, packageHash)) { - rs.downloadURL = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); - rs.downloadUrl = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); + rs.downloadUrl = rs.downloadURL = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); rs.description = _.get(packages, 'description', ''); - rs.isAvailable = true; + rs.isAvailable = _.eq(packages.is_disabled, 1) ? false : true; rs.isMandatory = _.eq(packages.is_mandatory, 1) ? true : false; rs.appVersion = appVersion; rs.packageHash = _.get(packages, 'package_hash', ''); rs.label = _.get(packages, 'label', ''); rs.packageSize = _.get(packages, 'size', 0); - rs.shouldRunBinaryVersion = false; + rs.rollout = _.get(packages, 'rollout', 100); } return packages; }) - .then((packages) => { - //差异化更新 + //增量更新 if (!_.isEmpty(packages) && !_.eq(_.get(packages, 'package_hash', ""), packageHash)) { return models.PackagesDiff.findOne({where: {package_id:packages.id, diff_against_package_hash: packageHash}}) .then((diffPackage) => { @@ -159,24 +209,45 @@ proto.getPackagesInfo = function (deploymentKey, label) { proto.reportStatusDownload = function(deploymentKey, label, clientUniqueId) { return this.getPackagesInfo(deploymentKey, label) .then((packages) => { - return models.PackagesMetrics.addOneOnDownloadById(packages.id); + return Promise.all([ + models.PackagesMetrics.addOneOnDownloadById(packages.id), + models.LogReportDownload.create({ + package_id: packages.id, + client_unique_id: clientUniqueId + }) + ]); }); }; proto.reportStatusDeploy = function (deploymentKey, label, clientUniqueId, others) { return this.getPackagesInfo(deploymentKey, label) .then((packages) => { + var constConfig = require('../const'); var status = _.get(others, "status"); var packageId = packages.id; if (_.eq(status, "DeploymentSucceeded")) { return Promise.all([ + models.LogReportDeploy.create({ + package_id: packageId, + client_unique_id: clientUniqueId, + previous_label: _.get(others, 'previousLabelOrAppVersion'), + previous_deployment_key: _.get(others, 'previousDeploymentKey'), + status: constConfig.DEPLOYMENT_SUCCEEDED + }), models.PackagesMetrics.addOneOnInstalledById(packageId), models.PackagesMetrics.addOneOnActiveById(packageId), ]); } else if (_.eq(status, "DeploymentFailed")) { return Promise.all([ + models.LogReportDeploy.create({ + package_id: packageId, + client_unique_id: clientUniqueId, + previous_label: _.get(others, 'previousLabelOrAppVersion'), + previous_deployment_key: _.get(others, 'previousDeploymentKey'), + status: constConfig.DEPLOYMENT_FAILED + }), models.PackagesMetrics.addOneOnInstalledById(packageId), - models.PackagesMetrics.addOneOnFailedById(packageId) + models.PackagesMetrics.addOneOnFailedById(packageId), ]); }else { return; diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 218a734a..511dd06e 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -12,8 +12,8 @@ var common = require('../utils/common'); var os = require('os'); var path = require('path'); var AppError = require('../app-error'); -var log4js = require('log4js'); var constConfig = require('../const'); +var log4js = require('log4js'); var log = log4js.getLogger("cps:PackageManager"); var proto = module.exports = function (){ @@ -459,15 +459,15 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, params) { originalLabel: packages.label, originalDeployment: sourceDeployment.name }; - if (_.isBoolean(isMandatory)) { - create_params.is_mandatory = params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO; + if (_.isBoolean(params.isMandatory)) { + create_params.isMandatory = params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO; } else { - create_params.is_mandatory = packages.is_mandatory + create_params.isMandatory = packages.is_mandatory } - if (_.isBoolean(isDisabled)) { - create_params.is_disabled = params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; + if (_.isBoolean(params.isDisabled)) { + create_params.isMandatory = params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; } else { - create_params.is_disabled = packages.is_disabled + create_params.isMandatory = packages.is_disabled } return self.createPackage(destDeploymentId, deploymentsVersions.app_version, packages.package_hash, packages.manifest_blob_url, packages.blob_url, create_params); }); @@ -509,8 +509,8 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) releaseMethod: 'Rollback', releaseUid: rollbackUid, isMandatory: rollbackPackage.is_mandatory, - isDisabled: packages.is_disabled, - rollout: packages.rollout, + isDisabled: rollbackPackage.is_disabled, + rollout: rollbackPackage.rollout, size: rollbackPackage.size, description: rollbackPackage.description, originalLabel: rollbackPackage.label, diff --git a/models/log_report_deploy.js b/models/log_report_deploy.js new file mode 100644 index 00000000..f8c39d5e --- /dev/null +++ b/models/log_report_deploy.js @@ -0,0 +1,24 @@ +"use strict"; + +module.exports = function(sequelize, DataTypes) { + var LogReportDeploy = sequelize.define("LogReportDeploy", { + id: { + type: DataTypes.BIGINT(20), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + status: DataTypes.INTEGER(3), + package_id : DataTypes.INTEGER(10), + client_unique_id : DataTypes.STRING, + previous_label : DataTypes.STRING, + previous_deployment_key : DataTypes.STRING, + created_at: DataTypes.DATE, + }, { + tableName: 'log_report_deploy', + underscored: true, + updatedAt: false, + paranoid: true + }); + return LogReportDeploy; +}; diff --git a/models/log_report_download.js b/models/log_report_download.js new file mode 100644 index 00000000..62966cf9 --- /dev/null +++ b/models/log_report_download.js @@ -0,0 +1,21 @@ +"use strict"; + +module.exports = function(sequelize, DataTypes) { + var LogReportDownload = sequelize.define("LogReportDownload", { + id: { + type: DataTypes.BIGINT(20), + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + package_id : DataTypes.INTEGER(10), + client_unique_id : DataTypes.STRING, + created_at: DataTypes.DATE, + }, { + tableName: 'log_report_download', + underscored: true, + updatedAt: false, + paranoid: true + }); + return LogReportDownload; +}; diff --git a/package.json b/package.json index 43b12f39..1e13b85f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.2.20", + "version": "0.3.0", "license": "MIT", "repository": { "type": "git", diff --git a/routes/apps.js b/routes/apps.js index 991d6152..4f5275b7 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -382,7 +382,7 @@ router.patch('/:appName/deployments/:deploymentName/release', router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeploymentName', middleware.checkToken, (req, res, next) => { - log.debug('promote:', req.body); + log.debug('req.body:', req.body); var appName = _.trim(req.params.appName); var sourceDeploymentName = _.trim(req.params.sourceDeploymentName); var destDeploymentName = _.trim(req.params.destDeploymentName); @@ -661,6 +661,9 @@ router.post('/', middleware.checkToken, (req, res, next) => { log.debug("addApp params:",req.body); var constName = require('../core/const'); var appName = req.body.name; + if (_.isEmpty(appName)) { + return res.status(406).send("Please input name!"); + } var osName = _.toLower(req.body.os); var os; if (osName == _.toLower(constName.IOS_NAME)) { @@ -684,9 +687,7 @@ router.post('/', middleware.checkToken, (req, res, next) => { var manuallyProvisionDeployments = req.body.manuallyProvisionDeployments; var uid = req.users.id; var appManager = new AppManager(); - if (_.isEmpty(appName)) { - return res.status(406).send("Please input name!"); - } + appManager.findAppByName(uid, appName) .then((appInfo) => { if (!_.isEmpty(appInfo)){ diff --git a/routes/index.js b/routes/index.js index 9b1eb15c..a42f2d5c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -5,6 +5,8 @@ var AppError = require('../core/app-error'); var middleware = require('../core/middleware'); var ClientManager = require('../core/services/client-manager'); var _ = require('lodash'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:index"); router.get('/', (req, res, next) => { res.render('index', { title: 'CodePushServer' }); @@ -39,9 +41,23 @@ router.get('/updateCheck', (req, res, next) => { var appVersion = _.get(req, "query.appVersion"); var label = _.get(req, "query.label"); var packageHash = _.get(req, "query.packageHash") + var clientUniqueId = _.get(req, "query.clientUniqueId") var clientManager = new ClientManager(); - clientManager.updateCheckFromCache(deploymentKey, appVersion, label, packageHash) + log.debug('req.query', req.query); + clientManager.updateCheckFromCache(deploymentKey, appVersion, label, packageHash, clientUniqueId) .then((rs) => { + //灰度检测 + return clientManager.chosenMan(rs.rollout, deploymentKey, appVersion, clientUniqueId) + .then((data)=>{ + if (!data) { + rs.isAvailable = false; + return rs; + } + return rs; + }); + }) + .then((rs) => { + delete rs.rollout; res.send({"updateInfo":rs}); }) .catch((e) => { @@ -54,6 +70,7 @@ router.get('/updateCheck', (req, res, next) => { }); router.post('/reportStatus/download', (req, res) => { + log.debug('req.body', req.body); var clientUniqueId = _.get(req, "body.clientUniqueId"); var label = _.get(req, "body.label"); var deploymentKey = _.get(req, "body.deploymentKey"); @@ -68,6 +85,7 @@ router.post('/reportStatus/download', (req, res) => { }); router.post('/reportStatus/deploy', (req, res) => { + log.debug('req.body', req.body); var clientUniqueId = _.get(req, "body.clientUniqueId"); var label = _.get(req, "body.label"); var deploymentKey = _.get(req, "body.deploymentKey"); diff --git a/sql/codepush-all.sql b/sql/codepush-all.sql index e20dfe06..ae8d512c 100644 --- a/sql/codepush-all.sql +++ b/sql/codepush-all.sql @@ -3,12 +3,14 @@ CREATE TABLE `apps` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '', `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `os` tinyint(3) unsigned NOT NULL DEFAULT '0', + `platform` tinyint(3) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name` (`name`(12)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `collaborators`; CREATE TABLE `collaborators` ( @@ -83,8 +85,10 @@ CREATE TABLE `packages` ( `original_deployment` varchar(20) NOT NULL DEFAULT '', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, - `released_by` bigint(20) unsigned NOT NULL, + `released_by` bigint(20) unsigned NOT NULL DEFAULT '0', `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', + `is_disabled` tinyint(3) unsigned NOT NULL DEFAULT '0', + `rollout` tinyint(3) unsigned NOT NULL DEFAULT '0', `deleted_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), @@ -170,5 +174,26 @@ CREATE TABLE `versions` ( LOCK TABLES `versions` WRITE; INSERT INTO `versions` (`id`, `type`, `version`) VALUES - (1,1,'0.2.15'); -UNLOCK TABLES; \ No newline at end of file + (1,1,'0.3.0'); +UNLOCK TABLES; + +DROP TABLE IF EXISTS `log_report_deploy`; +CREATE TABLE `log_report_deploy` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `status` tinyint(3) unsigned NOT NULL DEFAULT '0', + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `client_unique_id` varchar(100) NOT NULL DEFAULT '', + `previous_label` varchar(20) NOT NULL DEFAULT '', + `previous_deployment_key` varchar(64) NOT NULL DEFAULT '', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `log_report_download`; +CREATE TABLE `log_report_download` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `client_unique_id` varchar(100) NOT NULL DEFAULT '', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/codepush-v0.0.1.sql b/sql/codepush-v0.0.1.sql deleted file mode 100644 index ee7ed007..00000000 --- a/sql/codepush-v0.0.1.sql +++ /dev/null @@ -1,153 +0,0 @@ -DROP TABLE IF EXISTS `apps`; -CREATE TABLE `apps` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL DEFAULT '', - `uid` bigint(20) unsigned NOT NULL DEFAULT '0', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - `deleted_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_name` (`name`(12)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `collaborators`; -CREATE TABLE `collaborators` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `appid` int(10) unsigned NOT NULL DEFAULT '0', - `uid` bigint(20) unsigned NOT NULL DEFAULT '0', - `roles` varchar(20) NOT NULL DEFAULT '', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - `deleted_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_appid` (`appid`), - KEY `idx_uid` (`uid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -DROP TABLE IF EXISTS `deployments`; -CREATE TABLE `deployments` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `appid` int(10) unsigned NOT NULL DEFAULT '0', - `name` varchar(20) NOT NULL DEFAULT '', - `description` varchar(500) NOT NULL DEFAULT '', - `deployment_key` varchar(64) NOT NULL, - `last_deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', - `label_id` int(11) unsigned NOT NULL DEFAULT '0', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - `deleted_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_appid` (`appid`), - KEY `idx_deploymentkey` (`deployment_key`(40)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `deployments_history`; -CREATE TABLE `deployments_history` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', - `package_id` int(10) unsigned NOT NULL DEFAULT '0', - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `deleted_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_deployment_id` (`deployment_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -DROP TABLE IF EXISTS `deployments_versions`; -CREATE TABLE `deployments_versions` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', - `app_version` varchar(14) NOT NULL DEFAULT '', - `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `idx_did_appversion` (`deployment_id`,`app_version`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `packages`; -CREATE TABLE `packages` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', - `deployment_id` int(10) unsigned NOT NULL DEFAULT '0', - `description` varchar(500) NOT NULL DEFAULT '', - `package_hash` varchar(64) NOT NULL DEFAULT '', - `blob_url` varchar(255) NOT NULL DEFAULT '', - `size` int(11) unsigned NOT NULL DEFAULT '0', - `manifest_blob_url` varchar(255) NOT NULL DEFAULT '', - `release_method` varchar(20) NOT NULL DEFAULT '', - `label` varchar(20) NOT NULL DEFAULT '', - `original_label` varchar(20) NOT NULL DEFAULT '', - `original_deployment` varchar(20) NOT NULL DEFAULT '', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - `released_by` bigint(20) unsigned NOT NULL, - PRIMARY KEY (`id`), - KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), - KEY `idx_versions_id` (`deployment_version_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `packages_diff`; -CREATE TABLE `packages_diff` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `package_id` int(11) unsigned NOT NULL DEFAULT '0', - `diff_against_package_hash` varchar(64) NOT NULL DEFAULT '', - `diff_blob_url` varchar(255) NOT NULL DEFAULT '', - `diff_size` int(11) unsigned NOT NULL DEFAULT '0', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `packages_metrics`; -CREATE TABLE `packages_metrics` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `package_id` int(10) unsigned NOT NULL DEFAULT '0', - `active` int(10) unsigned NOT NULL DEFAULT '0', - `downloaded` int(10) unsigned NOT NULL DEFAULT '0', - `failed` int(10) unsigned NOT NULL DEFAULT '0', - `installed` int(10) unsigned NOT NULL DEFAULT '0', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `udx_packageid` (`package_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `user_tokens`; -CREATE TABLE `user_tokens` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `uid` bigint(20) unsigned NOT NULL DEFAULT '0', - `name` varchar(50) NOT NULL DEFAULT '', - `tokens` varchar(64) NOT NULL DEFAULT '', - `created_by` varchar(64) NOT NULL DEFAULT '', - `description` varchar(500) NOT NULL DEFAULT '', - `is_session` tinyint(3) unsigned NOT NULL DEFAULT '0', - `expires_at` timestamp NULL DEFAULT NULL, - `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `deleted_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `idx_uid` (`uid`), - KEY `idx_tokens` (`tokens`) KEY_BLOCK_SIZE=16 -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `users`; -CREATE TABLE `users` ( - `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(50) NOT NULL DEFAULT '', - `password` varchar(255) NOT NULL DEFAULT '', - `email` varchar(100) NOT NULL DEFAULT '', - `identical` varchar(10) NOT NULL DEFAULT '', - `ack_code` varchar(10) NOT NULL DEFAULT '', - `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `created_at` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `udx_identical` (`identical`), - KEY `udx_username` (`username`), - KEY `idx_email` (`email`) KEY_BLOCK_SIZE=20 -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -INSERT INTO `users` (`id`, `username`, `password`, `email`, `identical`, `ack_code`, `updated_at`, `created_at`) -VALUES - (1,'admin','$2a$12$mvUY9kTqW4kSoGuZFDW0sOSgKmNY8SPHVyVrSckBTLtXKf6vKX3W.','lisong2010@gmail.com','4ksvOXqog','oZmGE','2016-11-14 10:46:55','2016-02-29 21:24:49'); diff --git a/sql/codepush-v0.2.14.sql b/sql/codepush-v0.2.14-patch.sql similarity index 100% rename from sql/codepush-v0.2.14.sql rename to sql/codepush-v0.2.14-patch.sql diff --git a/sql/codepush-v0.2.15.sql b/sql/codepush-v0.2.15-patch.sql similarity index 100% rename from sql/codepush-v0.2.15.sql rename to sql/codepush-v0.2.15-patch.sql diff --git a/sql/codepush-v0.3.0-patch.sql b/sql/codepush-v0.3.0-patch.sql new file mode 100644 index 00000000..e148d35f --- /dev/null +++ b/sql/codepush-v0.3.0-patch.sql @@ -0,0 +1,26 @@ +ALTER TABLE `apps` ADD `os` TINYINT UNSIGNED NOT NULL DEFAULT 0; +ALTER TABLE `apps` ADD `platform` TINYINT UNSIGNED NOT NULL DEFAULT 0; +ALTER TABLE `packages` ADD `is_disabled` TINYINT UNSIGNED NOT NULL DEFAULT 0; +ALTER TABLE `packages` ADD `rollout` TINYINT UNSIGNED NOT NULL DEFAULT 0; + +CREATE TABLE `log_report_deploy` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `status` tinyint(3) unsigned NOT NULL DEFAULT '0', + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `client_unique_id` varchar(100) NOT NULL DEFAULT '', + `previous_label` varchar(20) NOT NULL DEFAULT '', + `previous_deployment_key` varchar(64) NOT NULL DEFAULT '', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS `log_report_download`; +CREATE TABLE `log_report_download` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `client_unique_id` varchar(100) NOT NULL DEFAULT '', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +UPDATE `versions` SET `version` = '0.3.0' WHERE `type` = '1'; \ No newline at end of file diff --git a/test/api/apps/apps.test.js b/test/api/apps/apps.test.js index 261c536f..d393a42f 100644 --- a/test/api/apps/apps.test.js +++ b/test/api/apps/apps.test.js @@ -13,8 +13,8 @@ describe('api/apps/apps.test.js', function() { var authToken; var machineName = `Login-${Math.random()}`; var friendlyName = `Login-${Math.random()}`; - var appName = 'test-ios'; - var newAppName = 'newtest-ios'; + var appName = 'test'; + var newAppName = 'newtest'; var bearerToken; var testDeployment = 'test'; var newTestDeployment = 'newtest'; @@ -65,23 +65,10 @@ describe('api/apps/apps.test.js', function() { }); }); - it('should not add apps successful when appName is invalid', function(done) { - var appName = 'test'; - request.post(`/apps`) - .set('Authorization', `Bearer ${bearerToken}`) - .send({name: appName}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(406); - res.text.should.equal(`appName have to point -android or -ios suffix! eg. ${appName}-android ${appName}-ios`); - done(); - }); - }); - it('should add apps successful', function(done) { request.post(`/apps`) .set('Authorization', `Bearer ${bearerToken}`) - .send({name: appName}) + .send({name: appName, os:'iOS', platform:'React-Native'}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(200); @@ -95,7 +82,7 @@ describe('api/apps/apps.test.js', function() { it('should not add apps successful when appName exists', function(done) { request.post(`/apps`) .set('Authorization', `Bearer ${bearerToken}`) - .send({name: appName}) + .send({name: appName, os:'iOS', platform:'React-Native'}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(406); @@ -429,19 +416,6 @@ describe('api/apps/apps.test.js', function() { }); }); - it(`should not rename apps successful when new name invalid`, function(done) { - var newAppName = 'newtest'; - request.patch(`/apps/${appName}`) - .set('Authorization', `Bearer ${bearerToken}`) - .send({name: newAppName}) - .end(function(err, res) { - should.not.exist(err); - res.status.should.equal(406); - res.text.should.equal(`new appName have to point -ios suffix! eg. Demo-ios`); - done(); - }); - }); - it(`should rename apps successful`, function(done) { request.patch(`/apps/${appName}`) .set('Authorization', `Bearer ${bearerToken}`) diff --git a/test/api/apps/release.test.js b/test/api/apps/release.test.js index d845dee2..00eb698d 100644 --- a/test/api/apps/release.test.js +++ b/test/api/apps/release.test.js @@ -53,7 +53,7 @@ describe('api/apps/release.test.js', function() { it('should add apps successful', function(done) { request.post(`/apps`) .set('Authorization', `Bearer ${bearerToken}`) - .send({name: appName}) + .send({name: appName, os:'iOS', platform:'React-Native'}) .end(function(err, res) { should.not.exist(err); res.status.should.equal(200); @@ -99,7 +99,6 @@ describe('api/apps/release.test.js', function() { .set('Authorization', `Bearer ${bearerToken}`) .send() .end(function(err, res) { - should.not.exist(err); res.status.should.equal(200); done(); }); diff --git a/test/api/index/index.test.js b/test/api/index/index.test.js index 0f8576a6..51f51289 100644 --- a/test/api/index/index.test.js +++ b/test/api/index/index.test.js @@ -117,7 +117,7 @@ describe('api/index/index.test.js', function() { .end(function(err, res) { should.not.exist(err); res.status.should.equal(404); - res.text.should.equal(`does not found deployment`); + res.text.should.equal(`Not found deployment, check deployment key is right.`); done(); }); }); From ec7e3de5c59833d982c35ef3ef717d86d0f53d97 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 19 Aug 2018 15:21:14 +0800 Subject: [PATCH 108/194] patch --- sql/codepush-v0.3.0-patch.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/codepush-v0.3.0-patch.sql b/sql/codepush-v0.3.0-patch.sql index e148d35f..e7d1b00a 100644 --- a/sql/codepush-v0.3.0-patch.sql +++ b/sql/codepush-v0.3.0-patch.sql @@ -1,7 +1,7 @@ ALTER TABLE `apps` ADD `os` TINYINT UNSIGNED NOT NULL DEFAULT 0; ALTER TABLE `apps` ADD `platform` TINYINT UNSIGNED NOT NULL DEFAULT 0; ALTER TABLE `packages` ADD `is_disabled` TINYINT UNSIGNED NOT NULL DEFAULT 0; -ALTER TABLE `packages` ADD `rollout` TINYINT UNSIGNED NOT NULL DEFAULT 0; +ALTER TABLE `packages` ADD `rollout` TINYINT UNSIGNED NOT NULL DEFAULT 100; CREATE TABLE `log_report_deploy` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, From 7c2065a7e976ad0be7417dccf34dd66d564f7df4 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 19 Aug 2018 15:41:31 +0800 Subject: [PATCH 109/194] fix --- sql/codepush-v0.3.0-patch.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/codepush-v0.3.0-patch.sql b/sql/codepush-v0.3.0-patch.sql index e7d1b00a..bd672fe5 100644 --- a/sql/codepush-v0.3.0-patch.sql +++ b/sql/codepush-v0.3.0-patch.sql @@ -14,7 +14,6 @@ CREATE TABLE `log_report_deploy` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `log_report_download`; CREATE TABLE `log_report_download` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `package_id` int(10) unsigned NOT NULL DEFAULT '0', From e45f2b2109ed5feaf8f1890d8bd281cabfe1221b Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 21 Aug 2018 20:18:11 +0800 Subject: [PATCH 110/194] fix --- CHANGELOG.md | 4 ++-- bin/www | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1776d06..75674533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,10 @@ ## 0.3.0 - 支持灰度发布 -- 适配`code-push app add` 命令,应用不在以名字区分平台,而是以类型区分平台 +- 适配`code-push app add` 命令,应用不再以名字区分平台,而是以类型区分平台 - 数据库表apps新增字段`os`,`platform` - 完善`code-push release/release-react/release-cordova` 命令 - 数据库表packages新增`is_disabled`,`rollout`字段 - 适配`code-push patch`命令 - 新增`log_report_download`,`log_report_deploy`日志表 -- 升级npm依赖包 \ No newline at end of file +- 升级npm依赖包 diff --git a/bin/www b/bin/www index 3fb0c6ec..2fcb804a 100755 --- a/bin/www +++ b/bin/www @@ -48,7 +48,7 @@ var server = http.createServer(app); var models = require('../models'); models.Versions.findOne({where:{type:1}}) .then(function(v){ - if (!v || v.get('version') != '0.2.15') { + if (!v || v.get('version') != '0.3.0') { throw new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); } server.listen(port, host); From d00c2926df45718b9ef8fa791a95660a3ba6526a Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 21 Aug 2018 20:19:54 +0800 Subject: [PATCH 111/194] 0.3.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 96936a75..41f25fce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.2.20", + "version": "0.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1e13b85f..73da6c07 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "repository": { "type": "git", From 385a25b7720df7d255c0457ad2bb5a1e7ce5f4a2 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 21 Aug 2018 20:27:24 +0800 Subject: [PATCH 112/194] add os --- config/config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/config.js b/config/config.js index f0884b79..3aabbec6 100644 --- a/config/config.js +++ b/config/config.js @@ -1,3 +1,5 @@ +var os = require('os'); + var config = {}; config.development = { // Config for database, only support mysql. From cb110b90f9dc90c25e725ca350998bea85ba07a1 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 21 Aug 2018 21:07:19 +0800 Subject: [PATCH 113/194] 0.3.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 41f25fce..2e09b98d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.3.1", + "version": "0.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 73da6c07..d0d2f29c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.3.1", + "version": "0.3.2", "license": "MIT", "repository": { "type": "git", From 7c1310195b5a3dcade599d2415826ee9da94a1cf Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 00:32:39 +0800 Subject: [PATCH 114/194] targetBinaryVersion --- bin/db | 6 +++- bin/www | 2 +- core/services/client-manager.js | 25 +++++++++++++- core/services/package-manager.js | 31 ++++++++++++----- core/utils/common.js | 57 +++++++++++++++++++++++++++++++- models/deployments_versions.js | 2 ++ sql/codepush-all.sql | 10 ++++-- sql/codepush-v0.4.0-patch.sql | 9 +++++ 8 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 sql/codepush-v0.4.0-patch.sql diff --git a/bin/db b/bin/db index 4a61541e..d8d029c0 100755 --- a/bin/db +++ b/bin/db @@ -8,6 +8,9 @@ var path = require('path'); var _ = require('lodash'); var mysql = require('mysql2'); var Promise = require("bluebird"); +var common = require("../core/utils/common"); +console.log(common.validatorVersion('^1.2.3')); +return; var yargs = require('yargs') .usage('Usage: $0 [options]') .command('init', '初始化数据库', { @@ -93,7 +96,7 @@ if (command === 'init') { version_no = _.get(rs,'0.version', '0.0.1'); } catch (e) { } - if (version_no == '0.3.0') { + if (version_no == '0.4.0') { console.log('Everything up-to-date.'); process.exit(0); } @@ -101,6 +104,7 @@ if (command === 'init') { {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14-patch.sql')}, {version:'0.2.15', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.15-patch.sql')}, {version:'0.3.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.3.0-patch.sql')} + {version:'0.4.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.4.0-patch.sql')} ]; for (var i = 0; i < allSqlFile.length; i++) { if(!_.gt(allSqlFile[i]['version'], version_no)) { diff --git a/bin/www b/bin/www index 2fcb804a..7b4757b3 100755 --- a/bin/www +++ b/bin/www @@ -48,7 +48,7 @@ var server = http.createServer(app); var models = require('../models'); models.Versions.findOne({where:{type:1}}) .then(function(v){ - if (!v || v.get('version') != '0.3.0') { + if (!v || v.get('version') != '0.4.0') { throw new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); } server.listen(port, host); diff --git a/core/services/client-manager.js b/core/services/client-manager.js index f0c75bd2..2851ae6a 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -8,6 +8,7 @@ var AppError = require('../app-error'); var config = require('../config'); var log4js = require('log4js'); var log = log4js.getLogger("cps:ClientManager"); +var Sequelize = require('sequelize'); var proto = module.exports = function (){ function ClientManager() { @@ -141,7 +142,29 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash, clie if (_.isEmpty(dep)) { throw new AppError.AppError('Not found deployment, check deployment key is right.'); } - return models.DeploymentsVersions.findOne({where: {deployment_id: dep.id, app_version: appVersion}}); + var version = common.parseVersion(appVersion); + return models.DeploymentsVersions.findAll({where: { + deployment_id: dep.id, + min_version: { [Sequelize.Op.lte]: version }, + max_version: { [Sequelize.Op.gt]: version } + }}) + .then((deploymentsVersionsMore) => { + var distance = 0; + var item = null; + _.map(deploymentsVersionsMore, function(value, index) { + if (index == 0) { + item = value; + distance = value.max_version - value.min_version; + } else { + if (distance > (value.max_version - value.min_version)) { + distance = value.max_version - value.min_version; + item = value; + } + } + }); + log.debug(item); + return item; + }); }) .then((deploymentsVersions) => { var packageId = _.get(deploymentsVersions, 'current_package_id', 0); diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 511dd06e..b02d67d3 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -68,9 +68,9 @@ proto.parseReqFile = function (req) { }); }; -proto.createDeploymentsVersionIfNotExist = function (deploymentId, appVersion, t) { +proto.createDeploymentsVersionIfNotExist = function (deploymentId, appVersion, minVersion, maxVersion, t) { return models.DeploymentsVersions.findOrCreate({ - where: {deployment_id: deploymentId, app_version: appVersion}, + where: {deployment_id: deploymentId, app_version: appVersion, min_version:minVersion, max_version:maxVersion}, defaults: {current_package_id: 0}, transaction: t }) @@ -115,7 +115,7 @@ proto.createPackage = function (deploymentId, appVersion, packageHash, manifestH return models.Deployments.generateLabelId(deploymentId) .then((labelId) => { return models.sequelize.transaction((t) => { - return self.createDeploymentsVersionIfNotExist(deploymentId, appVersion, t) + return self.createDeploymentsVersionIfNotExist(deploymentId, appVersion, params.min_version, params.max_version, t) .then((deploymentsVersions) => { return models.Packages.create({ deployment_version_id: deploymentsVersions.id, @@ -302,7 +302,8 @@ proto.createDiffPackages = function (originalPackage, destPackages) { proto.releasePackage = function (appId, deploymentId, packageInfo, filePath, releaseUid) { var self = this; var appVersion = packageInfo.appVersion; - if (!/^([0-9.]+)$/.test(appVersion)) { + var versionInfo = common.validatorVersion(appVersion); + if (!versionInfo[0]) { log.debug(`releasePackage targetBinaryVersion ${appVersion} not support.`); return Promise.reject(new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`)) } @@ -342,8 +343,11 @@ proto.releasePackage = function (appId, deploymentId, packageInfo, filePath, rel .then((dataCenter) => { var packageHash = dataCenter.packageHash; var manifestFile = dataCenter.manifestFilePath; - return self.createDeploymentsVersionIfNotExist(deploymentId, appVersion) + return models.DeploymentsVersions.findOne({where: {deployment_id: deploymentId, app_version:appVersion}}) .then((deploymentsVersions) => { + if (!deploymentsVersions) { + return false; + } return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packageHash); }) .then((isExist) => { @@ -372,7 +376,9 @@ proto.releasePackage = function (appId, deploymentId, packageInfo, filePath, rel isDisabled: isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO, rollout: rollout, size: stats.size, - description: description + description: description, + min_version: versionInfo[1], + max_version: versionInfo[2], } return self.createPackage(deploymentId, appVersion, packageHash, manifestHash, blobHash, params); }) @@ -437,8 +443,11 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, params) { if (!packages) { throw new AppError.AppError('does not exist packages.'); } - return self.createDeploymentsVersionIfNotExist(destDeploymentId, deploymentsVersions.app_version) + return models.DeploymentsVersions.findOne({where: {deployment_id: destDeploymentId, app_version:deploymentsVersions.app_version}}) .then((deploymentsVersions) => { + if (!deploymentsVersions) { + return false; + } return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packages.package_hash); }) .then((isExist) => { @@ -457,7 +466,9 @@ proto.promotePackage = function (sourceDeploymentId, destDeploymentId, params) { size: packages.size, description: params.description || packages.description, originalLabel: packages.label, - originalDeployment: sourceDeployment.name + originalDeployment: sourceDeployment.name, + min_version: deploymentsVersions.min_version, + max_version: deploymentsVersions.max_version, }; if (_.isBoolean(params.isMandatory)) { create_params.isMandatory = params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO; @@ -514,7 +525,9 @@ proto.rollbackPackage = function (deploymentVersionId, targetLabel, rollbackUid) size: rollbackPackage.size, description: rollbackPackage.description, originalLabel: rollbackPackage.label, - originalDeployment: '' + originalDeployment: '', + min_version: deploymentsVersions.min_version, + max_version: deploymentsVersions.max_version, }; return self.createPackage(deploymentsVersions.deployment_id, deploymentsVersions.app_version, diff --git a/core/utils/common.js b/core/utils/common.js index 863478ad..728203f2 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -13,6 +13,61 @@ var log4js = require('log4js'); var log = log4js.getLogger("cps:utils:common"); module.exports = common; +common.parseVersion = function (versionNo) { + var version = '0'; + var data = null; + if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + // "1.2.3" + version = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); + } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5})$/)) { + // "1.2" + version = data[1] + _.padStart(data[2], 5, '0') + _.padStart('0', 10, '0'); + } + return version; +}; + +common.validatorVersion = function (versionNo) { + var flag = false; + var min = '0'; + var max = '9999999999999999999'; + var data = null; + if (versionNo == "*") { + // "*" + flag = true; + } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + // "1.2.3" + flag = true; + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); + max = data[1] + _.padStart(data[2], 5, '0') + _.padStart((parseInt(data[3])+1), 10, '0'); + } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5})(\.\*){0,1}$/)) { + // "1.2" "1.2.*" + flag = true; + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart('0', 10, '0'); + max = data[1] + _.padStart((parseInt(data[2])+1), 5, '0') + _.padStart('0', 10, '0'); + } else if (data = versionNo.match(/^\~([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + //"~1.2.3" + flag = true; + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); + max = data[1] + _.padStart((parseInt(data[2])+1), 5, '0') + _.padStart('0', 10, '0'); + } else if (data = versionNo.match(/^\^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + //"^1.2.3" + flag = true; + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[2], 10, '0'); + max = _.toString((parseInt(data[1])+1)) + _.padStart(0, 5, '0') + _.padStart('0', 10, '0'); + } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})-([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + // "1.2.3-1.2.7" + flag = true; + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); + max = data[4] + _.padStart(data[5], 5, '0') + _.padStart((parseInt(data[6])+1), 10, '0'); + } else if (data = versionNo.match(/^>=([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})<([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + //">=1.2.3<1.2.7" + flag = true; + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); + max = data[4] + _.padStart(data[5], 5, '0') + _.padStart(data[6], 10, '0'); + } + return [flag, min, max]; +}; + common.createFileFromRequest = function (url, filePath) { return new Promise((resolve, reject) => { fs.exists(filePath, function (exists) { @@ -41,7 +96,7 @@ common.createFileFromRequest = function (url, filePath) { } }); }); -} +}; common.move = function (sourceDst, targertDst) { return new Promise((resolve, reject) => { diff --git a/models/deployments_versions.js b/models/deployments_versions.js index d42d06dc..41105ec8 100644 --- a/models/deployments_versions.js +++ b/models/deployments_versions.js @@ -11,6 +11,8 @@ module.exports = function(sequelize, DataTypes) { deployment_id: DataTypes.INTEGER(10), app_version: DataTypes.STRING, current_package_id: DataTypes.INTEGER(10), + min_version: DataTypes.BIGINT(20), + max_version: DataTypes.BIGINT(20), created_at: DataTypes.DATE, updated_at: DataTypes.DATE, }, { diff --git a/sql/codepush-all.sql b/sql/codepush-all.sql index ae8d512c..2e8d53b3 100644 --- a/sql/codepush-all.sql +++ b/sql/codepush-all.sql @@ -60,13 +60,17 @@ DROP TABLE IF EXISTS `deployments_versions`; CREATE TABLE `deployments_versions` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', - `app_version` varchar(14) NOT NULL DEFAULT '', + `app_version` varchar(100) NOT NULL DEFAULT '', `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, + `min_version` bigint(20) unsigned NOT NULL DEFAULT '0', + `max_version` bigint(20) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), - KEY `idx_did_appversion` (`deployment_id`,`app_version`) + KEY `idx_did_minversion` (`deployment_id`,`min_version`), + KEY `idx_did_maxversion` (`deployment_id`,`max_version`), + KEY `idx_did_appversion` (`deployment_id`,`app_version`(30)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `packages`; @@ -174,7 +178,7 @@ CREATE TABLE `versions` ( LOCK TABLES `versions` WRITE; INSERT INTO `versions` (`id`, `type`, `version`) VALUES - (1,1,'0.3.0'); + (1,1,'0.4.0'); UNLOCK TABLES; DROP TABLE IF EXISTS `log_report_deploy`; diff --git a/sql/codepush-v0.4.0-patch.sql b/sql/codepush-v0.4.0-patch.sql new file mode 100644 index 00000000..a8933f94 --- /dev/null +++ b/sql/codepush-v0.4.0-patch.sql @@ -0,0 +1,9 @@ +ALTER TABLE `deployments_versions` ADD `min_version` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `deployments_versions` ADD `max_version` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `deployments_versions` ADD INDEX `idx_did_min_version` (`deployment_id`, `min_version`); +ALTER TABLE `deployments_versions` ADD INDEX `idx_did_maxversion` (`deployment_id`, `max_version`); +ALTER TABLE `deployments_versions` CHANGE `app_version` `app_version` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ''; +ALTER TABLE `deployments_versions` DROP INDEX `idx_did_appversion`; +ALTER TABLE `deployments_versions` ADD INDEX `idx_did_appversion` (`deployment_id`, `app_version` (30)); + +UPDATE `versions` SET `version` = '0.4.0' WHERE `type` = '1'; \ No newline at end of file From 32e2ed566be6266ea3b70cc2b31b3065a11c07ec Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 00:37:31 +0800 Subject: [PATCH 115/194] changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75674533..aa82429b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ # Changelog for code-push-server +## 0.4.0 +- targetBinaryVersion 支持正则匹配 + - `*` 匹配所有版本 + - `1.2.3` 匹配特定版本`1.2.3` + - `1.2`/`1.2.*` 匹配所有1.2补丁版本 + - `>=1.2.3<1.3.7` + - `~1.2.3` 匹配`>=1.2.3<1.4.0` + - `^1.2.3` 匹配`>=1.2.3<2.0.0` ## 0.3.0 From 706c0c8f9bed258b514e1362c2bc42bf01777f17 Mon Sep 17 00:00:00 2001 From: lisong Date: Thu, 23 Aug 2018 09:21:02 +0800 Subject: [PATCH 116/194] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa82429b..7a3b8c7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - `1.2.3` 匹配特定版本`1.2.3` - `1.2`/`1.2.*` 匹配所有1.2补丁版本 - `>=1.2.3<1.3.7` - - `~1.2.3` 匹配`>=1.2.3<1.4.0` + - `~1.2.3` 匹配`>=1.2.3<1.3.0` - `^1.2.3` 匹配`>=1.2.3<2.0.0` ## 0.3.0 From 2cdebdbc867cc502a67c2e4a2d6dfb01375b4f97 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 20:20:46 +0800 Subject: [PATCH 117/194] package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0d2f29c..45eeb249 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.3.2", + "version": "0.4.0", "license": "MIT", "repository": { "type": "git", From f75bdadd670fb3cf161befa8f40d849824cd1d98 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 22:22:11 +0800 Subject: [PATCH 118/194] fix patch targetBinaryVersion --- core/middleware.js | 2 +- core/services/package-manager.js | 152 ++++++++++++++++++++++--------- core/utils/common.js | 2 +- routes/apps.js | 12 ++- 4 files changed, 117 insertions(+), 51 deletions(-) diff --git a/core/middleware.js b/core/middleware.js index 28bd0f80..0df910ff 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -35,7 +35,7 @@ var checkAuthToken = function (authToken) { var checkAccessToken = function (accessToken) { return new Promise((resolve, reject) => { if (_.isEmpty(accessToken)) { - throw new AppError.Unauthorized(); + reject(new AppError.Unauthorized()); } var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); diff --git a/core/services/package-manager.js b/core/services/package-manager.js index b02d67d3..ff263406 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -396,6 +396,36 @@ proto.modifyReleasePackage = function(packageId, params) { if (!packageInfo) { throw new AppError.AppError(`packageInfo not found`); } + if (!_.isNull(appVersion)) { + var versionInfo = common.validatorVersion(appVersion); + if (!versionInfo[0]) { + throw new AppError.AppError(`--targetBinaryVersion ${appVersion} not support.`); + } + return Promise.all([ + models.DeploymentsVersions.findOne({where: {deployment_id:packageInfo.deployment_id, app_version:appVersion}}), + models.DeploymentsVersions.findById(packageInfo.deployment_version_id) + ]) + .spread((v1, v2) => { + if (v1 && !_.eq(v1.id, v2.id)) { + log.debug(v1); + throw new AppError.AppError(`${appVersion} already exist.`); + } + if (!v2) { + throw new AppError.AppError(`packages not found.`); + } + return models.DeploymentsVersions.update({ + app_version:appVersion, + min_version:versionInfo[1], + max_version:versionInfo[2] + },{where: {id:v2.id}}); + }) + .then(()=>{ + return packageInfo + }); + } + return packageInfo; + }) + .then((packageInfo) => { var new_params = { description: description || packageInfo.description, }; @@ -412,75 +442,109 @@ proto.modifyReleasePackage = function(packageId, params) { }); }; -proto.promotePackage = function (sourceDeploymentId, destDeploymentId, params) { +proto.promotePackage = function (sourceDeploymentInfo, destDeploymentInfo, params) { var self = this; var appVersion = params.appVersion; - return models.Deployments.findById(sourceDeploymentId) - .then((sourceDeployment) => { - if (appVersion) { - return models.DeploymentsVersions.findOne({where: {deployment_id: sourceDeploymentId, app_version:appVersion}}) - .then((deploymentsVersions)=>{return [sourceDeployment, deploymentsVersions]}); + var label = params.label; + return new Promise((resolve, reject) => { + if (label) { + return models.Packages.findOne({where: {deployment_id: sourceDeploymentInfo.id, label:label}}) + .then((sourcePack)=>{ + if (!sourcePack) { + throw new AppError.AppError('label does not exist.'); + } + return models.DeploymentsVersions.findById(sourcePack.deployment_version_id) + .then((deploymentsVersions)=>{ + if (!deploymentsVersions) { + throw new AppError.AppError('deploymentsVersions does not exist.'); + } + resolve([sourcePack, deploymentsVersions]); + }); + }) + .catch((e) => { + reject(e); + }); } else { - var lastDeploymentVersionId = _.get(sourceDeployment, 'last_deployment_version_id', 0); + var lastDeploymentVersionId = _.get(sourceDeploymentInfo, 'last_deployment_version_id', 0); if (_.lte(lastDeploymentVersionId, 0)) { - throw new AppError.AppError('does not exist last_deployment_version_id.'); + throw new AppError.AppError(`does not exist last_deployment_version_id.`); } return models.DeploymentsVersions.findById(lastDeploymentVersionId) - .then((deploymentsVersions)=>{return [sourceDeployment, deploymentsVersions]}); + .then((deploymentsVersions)=>{ + var sourcePackId = _.get(deploymentsVersions, 'current_package_id', 0); + if (_.lte(sourcePackId, 0)) { + throw new AppError.AppError(`packageInfo not found.`); + } + return models.Packages.findById(sourcePackId) + .then((sourcePack) =>{ + if (!sourcePack) { + throw new AppError.AppError(`packageInfo not found.`); + } + resolve([sourcePack, deploymentsVersions]); + }); + }) + .catch((e) => { + reject(e); + }); } }) - .spread((sourceDeployment, deploymentsVersions) => { - if (!deploymentsVersions) { - throw new AppError.AppError('does not exist deployment_version.'); - } + .spread((sourcePack, deploymentsVersions)=>{ + var appFinalVersion = appVersion || deploymentsVersions.app_version; + log.debug('sourcePack',sourcePack); log.debug('deploymentsVersions',deploymentsVersions); - var packageId = _.get(deploymentsVersions, 'current_package_id', 0); - if (_.lte(packageId, 0)) { - throw new AppError.AppError('does not exist packages.'); - } - return models.Packages.findById(packageId) - .then((packages) => { - if (!packages) { - throw new AppError.AppError('does not exist packages.'); + log.debug('appFinalVersion', appFinalVersion); + return models.DeploymentsVersions.findOne({where: { + deployment_id:destDeploymentInfo.id, + app_version: appFinalVersion, + }}) + .then((destDeploymentsVersions)=>{ + if (!destDeploymentsVersions) { + return false; } - return models.DeploymentsVersions.findOne({where: {deployment_id: destDeploymentId, app_version:deploymentsVersions.app_version}}) - .then((deploymentsVersions) => { - if (!deploymentsVersions) { - return false; - } - return self.isMatchPackageHash(deploymentsVersions.get('current_package_id'), packages.package_hash); - }) - .then((isExist) => { - if (isExist){ - throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); - } - }) - .then(() => [sourceDeployment, deploymentsVersions, packages]); + return self.isMatchPackageHash(destDeploymentsVersions.get('current_package_id'), sourcePack.package_hash); + }) + .then((isExist) => { + if (isExist){ + throw new AppError.AppError("The uploaded package is identical to the contents of the specified deployment's current release."); + } + return [sourcePack, deploymentsVersions, appFinalVersion]; }); }) - .spread((sourceDeployment, deploymentsVersions, packages) => { + .spread((sourcePack, deploymentsVersions, appFinalVersion) => { + var versionInfo = common.validatorVersion(appFinalVersion); + if (!versionInfo[0]) { + log.debug(`targetBinaryVersion ${appVersion} not support.`); + throw new AppError.AppError(`targetBinaryVersion ${appVersion} not support.`); + } var create_params = { releaseMethod: constConfig.RELEAS_EMETHOD_PROMOTE, releaseUid: params.promoteUid || 0, rollout: params.rollout || 100, - size: packages.size, - description: params.description || packages.description, - originalLabel: packages.label, - originalDeployment: sourceDeployment.name, - min_version: deploymentsVersions.min_version, - max_version: deploymentsVersions.max_version, + size: sourcePack.size, + description: params.description || sourcePack.description, + originalLabel: sourcePack.label, + originalDeployment: sourceDeploymentInfo.name, + min_version: versionInfo[1], + max_version: versionInfo[2], }; if (_.isBoolean(params.isMandatory)) { create_params.isMandatory = params.isMandatory ? constConfig.IS_MANDATORY_YES : constConfig.IS_MANDATORY_NO; } else { - create_params.isMandatory = packages.is_mandatory + create_params.isMandatory = sourcePack.is_mandatory } if (_.isBoolean(params.isDisabled)) { create_params.isMandatory = params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; } else { - create_params.isMandatory = packages.is_disabled + create_params.isMandatory = sourcePack.is_disabled } - return self.createPackage(destDeploymentId, deploymentsVersions.app_version, packages.package_hash, packages.manifest_blob_url, packages.blob_url, create_params); + return self.createPackage( + destDeploymentInfo.id, + appFinalVersion, + sourcePack.package_hash, + sourcePack.manifest_blob_url, + sourcePack.blob_url, + create_params + ); }); }; diff --git a/core/utils/common.js b/core/utils/common.js index 728203f2..f2c57222 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -52,7 +52,7 @@ common.validatorVersion = function (versionNo) { } else if (data = versionNo.match(/^\^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { //"^1.2.3" flag = true; - min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[2], 10, '0'); + min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); max = _.toString((parseInt(data[1])+1)) + _.padStart(0, 5, '0') + _.padStart('0', 10, '0'); } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})-([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { // "1.2.3-1.2.7" diff --git a/routes/apps.js b/routes/apps.js index 4f5275b7..f9d0e7cb 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -292,7 +292,7 @@ router.post('/:appName/deployments/:deploymentName/release', .then(() => { packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch((e) => { - console.error(e); + log.error(e); }); }); } @@ -412,10 +412,12 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment clientManager.clearUpdateCheckCache(destDeploymentInfo.deployment_key, '*', '*', '*'); }); } - return [sourceDeploymentInfo.id, destDeploymentInfo.id]; + return [sourceDeploymentInfo, destDeploymentInfo]; }) - .spread((sourceDeploymentId, destDeploymentId) => { - return packageManager.promotePackage(sourceDeploymentId, destDeploymentId, req.body); + .spread((sourceDeploymentInfo, destDeploymentInfo) => { + var params = _.get(req.body, 'packageInfo'); + params.promoteUid = uid; + return packageManager.promotePackage(sourceDeploymentInfo, destDeploymentInfo, params); }); }) .then((packages) => { @@ -424,7 +426,7 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment .then(() => { packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) .catch((e) => { - console.log(e); + log.error(e); }); }); } From 845534d12d635a265b80ea50fdb4d7847c0547fe Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 22:37:00 +0800 Subject: [PATCH 119/194] fix test --- core/services/package-manager.js | 4 ++-- routes/apps.js | 4 ++-- test/api/apps/release.test.js | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index ff263406..b5fcd715 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -444,8 +444,8 @@ proto.modifyReleasePackage = function(packageId, params) { proto.promotePackage = function (sourceDeploymentInfo, destDeploymentInfo, params) { var self = this; - var appVersion = params.appVersion; - var label = params.label; + var appVersion = _.get(params,'appVersion', null); + var label = _.get(params,'label', null); return new Promise((resolve, reject) => { if (label) { return models.Packages.findOne({where: {deployment_id: sourceDeploymentInfo.id, label:label}}) diff --git a/routes/apps.js b/routes/apps.js index f9d0e7cb..30445c54 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -415,8 +415,8 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment return [sourceDeploymentInfo, destDeploymentInfo]; }) .spread((sourceDeploymentInfo, destDeploymentInfo) => { - var params = _.get(req.body, 'packageInfo'); - params.promoteUid = uid; + var params = _.get(req.body, 'packageInfo', {}); + _.set(params, 'promoteUid', uid); return packageManager.promotePackage(sourceDeploymentInfo, destDeploymentInfo, params); }); }) diff --git a/test/api/apps/release.test.js b/test/api/apps/release.test.js index 00eb698d..69ef150b 100644 --- a/test/api/apps/release.test.js +++ b/test/api/apps/release.test.js @@ -99,6 +99,7 @@ describe('api/apps/release.test.js', function() { .set('Authorization', `Bearer ${bearerToken}`) .send() .end(function(err, res) { + console.log(res); res.status.should.equal(200); done(); }); From e13b758801a42dd20b4f8a3e980c47993f09fbe6 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 22:51:58 +0800 Subject: [PATCH 120/194] fix --- core/middleware.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/middleware.js b/core/middleware.js index 0df910ff..2ac9a232 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -35,7 +35,7 @@ var checkAuthToken = function (authToken) { var checkAccessToken = function (accessToken) { return new Promise((resolve, reject) => { if (_.isEmpty(accessToken)) { - reject(new AppError.Unauthorized()); + return reject(new AppError.Unauthorized()); } var config = require('../core/config'); var tokenSecret = _.get(config, 'jwt.tokenSecret'); @@ -43,7 +43,7 @@ var checkAccessToken = function (accessToken) { try { var authData = jwt.verify(accessToken, tokenSecret); } catch (e) { - reject(new AppError.Unauthorized()); + return reject(new AppError.Unauthorized()); } var uid = _.get(authData, 'uid', null); var hash = _.get(authData, 'hash', null); From 63a7d60b72e8f67b4195ed268855c045bf6b314c Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 22:57:34 +0800 Subject: [PATCH 121/194] test --- test/api/apps/release.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/api/apps/release.test.js b/test/api/apps/release.test.js index 69ef150b..00eb698d 100644 --- a/test/api/apps/release.test.js +++ b/test/api/apps/release.test.js @@ -99,7 +99,6 @@ describe('api/apps/release.test.js', function() { .set('Authorization', `Bearer ${bearerToken}`) .send() .end(function(err, res) { - console.log(res); res.status.should.equal(200); done(); }); From ac3607c08ee462ec7ee9876385f42283ea61b669 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 23 Aug 2018 22:58:20 +0800 Subject: [PATCH 122/194] 0.4.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2e09b98d..8c7dcc96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.3.2", + "version": "0.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 45eeb249..ce34b280 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.0", + "version": "0.4.1", "license": "MIT", "repository": { "type": "git", From 2df71c74c92279bd593e3d244ddbe64fbeac011c Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 24 Aug 2018 07:47:11 +0800 Subject: [PATCH 123/194] fixdb --- bin/db | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/db b/bin/db index d8d029c0..c160e336 100755 --- a/bin/db +++ b/bin/db @@ -103,7 +103,7 @@ if (command === 'init') { var allSqlFile = [ {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14-patch.sql')}, {version:'0.2.15', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.15-patch.sql')}, - {version:'0.3.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.3.0-patch.sql')} + {version:'0.3.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.3.0-patch.sql')}, {version:'0.4.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.4.0-patch.sql')} ]; for (var i = 0; i < allSqlFile.length; i++) { From 5081116a8a9e23f5ed02a9981a97ccb57d1e336c Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 24 Aug 2018 07:47:43 +0800 Subject: [PATCH 124/194] 0.4.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8c7dcc96..82ebeb7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.1", + "version": "0.4.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ce34b280..0714d024 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.1", + "version": "0.4.2", "license": "MIT", "repository": { "type": "git", From e2091a7ee9547b242e785288141ec8f7a2d7d2f4 Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 24 Aug 2018 08:51:54 +0800 Subject: [PATCH 125/194] fixdbupgrade --- bin/db | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/bin/db b/bin/db index c160e336..949343ee 100755 --- a/bin/db +++ b/bin/db @@ -9,8 +9,6 @@ var _ = require('lodash'); var mysql = require('mysql2'); var Promise = require("bluebird"); var common = require("../core/utils/common"); -console.log(common.validatorVersion('^1.2.3')); -return; var yargs = require('yargs') .usage('Usage: $0 [options]') .command('init', '初始化数据库', { @@ -79,23 +77,26 @@ if (command === 'init') { if(connection2) connection2.end() }); } else if (command == 'upgrade'){ - var connection = mysql.createConnection({ - host: dbhost, - user: dbuser, - password: dbpassword, - database: dbname, - multipleStatements: true, - port: dbport - }); - Promise.promisifyAll(connection); - connection.connect(); + try { + var connection = mysql.createConnection({ + host: dbhost, + user: dbuser, + password: dbpassword, + database: dbname, + multipleStatements: true, + port: dbport + }); + Promise.promisifyAll(connection); + connection.connect() + } catch(e) { + console.error('connect mysql error, check params',e); + return; + } + return Promise.coroutine(function*(val){ var version_no = '0.0.1'; - try { - var rs = yield connection.queryAsync('select `version` from `versions` where `type`=1 limit 1'); - version_no = _.get(rs,'0.version', '0.0.1'); - } catch (e) { - } + var rs = yield connection.queryAsync('select `version` from `versions` where `type`=1 limit 1'); + version_no = _.get(rs,'0.version', '0.0.1'); if (version_no == '0.4.0') { console.log('Everything up-to-date.'); process.exit(0); @@ -110,8 +111,15 @@ if (command === 'init') { if(!_.gt(allSqlFile[i]['version'], version_no)) { continue; } - var sql = fs.readFileSync(allSqlFile[i]['path'], 'utf-8'); - yield connection.queryAsync(sql); + try { + var sql = fs.readFileSync(allSqlFile[i]['path'], 'utf-8'); + console.log('exec sql file:' + allSqlFile[i]['path']); + yield connection.queryAsync(sql); + console.log('success exec sql file:' + allSqlFile[i]['path']); + } catch (e) { + console.error('error exec sql file:' + allSqlFile[i]['path']); + throw e; + } } })() .then(function(){ From 0489f3bce01084daaa1304761bf4b0ddc0c9e0fa Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 24 Aug 2018 08:52:16 +0800 Subject: [PATCH 126/194] 0.4.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82ebeb7c..ac0cce10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.2", + "version": "0.4.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0714d024..2db86984 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.2", + "version": "0.4.3", "license": "MIT", "repository": { "type": "git", From 3c555551a71acdd7695b68aae0d0477ed5a50ea1 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 25 Aug 2018 23:54:11 +0800 Subject: [PATCH 127/194] =?UTF-8?q?docker=E9=83=A8=E7=BD=B2=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/README.md | 115 +++++++++++++++++ docker/code-push-server/Dockerfile | 8 ++ docker/config.js | 93 ++++++++++++++ docker/docker-compose.yml | 51 ++++++++ docker/sql/codepush-all.sql | 193 +++++++++++++++++++++++++++++ sql/codepush-all.sql | 42 ++----- 6 files changed, 473 insertions(+), 29 deletions(-) create mode 100644 docker/README.md create mode 100644 docker/code-push-server/Dockerfile create mode 100644 docker/config.js create mode 100644 docker/docker-compose.yml create mode 100644 docker/sql/codepush-all.sql diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..4b1cbf1a --- /dev/null +++ b/docker/README.md @@ -0,0 +1,115 @@ +# docker 部署 code-push-server + +>该文档用于描述docker部署code-push-server,实例包含两个部分 + +- code-push-server部分 + - 更新包默认采用`local`存储(即存储在本地机器上)。使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 + - 默认开启5个实例,使用swarn内部默认负载均衡策略,可以根据自己机器设置docker-compose.yml文件中deploy参数。 + - docker-compose.yml只提供了应用部分参数设置,如需要其他特定配置,可以修改文件config.js。 +- mysql部分 + - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 + - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用 + + +## 安装docker + +参考docker官方安装教程 + +- [>>mac点这里](https://docs.docker.com/docker-for-mac/install/) +- [>>windows点这里](https://docs.docker.com/docker-for-windows/install/) +- linux基本都自带,但是需要启动,如果版本太老,请更新到最新稳定版 + + +`$ docker info` 能成功输出相关信息,则安装成功,才能继续下面步骤 + +## 启动swarm + +```bash +$ docker swarm init +``` + + +## 获取代码 + +```bash +$ git clone https://github.com/lisong/code-push-server.git +$ cd code-push-server/docker +``` + +## 修改配置文件 + +```bash +$ vim docker-compose.yml +``` + +*将`DOWNLOAD_URL`中`YOU_MACHINE_IP`替换成本机ip* +*将`MYSQL_HOST`中`YOU_MACHINE_IP`替换成本机ip* + +## jwt.tokenSecret修改 + +> code-push-server 验证登录验证方式使用的json web token加密方式,该对称加密算法是公开的,所以修改config.js中tokenSecret值很重要。 + +* 非常重要!非常重要! 非常重要!* + +> 可以打开连接`https://www.grc.com/passwords.htm`获取 `63 random alpha-numeric characters`类型的随机生成数作为密钥 + +## 部署 + +``` +$ docker stack deploy -c docker-compose.yml code-push-server +``` + +> 如果网速不佳,需要漫长而耐心的等待。。。去和妹子聊会天吧^_^ + + +## 查看进展 + +``` +$ docker service ls +$ docker service ps code-push-server_db +$ docker service ps code-push-server_server +``` + +> 确认`CURRENT STATE` 为 `Running about ...`, 则已经部署完成 + +## 访问接口简单验证 + +`$ curl -I http://127.0.0.1:3000/` + +返回`200 OK` + +```http +HTTP/1.1 200 OK +X-DNS-Prefetch-Control: off +X-Frame-Options: SAMEORIGIN +Strict-Transport-Security: max-age=15552000; includeSubDomains +X-Download-Options: noopen +X-Content-Type-Options: nosniff +X-XSS-Protection: 1; mode=block +Content-Type: text/html; charset=utf-8 +Content-Length: 592 +ETag: W/"250-IiCMcM1ZUFSswSYCU0KeFYFEMO8" +Date: Sat, 25 Aug 2018 15:45:46 GMT +Connection: keep-alive +``` + +## 查看服务日志 + +```shell +$ docker service logs code-push-server_server +$ docker service logs code-push-server_db +``` + +## 查看存储 `docker volume ls` + +DRIVER | VOLUME NAME | 描述 +------ | ----- | ------- +local | code-push-server_data-mysql | 数据库存储数据目录 +local | code-push-server_data-storage | 存储打包文件目录 +local | code-push-server_data-tmp | 用于计算更新包差异文件临时目录 + +## 销毁退出应用 + +```bash +$ docker stack rm code-push-server +``` diff --git a/docker/code-push-server/Dockerfile b/docker/code-push-server/Dockerfile new file mode 100644 index 00000000..cb478ddf --- /dev/null +++ b/docker/code-push-server/Dockerfile @@ -0,0 +1,8 @@ +FROM node:8.11.4-alpine + +RUN npm config set registry https://registry.npm.taobao.org/ \ +&& npm i -g code-push-server@0.4.3 --no-optional + +EXPOSE 3000 + +CMD ["code-push-server"] diff --git a/docker/config.js b/docker/config.js new file mode 100644 index 00000000..5caf4104 --- /dev/null +++ b/docker/config.js @@ -0,0 +1,93 @@ +var config = {}; +config.development = { + // Config for database, only support mysql. + db: { + username: process.env.MYSQL_USERNAME, + password: process.env.MYSQL_PASSWORD, + database: process.env.MYSQL_DATABASE, + host: process.env.MYSQL_HOST, + port: process.env.MYSQL_PORT || 3306, + dialect: "mysql", + logging: false, + operatorsAliases: false, + }, + // Config for local storage when storageType value is "local". + local: { + // Binary files storage dir, Do not use tmpdir and it's public download dir. + storageDir: process.env.STORAGE_DIR, + // Binary files download host address which Code Push Server listen to. the files storage in storageDir. + downloadUrl: process.env.DOWNLOAD_URL, + // public static download spacename. + public: '/download' + }, + jwt: { + // Recommended: 63 random alpha-numeric characters + // Generate using: https://www.grc.com/passwords.htm + tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' + }, + common: { + /* + * tryLoginTimes is control login error times to avoid force attack. + * if value is 0, no limit for login auth, it may not safe for account. when it's a number, it means you can + * try that times today. but it need config redis server. + */ + tryLoginTimes: 0, + // CodePush Web(https://github.com/lisong/code-push-web) login address. + //codePushWebUrl: "http://127.0.0.1:3001/login", + // create patch updates's number. default value is 3 + diffNums: 3, + // data dir for caclulate diff files. it's optimization. + dataDir: process.env.DATA_DIR, + // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") + storageType: "local", + // options value is (true | false), when it's true, it will cache updateCheck results in redis. + updateCheckCache: false, + // options value is (true | false), when it's true, it will cache rollout results in redis + rolloutClientUniqueIdCache: false, + }, + // Config for smtp email,register module need validate user email project source https://github.com/nodemailer/nodemailer + smtpConfig:{ + host: "smtp.aliyun.com", + port: 465, + secure: true, + auth: { + user: "", + pass: "" + } + }, + // Config for redis (register module, tryLoginTimes module) + redis: { + default: { + host: "127.0.0.1", + port: 6379, + retry_strategy: function (options) { + if (options.error.code === 'ECONNREFUSED') { + // End reconnecting on a specific error and flush all commands with a individual error + return new Error('The server refused the connection'); + } + if (options.total_retry_time > 1000 * 60 * 60) { + // End reconnecting after a specific timeout and flush all commands with a individual error + return new Error('Retry time exhausted'); + } + if (options.times_connected > 10) { + // End reconnecting with built in error + return undefined; + } + // reconnect after + return Math.max(options.attempt * 100, 3000); + } + } + } +} + +config.development.log4js = { + appenders: {console: { type: 'console'}}, + categories : { + "default": { appenders: ['console'], level:'error'}, + "startup": { appenders: ['console'], level:'info'}, + "http": { appenders: ['console'], level:'info'} + } +} + +config.production = Object.assign({}, config.development); +module.exports = config; diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..473f02f9 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,51 @@ +version: "3.3" +services: + server: + image: tablee/code-push-server:v0.4.3 + volumes: + - data-storage:/data/storage + - data-tmp:/data/tmp + - ./config.js:/config.js + environment: + DOWNLOAD_URL: "http://YOU_MACHINE_IP:3000/download" + MYSQL_HOST: "YOU_MACHINE_IP" + MYSQL_PORT: "3308" + MYSQL_USERNAME: "root" + MYSQL_PASSWORD: null + MYSQL_DATABASE: "codepush" + STORAGE_DIR: "/data/storage" + DATA_DIR: "/data/tmp" + NODE_ENV: "production" + CONFIG_FILE: "/config.js" + deploy: + replicas: 5 + resources: + limits: + cpus: "1" + memory: 1000M + restart_policy: + condition: on-failure + ports: + - "3000:3000" + networks: + - servernet + depends_on: + - "db" + db: + image: mysql:5.7.23 + volumes: + - data-mysql:/var/lib/mysql + - ./sql/codepush-all.sql:/docker-entrypoint-initdb.d/codepush-all.sql + ports: + - "3308:3306" + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: "On" + networks: + - dbnet +networks: + servernet: + dbnet: +volumes: + data-storage: + data-tmp: + data-mysql: diff --git a/docker/sql/codepush-all.sql b/docker/sql/codepush-all.sql new file mode 100644 index 00000000..e36a34dd --- /dev/null +++ b/docker/sql/codepush-all.sql @@ -0,0 +1,193 @@ +CREATE DATABASE IF NOT EXISTS `codepush`; + +use `codepush`; +CREATE TABLE IF NOT EXISTS `apps` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL DEFAULT '', + `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `os` tinyint(3) unsigned NOT NULL DEFAULT '0', + `platform` tinyint(3) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_name` (`name`(12)) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `collaborators` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `appid` int(10) unsigned NOT NULL DEFAULT '0', + `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `roles` varchar(20) NOT NULL DEFAULT '', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_appid` (`appid`), + KEY `idx_uid` (`uid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `deployments` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `appid` int(10) unsigned NOT NULL DEFAULT '0', + `name` varchar(20) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', + `deployment_key` varchar(64) NOT NULL, + `last_deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', + `label_id` int(11) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_appid` (`appid`), + KEY `idx_deploymentkey` (`deployment_key`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `deployments_history` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_deployment_id` (`deployment_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `deployments_versions` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', + `app_version` varchar(100) NOT NULL DEFAULT '', + `current_package_id` int(10) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, + `min_version` bigint(20) unsigned NOT NULL DEFAULT '0', + `max_version` bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `idx_did_minversion` (`deployment_id`,`min_version`), + KEY `idx_did_maxversion` (`deployment_id`,`max_version`), + KEY `idx_did_appversion` (`deployment_id`,`app_version`(30)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `packages` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', + `deployment_id` int(10) unsigned NOT NULL DEFAULT '0', + `description` varchar(500) NOT NULL DEFAULT '', + `package_hash` varchar(64) NOT NULL DEFAULT '', + `blob_url` varchar(255) NOT NULL DEFAULT '', + `size` int(11) unsigned NOT NULL DEFAULT '0', + `manifest_blob_url` varchar(255) NOT NULL DEFAULT '', + `release_method` varchar(20) NOT NULL DEFAULT '', + `label` varchar(20) NOT NULL DEFAULT '', + `original_label` varchar(20) NOT NULL DEFAULT '', + `original_deployment` varchar(20) NOT NULL DEFAULT '', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `released_by` bigint(20) unsigned NOT NULL DEFAULT '0', + `is_mandatory` tinyint(3) unsigned NOT NULL DEFAULT '0', + `is_disabled` tinyint(3) unsigned NOT NULL DEFAULT '0', + `rollout` tinyint(3) unsigned NOT NULL DEFAULT '0', + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_deploymentid_label` (`deployment_id`,`label`(8)), + KEY `idx_versions_id` (`deployment_version_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `packages_diff` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(11) unsigned NOT NULL DEFAULT '0', + `diff_against_package_hash` varchar(64) NOT NULL DEFAULT '', + `diff_blob_url` varchar(255) NOT NULL DEFAULT '', + `diff_size` int(11) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `packages_metrics` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `active` int(10) unsigned NOT NULL DEFAULT '0', + `downloaded` int(10) unsigned NOT NULL DEFAULT '0', + `failed` int(10) unsigned NOT NULL DEFAULT '0', + `installed` int(10) unsigned NOT NULL DEFAULT '0', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_packageid` (`package_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `user_tokens` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `uid` bigint(20) unsigned NOT NULL DEFAULT '0', + `name` varchar(50) NOT NULL DEFAULT '', + `tokens` varchar(64) NOT NULL DEFAULT '', + `created_by` varchar(64) NOT NULL DEFAULT '', + `description` varchar(500) NOT NULL DEFAULT '', + `is_session` tinyint(3) unsigned NOT NULL DEFAULT '0', + `expires_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_uid` (`uid`), + KEY `idx_tokens` (`tokens`) KEY_BLOCK_SIZE=16 +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `users` ( + `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL DEFAULT '', + `password` varchar(255) NOT NULL DEFAULT '', + `email` varchar(100) NOT NULL DEFAULT '', + `identical` varchar(10) NOT NULL DEFAULT '', + `ack_code` varchar(10) NOT NULL DEFAULT '', + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `udx_identical` (`identical`), + KEY `udx_username` (`username`), + KEY `idx_email` (`email`) KEY_BLOCK_SIZE=20 +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `users` (`id`, `username`, `password`, `email`, `identical`, `ack_code`, `updated_at`, `created_at`) +VALUES + (1,'admin','$2a$12$mvUY9kTqW4kSoGuZFDW0sOSgKmNY8SPHVyVrSckBTLtXKf6vKX3W.','lisong2010@gmail.com','4ksvOXqog','oZmGE','2016-11-14 10:46:55','2016-02-29 21:24:49'); + + +CREATE TABLE IF NOT EXISTS `versions` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '1.DBversion', + `version` varchar(10) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + UNIQUE KEY `udx_type` (`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +LOCK TABLES `versions` WRITE; +INSERT INTO `versions` (`id`, `type`, `version`) +VALUES + (1,1,'0.4.0'); +UNLOCK TABLES; + +CREATE TABLE IF NOT EXISTS `log_report_deploy` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `status` tinyint(3) unsigned NOT NULL DEFAULT '0', + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `client_unique_id` varchar(100) NOT NULL DEFAULT '', + `previous_label` varchar(20) NOT NULL DEFAULT '', + `previous_deployment_key` varchar(64) NOT NULL DEFAULT '', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `log_report_download` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `package_id` int(10) unsigned NOT NULL DEFAULT '0', + `client_unique_id` varchar(100) NOT NULL DEFAULT '', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/codepush-all.sql b/sql/codepush-all.sql index 2e8d53b3..4b0fd681 100644 --- a/sql/codepush-all.sql +++ b/sql/codepush-all.sql @@ -1,5 +1,4 @@ -DROP TABLE IF EXISTS `apps`; -CREATE TABLE `apps` ( +CREATE TABLE IF NOT EXISTS `apps` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '', `uid` bigint(20) unsigned NOT NULL DEFAULT '0', @@ -12,8 +11,7 @@ CREATE TABLE `apps` ( KEY `idx_name` (`name`(12)) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `collaborators`; -CREATE TABLE `collaborators` ( +CREATE TABLE IF NOT EXISTS `collaborators` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `appid` int(10) unsigned NOT NULL DEFAULT '0', `uid` bigint(20) unsigned NOT NULL DEFAULT '0', @@ -26,9 +24,7 @@ CREATE TABLE `collaborators` ( KEY `idx_uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `deployments`; -CREATE TABLE `deployments` ( +CREATE TABLE IF NOT EXISTS `deployments` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `appid` int(10) unsigned NOT NULL DEFAULT '0', `name` varchar(20) NOT NULL DEFAULT '', @@ -44,8 +40,7 @@ CREATE TABLE `deployments` ( KEY `idx_deploymentkey` (`deployment_key`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `deployments_history`; -CREATE TABLE `deployments_history` ( +CREATE TABLE IF NOT EXISTS `deployments_history` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', `package_id` int(10) unsigned NOT NULL DEFAULT '0', @@ -55,9 +50,7 @@ CREATE TABLE `deployments_history` ( KEY `idx_deployment_id` (`deployment_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -DROP TABLE IF EXISTS `deployments_versions`; -CREATE TABLE `deployments_versions` ( +CREATE TABLE IF NOT EXISTS `deployments_versions` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `deployment_id` int(11) unsigned NOT NULL DEFAULT '0', `app_version` varchar(100) NOT NULL DEFAULT '', @@ -73,8 +66,7 @@ CREATE TABLE `deployments_versions` ( KEY `idx_did_appversion` (`deployment_id`,`app_version`(30)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `packages`; -CREATE TABLE `packages` ( +CREATE TABLE IF NOT EXISTS `packages` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `deployment_version_id` int(10) unsigned NOT NULL DEFAULT '0', `deployment_id` int(10) unsigned NOT NULL DEFAULT '0', @@ -99,8 +91,7 @@ CREATE TABLE `packages` ( KEY `idx_versions_id` (`deployment_version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `packages_diff`; -CREATE TABLE `packages_diff` ( +CREATE TABLE IF NOT EXISTS `packages_diff` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `package_id` int(11) unsigned NOT NULL DEFAULT '0', `diff_against_package_hash` varchar(64) NOT NULL DEFAULT '', @@ -113,8 +104,7 @@ CREATE TABLE `packages_diff` ( KEY `idx_packageid_hash` (`package_id`,`diff_against_package_hash`(40)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `packages_metrics`; -CREATE TABLE `packages_metrics` ( +CREATE TABLE IF NOT EXISTS `packages_metrics` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `package_id` int(10) unsigned NOT NULL DEFAULT '0', `active` int(10) unsigned NOT NULL DEFAULT '0', @@ -128,8 +118,7 @@ CREATE TABLE `packages_metrics` ( KEY `idx_packageid` (`package_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `user_tokens`; -CREATE TABLE `user_tokens` ( +CREATE TABLE IF NOT EXISTS `user_tokens` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `name` varchar(50) NOT NULL DEFAULT '', @@ -145,8 +134,7 @@ CREATE TABLE `user_tokens` ( KEY `idx_tokens` (`tokens`) KEY_BLOCK_SIZE=16 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `users`; -CREATE TABLE `users` ( +CREATE TABLE IF NOT EXISTS `users` ( `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL DEFAULT '', `password` varchar(255) NOT NULL DEFAULT '', @@ -165,9 +153,7 @@ INSERT INTO `users` (`id`, `username`, `password`, `email`, `identical`, `ack_co VALUES (1,'admin','$2a$12$mvUY9kTqW4kSoGuZFDW0sOSgKmNY8SPHVyVrSckBTLtXKf6vKX3W.','lisong2010@gmail.com','4ksvOXqog','oZmGE','2016-11-14 10:46:55','2016-02-29 21:24:49'); - -DROP TABLE IF EXISTS `versions`; -CREATE TABLE `versions` ( +CREATE TABLE IF NOT EXISTS `versions` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '1.DBversion', `version` varchar(10) NOT NULL DEFAULT '', @@ -181,8 +167,7 @@ VALUES (1,1,'0.4.0'); UNLOCK TABLES; -DROP TABLE IF EXISTS `log_report_deploy`; -CREATE TABLE `log_report_deploy` ( +CREATE TABLE IF NOT EXISTS `log_report_deploy` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `status` tinyint(3) unsigned NOT NULL DEFAULT '0', `package_id` int(10) unsigned NOT NULL DEFAULT '0', @@ -193,8 +178,7 @@ CREATE TABLE `log_report_deploy` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DROP TABLE IF EXISTS `log_report_download`; -CREATE TABLE `log_report_download` ( +CREATE TABLE IF NOT EXISTS `log_report_download` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `package_id` int(10) unsigned NOT NULL DEFAULT '0', `client_unique_id` varchar(100) NOT NULL DEFAULT '', From 4481b16eacc6f43d3c4cb956e1b1f8604c3af19d Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 01:17:46 +0800 Subject: [PATCH 128/194] add docs --- README.md | 226 +++------------------------------------------- docs/README.md | 237 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+), 213 deletions(-) create mode 100644 docs/README.md diff --git a/README.md b/README.md index bc9613d1..63352e78 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,12 @@ [![Known Vulnerabilities](https://snyk.io/test/npm/code-push-server/badge.svg)](https://snyk.io/test/npm/code-push-server) [![Licenses](https://img.shields.io/npm/l/code-push-server.svg)](https://spdx.org/licenses/MIT) -CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use local storage, just modify config.js file, it's simple configure. +CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use [local/s3/oss] storage, just modify config.js file, it's simple configure. ## qq交流群 -- 628921445 -- 535491067 + +- NO.2群: 628921445 +- NO.1群: 535491067 ## 正确使用code-push热更新 @@ -44,221 +45,20 @@ $ code-push login http://api.code-push.com #登录 [Cordova CodePushDemo](https://github.com/lisong/code-push-cordova-demo-app) -## INSTALL FROM NPM PACKAGE - -```shell -$ npm install code-push-server -g -$ code-push-server-db init --dbhost localhost --dbuser root --dbpassword #初始化mysql数据库 -$ code-push-server #启动服务 浏览器中打开 http://127.0.0.1:3000 -``` - -## INSTALL FROM SOURCE CODE - -```shell -$ git clone https://github.com/lisong/code-push-server.git -$ cd code-push-server -$ npm install -$ ./bin/db init --dbhost localhost --dbuser root --dbpassword #初始化mysql数据库 -$ ./bin/www #启动服务 浏览器中打开 http://127.0.0.1:3000 -``` - -## UPGRADE - -*from source code* - -```shell -$ cd /path/to/code-push-server -$ git pull --rebase origin master -$ ./bin/db upgrade --dbhost localhost --dbuser root --dbpassword #升级codepush数据库 -$ #restart code-push-server -``` - -*from npm package* - -```shell -$ code-push-server-db upgrade --dbhost localhost --dbuser root --dbpassword #升级codepush数据库 -$ #restart code-push-server -``` - -## CONFIG -```shell -$ vim config/config.js -``` -请检查如下配置是否和你的环境一致,尤其是downloadUrl参数 - -``` - db: { - username: "root", - password: null, - database: "codepush", - host: "127.0.0.1", - dialect: "mysql" - }, - //七牛云存储配置 当storageType为qiniu时需要配置 - qiniu: { - accessKey: "", - secretKey: "", - bucketName: "", - downloadUrl: "" //文件下载域名地址 - }, - //阿里云存储配置 当storageType为oss时需要配置 - oss: { - accessKeyId: "", - secretAccessKey: "", - endpoint: "", - bucketName: "", - prefix: "", // 对象Key的前缀,允许放到子文件夹里面 - downloadUrl: "", // 文件下载域名地址,需要包含前缀 - }, - //文件存储在本地配置 当storageType为local时需要配置 - local: { - storageDir: "/Users/tablee/workspaces/storage", - //文件下载地址 CodePush Server 地址 + '/download' download对应app.js里面的地址 - downloadUrl: "http://localhost:3000/download", - // public static download spacename. - public: '/download' - }, - jwt: { - // 登录jwt签名密钥,必须更改,否则有安全隐患,可以使用随机生成的字符串 - // Recommended: 63 random alpha-numeric characters - // Generate using: https://www.grc.com/passwords.htm - tokenSecret: 'INSERT_RANDOM_TOKEN_KEY' - }, - common: { - dataDir: "/Users/tablee/workspaces/data", - //选择存储类型,目前支持local,oss,qiniu,s3配置 - storageType: "local" - }, -``` -read [config.js](https://github.com/lisong/code-push-server/blob/master/config/config.js) - - -## Storage mode [local/qiniu/s3] - -- 配置local存储,修改config/config.js中storageType值为local,配置中local下面storageDir和downloadUrl,如果不在同一台机器上,downloadUrl请指定域名或者ip地址 - - -## RUN - -```shell -$ node ./bin/www # or code-push-server -``` - -or point config file and ENV - -```shell -$ CONFIG_FILE=/path/to/config.js NODE_ENV=production node ./bin/www # or CONFIG_FILE=/path/to/config.js NODE_ENV=production code-push-server -``` - -notice. you have to change `tokenSecret` in config.js for security. +## HOW TO INSTALL code-push-server -## Default listen Host/Port 0.0.0.0/3000 -you can change like this. +- [docker](./docker/README.md) (recommend) +- [manual operation](./docs/README.md) -```shell -$ PORT=3000 HOST=127.0.0.1 NODE_ENV=production node ./bin/www # or PORT=3000 HOST=127.0.0.1 NODE_ENV=production code-push-server -``` - -## [code-push-cli](https://github.com/Microsoft/code-push) -Use code-push-cli manager CodePushServer - -```shell -$ npm install code-push-cli@latest -g -$ code-push login http://127.0.0.1:3000 #login in browser account:admin password:123456 -``` - -change admin password eg. - -```shell -$ curl -X PATCH -H "Authorization: Bearer mytoken" -H "Accept: application/json" -H "Content-Type:application/json" -d '{"oldPassword":"123456","newPassword":"654321"}' http://127.0.0.1:3000/users/password -``` - -## [react-native-code-push](https://github.com/Microsoft/react-native-code-push) for react-native - -```shell -$ cd /path/to/project -$ npm install react-native-code-push@latest --save -``` - -## config react-native project -Follow the react-native-code-push docs, addition iOS add a new entry named CodePushServerURL, whose value is the key of ourself CodePushServer URL. Andriod use the new CodePush constructor in MainApplication point CodePushServerUrl - -iOS eg. in file Info.plist - -```xml -... -CodePushDeploymentKey -YourCodePushKey -CodePushServerURL -YourCodePushServerUrl -... -``` +## HOW TO USE -Android eg. in file MainApplication.java +- [normal](./docs/react-native-code-push.md) +- [eact-native-code-push](https://github.com/Microsoft/react-native-code-push) +- [code-push](https://github.com/Microsoft/code-push) -```java -@Override -protected List getPackages() { - return Arrays.asList( - new MainReactPackage(), - new CodePush( - "YourKey", - MainApplication.this, - BuildConfig.DEBUG, - "YourCodePushServerUrl" - ) - ); -} -``` - - -## [cordova-plugin-code-push](https://github.com/Microsoft/cordova-plugin-code-push) for cordova - -```shell -$ cd /path/to/project -$ cordova plugin add cordova-plugin-code-push@latest --save -``` - -## config cordova project - -edit config.xml. add code below. - -```xml - - - - - - - - -``` - -## Production Manage -use [pm2](http://pm2.keymetrics.io/) to manage process. - -```shell -$ npm install pm2 -g -$ cp config/config.js /path/to/production/config.js -$ vim /path/to/production/config.js #configure your env. -$ cp docs/process.json /path/to/production/process.json -$ vim /path/to/production/process.json #configure your env. -$ pm2 start /path/to/production/process.json -``` -## Use [CodePush Web](https://github.com/lisong/code-push-web) manage apps - -add codePushWebUrl config in ./config/config.js - -eg. - -```json -... -"common": { - "codePushWebUrl": "Your CodePush Web address", -} -... -``` +## ISSUES +[code-push-server 使用](https://github.com/lisong/code-push-server/issues/135) ## License MIT License [read](https://github.com/lisong/code-push-server/blob/master/LICENSE) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..76f3ca97 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,237 @@ + +## INSTALL NPM + +[see](https://nodejs.org/en/download/) + +> (chosen latest LTS version) + +## INSTALL PM2 + +```bash +$ sudo npm i -g pm2 +``` + +## INSTALL MYSQL + +[Linux](https://dev.mysql.com/doc/refman/8.0/en/linux-installation.html) +[macOS](https://dev.mysql.com/doc/refman/8.0/en/osx-installation.html) +[Microsoft Windows](https://dev.mysql.com/doc/refman/8.0/en/windows-installation.html) +[Others](https://dev.mysql.com/doc/refman/8.0/en/installing.html) + + +## GET code-push-server FROM NPM + +```shell +$ npm install code-push-server@latest -g +``` + + +## GET code-push-server FROM SOURCE CODE + +```shell +$ git clone https://github.com/lisong/code-push-server.git +$ cd code-push-server +$ npm install +``` + +## INIT DATABASE + +```shell +$ code-push-server-db init --dbhost "your mysql host" --dbport "your mysql port" --dbuser "your mysql user" --dbpassword "your mysql password" +``` + +or from source code + +```shell +$ ./bin/db init --dbhost "your mysql host" --dbport "your mysql port" --dbuser "your mysql user" --dbpassword "your mysql password" +``` + +> output: success + +## CONFIGURE for code-push-server + +save the file [config.js](../config/config.js) + +some config have to change: + +- `local`.`storageDir` change to your directory,make sure have read/write permissions. +- `local`.`downloadUrl` replace `127.0.0.1` to your machine ip. +- `common`.`dataDir` change to your directory,make sure have read/write permissions. +- `jwt`.`tokenSecret` get the random string from `https://www.grc.com/passwords.htm`, and replace the value `INSERT_RANDOM_TOKEN_KEY`. +- `db` config: `username`,`password`,`host`,`port` change your own's + +## CONFIGURE for pm2 + +save the file [config.js](./process.json) + +some config have to change: + +- `script` if you install code-push-server from npm use `code-push-server`,or use `"your source code dir"/bin/www` +- `CONFIG_FILE` above config.js file path,use absolute path. + +## START SERVICE + +```shell +$ pm2 start process.json +``` + +## RESTART SERVICE + +```shell +$ pm2 restart process.json +``` + +## STOP SERVICE + +```shell +$ pm2 stop process.json +``` + +## CHECK SERVICE IS OK + +```shell +$ curl -I http://127.0.0.1:3000/ +``` + +> return httpCode `200 OK` + +```http +HTTP/1.1 200 OK +X-DNS-Prefetch-Control: off +X-Frame-Options: SAMEORIGIN +Strict-Transport-Security: max-age=15552000; includeSubDomains +X-Download-Options: noopen +X-Content-Type-Options: nosniff +X-XSS-Protection: 1; mode=block +Content-Type: text/html; charset=utf-8 +Content-Length: 592 +ETag: W/"250-IiCMcM1ZUFSswSYCU0KeFYFEMO8" +Date: Sat, 25 Aug 2018 15:45:46 GMT +Connection: keep-alive +``` + + +## UPGRADE + +*from npm package* + +```shell +$ npm install -g code-push-server@latest +$ code-push-server-db upgrade --dbhost "your mysql host" --dbport "your mysql port" --dbuser "your mysql user" --dbpassword "your mysql password" # upgrade codepush database +$ pm2 restart code-push-server # restart service +``` + +*from source code* + +```shell +$ cd /path/to/code-push-server +$ git pull --rebase origin master +$ ./bin/db upgrade --dbhost "your mysql host" --dbport "your mysql port" --dbuser "your mysql user" --dbpassword "your mysql password" +# upgrade codepush database +$ pm2 restart code-push-server # restart service +``` + + +## view pm2 logs + +```shell +$ pm2 ls +$ pm2 show code-push-server +$ tail -f "output file path" +``` + + +## Support Storage mode + +- local (default) +- qiniu (qiniu) +- s3 (aws) +- oss (aliyun) + +## Default listen Host/Port 0.0.0.0/3000 + +> you can change it in process.json, env: PORT,HOST + + +## [code-push-cli](https://github.com/Microsoft/code-push) + +> Use code-push-cli manager CodePushServer + +```shell +$ npm install code-push-cli@latest -g +$ code-push login http://YOU_SERVICE_IP:3000 #login in browser account:admin password:123456 +``` + +> change admin password eg. + +```shell +$ curl -X PATCH -H "Authorization: Bearer mytoken" -H "Accept: application/json" -H "Content-Type:application/json" -d '{"oldPassword":"123456","newPassword":"654321"}' http://YOU_SERVICE_IP:3000/users/password +``` + + +## config react-native project + +> Follow the react-native-code-push docs, addition iOS add a new entry named CodePushServerURL, whose value is the key of ourself CodePushServer URL. Andriod use the new CodePush constructor in MainApplication point CodePushServerUrl + +iOS eg. in file Info.plist + +```xml +... +CodePushDeploymentKey +YourCodePushKey +CodePushServerURL +YourCodePushServerUrl +... +``` + +Android eg. in file MainApplication.java + +```java +@Override +protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), + new CodePush( + "YourKey", + MainApplication.this, + BuildConfig.DEBUG, + "YourCodePushServerUrl" + ) + ); +} +``` + + +## [cordova-plugin-code-push](https://github.com/Microsoft/cordova-plugin-code-push) for cordova + +```shell +$ cd /path/to/project +$ cordova plugin add cordova-plugin-code-push@latest --save +``` + +## config cordova project + +edit config.xml. add code below. + +```xml + + + + + + + + +``` + +## Use [CodePush Web](https://github.com/lisong/code-push-web) manage apps + +> add codePushWebUrl config in config.js + +eg. + +```javascript +"common": { + "codePushWebUrl": "Your CodePush Web address", +} +``` \ No newline at end of file From 70444f02a2498c2a0f7a6f1caab7fdfc91ecf861 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 01:46:13 +0800 Subject: [PATCH 129/194] fix docs --- README.md | 10 ++++------ docker/README.md | 9 +++++++-- docker/config.js | 6 +++--- docker/docker-compose.yml | 11 ++++++++++- docs/README.md | 11 ++++++++++- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 63352e78..7c1dd385 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,8 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in - 推荐使用code-push release-react 命令发布应用,该命令合并了打包和发布命令(eg. code-push release-react CodePushDemo-ios ios -d Production) - 每次向App Store提交新的版本时,也应该基于该提交版本同时向code-push-server发布一个初始版本。(因为后面每次向code-push-server发布版本时,code-puse-server都会和初始版本比较,生成补丁版本) -## EXAMPLE -api.code-push.com 只是一个测试server,不要将自己生产环境的项目放在上面,服务器的宽带只有1M,而且服务没有做负载均衡和监控,稳定性不能保证,烦请大家自己搭建自己的服务。 -### shell命令行端 +### shell login ```shell $ code-push login http://api.code-push.com #登录 @@ -39,7 +37,7 @@ $ code-push login http://api.code-push.com #登录 访问:http://www.code-push.com -### 客户端eg. +### client eg. [ReactNative CodePushDemo](https://github.com/lisong/code-push-demo-app) @@ -53,12 +51,12 @@ $ code-push login http://api.code-push.com #登录 ## HOW TO USE - [normal](./docs/react-native-code-push.md) -- [eact-native-code-push](https://github.com/Microsoft/react-native-code-push) +- [react-native-code-push](https://github.com/Microsoft/react-native-code-push) - [code-push](https://github.com/Microsoft/code-push) ## ISSUES -[code-push-server 使用](https://github.com/lisong/code-push-server/issues/135) +[code-push-server normal problem](https://github.com/lisong/code-push-server/issues/135) ## License MIT License [read](https://github.com/lisong/code-push-server/blob/master/LICENSE) diff --git a/docker/README.md b/docker/README.md index 4b1cbf1a..5d19eba6 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,6 +1,6 @@ # docker 部署 code-push-server ->该文档用于描述docker部署code-push-server,实例包含两个部分 +>该文档用于描述docker部署code-push-server,实例包含三个部分 - code-push-server部分 - 更新包默认采用`local`存储(即存储在本地机器上)。使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 @@ -9,7 +9,10 @@ - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用 - +- redis部分 + - `tryLoginTimes` 登录错误次数限制 + - `updateCheckCache` 提升应用性能提升 + - `updateCheckCache` 灰度发布 ## 安装docker @@ -67,6 +70,7 @@ $ docker stack deploy -c docker-compose.yml code-push-server ``` $ docker service ls $ docker service ps code-push-server_db +$ docker service ps code-push-server_redis $ docker service ps code-push-server_server ``` @@ -98,6 +102,7 @@ Connection: keep-alive ```shell $ docker service logs code-push-server_server $ docker service logs code-push-server_db +$ docker service logs code-push-server_redis ``` ## 查看存储 `docker volume ls` diff --git a/docker/config.js b/docker/config.js index 5caf4104..f78fc3b6 100644 --- a/docker/config.js +++ b/docker/config.js @@ -31,7 +31,7 @@ config.development = { * if value is 0, no limit for login auth, it may not safe for account. when it's a number, it means you can * try that times today. but it need config redis server. */ - tryLoginTimes: 0, + tryLoginTimes: 4, // CodePush Web(https://github.com/lisong/code-push-web) login address. //codePushWebUrl: "http://127.0.0.1:3001/login", // create patch updates's number. default value is 3 @@ -58,8 +58,8 @@ config.development = { // Config for redis (register module, tryLoginTimes module) redis: { default: { - host: "127.0.0.1", - port: 6379, + host: process.env.REDIS_HOST, + port: process.env.REDIS_PORT || 6379, retry_strategy: function (options) { if (options.error.code === 'ECONNREFUSED') { // End reconnecting on a specific error and flush all commands with a individual error diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 473f02f9..d58fd10d 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -17,6 +17,8 @@ services: DATA_DIR: "/data/tmp" NODE_ENV: "production" CONFIG_FILE: "/config.js" + REDIS_HOST: "YOU_MACHINE_IP" + REDIS_PORT: "6388" deploy: replicas: 5 resources: @@ -30,7 +32,8 @@ services: networks: - servernet depends_on: - - "db" + - db + - redis db: image: mysql:5.7.23 volumes: @@ -42,6 +45,12 @@ services: MYSQL_ALLOW_EMPTY_PASSWORD: "On" networks: - dbnet + redis: + image: redis:3.2 + ports: + - "6388:6379" + networks: + - dbnet networks: servernet: dbnet: diff --git a/docs/README.md b/docs/README.md index 76f3ca97..c745084a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -111,6 +111,15 @@ Connection: keep-alive ``` +## Use redis impove concurrent and security + +> config redis in config.js + +- `updateCheckCache` +- `rolloutClientUniqueIdCache` +- `tryLoginTimes` + + ## UPGRADE *from npm package* @@ -234,4 +243,4 @@ eg. "common": { "codePushWebUrl": "Your CodePush Web address", } -``` \ No newline at end of file +``` From 645b2aa421b72f14a820ee901bc42b9b9c89dc90 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:51:08 +0800 Subject: [PATCH 130/194] Update README.md --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 5d19eba6..96bcea19 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,7 +4,7 @@ - code-push-server部分 - 更新包默认采用`local`存储(即存储在本地机器上)。使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - - 默认开启5个实例,使用swarn内部默认负载均衡策略,可以根据自己机器设置docker-compose.yml文件中deploy参数。 + - 默认开启5个实例,使用swarm内部默认负载均衡策略,可以根据自己机器设置docker-compose.yml文件中deploy参数。 - docker-compose.yml只提供了应用部分参数设置,如需要其他特定配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 From 485c7e916647fe2207e52a4343ab4b769cccad3a Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:51:45 +0800 Subject: [PATCH 131/194] Update README.md --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 96bcea19..0c22bf39 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,7 +4,7 @@ - code-push-server部分 - 更新包默认采用`local`存储(即存储在本地机器上)。使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - - 默认开启5个实例,使用swarm内部默认负载均衡策略,可以根据自己机器设置docker-compose.yml文件中deploy参数。 + - 默认开启5个实例,使用swarm内部默认负载均衡策略,可以根据自己机器配置设置docker-compose.yml文件中deploy参数。 - docker-compose.yml只提供了应用部分参数设置,如需要其他特定配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 From be94b4bd38c7946ec9a8759a2cb5e4641ec27957 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:52:46 +0800 Subject: [PATCH 132/194] Update README.md --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 0c22bf39..254cf31c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -5,7 +5,7 @@ - code-push-server部分 - 更新包默认采用`local`存储(即存储在本地机器上)。使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - 默认开启5个实例,使用swarm内部默认负载均衡策略,可以根据自己机器配置设置docker-compose.yml文件中deploy参数。 - - docker-compose.yml只提供了应用部分参数设置,如需要其他特定配置,可以修改文件config.js。 + - docker-compose.yml只提供了应用的一部分参数设置,如需要设置其他配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用 From 28b14200f28d5645e75cc4b66258260aeae5e7b1 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:54:10 +0800 Subject: [PATCH 133/194] Update README.md --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 254cf31c..6c94708c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -8,7 +8,7 @@ - docker-compose.yml只提供了应用的一部分参数设置,如需要设置其他配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用 + - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用,只需要给予`select``update``insert`权限即可 - redis部分 - `tryLoginTimes` 登录错误次数限制 - `updateCheckCache` 提升应用性能提升 From d368bcaead9d24db118b9b5fba94f6ea8e6a8df4 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:54:36 +0800 Subject: [PATCH 134/194] Update README.md --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 6c94708c..49b40fa9 100644 --- a/docker/README.md +++ b/docker/README.md @@ -8,7 +8,7 @@ - docker-compose.yml只提供了应用的一部分参数设置,如需要设置其他配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用,只需要给予`select``update``insert`权限即可 + - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用,只需要给予`select,update,insert`权限即可 - redis部分 - `tryLoginTimes` 登录错误次数限制 - `updateCheckCache` 提升应用性能提升 From 67d087d60d7befdeab8fb5af0cea5e5e6c996cc8 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:56:19 +0800 Subject: [PATCH 135/194] Update README.md --- docker/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker/README.md b/docker/README.md index 49b40fa9..8cdee2c6 100644 --- a/docker/README.md +++ b/docker/README.md @@ -46,8 +46,11 @@ $ vim docker-compose.yml ``` *将`DOWNLOAD_URL`中`YOU_MACHINE_IP`替换成本机ip* + *将`MYSQL_HOST`中`YOU_MACHINE_IP`替换成本机ip* +*将`REDIS_HOST`中`YOU_MACHINE_IP`替换成本机ip* + ## jwt.tokenSecret修改 > code-push-server 验证登录验证方式使用的json web token加密方式,该对称加密算法是公开的,所以修改config.js中tokenSecret值很重要。 From e1e6df8dd9e705505f61cf290242e3e4ec3711a9 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 26 Aug 2018 01:57:17 +0800 Subject: [PATCH 136/194] Update README.md --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 8cdee2c6..e1a42c05 100644 --- a/docker/README.md +++ b/docker/README.md @@ -55,7 +55,7 @@ $ vim docker-compose.yml > code-push-server 验证登录验证方式使用的json web token加密方式,该对称加密算法是公开的,所以修改config.js中tokenSecret值很重要。 -* 非常重要!非常重要! 非常重要!* +*非常重要!非常重要! 非常重要!* > 可以打开连接`https://www.grc.com/passwords.htm`获取 `63 random alpha-numeric characters`类型的随机生成数作为密钥 From b6cc5bcfd1feff861eaeaef6969538282f378065 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 09:53:14 +0800 Subject: [PATCH 137/194] fix --- docker/README.md | 1 + docker/docker-compose.yml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docker/README.md b/docker/README.md index e1a42c05..cd123a23 100644 --- a/docker/README.md +++ b/docker/README.md @@ -120,4 +120,5 @@ local | code-push-server_data-tmp | 用于计算更新包差异文件临时目 ```bash $ docker stack rm code-push-server +$ docker swarm leave --force ``` diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index d58fd10d..b5d2ba6c 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -23,7 +23,7 @@ services: replicas: 5 resources: limits: - cpus: "1" + cpus: "2" memory: 1000M restart_policy: condition: on-failure @@ -46,7 +46,7 @@ services: networks: - dbnet redis: - image: redis:3.2 + image: redis:4.0.11-alpine ports: - "6388:6379" networks: From 5a9f62ca8e5e22efe21be844f855359641807a15 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 10:13:56 +0800 Subject: [PATCH 138/194] fix --- docker/README.md | 13 +++++++++++++ docker/docker-compose.yml | 3 +++ 2 files changed, 16 insertions(+) diff --git a/docker/README.md b/docker/README.md index cd123a23..b5e961b4 100644 --- a/docker/README.md +++ b/docker/README.md @@ -100,6 +100,18 @@ Date: Sat, 25 Aug 2018 15:45:46 GMT Connection: keep-alive ``` +## 浏览器登录 + +> 默认用户名:admin 密码:123456 记得要修改默认密码哦 +> 如果登录连续输错密码超过一定次数,会限定无法再登录. 需要清空redis缓存 + +```shell +$ redis-cli -p6388 # 进入redis +> flushall +> quit +``` + + ## 查看服务日志 ```shell @@ -115,6 +127,7 @@ DRIVER | VOLUME NAME | 描述 local | code-push-server_data-mysql | 数据库存储数据目录 local | code-push-server_data-storage | 存储打包文件目录 local | code-push-server_data-tmp | 用于计算更新包差异文件临时目录 +local | code-push-server_data-redis | redis落地数据 ## 销毁退出应用 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index b5d2ba6c..2a5a9c15 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -47,6 +47,8 @@ services: - dbnet redis: image: redis:4.0.11-alpine + volumes: + - data-redis:/data ports: - "6388:6379" networks: @@ -58,3 +60,4 @@ volumes: data-storage: data-tmp: data-mysql: + data-redis: From 8e7d96c8c82bca6a04b06a760be2bb8899bacd34 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 10:18:18 +0800 Subject: [PATCH 139/194] 0.4.4 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac0cce10..c520f3af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.3", + "version": "0.4.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2db86984..d176c9e2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.3", + "version": "0.4.4", "license": "MIT", "repository": { "type": "git", From 231756d36bf5929e056dee3ef93ccc006a6dc10e Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 10:34:14 +0800 Subject: [PATCH 140/194] update readme --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index b5e961b4..8613caa5 100644 --- a/docker/README.md +++ b/docker/README.md @@ -20,7 +20,7 @@ - [>>mac点这里](https://docs.docker.com/docker-for-mac/install/) - [>>windows点这里](https://docs.docker.com/docker-for-windows/install/) -- linux基本都自带,但是需要启动,如果版本太老,请更新到最新稳定版 +- [>>linux](https://docs.docker.com/install/linux/docker-ce/ubuntu/) `$ docker info` 能成功输出相关信息,则安装成功,才能继续下面步骤 From 8f135caecd3d87aaf8cff6d0f015d4b2eebb0739 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 10:44:33 +0800 Subject: [PATCH 141/194] update readme --- docker/README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docker/README.md b/docker/README.md index 8613caa5..faa37619 100644 --- a/docker/README.md +++ b/docker/README.md @@ -27,21 +27,21 @@ ## 启动swarm -```bash -$ docker swarm init +```shell +$ sudo docker swarm init ``` ## 获取代码 -```bash +```shell $ git clone https://github.com/lisong/code-push-server.git $ cd code-push-server/docker ``` ## 修改配置文件 -```bash +```shell $ vim docker-compose.yml ``` @@ -61,8 +61,8 @@ $ vim docker-compose.yml ## 部署 -``` -$ docker stack deploy -c docker-compose.yml code-push-server +```shell +$ sudo docker stack deploy -c docker-compose.yml code-push-server ``` > 如果网速不佳,需要漫长而耐心的等待。。。去和妹子聊会天吧^_^ @@ -70,11 +70,11 @@ $ docker stack deploy -c docker-compose.yml code-push-server ## 查看进展 -``` -$ docker service ls -$ docker service ps code-push-server_db -$ docker service ps code-push-server_redis -$ docker service ps code-push-server_server +```shell +$ sudo docker service ls +$ sudo docker service ps code-push-server_db +$ sudo docker service ps code-push-server_redis +$ sudo docker service ps code-push-server_server ``` > 确认`CURRENT STATE` 为 `Running about ...`, 则已经部署完成 @@ -115,9 +115,9 @@ $ redis-cli -p6388 # 进入redis ## 查看服务日志 ```shell -$ docker service logs code-push-server_server -$ docker service logs code-push-server_db -$ docker service logs code-push-server_redis +$ sudo docker service logs code-push-server_server +$ sudo docker service logs code-push-server_db +$ sudo docker service logs code-push-server_redis ``` ## 查看存储 `docker volume ls` @@ -132,6 +132,6 @@ local | code-push-server_data-redis | redis落地数据 ## 销毁退出应用 ```bash -$ docker stack rm code-push-server -$ docker swarm leave --force +$ sudo docker stack rm code-push-server +$ sudo docker swarm leave --force ``` From 201626f43b656fe8058d316bd5f5ff08d4682b78 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 16:44:45 +0800 Subject: [PATCH 142/194] =?UTF-8?q?=E8=A2=ABdocker-compose=20replicas=20?= =?UTF-8?q?=E5=9D=91=E4=BA=86=E4=B8=80=E6=8A=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/README.md | 2 +- docker/code-push-server/Dockerfile | 8 +++++--- docker/code-push-server/process.json | 11 +++++++++++ docker/docker-compose.yml | 12 ++++++------ docker/sql/codepush-all.sql | 4 ++++ 5 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 docker/code-push-server/process.json diff --git a/docker/README.md b/docker/README.md index faa37619..afdf433c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,7 +4,7 @@ - code-push-server部分 - 更新包默认采用`local`存储(即存储在本地机器上)。使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - - 默认开启5个实例,使用swarm内部默认负载均衡策略,可以根据自己机器配置设置docker-compose.yml文件中deploy参数。 + - 内部使用pm2 cluster模式管理进程,默认开启进程数为cpu数,可以根据自己机器配置设置docker-compose.yml文件中deploy参数。 - docker-compose.yml只提供了应用的一部分参数设置,如需要设置其他配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 diff --git a/docker/code-push-server/Dockerfile b/docker/code-push-server/Dockerfile index cb478ddf..b13c4741 100644 --- a/docker/code-push-server/Dockerfile +++ b/docker/code-push-server/Dockerfile @@ -1,8 +1,10 @@ FROM node:8.11.4-alpine -RUN npm config set registry https://registry.npm.taobao.org/ \ -&& npm i -g code-push-server@0.4.3 --no-optional +RUN npm config set registry https://registry.npm.taobao.org/ \ +&& npm i -g code-push-server@0.4.3 pm2@latest --no-optional + +COPY ./process.json /process.json EXPOSE 3000 -CMD ["code-push-server"] +CMD ["pm2-docker", "start", "/process.json"] diff --git a/docker/code-push-server/process.json b/docker/code-push-server/process.json new file mode 100644 index 00000000..493010d3 --- /dev/null +++ b/docker/code-push-server/process.json @@ -0,0 +1,11 @@ +{ + "apps" : [ + { + "name" : "code-push-server", + "max_memory_restart" : "500M", + "script" : "code-push-server", + "instances" : "max", //开启实例数量,max为cpu核数 + "exec_mode" : "cluster", //集群模式,最大提升网站并发 + } + ] +} \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 2a5a9c15..6b8193fc 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,7 +1,7 @@ -version: "3.3" +version: "3.7" services: server: - image: tablee/code-push-server:v0.4.3 + image: tablee/code-push-server:v0.4.4 volumes: - data-storage:/data/storage - data-tmp:/data/tmp @@ -10,8 +10,8 @@ services: DOWNLOAD_URL: "http://YOU_MACHINE_IP:3000/download" MYSQL_HOST: "YOU_MACHINE_IP" MYSQL_PORT: "3308" - MYSQL_USERNAME: "root" - MYSQL_PASSWORD: null + MYSQL_USERNAME: "codepush" + MYSQL_PASSWORD: "123456" MYSQL_DATABASE: "codepush" STORAGE_DIR: "/data/storage" DATA_DIR: "/data/tmp" @@ -20,7 +20,6 @@ services: REDIS_HOST: "YOU_MACHINE_IP" REDIS_PORT: "6388" deploy: - replicas: 5 resources: limits: cpus: "2" @@ -52,10 +51,11 @@ services: ports: - "6388:6379" networks: - - dbnet + - redisnet networks: servernet: dbnet: + redisnet: volumes: data-storage: data-tmp: diff --git a/docker/sql/codepush-all.sql b/docker/sql/codepush-all.sql index e36a34dd..f0b53688 100644 --- a/docker/sql/codepush-all.sql +++ b/docker/sql/codepush-all.sql @@ -1,5 +1,9 @@ CREATE DATABASE IF NOT EXISTS `codepush`; +GRANT SELECT,UPDATE,INSERT ON `codepush`.* TO 'codepush'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; + +flush privileges; + use `codepush`; CREATE TABLE IF NOT EXISTS `apps` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, From 7c014794a4bd08b59daad1cd02602a0c448ab822 Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 28 Aug 2018 19:17:49 +0800 Subject: [PATCH 143/194] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index c745084a..1c779ae3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,5 @@ -## INSTALL NPM +## INSTALL NODE AND NPM [see](https://nodejs.org/en/download/) From 200660eaf85cabc22e70ed60084efbea5dda43db Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 28 Aug 2018 19:18:50 +0800 Subject: [PATCH 144/194] Update README.md --- docs/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/README.md b/docs/README.md index 1c779ae3..72ba61d3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,10 +13,10 @@ $ sudo npm i -g pm2 ## INSTALL MYSQL -[Linux](https://dev.mysql.com/doc/refman/8.0/en/linux-installation.html) -[macOS](https://dev.mysql.com/doc/refman/8.0/en/osx-installation.html) -[Microsoft Windows](https://dev.mysql.com/doc/refman/8.0/en/windows-installation.html) -[Others](https://dev.mysql.com/doc/refman/8.0/en/installing.html) +- [Linux](https://dev.mysql.com/doc/refman/8.0/en/linux-installation.html) +- [macOS](https://dev.mysql.com/doc/refman/8.0/en/osx-installation.html) +- [Microsoft Windows](https://dev.mysql.com/doc/refman/8.0/en/windows-installation.html) +- [Others](https://dev.mysql.com/doc/refman/8.0/en/installing.html) ## GET code-push-server FROM NPM From 094efce6280f91222e833e96b8c60634552fa079 Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 28 Aug 2018 19:19:51 +0800 Subject: [PATCH 145/194] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 72ba61d3..989d072b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -62,7 +62,7 @@ some config have to change: ## CONFIGURE for pm2 -save the file [config.js](./process.json) +save the file [process.json](./process.json) some config have to change: From c93f2265ab23f00aca1f62123def14e08bd9795d Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 28 Aug 2018 19:27:19 +0800 Subject: [PATCH 146/194] Update react-native-code-push.md --- docs/react-native-code-push.md | 44 ++++++++++------------------------ 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index c27e8413..979057cc 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -40,22 +40,19 @@ $ npm install --save react-native-code-push@latest #安装react-native-code-pus $ react-native link react-native-code-push #连接到项目中,提示输入配置可以先行忽略 ``` -#### 4. [code-push-server](https://github.com/lisong/code-push-server) 微软云服务在中国太慢,可以用它搭建自己的服务端。具体配置参考该项目 +#### 4. [code-push-server](https://github.com/lisong/code-push-server) 微软云服务在中国太慢,可以用它搭建自己的服务端。 -```shell -$ npm install code-push-server -g -$ code-push-server-db init --dbhost localhost --dbuser root --dbpassword #初始化数据库 -$ code-push-server #启动服务 浏览器中打开 http://127.0.0.1:3000 -``` +- [docker](../docker/README.md) (recommend) +- [manual operation](./README.md) ## 创建服务端应用 基于code-push-server服务 ```shell -$ code-push login http://127.0.0.1:3000 #浏览器中登录获取token,用户名:admin, 密码:123456 -$ code-push app add CodePushDemo-ios #创建iOS版, 获取Production DeploymentKey -$ code-push app add CodePushDemo-android #创建android版,获取获取Production DeploymentKey +$ code-push login http://YOUR_CODE_PUSH_SERVER_IP:3000 #浏览器中登录获取token,用户名:admin, 密码:123456 +$ code-push app add CodePushDemoiOS ios react-native #创建iOS版, 获取Production DeploymentKey +$ code-push app add CodePushDemoAndroid andriod react-native #创建android版,获取获取Production DeploymentKey ``` ## 配置CodePushDemo react-native项目 @@ -66,7 +63,7 @@ $ code-push app add CodePushDemo-android #创建android版,获取获取Product 1. `CodePushDeploymentKey`值设置为CodePushDemo-ios的Production DeploymentKey值。 -2. `CodePushServerURL`值设置为code-push-server服务地址 http://127.0.0.1:3000/ 不在同一台机器的时候,请将127.0.0.1改成外网ip或者域名地址。 +2. `CodePushServerURL`值设置为code-push-server服务地址 http://YOUR_CODE_PUSH_SERVER_IP:3000/ 不在同一台机器的时候,请将YOUR_CODE_PUSH_SERVER_IP改成外网ip或者域名地址。 3. 将默认版本号1.0改成三位1.0.0 @@ -85,12 +82,10 @@ $ code-push app add CodePushDemo-android #创建android版,获取获取Product 1. `YourKey`替换成CodePushDemo-android的Production DeploymentKey值 -2. `YourCodePushServerUrl`值设置为code-push-server服务地址 http://127.0.0.1:3000/ 不在同一台机器的时候,请将127.0.0.1改成外网ip或者域名地址。 +2. `YourCodePushServerUrl`值设置为code-push-server服务地址 http://YOUR_CODE_PUSH_SERVER_IP:3000/ 不在同一台机器的时候,请将YOUR_CODE_PUSH_SERVER_IP改成外网ip或者域名地址。 3. 将默认版本号1.0改成三位1.0.0 -4. android模拟器和code-push-server在同一台机器上时,需要额外运行命令`adb reverse tcp:3000 tcp:3000` 代理端口,否则无法访问127.0.0.1:3000端口 - ```java @Override protected List getPackages() { @@ -108,7 +103,7 @@ protected List getPackages() { ## 添加更新检查 -可以参考[demo.js](https://github.com/lisong/code-push-demo-app/blob/master/demo.js) +可以参考[code-push-demo-app](https://github.com/lisong/code-push-demo-app/) 可以在入口componentDidMount添加 ```javascript @@ -124,16 +119,6 @@ CodePush.sync({ import CodePush from "react-native-code-push" ``` -> notice: -> -> demo.js中用到ECMAScript中Decorators语法,需要安装`$ npm install babel-preset-react-native-stage-0 --save`, -> 同时在.babelrc中添加'react-native-stage-0/decorator-support'. -> -> eg. -> { -> "presets": ["react-native", "react-native-stage-0/decorator-support"] -> } - ## 运行CodePushDemo react-native项目 #### iOS @@ -163,16 +148,11 @@ $ code-push release-react CodePushDemo-ios ios -d Production #iOS版 $ code-push release-react CodePushDemo-android android -d Production #android版 ``` +## 例子 -## 注意事项 +[code-push-demo-app](https://github.com/lisong/code-push-demo-app) -- 苹果允许使用热更新[Apple's developer agreement](https://developer.apple.com/programs/ios/information/iOS_Program_Information_4_3_15.pdf), 但是规定不能弹框提示用户更新,影响用户体验。 而Google Play恰好相反,必须弹框告知用户更新。然而中国的android市场都必须关闭更新弹框,否则会在审核应用时以“请上传最新版本的二进制应用包”驳回应用。 -- react-native 不同平台bundle包不一样,在使用code-push-server的时候必须创建不同的应用来区分(eg. CodePushDemo-ios 和 CodePushDemo-android) -- react-native-code-push只更新资源文件,不会更新java和Objective C,所以npm升级依赖包版本的时候,如果依赖包使用的本地化实现, 这时候必须更改应用版本号(ios修改Info.plist中的CFBundleShortVersionString, android修改build.gradle中的versionName), 然后重新编译app发布到应用商店。 -- 推荐使用code-push release-react 命令发布应用,该命令合并了打包和发布命令(eg. code-push release-react CodePushDemo-ios ios -d Production) -- 每次向App Store提交新的版本时,也应该基于该提交版本同时向code-push-server发布一个初始版本。(因为后面每次向code-push-server发布版本时,code-puse-server都会和初始版本比较,生成补丁版本) -## 例子 +### 更多信息参考[code-push-server](https://github.com/lisong/code-push-server) -[code-push-demo-app](https://github.com/lisong/code-push-demo-app) From 4da1af1d33c993fdb91b4989a07306d0a6ea85c6 Mon Sep 17 00:00:00 2001 From: lisong Date: Thu, 30 Aug 2018 20:35:21 +0800 Subject: [PATCH 147/194] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7c1dd385..bce6b3fc 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,8 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in ## qq交流群 -- NO.2群: 628921445 -- NO.1群: 535491067 +- NO.2QQ群: 628921445 +- NO.1QQ群: 535491067 ## 正确使用code-push热更新 From 9c559e6da8b6682a8034edd8cd5fe641aa6b7f49 Mon Sep 17 00:00:00 2001 From: lisong Date: Thu, 30 Aug 2018 20:42:27 +0800 Subject: [PATCH 148/194] Update README.md --- docker/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/README.md b/docker/README.md index afdf433c..72169245 100644 --- a/docker/README.md +++ b/docker/README.md @@ -11,8 +11,8 @@ - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用,只需要给予`select,update,insert`权限即可 - redis部分 - `tryLoginTimes` 登录错误次数限制 - - `updateCheckCache` 提升应用性能提升 - - `updateCheckCache` 灰度发布 + - `updateCheckCache` 提升应用性能 + - `rolloutClientUniqueIdCache` 灰度发布 ## 安装docker @@ -20,7 +20,7 @@ - [>>mac点这里](https://docs.docker.com/docker-for-mac/install/) - [>>windows点这里](https://docs.docker.com/docker-for-windows/install/) -- [>>linux](https://docs.docker.com/install/linux/docker-ce/ubuntu/) +- [>>linux点这里](https://docs.docker.com/install/linux/docker-ce/ubuntu/) `$ docker info` 能成功输出相关信息,则安装成功,才能继续下面步骤 From afeb1f6b2799ee65b006c461a46783266defb1ec Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 26 Aug 2018 16:50:50 +0800 Subject: [PATCH 149/194] 0.4.5 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c520f3af..c738ffc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.4", + "version": "0.4.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d176c9e2..2fc304af 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.4", + "version": "0.4.5", "license": "MIT", "repository": { "type": "git", From c1a299f8738fed16ebf283233589853914b76048 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Sep 2018 11:27:47 +0800 Subject: [PATCH 150/194] sopport tencent cloud cos storageType --- README.md | 21 +++- config/config.js | 10 +- core/utils/common.js | 38 +++++- docs/README.md | 1 + package-lock.json | 272 +++++++++++++++++++------------------------ package.json | 3 +- 6 files changed, 184 insertions(+), 161 deletions(-) diff --git a/README.md b/README.md index bce6b3fc..dfd31ffe 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,20 @@ [![Known Vulnerabilities](https://snyk.io/test/npm/code-push-server/badge.svg)](https://snyk.io/test/npm/code-push-server) [![Licenses](https://img.shields.io/npm/l/code-push-server.svg)](https://spdx.org/licenses/MIT) -CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use [local/s3/oss] storage, just modify config.js file, it's simple configure. +CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use [local/s3/oss/tencentcloud] storage, just modify config.js file, it's simple configure. + +## Support Storage mode + +- local *storage bundle file in local machine* +- qiniu *storage bundle file in [qiniu](http://www.qiniu.com/)* +- s3 *storage bundle file in [aws](https://aws.amazon.com/)* +- oss *storage bundle file in [aliyun](https://www.aliyun.com/product/oss)* +- tencentcloud *storage bundle file in [tencentcloud](https://cloud.tencent.com/product/cos)* ## qq交流群 -- NO.2QQ群: 628921445 -- NO.1QQ群: 535491067 +- QQ群: 628921445 +- QQ群: 535491067 ## 正确使用code-push热更新 @@ -56,7 +64,12 @@ $ code-push login http://api.code-push.com #登录 ## ISSUES -[code-push-server normal problem](https://github.com/lisong/code-push-server/issues/135) + +[code-push-server normal solution](https://github.com/lisong/code-push-server/issues/135) + +[An unknown error occurred](https://github.com/lisong/code-push-server/issues?utf8=%E2%9C%93&q=unknown) + +[modify password](https://github.com/lisong/code-push-server/issues/43) ## License MIT License [read](https://github.com/lisong/code-push-server/blob/master/LICENSE) diff --git a/config/config.js b/config/config.js index 3aabbec6..551cb643 100644 --- a/config/config.js +++ b/config/config.js @@ -38,6 +38,14 @@ config.development = { prefix: "", // Key prefix in object key downloadUrl: "", // binary files download host address. }, + // Config for tencentyun COS (https://cloud.tencent.com/product/cos) when storageType value is "oss". + tencentcloud: { + accessKeyId: "", + secretAccessKey: "", + bucketName: "", + region: "", + downloadUrl: "", // binary files download host address. + }, // Config for local storage when storageType value is "local". local: { // Binary files storage dir, Do not use tmpdir and it's public download dir. @@ -65,7 +73,7 @@ config.development = { diffNums: 3, // data dir for caclulate diff files. it's optimization. dataDir: process.env.DATA_DIR || os.tmpdir(), - // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3") + // storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3"| "oss" || "tencentcloud") storageType: process.env.STORAGE_TYPE || "local", // options value is (true | false), when it's true, it will cache updateCheck results in redis. updateCheckCache: false, diff --git a/core/utils/common.js b/core/utils/common.js index f2c57222..fe8ecf3e 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -183,14 +183,19 @@ common.getUploadTokenQiniu = function (mac, bucket, key) { }; common.uploadFileToStorage = function (key, filePath) { - if (_.get(config, 'common.storageType') === 'local') { + var storageType = _.get(config, 'common.storageType'); + if ( storageType === 'local') { return common.uploadFileToLocal(key, filePath); - } else if (_.get(config, 'common.storageType') === 's3') { + } else if (storageType === 's3') { return common.uploadFileToS3(key, filePath); - } else if (_.get(config, 'common.storageType') === 'oss') { + } else if (storageType === 'oss') { return common.uploadFileToOSS(key, filePath); + } else if (storageType === 'qiniu') { + return common.uploadFileToQiniu(key, filePath); + } else if (storageType === 'tencentcloud') { + return common.uploadFileToTencentCloud(key, filePath); } - return common.uploadFileToQiniu(key, filePath); + throw new AppError.AppError(`${storageType} storageType does not support.`); }; common.uploadFileToLocal = function (key, filePath) { @@ -360,16 +365,41 @@ common.uploadFileToOSS = function (key, filePath) { return new Promise((resolve, reject) => { upload.on('error', (error) => { + log.debug("uploadFileToOSS", error); reject(error); }); upload.on('uploaded', (details) => { + log.debug("uploadFileToOSS", details); resolve(details.ETag); }); fs.createReadStream(filePath).pipe(upload); }); }; +common.uploadFileToTencentCloud = function (key, filePath) { + return new Promise((resolve, reject) => { + var COS = require('cos-nodejs-sdk-v5'); + var cosIn = new COS({ + SecretId: _.get(config, 'tencentcloud.accessKeyId'), + SecretKey: _.get(config, 'tencentcloud.secretAccessKey') + }); + cosIn.sliceUploadFile({ + Bucket: _.get(config, 'tencentcloud.bucketName'), + Region: _.get(config, 'tencentcloud.region'), + Key: key, + FilePath: filePath + }, function (err, data) { + log.debug("uploadFileToTencentCloud", err, data); + if (err) { + reject(new AppError.AppError(JSON.stringify(err))); + }else { + resolve(data.Key); + } + }); + }); +} + common.diffCollectionsSync = function (collection1, collection2) { var diffFiles = []; var collection1Only = []; diff --git a/docs/README.md b/docs/README.md index 989d072b..92099f73 100644 --- a/docs/README.md +++ b/docs/README.md @@ -156,6 +156,7 @@ $ tail -f "output file path" - qiniu (qiniu) - s3 (aws) - oss (aliyun) +- tencentcloud ## Default listen Host/Port 0.0.0.0/3000 diff --git a/package-lock.json b/package-lock.json index c738ffc4..03943ca3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,18 +100,6 @@ "resolved": "http://registry.npm.taobao.org/aliyun-oss-upload-stream/download/aliyun-oss-upload-stream-1.3.0.tgz", "integrity": "sha1-ODAbGfA0QGhDjrY5d6DNldYEcMA=" }, - "aliyun-sdk": { - "version": "1.11.5", - "resolved": "http://registry.npm.taobao.org/aliyun-sdk/download/aliyun-sdk-1.11.5.tgz", - "integrity": "sha1-kwWBkrN0Wn+AbLJW+L+oEBb2dy0=", - "requires": { - "node_memcached": "1.1.3", - "pomelo-protobuf": "0.4.0", - "protobufjs": "4.1.3", - "xml2js": "0.4.4", - "xmlbuilder": "2.6.5" - } - }, "ambi": { "version": "2.5.0", "resolved": "http://registry.npm.taobao.org/ambi/download/ambi-2.5.0.tgz", @@ -176,15 +164,6 @@ "resolved": "http://registry.npm.taobao.org/asap/download/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, - "ascli": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/ascli/download/ascli-1.0.1.tgz", - "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", - "requires": { - "colour": "0.7.1", - "optjs": "3.2.2" - } - }, "asn1": { "version": "0.2.3", "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.3.tgz", @@ -392,30 +371,11 @@ "resolved": "http://registry.npm.taobao.org/buffer-equal-constant-time/download/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, - "bufferview": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/bufferview/download/bufferview-1.0.1.tgz", - "integrity": "sha1-ev10pF+Tf6QiodM4wIu/3HbNcl0=" - }, - "bytebuffer": { - "version": "4.1.0", - "resolved": "http://registry.npm.taobao.org/bytebuffer/download/bytebuffer-4.1.0.tgz", - "integrity": "sha1-TFgmngUqseSx9/82T9+zzogpBqo=", - "requires": { - "bufferview": "1.0.1", - "long": "2.4.0" - } - }, "bytes": { "version": "3.0.0", "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, - "camelcase": { - "version": "2.1.1", - "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, "camelize": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/camelize/download/camelize-1.0.0.tgz", @@ -484,16 +444,6 @@ } } }, - "cliui": { - "version": "3.2.0", - "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, "cls-bluebird": { "version": "2.1.0", "resolved": "http://registry.npm.taobao.org/cls-bluebird/download/cls-bluebird-2.1.0.tgz", @@ -518,11 +468,6 @@ "resolved": "http://registry.npm.taobao.org/coffee-script/download/coffee-script-1.12.7.tgz", "integrity": "sha1-wF2uDLeVkdBbMHCoQzqYyaiczFM=" }, - "colour": { - "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/colour/download/colour-0.7.1.tgz", - "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" - }, "combined-stream": { "version": "1.0.6", "resolved": "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.6.tgz", @@ -552,6 +497,19 @@ "typedarray": "0.0.6" } }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, "constantinople": { "version": "3.1.2", "resolved": "http://registry.npm.taobao.org/constantinople/download/constantinople-3.1.2.tgz", @@ -613,6 +571,33 @@ "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cos-nodejs-sdk-v5": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/cos-nodejs-sdk-v5/-/cos-nodejs-sdk-v5-2.4.10.tgz", + "integrity": "sha512-espPlCyyOc4vBKKI6Mwb5ZKzjYDgd0GOK4H0msiryupc3wlQCfPqJM+PubVlUEssqK58wIiV9Bq4Bo/ts2irjg==", + "requires": { + "configstore": "3.1.2", + "qcloudapi-sdk": "0.2.0", + "request": "2.85.0", + "xml2js": "0.4.19" + }, + "dependencies": { + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": "0.6.1", + "xmlbuilder": "9.0.7" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + } + } + }, "crc32": { "version": "0.2.2", "resolved": "http://registry.npm.taobao.org/crc32/download/crc32-0.2.2.tgz", @@ -646,6 +631,11 @@ } } }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, "csextends": { "version": "1.1.1", "resolved": "http://registry.npm.taobao.org/csextends/download/csextends-1.1.1.tgz", @@ -748,6 +738,19 @@ "resolved": "http://registry.npm.taobao.org/dont-sniff-mimetype/download/dont-sniff-mimetype-1.0.0.tgz", "integrity": "sha1-WTKJDcn04vGeXrAqIAJuXl78j1g=" }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "1.0.1" + } + }, + "dot-qs": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dot-qs/-/dot-qs-0.2.0.tgz", + "integrity": "sha1-02UX/iS3zaYfznpQJqACSvr1pDk=" + }, "dottie": { "version": "2.0.0", "resolved": "http://registry.npm.taobao.org/dottie/download/dottie-2.0.0.tgz", @@ -1116,6 +1119,7 @@ "version": "5.0.15", "resolved": "http://registry.npm.taobao.org/glob/download/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, "requires": { "inflight": "1.0.6", "inherits": "2.0.3", @@ -1337,6 +1341,11 @@ "resolved": "http://registry.npm.taobao.org/ignorepatterns/download/ignorepatterns-1.1.0.tgz", "integrity": "sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4=" }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, "inflight": { "version": "1.0.6", "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", @@ -1395,6 +1404,11 @@ "number-is-nan": "1.0.1" } }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, "is-promise": { "version": "2.1.0", "resolved": "http://registry.npm.taobao.org/is-promise/download/is-promise-2.1.0.tgz", @@ -1814,11 +1828,6 @@ "streamroller": "0.7.0" } }, - "long": { - "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/long/download/long-2.4.0.tgz", - "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" - }, "longest": { "version": "1.0.1", "resolved": "http://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz", @@ -1833,6 +1842,14 @@ "yallist": "2.1.2" } }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "3.0.0" + } + }, "make-plural": { "version": "3.0.6", "resolved": "http://registry.npm.taobao.org/make-plural/download/make-plural-3.0.6.tgz", @@ -2163,24 +2180,6 @@ "resolved": "http://registry.npm.taobao.org/nocache/download/nocache-2.0.0.tgz", "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" }, - "node_memcached": { - "version": "1.1.3", - "resolved": "http://registry.npm.taobao.org/node_memcached/download/node_memcached-1.1.3.tgz", - "integrity": "sha1-icFSr4itKIF/ANiRyZBFHV1xLqg=", - "requires": { - "debug": "2.6.9" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "requires": { - "ms": "2.0.0" - } - } - } - }, "nodemailer": { "version": "4.6.3", "resolved": "http://registry.npm.taobao.org/nodemailer/download/nodemailer-4.6.3.tgz", @@ -2270,19 +2269,6 @@ "wordwrap": "1.0.0" } }, - "optjs": { - "version": "3.2.2", - "resolved": "http://registry.npm.taobao.org/optjs/download/optjs-3.2.2.tgz", - "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" - }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, "os-name": { "version": "1.0.3", "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz", @@ -2381,16 +2367,16 @@ "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, "platform": { "version": "1.3.5", "resolved": "http://registry.npm.taobao.org/platform/download/platform-1.3.5.tgz", "integrity": "sha1-+2lYxpbgfikY0u7aDwvJRI1zNEQ=" }, - "pomelo-protobuf": { - "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/pomelo-protobuf/download/pomelo-protobuf-0.4.0.tgz", - "integrity": "sha1-5F6aCkRusYZn4MbhPutT1Hrdvag=" - }, "prelude-ls": { "version": "1.1.2", "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", @@ -2410,33 +2396,6 @@ "asap": "2.0.6" } }, - "protobufjs": { - "version": "4.1.3", - "resolved": "http://registry.npm.taobao.org/protobufjs/download/protobufjs-4.1.3.tgz", - "integrity": "sha1-jjbRsCJsu2jWR+S0TCoUTzfyd54=", - "requires": { - "ascli": "1.0.1", - "bytebuffer": "4.1.0", - "glob": "5.0.15", - "yargs": "3.32.0" - }, - "dependencies": { - "yargs": { - "version": "3.32.0", - "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "requires": { - "camelcase": "2.1.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "string-width": "1.0.2", - "window-size": "0.1.4", - "y18n": "3.2.1" - } - } - } - }, "proxy-addr": { "version": "2.0.3", "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.3.tgz", @@ -2570,6 +2529,23 @@ "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" }, + "qcloudapi-sdk": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/qcloudapi-sdk/-/qcloudapi-sdk-0.2.0.tgz", + "integrity": "sha512-Hy6a+95zDheaeMbA/N/7AEuAoOhwjR1POPI9xCwfsPc3b24ZzyH1M4PKgO9sq7Rq62+14ZTessHMdXJ+6NaeQg==", + "requires": { + "dot-qs": "0.2.0", + "object-assign": "3.0.0", + "request": "2.85.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + } + } + }, "qiniu": { "version": "7.1.3", "resolved": "http://registry.npm.taobao.org/qiniu/download/qiniu-7.1.3.tgz", @@ -3311,6 +3287,14 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "1.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "http://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz", @@ -3441,11 +3425,6 @@ "semver": "5.5.0" } }, - "window-size": { - "version": "0.1.4", - "resolved": "http://registry.npm.taobao.org/window-size/download/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" - }, "with": { "version": "5.1.1", "resolved": "http://registry.npm.taobao.org/with/download/with-5.1.1.tgz", @@ -3483,34 +3462,25 @@ "resolved": "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, "x-xss-protection": { "version": "1.1.0", "resolved": "http://registry.npm.taobao.org/x-xss-protection/download/x-xss-protection-1.1.0.tgz", "integrity": "sha1-TxiYwzLesefyvhKA77PixT1pwac=" }, - "xml2js": { - "version": "0.4.4", - "resolved": "http://registry.npm.taobao.org/xml2js/download/xml2js-0.4.4.tgz", - "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=", - "requires": { - "sax": "0.6.1", - "xmlbuilder": "2.6.5" - } - }, - "xmlbuilder": { - "version": "2.6.5", - "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-2.6.5.tgz", - "integrity": "sha1-b/etYPty0idk8AehZLd/K/FABSY=", - "requires": { - "lodash": "3.10.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" }, "xregexp": { "version": "2.0.0", diff --git a/package.json b/package.json index 2fc304af..2fbbe297 100644 --- a/package.json +++ b/package.json @@ -39,12 +39,13 @@ }, "dependencies": { "aliyun-oss-upload-stream": "^1.3.0", - "aliyun-sdk": "^1.11.5", + "aliyun-sdk": "^1.11.10", "aws-sdk": "^2.7.0", "bcryptjs": "^2.3.0", "bluebird": "^3.4.1", "body-parser": "^1.15.2", "cookie-parser": "^1.4.3", + "cos-nodejs-sdk-v5": "^2.4.10", "debug": "^3.1.0", "express": "^4.14.0", "extract-zip": "^1.6.0", From d069ec2904f6daaa309565434b492908545b535d Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Sep 2018 11:28:09 +0800 Subject: [PATCH 151/194] 0.4.6 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03943ca3..4ec45bce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.5", + "version": "0.4.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2fbbe297..17505c04 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.5", + "version": "0.4.6", "license": "MIT", "repository": { "type": "git", From 662683989ecfa364088e18738b9233094ec32de1 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Sep 2018 11:31:29 +0800 Subject: [PATCH 152/194] docker --- docker/code-push-server/Dockerfile | 2 +- docker/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/code-push-server/Dockerfile b/docker/code-push-server/Dockerfile index b13c4741..6e68d115 100644 --- a/docker/code-push-server/Dockerfile +++ b/docker/code-push-server/Dockerfile @@ -1,7 +1,7 @@ FROM node:8.11.4-alpine RUN npm config set registry https://registry.npm.taobao.org/ \ -&& npm i -g code-push-server@0.4.3 pm2@latest --no-optional +&& npm i -g code-push-server@0.4.7 pm2@latest --no-optional COPY ./process.json /process.json diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 6b8193fc..4682d9d3 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: server: - image: tablee/code-push-server:v0.4.4 + image: tablee/code-push-server:v0.4.7 volumes: - data-storage:/data/storage - data-tmp:/data/tmp From 64135ad08bd7604e13b4160da4c77690222a8460 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 1 Sep 2018 11:31:35 +0800 Subject: [PATCH 153/194] 0.4.7 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ec45bce..e64f3da5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.6", + "version": "0.4.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 17505c04..0473fe58 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.6", + "version": "0.4.7", "license": "MIT", "repository": { "type": "git", From 3452d9bd9b9bb9c307107f5eb3e97206df768bfb Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 2 Sep 2018 20:40:12 +0800 Subject: [PATCH 154/194] fix readme --- CHANGELOG.md | 25 +++++++++++++++++++++++-- README.md | 6 +++--- core/const.js | 1 + core/services/package-manager.js | 2 +- docker/README.md | 2 +- docs/README.md | 6 +++--- docs/react-native-code-push.md | 4 ++-- package-lock.json | 5 +++++ 8 files changed, 39 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a3b8c7f..1975b1f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,33 @@ # Changelog for code-push-server -## 0.4.0 -- targetBinaryVersion 支持正则匹配 +## 0.4.7 + +### 新特性 + +- targetBinaryVersion 支持正则匹配, `deployments_versions`新增字段`min_version`,`max_version` - `*` 匹配所有版本 - `1.2.3` 匹配特定版本`1.2.3` - `1.2`/`1.2.*` 匹配所有1.2补丁版本 - `>=1.2.3<1.3.7` - `~1.2.3` 匹配`>=1.2.3<1.3.0` - `^1.2.3` 匹配`>=1.2.3<2.0.0` +- 添加docker编排服务部署,更新文档 +- Support Tencent cloud cos storageType + +## 如何升级到该版本 + +- 升级数据库 +`$ ./bin/db upgrade` +or +`$ mysql codepush < ./sql/codepush-v0.4.0-patch.sql` + +- 处理存量数据 +``` shell + $ git clone https://github.com/lisong/tools + $ cd tools + $ npm i + $ vim ./bin/fixMinMaxVersion //修改数据配置 + $ node ./bin/fixMinMaxVersion //出现提示 success +``` ## 0.3.0 diff --git a/README.md b/README.md index dfd31ffe..ef314629 100644 --- a/README.md +++ b/README.md @@ -53,12 +53,12 @@ $ code-push login http://api.code-push.com #登录 ## HOW TO INSTALL code-push-server -- [docker](./docker/README.md) (recommend) -- [manual operation](./docs/README.md) +- [docker](https://github.com/lisong/code-push-server/blob/master/docker/README.md) (recommend) +- [manual operation](https://github.com/lisong/code-push-server/blob/master/docs/README.md) ## HOW TO USE -- [normal](./docs/react-native-code-push.md) +- [normal](https://github.com/lisong/code-push-server/blob/master/docs/react-native-code-push.md) - [react-native-code-push](https://github.com/Microsoft/react-native-code-push) - [code-push](https://github.com/Microsoft/code-push) diff --git a/core/const.js b/core/const.js index c224b64e..d053729a 100644 --- a/core/const.js +++ b/core/const.js @@ -37,5 +37,6 @@ define("RELEAS_EMETHOD_UPLOAD", 'Upload'); define("DEPLOYMENT_SUCCEEDED", 1); define("DEPLOYMENT_FAILED", 2); +define("DIFF_MANIFEST_FILE_NAME", 'hotcodepush.json'); diff --git a/core/services/package-manager.js b/core/services/package-manager.js index b5fcd715..62db4e20 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -195,7 +195,7 @@ proto.zipDiffPackage = function (fileName, files, baseDirectoryPath, hotCodePush var file = files[i]; zipFile.addFile(`${baseDirectoryPath}/${file}`, slash(file)); } - zipFile.addFile(hotCodePushFile, 'hotcodepush.json'); + zipFile.addFile(hotCodePushFile, constConfig.DIFF_MANIFEST_FILE_NAME); zipFile.end(); }); } diff --git a/docker/README.md b/docker/README.md index 72169245..236aca12 100644 --- a/docker/README.md +++ b/docker/README.md @@ -81,7 +81,7 @@ $ sudo docker service ps code-push-server_server ## 访问接口简单验证 -`$ curl -I http://127.0.0.1:3000/` +`$ curl -I http://YOUR_CODE_PUSH_SERVER_IP:3000/` 返回`200 OK` diff --git a/docs/README.md b/docs/README.md index 92099f73..10d25ae1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -50,7 +50,7 @@ $ ./bin/db init --dbhost "your mysql host" --dbport "your mysql port" --dbuser ## CONFIGURE for code-push-server -save the file [config.js](../config/config.js) +save the file [config.js](https://github.com/lisong/code-push-server/blob/master/config/config.js) some config have to change: @@ -62,7 +62,7 @@ some config have to change: ## CONFIGURE for pm2 -save the file [process.json](./process.json) +save the file [process.json](https://github.com/lisong/code-push-server/blob/master/docs/process.json) some config have to change: @@ -90,7 +90,7 @@ $ pm2 stop process.json ## CHECK SERVICE IS OK ```shell -$ curl -I http://127.0.0.1:3000/ +$ curl -I http://YOUR_CODE_PUSH_SERVER_IP:3000/ ``` > return httpCode `200 OK` diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index 979057cc..feab43f1 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -42,8 +42,8 @@ $ react-native link react-native-code-push #连接到项目中,提示输入 #### 4. [code-push-server](https://github.com/lisong/code-push-server) 微软云服务在中国太慢,可以用它搭建自己的服务端。 -- [docker](../docker/README.md) (recommend) -- [manual operation](./README.md) +- [docker](https://github.com/lisong/code-push-server/blob/master/docker/README.md) (recommend) +- [manual operation](https://github.com/lisong/code-push-server/blob/master/docs/README.md) ## 创建服务端应用 diff --git a/package-lock.json b/package-lock.json index e64f3da5..85f32bc9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -715,6 +715,11 @@ "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", "dev": true }, + "diff-match-patch": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.1.tgz", + "integrity": "sha512-A0QEhr4PxGUMEtKxd6X+JLnOTFd3BfIPSDpsc4dMvj+CbSaErDwTpoTo/nFJDMSrjxLW4BiNq+FbNisAAHhWeQ==" + }, "digest-header": { "version": "0.0.1", "resolved": "http://registry.npm.taobao.org/digest-header/download/digest-header-0.0.1.tgz", From e563e56a8d283a75b58b111dbb129cc3d6d03078 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 8 Sep 2018 20:54:43 +0800 Subject: [PATCH 155/194] support google diff-match-patch --- Makefile | 4 +- bin/db | 6 +- bin/www | 5 +- core/const.js | 7 + core/services/datacenter-manager.js | 27 +- core/services/package-manager.js | 146 +- core/utils/common.js | 39 +- docker/code-push-server/Dockerfile | 2 +- docker/docker-compose.yml | 2 +- docker/sql/codepush-all.sql | 3 +- models/apps.js | 1 + package-lock.json | 3145 +++++++++++++++++++++++++-- package.json | 2 + routes/apps.js | 28 +- sql/codepush-all.sql | 3 +- sql/codepush-v0.5.0-patch.sql | 3 + 16 files changed, 3117 insertions(+), 306 deletions(-) create mode 100644 sql/codepush-v0.5.0-patch.sql diff --git a/Makefile b/Makefile index 6ffcf5ba..7e59757b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ test: test-integration test-integration: @echo "\nRunning integration tests..." - @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init & + @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init @NODE_ENV=test PORT=3000 HOST=127.0.0.1 CONFIG_FILE=${ROOT}/config/config.test.js node bin/www & @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha \ test/api/users test/api/auth test/api/account test/api/accessKeys test/api/apps test/api/index --recursive --timeout 15000 @@ -18,7 +18,7 @@ coverage: rm -rf coverage # @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js cover --report lcovonly --dir coverage/core ./node_modules/.bin/_mocha \ # test/unit -- -R spec --recursive --timeout 15000 - @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init & + @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js mocha test/api/init @NODE_ENV=test PORT=3000 HOST=127.0.0.1 CONFIG_FILE=${ROOT}/config/config.test.js node bin/www & @NODE_ENV=test CONFIG_FILE=${ROOT}/config/config.test.js ./node_modules/istanbul/lib/cli.js cover --report lcovonly --dir coverage/api ./node_modules/.bin/_mocha \ test/api/users test/api/auth test/api/account test/api/accessKeys test/api/apps test/api/index -- -R spec --recursive --timeout 15000 diff --git a/bin/db b/bin/db index 949343ee..005b8810 100755 --- a/bin/db +++ b/bin/db @@ -9,6 +9,7 @@ var _ = require('lodash'); var mysql = require('mysql2'); var Promise = require("bluebird"); var common = require("../core/utils/common"); +var constConfig = require('../core/const'); var yargs = require('yargs') .usage('Usage: $0 [options]') .command('init', '初始化数据库', { @@ -97,7 +98,7 @@ if (command === 'init') { var version_no = '0.0.1'; var rs = yield connection.queryAsync('select `version` from `versions` where `type`=1 limit 1'); version_no = _.get(rs,'0.version', '0.0.1'); - if (version_no == '0.4.0') { + if (version_no == constConfig.CURRENT_DB_VERSION) { console.log('Everything up-to-date.'); process.exit(0); } @@ -105,7 +106,8 @@ if (command === 'init') { {version:'0.2.14', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.14-patch.sql')}, {version:'0.2.15', 'path':path.resolve(__dirname, '../sql/codepush-v0.2.15-patch.sql')}, {version:'0.3.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.3.0-patch.sql')}, - {version:'0.4.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.4.0-patch.sql')} + {version:'0.4.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.4.0-patch.sql')}, + {version:'0.5.0', 'path':path.resolve(__dirname, '../sql/codepush-v0.5.0-patch.sql')} ]; for (var i = 0; i < allSqlFile.length; i++) { if(!_.gt(allSqlFile[i]['version'], version_no)) { diff --git a/bin/www b/bin/www index 7b4757b3..4f086a7b 100755 --- a/bin/www +++ b/bin/www @@ -9,6 +9,7 @@ var http = require('http'); var validator = require('validator') var _ = require('lodash') var config = require('../core/config'); +var constConfig = require('../core/const'); log4js.configure(_.get(config, 'log4js', { appenders: {console: { type: 'console'}}, categories : { default: { appenders: ['console'], level: 'info' }} @@ -48,8 +49,8 @@ var server = http.createServer(app); var models = require('../models'); models.Versions.findOne({where:{type:1}}) .then(function(v){ - if (!v || v.get('version') != '0.4.0') { - throw new Error(`Please upgrade your database. usage bin/db upgrade or code-push-server-db upgrade`); + if (!v || v.get('version') != constConfig.CURRENT_DB_VERSION) { + throw new Error('Please upgrade your database. usage `npm run upgrade` or `code-push-server-db upgrade`'); } server.listen(port, host); server.on('error', onError); diff --git a/core/const.js b/core/const.js index d053729a..f1d9b23b 100644 --- a/core/const.js +++ b/core/const.js @@ -39,4 +39,11 @@ define("DEPLOYMENT_FAILED", 2); define("DIFF_MANIFEST_FILE_NAME", 'hotcodepush.json'); +//文本文件是否使用google diff-match-patch 计算差异 +define("IS_USE_DIFF_TEXT_NO", 0); +define("IS_USE_DIFF_TEXT_YES", 1); + + +define("CURRENT_DB_VERSION", '0.5.0'); + diff --git a/core/services/datacenter-manager.js b/core/services/datacenter-manager.js index 1193d2ea..c59d29ff 100644 --- a/core/services/datacenter-manager.js +++ b/core/services/datacenter-manager.js @@ -11,6 +11,7 @@ const CONTENTS_NAME = 'contents'; var AppError = require('../app-error'); var log4js = require('log4js'); var log = log4js.getLogger("cps:DataCenterManager"); +var path = require('path'); var proto = module.exports = function (){ function DataCenterManager() { @@ -30,18 +31,18 @@ proto.getDataDir = function () { proto.hasPackageStoreSync = function (packageHash) { var dataDir = this.getDataDir(); - var packageHashPath = `${dataDir}/${packageHash}`; - var manifestFile = `${packageHashPath}/${MANIFEST_FILE_NAME}`; - var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; + var packageHashPath = path.join(dataDir, packageHash); + var manifestFile = path.join(packageHashPath, MANIFEST_FILE_NAME); + var contentPath = path.join(packageHashPath, CONTENTS_NAME); return fs.existsSync(manifestFile) && fs.existsSync(contentPath); } proto.getPackageInfo = function (packageHash) { if (this.hasPackageStoreSync(packageHash)){ var dataDir = this.getDataDir(); - var packageHashPath = `${dataDir}/${packageHash}`; - var manifestFile = `${packageHashPath}/${MANIFEST_FILE_NAME}`; - var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; + var packageHashPath = path.join(dataDir, packageHash); + var manifestFile = path.join(packageHashPath, MANIFEST_FILE_NAME); + var contentPath = path.join(packageHashPath, CONTENTS_NAME); return this.buildPackageInfo(packageHash, packageHashPath, contentPath, manifestFile); } else { throw new AppError.AppError('can\'t get PackageInfo'); @@ -59,9 +60,9 @@ proto.buildPackageInfo = function (packageHash, packageHashPath, contentPath, ma proto.validateStore = function (providePackageHash) { var dataDir = this.getDataDir(); - var packageHashPath = `${dataDir}/${providePackageHash}`; - var manifestFile = `${packageHashPath}/${MANIFEST_FILE_NAME}`; - var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; + var packageHashPath = path.join(dataDir, providePackageHash); + var manifestFile = path.join(packageHashPath, MANIFEST_FILE_NAME); + var contentPath = path.join(packageHashPath, CONTENTS_NAME); if (!this.hasPackageStoreSync(providePackageHash)) { log.debug(`validateStore providePackageHash not exist`); return Promise.resolve(false); @@ -98,9 +99,9 @@ proto.storePackage = function (sourceDst, force) { var packageHash = security.packageHashSync(manifestJson); log.debug('storePackage manifestJson packageHash:', packageHash); var dataDir = self.getDataDir(); - var packageHashPath = `${dataDir}/${packageHash}`; - var manifestFile = `${packageHashPath}/${MANIFEST_FILE_NAME}`; - var contentPath = `${packageHashPath}/${CONTENTS_NAME}`; + var packageHashPath = path.join(dataDir, packageHash); + var manifestFile = path.join(packageHashPath, MANIFEST_FILE_NAME); + var contentPath = path.join(packageHashPath, CONTENTS_NAME); return self.validateStore(packageHash) .then((isValidate) => { if (!force && isValidate) { @@ -109,7 +110,7 @@ proto.storePackage = function (sourceDst, force) { log.debug(`storePackage cover from sourceDst:`, sourceDst); return common.createEmptyFolder(packageHashPath) .then(() => { - return common.move(sourceDst, contentPath) + return common.copy(sourceDst, contentPath) .then(() => { var manifestString = JSON.stringify(manifestJson); fs.writeFileSync(manifestFile, manifestString); diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 62db4e20..1b9b8b0c 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -166,9 +166,9 @@ proto.downloadPackageAndExtract = function (workDirectoryPath, packageHash, blob return dataCenterManager.getPackageInfo(packageHash); } else { var downloadURL = common.getBlobDownloadUrl(blobHash); - return common.createFileFromRequest(downloadURL, `${workDirectoryPath}/${blobHash}`) + return common.createFileFromRequest(downloadURL, path.join(workDirectoryPath, blobHash)) .then((download) => { - return common.unzipFile(`${workDirectoryPath}/${blobHash}`, `${workDirectoryPath}/current`) + return common.unzipFile(path.join(workDirectoryPath, blobHash), path.join(workDirectoryPath, 'current')) .then((outputPath) => { return dataCenterManager.storePackage(outputPath, true); }); @@ -193,14 +193,22 @@ proto.zipDiffPackage = function (fileName, files, baseDirectoryPath, hotCodePush }); for (var i = 0; i < files.length; ++i) { var file = files[i]; - zipFile.addFile(`${baseDirectoryPath}/${file}`, slash(file)); + zipFile.addFile(path.join(baseDirectoryPath, file), slash(file)); } zipFile.addFile(hotCodePushFile, constConfig.DIFF_MANIFEST_FILE_NAME); zipFile.end(); }); } -proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCenter, diffPackageHash, diffManifestBlobHash) { +proto.generateOneDiffPackage = function ( + workDirectoryPath, + packageId, + originDataCenter, + oldPackageDataCenter, + diffPackageHash, + diffManifestBlobHash, + isUseDiffText +) { var self = this; return models.PackagesDiff.findOne({ where:{ @@ -212,24 +220,53 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente if (!_.isEmpty(diffPackage)) { return; } + log.debug('originDataCenter', originDataCenter); + log.debug('oldPackageDataCenter', oldPackageDataCenter); var downloadURL = common.getBlobDownloadUrl(diffManifestBlobHash); - return common.createFileFromRequest(downloadURL, `${workDirectoryPath}/${diffManifestBlobHash}`) + return common.createFileFromRequest(downloadURL, path.join(workDirectoryPath,diffManifestBlobHash)) .then(() => { - var originContentPath = dataCenter.contentPath; - var originManifestJson = JSON.parse(fs.readFileSync(dataCenter.manifestFilePath, "utf8")) - var diffManifestJson = JSON.parse(fs.readFileSync(`${workDirectoryPath}/${diffManifestBlobHash}`, "utf8")) + var dataCenterContentPath = path.join(workDirectoryPath, 'dataCenter'); + common.copySync(originDataCenter.contentPath, dataCenterContentPath); + var oldPackageDataCenterContentPath = oldPackageDataCenter.contentPath; + var originManifestJson = JSON.parse(fs.readFileSync(originDataCenter.manifestFilePath, "utf8")) + var diffManifestJson = JSON.parse(fs.readFileSync(path.join(workDirectoryPath, diffManifestBlobHash), "utf8")) var json = common.diffCollectionsSync(originManifestJson, diffManifestJson); var files = _.concat(json.diff, json.collection1Only); - var hotcodepush = {deletedFiles: json.collection2Only}; - var hotCodePushFile = `${workDirectoryPath}/${diffManifestBlobHash}_hotcodepush`; + var hotcodepush = {deletedFiles: json.collection2Only, patchedFiles:[]}; + if (isUseDiffText == constConfig.IS_USE_DIFF_TEXT_YES) { + //使用google diff-match-patch + _.forEach(json.diff, function(tmpFilePath) { + var dataCenterContentPathTmpFilePath = path.join(dataCenterContentPath, tmpFilePath); + var oldPackageDataCenterContentPathTmpFilePath = path.join(oldPackageDataCenterContentPath, tmpFilePath); + if ( + fs.existsSync(dataCenterContentPathTmpFilePath) + && fs.existsSync(oldPackageDataCenterContentPathTmpFilePath) + && common.detectIsTextFile(dataCenterContentPathTmpFilePath) + && common.detectIsTextFile(oldPackageDataCenterContentPathTmpFilePath) + ) { + var textOld = fs.readFileSync(oldPackageDataCenterContentPathTmpFilePath, 'utf-8'); + var textNew = fs.readFileSync(dataCenterContentPathTmpFilePath, 'utf-8'); + if (!textOld || !textNew) { + return; + } + var DiffMatchPatch = require('diff-match-patch'); + var dmp = new DiffMatchPatch(); + var patchs = dmp.patch_make(textOld, textNew); + var patchText = dmp.patch_toText(patchs); + if (patchText && patchText.length < _.parseInt(textNew.length * 0.8)) { + fs.writeFileSync(dataCenterContentPathTmpFilePath, patchText); + hotcodepush.patchedFiles.push(tmpFilePath); + } + } + }); + } + var hotCodePushFile = path.join(workDirectoryPath,`${diffManifestBlobHash}_hotcodepush`);; fs.writeFileSync(hotCodePushFile, JSON.stringify(hotcodepush)); - var fileName = `${workDirectoryPath}/${diffManifestBlobHash}.zip`; - - return self.zipDiffPackage(fileName, files, originContentPath, hotCodePushFile) + var fileName = path.join(workDirectoryPath,`${diffManifestBlobHash}.zip`);; + return self.zipDiffPackage(fileName, files, dataCenterContentPath, hotCodePushFile) .then((data) => { return security.qetag(data.path) .then((diffHash) => { - log.debug('diff'); return common.uploadFileToStorage(diffHash, fileName) .then(() => { var stats = fs.statSync(fileName); @@ -246,40 +283,36 @@ proto.generateOneDiffPackage = function (workDirectoryPath, packageId, dataCente }); }; -proto.createDiffPackagesByLastNums = function (packageId, num) { +proto.createDiffPackagesByLastNums = function (appId, originalPackage, num) { var self = this; - return models.Packages.findById(packageId) - .then((originalPackage) => { - if (_.isEmpty(originalPackage)) { - throw AppError.AppError('can\'t find Package'); - } - var Sequelize = require('sequelize'); - return Promise.all([ - models.Packages.findAll({ - where:{ - deployment_version_id: originalPackage.deployment_version_id, - id: {[Sequelize.Op.lt]: packageId}}, - order: [['id','desc']], - limit: num - }), - models.Packages.findAll({ - where:{ - deployment_version_id: originalPackage.deployment_version_id, - id: {[Sequelize.Op.lt]: packageId}}, - order: [['id','asc']], - limit: 2 - }) - ]) - .spread((lastNumsPackages, basePackages) => { - return _.unionBy(lastNumsPackages, basePackages, 'id'); - }) - .then((lastNumsPackages) => { - return self.createDiffPackages(originalPackage, lastNumsPackages); - }); + var Sequelize = require('sequelize'); + var packageId = originalPackage.id; + return Promise.all([ + models.Packages.findAll({ + where:{ + deployment_version_id: originalPackage.deployment_version_id, + id: {[Sequelize.Op.lt]: packageId}}, + order: [['id','desc']], + limit: num + }), + models.Packages.findAll({ + where:{ + deployment_version_id: originalPackage.deployment_version_id, + id: {[Sequelize.Op.lt]: packageId}}, + order: [['id','asc']], + limit: 2 + }), + models.Apps.findById(appId), + ]) + .spread((lastNumsPackages, basePackages, appInfo) => { + return [_.uniqBy(_.unionBy(lastNumsPackages, basePackages, 'id'), 'package_hash'), appInfo]; + }) + .spread((lastNumsPackages, appInfo) => { + return self.createDiffPackages(originalPackage, lastNumsPackages, _.get(appInfo, 'is_use_diff_text', constConfig.IS_USE_DIFF_TEXT_NO)); }); }; -proto.createDiffPackages = function (originalPackage, destPackages) { +proto.createDiffPackages = function (originalPackage, destPackages, isUseDiffText) { if (!_.isArray(destPackages)) { return Promise.reject(new AppError.AppError('第二个参数必须是数组')); } @@ -291,10 +324,26 @@ proto.createDiffPackages = function (originalPackage, destPackages) { var manifest_blob_url = _.get(originalPackage, 'manifest_blob_url'); var blob_url = _.get(originalPackage, 'blob_url'); var workDirectoryPath = path.join(os.tmpdir(), 'codepush_' + security.randToken(32)); + log.debug('workDirectoryPath', workDirectoryPath); return common.createEmptyFolder(workDirectoryPath) .then(() => self.downloadPackageAndExtract(workDirectoryPath, package_hash, blob_url)) - .then((dataCenter) => Promise.map(destPackages, - (v) => self.generateOneDiffPackage(workDirectoryPath, originalPackage.id, dataCenter, v.package_hash, v.manifest_blob_url) + .then((originDataCenter) => Promise.map(destPackages, + (v) => { + var diffWorkDirectoryPath = path.join(workDirectoryPath, _.get(v, 'package_hash')); + common.createEmptyFolderSync(diffWorkDirectoryPath); + return self.downloadPackageAndExtract(diffWorkDirectoryPath, _.get(v, 'package_hash'), _.get(v, 'blob_url')) + .then((oldPackageDataCenter) => + self.generateOneDiffPackage( + diffWorkDirectoryPath, + originalPackage.id, + originDataCenter, + oldPackageDataCenter, + v.package_hash, + v.manifest_blob_url, + isUseDiffText + ) + ) + } )) .finally(() => common.deleteFolderSync(workDirectoryPath)); } @@ -312,7 +361,8 @@ proto.releasePackage = function (appId, deploymentId, packageInfo, filePath, rel var rollout = packageInfo.rollout; //灰度百分比 var isMandatory = packageInfo.isMandatory; //是否强制更新,无法跳过 var tmpDir = os.tmpdir(); - var directoryPath = path.join(tmpDir, 'codepush_' + security.randToken(32)); + var directoryPathParent = path.join(tmpDir, 'codepuh_' + security.randToken(32)); + var directoryPath = path.join(directoryPathParent, 'current'); log.debug(`releasePackage generate an random dir path: ${directoryPath}`); return Promise.all([ security.qetag(filePath), @@ -382,7 +432,7 @@ proto.releasePackage = function (appId, deploymentId, packageInfo, filePath, rel } return self.createPackage(deploymentId, appVersion, packageHash, manifestHash, blobHash, params); }) - .finally(() => common.deleteFolderSync(directoryPath)) + .finally(() => common.deleteFolderSync(directoryPathParent)) }; proto.modifyReleasePackage = function(packageId, params) { diff --git a/core/utils/common.js b/core/utils/common.js index fe8ecf3e..0a4acd9c 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -9,10 +9,25 @@ var validator = require('validator'); var qiniu = require("qiniu"); var common = {}; var AppError = require('../app-error'); +var jschardet = require("jschardet"); var log4js = require('log4js'); +var path = require('path'); var log = log4js.getLogger("cps:utils:common"); module.exports = common; +common.detectIsTextFile = function(filePath) { + var fd = fs.openSync(filePath, 'r'); + var buffer = new Buffer(4096); + fs.readSync(fd, buffer, 0, 4096, 0); + fs.closeSync(fd); + var rs = jschardet.detect(buffer); + log.debug('detectIsTextFile:', filePath, rs); + if (rs.confidence == 1) { + return true; + } + return false; +} + common.parseVersion = function (versionNo) { var version = '0'; var data = null; @@ -98,9 +113,27 @@ common.createFileFromRequest = function (url, filePath) { }); }; +common.copySync = function (sourceDst, targertDst) { + return fsextra.copySync(sourceDst, targertDst, {overwrite: true}); +}; + +common.copy = function (sourceDst, targertDst) { + return new Promise((resolve, reject) => { + fsextra.copy(sourceDst, targertDst, {overwrite: true}, function (err) { + if (err) { + log.error(err); + reject(err); + } else { + log.debug(`copy success sourceDst:${sourceDst} targertDst:${targertDst}`); + resolve(); + } + }); + }); +}; + common.move = function (sourceDst, targertDst) { return new Promise((resolve, reject) => { - fsextra.move(sourceDst, targertDst, {clobber: true, limit: 16}, function (err) { + fsextra.move(sourceDst, targertDst, {overwrite: true}, function (err) { if (err) { log.error(err); reject(err); @@ -217,8 +250,8 @@ common.uploadFileToLocal = function (key, filePath) { throw new AppError.AppError(e.message); } var subDir = key.substr(0, 2).toLowerCase(); - var finalDir = `${storageDir}/${subDir}`; - var fileName = `${finalDir}/${key}`; + var finalDir = path.join(storageDir, subDir); + var fileName = path.join(finalDir, key); if (fs.existsSync(fileName)) { return resolve(key); } diff --git a/docker/code-push-server/Dockerfile b/docker/code-push-server/Dockerfile index 6e68d115..48247992 100644 --- a/docker/code-push-server/Dockerfile +++ b/docker/code-push-server/Dockerfile @@ -1,7 +1,7 @@ FROM node:8.11.4-alpine RUN npm config set registry https://registry.npm.taobao.org/ \ -&& npm i -g code-push-server@0.4.7 pm2@latest --no-optional +&& npm i -g code-push-server@0.5.0 pm2@latest --no-optional COPY ./process.json /process.json diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 4682d9d3..d0cef819 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: server: - image: tablee/code-push-server:v0.4.7 + image: tablee/code-push-server:v0.5.0 volumes: - data-storage:/data/storage - data-tmp:/data/tmp diff --git a/docker/sql/codepush-all.sql b/docker/sql/codepush-all.sql index f0b53688..7bf4047d 100644 --- a/docker/sql/codepush-all.sql +++ b/docker/sql/codepush-all.sql @@ -11,6 +11,7 @@ CREATE TABLE IF NOT EXISTS `apps` ( `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `os` tinyint(3) unsigned NOT NULL DEFAULT '0', `platform` tinyint(3) unsigned NOT NULL DEFAULT '0', + `is_use_diff_text` tinyint(3) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, @@ -174,7 +175,7 @@ CREATE TABLE IF NOT EXISTS `versions` ( LOCK TABLES `versions` WRITE; INSERT INTO `versions` (`id`, `type`, `version`) VALUES - (1,1,'0.4.0'); + (1,1,'0.5.0'); UNLOCK TABLES; CREATE TABLE IF NOT EXISTS `log_report_deploy` ( diff --git a/models/apps.js b/models/apps.js index a34425a7..00e0372f 100644 --- a/models/apps.js +++ b/models/apps.js @@ -12,6 +12,7 @@ module.exports = function(sequelize, DataTypes) { uid: DataTypes.BIGINT(20), os: DataTypes.INTEGER(3), platform: DataTypes.INTEGER(3), + is_use_diff_text: DataTypes.INTEGER(3), created_at: DataTypes.DATE, updated_at: DataTypes.DATE, }, { diff --git a/package-lock.json b/package-lock.json index 85f32bc9..74c1a909 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1052,8 +1052,15 @@ "integrity": "sha1-UfOXDyYTbrCtRDBN5M67UCB7RHk=", "requires": { "destroy": "1.0.4", - "mime": "1.4.1", + "mime": "1.6.0", "pause-stream": "0.0.11" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=" + } } }, "forwarded": { @@ -1945,11 +1952,6 @@ "resolved": "http://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, - "mime": { - "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.4.1.tgz", - "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" - }, "mime-db": { "version": "1.33.0", "resolved": "http://registry.npm.taobao.org/mime-db/download/mime-db-1.33.0.tgz", @@ -2198,221 +2200,2917 @@ "abbrev": "1.1.1" } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "2.0.1" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/on-headers/download/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" - }, - "once": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/optimist/download/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - } - }, - "os-name": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz", - "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", - "requires": { - "osx-release": "1.1.0", - "win-release": "1.1.1" - } - }, - "osx-release": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz", - "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "npm": { + "version": "6.4.1", + "resolved": "http://registry.npm.taobao.org/npm/download/npm-6.4.1.tgz", + "integrity": "sha1-Tzn5M3tVeij67Up3HVyIAta0KIs=", "requires": { - "minimist": "1.2.0" + "JSONStream": "1.3.4", + "abbrev": "1.1.1", + "ansicolors": "0.3.2", + "ansistyles": "0.1.3", + "aproba": "1.2.0", + "archy": "1.0.0", + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "byte-size": "4.0.3", + "cacache": "11.2.0", + "call-limit": "1.1.0", + "chownr": "1.0.1", + "ci-info": "1.4.0", + "cli-columns": "3.1.2", + "cli-table3": "0.5.0", + "cmd-shim": "2.0.2", + "columnify": "1.5.4", + "config-chain": "1.1.11", + "debuglog": "1.0.1", + "detect-indent": "5.0.0", + "detect-newline": "2.1.0", + "dezalgo": "1.0.3", + "editor": "1.0.0", + "figgy-pudding": "3.4.1", + "find-npm-prefix": "1.0.2", + "fs-vacuum": "1.2.10", + "fs-write-stream-atomic": "1.0.10", + "gentle-fs": "2.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "has-unicode": "2.0.1", + "hosted-git-info": "2.7.1", + "iferr": "1.0.2", + "imurmurhash": "0.1.4", + "inflight": "1.0.6", + "inherits": "2.0.3", + "ini": "1.3.5", + "init-package-json": "1.10.3", + "is-cidr": "2.0.6", + "json-parse-better-errors": "1.0.2", + "lazy-property": "1.0.0", + "libcipm": "2.0.2", + "libnpmhook": "4.0.1", + "libnpx": "10.2.0", + "lock-verify": "2.0.2", + "lockfile": "1.0.4", + "lodash._baseindexof": "3.1.0", + "lodash._baseuniq": "4.6.0", + "lodash._bindcallback": "3.0.1", + "lodash._cacheindexof": "3.0.2", + "lodash._createcache": "3.1.2", + "lodash._getnative": "3.9.1", + "lodash.clonedeep": "4.5.0", + "lodash.restparam": "3.6.1", + "lodash.union": "4.6.0", + "lodash.uniq": "4.5.0", + "lodash.without": "4.4.0", + "lru-cache": "4.1.3", + "meant": "1.0.1", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "node-gyp": "3.8.0", + "nopt": "4.0.1", + "normalize-package-data": "2.4.0", + "npm-audit-report": "1.3.1", + "npm-cache-filename": "1.0.2", + "npm-install-checks": "3.0.0", + "npm-lifecycle": "2.1.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.11", + "npm-pick-manifest": "2.1.0", + "npm-profile": "3.0.2", + "npm-registry-client": "8.6.0", + "npm-registry-fetch": "1.1.0", + "npm-user-validate": "1.0.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "opener": "1.5.0", + "osenv": "0.1.5", + "pacote": "8.1.6", + "path-is-inside": "1.0.2", + "promise-inflight": "1.0.1", + "qrcode-terminal": "0.12.0", + "query-string": "6.1.0", + "qw": "1.0.1", + "read": "1.0.7", + "read-cmd-shim": "1.0.1", + "read-installed": "4.0.3", + "read-package-json": "2.0.13", + "read-package-tree": "5.2.1", + "readable-stream": "2.3.6", + "readdir-scoped-modules": "1.0.2", + "request": "2.88.0", + "retry": "0.12.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "sha": "2.0.1", + "slide": "1.1.6", + "sorted-object": "2.0.1", + "sorted-union-stream": "2.1.3", + "ssri": "6.0.0", + "stringify-package": "1.0.0", + "tar": "4.4.6", + "text-table": "0.2.0", + "tiny-relative-date": "1.3.0", + "uid-number": "0.0.6", + "umask": "1.1.0", + "unique-filename": "1.1.0", + "unpipe": "1.0.0", + "update-notifier": "2.5.0", + "uuid": "3.3.2", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "3.0.0", + "which": "1.3.1", + "worker-farm": "1.6.0", + "write-file-atomic": "2.3.0" }, "dependencies": { - "minimist": { + "JSONStream": { + "version": "1.3.4", + "bundled": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "5.0.0" + } + }, + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "1.2.1" + } + }, + "ajv": { + "version": "5.5.2", + "bundled": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "2.1.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true + }, + "aproba": { "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-2.0.0.tgz", - "integrity": "sha1-5iTtVO6MRgp3izyfNnBJb/ileuw=", - "requires": { - "p-try": "2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", - "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", - "requires": { - "p-limit": "2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-2.0.0.tgz", - "integrity": "sha1-hQgLuHxkaI+keZb+j3376CEXYLE=" - }, - "parseurl": { - "version": "1.3.2", - "resolved": "http://registry.npm.taobao.org/parseurl/download/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "http://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "path-parse": { - "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "requires": { - "through": "2.3.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "platform": { - "version": "1.3.5", - "resolved": "http://registry.npm.taobao.org/platform/download/platform-1.3.5.tgz", - "integrity": "sha1-+2lYxpbgfikY0u7aDwvJRI1zNEQ=" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz", - "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" - }, - "promise": { - "version": "7.3.1", - "resolved": "http://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", - "requires": { - "asap": "2.0.6" - } - }, - "proxy-addr": { - "version": "2.0.3", - "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.3.tgz", - "integrity": "sha1-NV8mJQWmIWRrMTCnKOtkfiIFU0E=", - "requires": { - "forwarded": "0.1.2", - "ipaddr.js": "1.6.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bin-links": { + "version": "1.1.2", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "cmd-shim": "2.0.2", + "gentle-fs": "2.0.1", + "graceful-fs": "4.1.11", + "write-file-atomic": "2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "bluebird": { + "version": "3.5.1", + "bundled": true + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "builtins": { + "version": "1.0.3", + "bundled": true + }, + "byline": { + "version": "5.0.0", + "bundled": true + }, + "byte-size": { + "version": "4.0.3", + "bundled": true + }, + "cacache": { + "version": "11.2.0", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "figgy-pudding": "3.4.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "6.0.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + } + }, + "call-limit": { + "version": "1.1.0", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "ci-info": { + "version": "1.4.0", + "bundled": true + }, + "cidr-regex": { + "version": "2.0.9", + "bundled": true, + "requires": { + "ip-regex": "2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "bundled": true, + "requires": { + "colors": "1.1.2", + "object-assign": "4.1.1", + "string-width": "2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "bundled": true + }, + "cmd-shim": { + "version": "2.0.2", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1" + } + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.1.2", + "bundled": true, + "optional": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "requires": { + "strip-ansi": "3.0.1", + "wcwidth": "1.0.1" + } + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ini": "1.3.5", + "proto-list": "1.2.4" + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "copy-concurrently": { + "version": "1.0.5", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "cyclist": { + "version": "0.2.2", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "1.0.4" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true, + "requires": { + "asap": "2.0.6", + "wrappy": "1.0.2" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "dotenv": { + "version": "5.0.1", + "bundled": true + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "duplexify": { + "version": "3.6.0", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" + } + }, + "editor": { + "version": "1.0.0", + "bundled": true + }, + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "0.4.23" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "errno": { + "version": "0.1.7", + "bundled": true, + "requires": { + "prr": "1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "4.2.4" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "figgy-pudding": { + "version": "3.4.1", + "bundled": true + }, + "find-npm-prefix": { + "version": "1.0.2", + "bundled": true + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.2", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.19" + } + }, + "from2": { + "version": "2.3.0", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, + "fs-vacuum": { + "version": "1.2.10", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "path-is-inside": "1.0.2", + "rimraf": "2.6.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "bundled": true + }, + "gentle-fs": { + "version": "2.0.1", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "fs-vacuum": "1.2.10", + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "path-is-inside": "1.0.2", + "read-cmd-shim": "1.0.1", + "slide": "1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "1.3.5" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.1.0", + "bundled": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "2.1.1" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "iferr": { + "version": "1.0.2", + "bundled": true + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "init-package-json": { + "version": "1.10.3", + "bundled": true, + "requires": { + "glob": "7.1.2", + "npm-package-arg": "6.1.0", + "promzard": "0.3.0", + "read": "1.0.7", + "read-package-json": "2.0.13", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "ip": { + "version": "1.1.5", + "bundled": true + }, + "ip-regex": { + "version": "2.1.0", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "1.4.0" + } + }, + "is-cidr": { + "version": "2.0.6", + "bundled": true, + "requires": { + "cidr-regex": "2.0.9" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lazy-property": { + "version": "1.0.0", + "bundled": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "libcipm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "find-npm-prefix": "1.0.2", + "graceful-fs": "4.1.11", + "lock-verify": "2.0.2", + "mkdirp": "0.5.1", + "npm-lifecycle": "2.1.0", + "npm-logical-tree": "1.2.1", + "npm-package-arg": "6.1.0", + "pacote": "8.1.6", + "protoduck": "5.0.0", + "read-package-json": "2.0.13", + "rimraf": "2.6.2", + "worker-farm": "1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "bundled": true, + "requires": { + "figgy-pudding": "3.4.1", + "npm-registry-fetch": "3.1.1" + }, + "dependencies": { + "npm-registry-fetch": { + "version": "3.1.1", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "figgy-pudding": "3.4.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "npm-package-arg": "6.1.0" + } + } + } + }, + "libnpx": { + "version": "10.2.0", + "bundled": true, + "requires": { + "dotenv": "5.0.1", + "npm-package-arg": "6.1.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "update-notifier": "2.5.0", + "which": "1.3.1", + "y18n": "4.0.0", + "yargs": "11.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lock-verify": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-package-arg": "6.1.0", + "semver": "5.5.0" + } + }, + "lockfile": { + "version": "1.0.4", + "bundled": true, + "requires": { + "signal-exit": "3.0.2" + } + }, + "lodash._baseindexof": { + "version": "3.1.0", + "bundled": true + }, + "lodash._baseuniq": { + "version": "4.6.0", + "bundled": true, + "requires": { + "lodash._createset": "4.0.3", + "lodash._root": "3.0.1" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "bundled": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "bundled": true + }, + "lodash._createcache": { + "version": "3.1.2", + "bundled": true, + "requires": { + "lodash._getnative": "3.9.1" + } + }, + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lodash.uniq": { + "version": "4.5.0", + "bundled": true + }, + "lodash.without": { + "version": "4.4.0", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agentkeepalive": "3.4.1", + "cacache": "11.2.0", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "4.0.1", + "ssri": "6.0.0" + } + }, + "meant": { + "version": "1.0.1", + "bundled": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "mime-db": { + "version": "1.35.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.19", + "bundled": true, + "requires": { + "mime-db": "1.35.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, + "mississippi": { + "version": "3.0.0", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "3.0.0", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "0.1.12", + "json-parse-better-errors": "1.0.2", + "safe-buffer": "5.1.2" + } + }, + "node-gyp": { + "version": "3.8.0", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.88.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.4" + } + }, + "npm-audit-report": { + "version": "1.3.1", + "bundled": true, + "requires": { + "cli-table3": "0.5.0", + "console-control-strings": "1.1.0" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true + }, + "npm-cache-filename": { + "version": "1.0.2", + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true, + "requires": { + "semver": "5.5.0" + } + }, + "npm-lifecycle": { + "version": "2.1.0", + "bundled": true, + "requires": { + "byline": "5.0.0", + "graceful-fs": "4.1.11", + "node-gyp": "3.8.0", + "resolve-from": "4.0.0", + "slide": "1.1.6", + "uid-number": "0.0.6", + "umask": "1.1.0", + "which": "1.3.1" + } + }, + "npm-logical-tree": { + "version": "1.2.1", + "bundled": true + }, + "npm-package-arg": { + "version": "6.1.0", + "bundled": true, + "requires": { + "hosted-git-info": "2.7.1", + "osenv": "0.1.5", + "semver": "5.5.0", + "validate-npm-package-name": "3.0.0" + } + }, + "npm-packlist": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.5" + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "bundled": true, + "requires": { + "npm-package-arg": "6.1.0", + "semver": "5.5.0" + } + }, + "npm-profile": { + "version": "3.0.2", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "make-fetch-happen": "4.0.1" + } + }, + "npm-registry-client": { + "version": "8.6.0", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "graceful-fs": "4.1.11", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "request": "2.88.0", + "retry": "0.10.1", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "slide": "1.1.6", + "ssri": "5.3.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "figgy-pudding": "2.0.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "3.0.0", + "npm-package-arg": "6.1.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + } + } + }, + "figgy-pudding": { + "version": "2.0.1", + "bundled": true + }, + "make-fetch-happen": { + "version": "3.0.0", + "bundled": true, + "requires": { + "agentkeepalive": "3.4.1", + "cacache": "10.0.4", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "3.0.1", + "ssri": "5.3.0" + } + }, + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "2.0.1" + } + }, + "npm-user-validate": { + "version": "1.0.0", + "bundled": true + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "opener": { + "version": "1.5.0", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" + } + }, + "pacote": { + "version": "8.1.6", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "cacache": "11.2.0", + "get-stream": "3.0.0", + "glob": "7.1.2", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "minimatch": "3.0.4", + "minipass": "2.3.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.11", + "npm-pick-manifest": "2.1.0", + "osenv": "0.1.5", + "promise-inflight": "1.0.1", + "promise-retry": "1.1.1", + "protoduck": "5.0.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "ssri": "6.0.0", + "tar": "4.4.6", + "unique-filename": "1.1.0", + "which": "1.3.1" + } + }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true + }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "1.1.2", + "retry": "0.10.1" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "requires": { + "read": "1.0.7" + } + }, + "proto-list": { + "version": "1.2.4", + "bundled": true + }, + "protoduck": { + "version": "5.0.0", + "bundled": true, + "requires": { + "genfun": "4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.29", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "bundled": true, + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "query-string": { + "version": "6.1.0", + "bundled": true, + "requires": { + "decode-uri-component": "0.2.0", + "strict-uri-encode": "2.0.0" + } + }, + "qw": { + "version": "1.0.1", + "bundled": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "read": { + "version": "1.0.7", + "bundled": true, + "requires": { + "mute-stream": "0.0.7" + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "read-installed": { + "version": "4.0.3", + "bundled": true, + "requires": { + "debuglog": "1.0.1", + "graceful-fs": "4.1.11", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2", + "semver": "5.5.0", + "slide": "1.1.6", + "util-extend": "1.0.3" + } + }, + "read-package-json": { + "version": "2.0.13", + "bundled": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "json-parse-better-errors": "1.0.2", + "normalize-package-data": "2.4.0", + "slash": "1.0.0" + } + }, + "read-package-tree": { + "version": "5.2.1", + "bundled": true, + "requires": { + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "once": "1.4.0", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "bundled": true, + "requires": { + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "graceful-fs": "4.1.11", + "once": "1.4.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "bundled": true, + "requires": { + "rc": "1.2.7", + "safe-buffer": "5.1.2" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "1.2.7" + } + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.19", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, + "retry": { + "version": "0.12.0", + "bundled": true + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-queue": { + "version": "1.0.3", + "bundled": true, + "requires": { + "aproba": "1.2.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "5.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "sha": { + "version": "2.0.1", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "readable-stream": "2.3.6" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "smart-buffer": { + "version": "4.0.1", + "bundled": true + }, + "socks": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "2.2.0" + } + }, + "sorted-object": { + "version": "2.0.1", + "bundled": true + }, + "sorted-union-stream": { + "version": "2.1.3", + "bundled": true, + "requires": { + "from2": "1.3.0", + "stream-iterate": "1.2.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sshpk": { + "version": "1.14.2", + "bundled": true, + "requires": { + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "ssri": { + "version": "6.0.0", + "bundled": true + }, + "stream-each": { + "version": "1.2.2", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" + } + }, + "stream-iterate": { + "version": "1.2.0", + "bundled": true, + "requires": { + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "stringify-package": { + "version": "1.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "tar": { + "version": "4.4.6", + "bundled": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "1.1.29", + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "umask": { + "version": "1.1.0", + "bundled": true + }, + "unique-filename": { + "version": "1.1.0", + "bundled": true, + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "bundled": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.5.0", + "bundled": true, + "requires": { + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "util-extend": { + "version": "1.0.3", + "bundled": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "requires": { + "builtins": "1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "1.0.3" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "bundled": true, + "requires": { + "errno": "0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "11.0.0", + "bundled": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "bundled": true + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/on-headers/download/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/optimist/download/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-name": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "requires": { + "osx-release": "1.1.0", + "win-release": "1.1.1" + } + }, + "osx-release": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "http://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-2.0.0.tgz", + "integrity": "sha1-5iTtVO6MRgp3izyfNnBJb/ileuw=", + "requires": { + "p-try": "2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "requires": { + "p-limit": "2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-2.0.0.tgz", + "integrity": "sha1-hQgLuHxkaI+keZb+j3376CEXYLE=" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "http://registry.npm.taobao.org/parseurl/download/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "http://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "http://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "2.3.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "http://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "platform": { + "version": "1.3.5", + "resolved": "http://registry.npm.taobao.org/platform/download/platform-1.3.5.tgz", + "integrity": "sha1-+2lYxpbgfikY0u7aDwvJRI1zNEQ=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz", + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + }, + "promise": { + "version": "7.3.1", + "resolved": "http://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "requires": { + "asap": "2.0.6" + } + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.3.tgz", + "integrity": "sha1-NV8mJQWmIWRrMTCnKOtkfiIFU0E=", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "pug": { @@ -2814,6 +5512,11 @@ "requires": { "ms": "2.0.0" } + }, + "mime": { + "version": "1.4.1", + "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.4.1.tgz", + "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" } } }, @@ -3094,7 +5797,7 @@ "form-data": "2.3.2", "formidable": "1.2.1", "methods": "1.1.2", - "mime": "1.4.1", + "mime": "1.6.0", "qs": "6.5.1", "readable-stream": "2.3.5" }, @@ -3107,6 +5810,12 @@ "requires": { "ms": "2.0.0" } + }, + "mime": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz", + "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", + "dev": true } } }, diff --git a/package.json b/package.json index 0473fe58..a4ec5a09 100644 --- a/package.json +++ b/package.json @@ -47,12 +47,14 @@ "cookie-parser": "^1.4.3", "cos-nodejs-sdk-v5": "^2.4.10", "debug": "^3.1.0", + "diff-match-patch": "^1.0.1", "express": "^4.14.0", "extract-zip": "^1.6.0", "formidable": "^1.2.1", "fs-extra": "^7.0.0", "helmet": "^3.1.0", "i18n": "^0.8.3", + "jschardet": "^1.6.0", "jsonwebtoken": "^8.2.0", "lodash": "^4.17.5", "log4js": "^3.0.5", diff --git a/routes/apps.js b/routes/apps.js index 30445c54..057a67a3 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -290,7 +290,7 @@ router.post('/:appName/deployments/:deploymentName/release', if (packages) { Promise.delay(2000) .then(() => { - packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) + packageManager.createDiffPackagesByLastNums(deploymentInfo.appid, packages, _.get(config, 'common.diffNums', 1)) .catch((e) => { log.error(e); }); @@ -417,20 +417,20 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment .spread((sourceDeploymentInfo, destDeploymentInfo) => { var params = _.get(req.body, 'packageInfo', {}); _.set(params, 'promoteUid', uid); - return packageManager.promotePackage(sourceDeploymentInfo, destDeploymentInfo, params); - }); - }) - .then((packages) => { - if (packages) { - Promise.delay(2000) - .then(() => { - packageManager.createDiffPackagesByLastNums(packages.id, _.get(config, 'common.diffNums', 1)) - .catch((e) => { - log.error(e); + return [packageManager.promotePackage(sourceDeploymentInfo, destDeploymentInfo, params),destDeploymentInfo]; + }) + .spread((packages, destDeploymentInfo) => { + if (packages) { + Promise.delay(2000) + .then(() => { + packageManager.createDiffPackagesByLastNums(destDeploymentInfo.appid, packages, _.get(config, 'common.diffNums', 1)) + .catch((e) => { + log.error(e); + }); }); - }); - } - return packages; + } + return packages; + }) }) .then((packages) => { res.send({package:packages}); diff --git a/sql/codepush-all.sql b/sql/codepush-all.sql index 4b0fd681..7e2d8776 100644 --- a/sql/codepush-all.sql +++ b/sql/codepush-all.sql @@ -4,6 +4,7 @@ CREATE TABLE IF NOT EXISTS `apps` ( `uid` bigint(20) unsigned NOT NULL DEFAULT '0', `os` tinyint(3) unsigned NOT NULL DEFAULT '0', `platform` tinyint(3) unsigned NOT NULL DEFAULT '0', + `is_use_diff_text` tinyint(3) unsigned NOT NULL DEFAULT '0', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created_at` timestamp NULL DEFAULT NULL, `deleted_at` timestamp NULL DEFAULT NULL, @@ -164,7 +165,7 @@ CREATE TABLE IF NOT EXISTS `versions` ( LOCK TABLES `versions` WRITE; INSERT INTO `versions` (`id`, `type`, `version`) VALUES - (1,1,'0.4.0'); + (1,1,'0.5.0'); UNLOCK TABLES; CREATE TABLE IF NOT EXISTS `log_report_deploy` ( diff --git a/sql/codepush-v0.5.0-patch.sql b/sql/codepush-v0.5.0-patch.sql new file mode 100644 index 00000000..09b822d3 --- /dev/null +++ b/sql/codepush-v0.5.0-patch.sql @@ -0,0 +1,3 @@ +ALTER TABLE `apps` ADD `is_use_diff_text` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0'; + +UPDATE `versions` SET `version` = '0.5.0' WHERE `type` = '1'; \ No newline at end of file From c9b56534fc3939b7b0e10e40a0d674d043ac5625 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 8 Sep 2018 20:56:32 +0800 Subject: [PATCH 156/194] 0.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4ec5a09..5f28e9a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.4.7", + "version": "0.5.0", "license": "MIT", "repository": { "type": "git", From 324d29b7deae3be9457525f5e82c4c300da742f9 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 8 Sep 2018 22:30:34 +0800 Subject: [PATCH 157/194] fix rollback --- routes/apps.js | 54 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/routes/apps.js b/routes/apps.js index 057a67a3..8edc39a9 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -288,7 +288,7 @@ router.post('/:appName/deployments/:deploymentName/release', }) .then((packages) => { if (packages) { - Promise.delay(2000) + Promise.delay(1000) .then(() => { packageManager.createDiffPackagesByLastNums(deploymentInfo.appid, packages, _.get(config, 'common.diffNums', 1)) .catch((e) => { @@ -403,15 +403,6 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment if (!destDeploymentInfo) { throw new AppError.AppError(`${destDeploymentName} does not exist.`); } - //clear cache if exists. - if (_.get(config, 'common.updateCheckCache', false) !== false) { - Promise.delay(2500) - .then(() => { - var ClientManager = require('../core/services/client-manager'); - var clientManager = new ClientManager(); - clientManager.clearUpdateCheckCache(destDeploymentInfo.deployment_key, '*', '*', '*'); - }); - } return [sourceDeploymentInfo, destDeploymentInfo]; }) .spread((sourceDeploymentInfo, destDeploymentInfo) => { @@ -421,7 +412,7 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment }) .spread((packages, destDeploymentInfo) => { if (packages) { - Promise.delay(2000) + Promise.delay(1000) .then(() => { packageManager.createDiffPackagesByLastNums(destDeploymentInfo.appid, packages, _.get(config, 'common.diffNums', 1)) .catch((e) => { @@ -429,6 +420,15 @@ router.post('/:appName/deployments/:sourceDeploymentName/promote/:destDeployment }); }); } + //clear cache if exists. + if (_.get(config, 'common.updateCheckCache', false) !== false) { + Promise.delay(2500) + .then(() => { + var ClientManager = require('../core/services/client-manager'); + var clientManager = new ClientManager(); + clientManager.clearUpdateCheckCache(destDeploymentInfo.deployment_key, '*', '*', '*'); + }); + } return packages; }) }) @@ -456,16 +456,28 @@ var rollbackCb = function (req, res, next) { return deployments.findDeloymentByName(deploymentName, col.appid); }) .then((dep) => { - //clear cache if exists. - if (_.get(config, 'common.updateCheckCache', false) !== false) { - Promise.delay(2500) - .then(() => { - var ClientManager = require('../core/services/client-manager'); - var clientManager = new ClientManager(); - clientManager.clearUpdateCheckCache(dep.deployment_key, '*', '*', '*'); - }); - } - return packageManager.rollbackPackage(dep.last_deployment_version_id, targetLabel, uid); + return packageManager.rollbackPackage(dep.last_deployment_version_id, targetLabel, uid) + .then((packageInfo)=>{ + if (packageInfo) { + Promise.delay(1000) + .then(() => { + packageManager.createDiffPackagesByLastNums(dep.appid, packageInfo, 1) + .catch((e) => { + log.error(e); + }); + }); + } + //clear cache if exists. + if (_.get(config, 'common.updateCheckCache', false) !== false) { + Promise.delay(2500) + .then(() => { + var ClientManager = require('../core/services/client-manager'); + var clientManager = new ClientManager(); + clientManager.clearUpdateCheckCache(dep.deployment_key, '*', '*', '*'); + }); + } + return packageInfo; + }); }) .then(() => { res.send('ok'); From 6b58d009fd3a03dfeb4b449eceddc10c47222be5 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 8 Sep 2018 23:45:00 +0800 Subject: [PATCH 158/194] fix --- package-lock.json | 4036 +++++++++------------------------------------ 1 file changed, 748 insertions(+), 3288 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74c1a909..de921ab4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.4.7", + "version": "0.5.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -14,7 +14,7 @@ "resolved": "http://registry.npm.taobao.org/@types/babylon/download/@types/babylon-6.16.2.tgz", "integrity": "sha1-BizmO2k9mvHCRvWu35KLycMFicg=", "requires": { - "@types/babel-types": "7.0.1" + "@types/babel-types": "*" } }, "@types/geojson": { @@ -37,7 +37,7 @@ "resolved": "http://registry.npm.taobao.org/accepts/download/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, @@ -51,7 +51,7 @@ "resolved": "http://registry.npm.taobao.org/acorn-globals/download/acorn-globals-3.1.0.tgz", "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", "requires": { - "acorn": "4.0.13" + "acorn": "^4.0.4" }, "dependencies": { "acorn": { @@ -71,7 +71,7 @@ "resolved": "http://registry.npm.taobao.org/agentkeepalive/download/agentkeepalive-3.3.0.tgz", "integrity": "sha1-bV3lgpr9O+JxIgGjknX9EcZRhXw=", "requires": { - "humanize-ms": "1.2.1" + "humanize-ms": "^1.2.1" } }, "ajv": { @@ -79,10 +79,10 @@ "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "align-text": { @@ -90,9 +90,9 @@ "resolved": "http://registry.npm.taobao.org/align-text/download/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" } }, "aliyun-oss-upload-stream": { @@ -100,13 +100,25 @@ "resolved": "http://registry.npm.taobao.org/aliyun-oss-upload-stream/download/aliyun-oss-upload-stream-1.3.0.tgz", "integrity": "sha1-ODAbGfA0QGhDjrY5d6DNldYEcMA=" }, + "aliyun-sdk": { + "version": "1.11.10", + "resolved": "http://registry.npm.taobao.org/aliyun-sdk/download/aliyun-sdk-1.11.10.tgz", + "integrity": "sha1-ZDvH+GDrv08F7mmfoGp05eQR8lA=", + "requires": { + "node_memcached": "1.1.3", + "pomelo-protobuf": "^0.4.0", + "protobufjs": "^4.1.2", + "xml2js": "0.4.4", + "xmlbuilder": "^2.4.5" + } + }, "ambi": { "version": "2.5.0", "resolved": "http://registry.npm.taobao.org/ambi/download/ambi-2.5.0.tgz", "integrity": "sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA=", "requires": { - "editions": "1.3.4", - "typechecker": "4.5.0" + "editions": "^1.1.1", + "typechecker": "^4.3.0" }, "dependencies": { "typechecker": { @@ -114,7 +126,7 @@ "resolved": "http://registry.npm.taobao.org/typechecker/download/typechecker-4.5.0.tgz", "integrity": "sha1-w4KSAJeBI2S7r0WVsKtliCRBF6Y=", "requires": { - "editions": "1.3.4" + "editions": "^1.3.4" } } } @@ -144,7 +156,7 @@ "resolved": "http://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz", "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" }, "dependencies": { "sprintf-js": { @@ -164,6 +176,15 @@ "resolved": "http://registry.npm.taobao.org/asap/download/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, + "ascli": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/ascli/download/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, "asn1": { "version": "0.2.3", "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.3.tgz", @@ -190,7 +211,7 @@ "integrity": "sha1-kCt1Jedv+fpyzQOLc7ikfIxnGmI=", "requires": { "buffer": "4.9.1", - "events": "1.1.1", + "events": "^1.1.1", "jmespath": "0.15.0", "querystring": "0.2.0", "sax": "1.2.1", @@ -210,8 +231,8 @@ "resolved": "http://registry.npm.taobao.org/xml2js/download/xml2js-0.4.17.tgz", "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", "requires": { - "sax": "1.2.1", - "xmlbuilder": "4.2.1" + "sax": ">=0.6.0", + "xmlbuilder": "^4.1.0" } }, "xmlbuilder": { @@ -219,7 +240,7 @@ "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-4.2.1.tgz", "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", "requires": { - "lodash": "4.17.5" + "lodash": "^4.0.0" } } } @@ -239,8 +260,8 @@ "resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "requires": { - "core-js": "2.5.3", - "regenerator-runtime": "0.11.1" + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, "babel-types": { @@ -248,10 +269,10 @@ "resolved": "http://registry.npm.taobao.org/babel-types/download/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.5", - "to-fast-properties": "1.0.3" + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" } }, "babylon": { @@ -288,7 +309,7 @@ "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "bcryptjs": { @@ -307,15 +328,15 @@ "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.16" + "type-is": "~1.6.15" }, "dependencies": { "debug": { @@ -333,7 +354,7 @@ "resolved": "http://registry.npm.taobao.org/boom/download/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } }, "brace-expansion": { @@ -341,7 +362,7 @@ "resolved": "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -356,9 +377,9 @@ "resolved": "http://registry.npm.taobao.org/buffer/download/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "requires": { - "base64-js": "1.2.3", - "ieee754": "1.1.10", - "isarray": "1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "buffer-crc32": { @@ -371,11 +392,30 @@ "resolved": "http://registry.npm.taobao.org/buffer-equal-constant-time/download/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "bufferview": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/bufferview/download/bufferview-1.0.1.tgz", + "integrity": "sha1-ev10pF+Tf6QiodM4wIu/3HbNcl0=" + }, + "bytebuffer": { + "version": "4.1.0", + "resolved": "http://registry.npm.taobao.org/bytebuffer/download/bytebuffer-4.1.0.tgz", + "integrity": "sha1-TFgmngUqseSx9/82T9+zzogpBqo=", + "requires": { + "bufferview": "~1", + "long": "~2 >=2.3.0" + } + }, "bytes": { "version": "3.0.0", "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "camelcase": { + "version": "2.1.1", + "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, "camelize": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/camelize/download/camelize-1.0.0.tgz", @@ -386,8 +426,8 @@ "resolved": "http://registry.npm.taobao.org/cardinal/download/cardinal-1.0.0.tgz", "integrity": "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=", "requires": { - "ansicolors": "0.2.1", - "redeyed": "1.0.1" + "ansicolors": "~0.2.1", + "redeyed": "~1.0.0" } }, "caseless": { @@ -400,8 +440,8 @@ "resolved": "http://registry.npm.taobao.org/center-align/download/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "character-parser": { @@ -409,7 +449,7 @@ "resolved": "http://registry.npm.taobao.org/character-parser/download/character-parser-2.2.0.tgz", "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", "requires": { - "is-regex": "1.0.4" + "is-regex": "^1.0.3" } }, "circular-json": { @@ -422,8 +462,8 @@ "resolved": "http://registry.npm.taobao.org/clean-css/download/clean-css-3.4.28.tgz", "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", "requires": { - "commander": "2.8.1", - "source-map": "0.4.4" + "commander": "2.8.x", + "source-map": "0.4.x" }, "dependencies": { "commander": { @@ -431,7 +471,7 @@ "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.8.1.tgz", "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", "requires": { - "graceful-readlink": "1.0.1" + "graceful-readlink": ">= 1.0.0" } }, "source-map": { @@ -439,18 +479,28 @@ "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } }, + "cliui": { + "version": "3.2.0", + "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, "cls-bluebird": { "version": "2.1.0", "resolved": "http://registry.npm.taobao.org/cls-bluebird/download/cls-bluebird-2.1.0.tgz", "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", "requires": { - "is-bluebird": "1.0.2", - "shimmer": "1.2.0" + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" } }, "co": { @@ -468,12 +518,17 @@ "resolved": "http://registry.npm.taobao.org/coffee-script/download/coffee-script-1.12.7.tgz", "integrity": "sha1-wF2uDLeVkdBbMHCoQzqYyaiczFM=" }, + "colour": { + "version": "0.7.1", + "resolved": "http://registry.npm.taobao.org/colour/download/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, "combined-stream": { "version": "1.0.6", "resolved": "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "component-emitter": { @@ -492,9 +547,9 @@ "resolved": "http://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.0.tgz", "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "configstore": { @@ -502,12 +557,12 @@ "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.3.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" } }, "constantinople": { @@ -515,10 +570,10 @@ "resolved": "http://registry.npm.taobao.org/constantinople/download/constantinople-3.1.2.tgz", "integrity": "sha1-1F7XJPV9PRBQABen06iJwTga5kc=", "requires": { - "@types/babel-types": "7.0.1", - "@types/babylon": "6.16.2", - "babel-types": "6.26.0", - "babylon": "6.18.0" + "@types/babel-types": "^7.0.0", + "@types/babylon": "^6.16.2", + "babel-types": "^6.26.0", + "babylon": "^6.18.0" } }, "content-disposition": { @@ -576,10 +631,10 @@ "resolved": "https://registry.npmjs.org/cos-nodejs-sdk-v5/-/cos-nodejs-sdk-v5-2.4.10.tgz", "integrity": "sha512-espPlCyyOc4vBKKI6Mwb5ZKzjYDgd0GOK4H0msiryupc3wlQCfPqJM+PubVlUEssqK58wIiV9Bq4Bo/ts2irjg==", "requires": { - "configstore": "3.1.2", - "qcloudapi-sdk": "0.2.0", - "request": "2.85.0", - "xml2js": "0.4.19" + "configstore": "^3.1.2", + "qcloudapi-sdk": "^0.2.0", + "request": "^2.81.0", + "xml2js": "^0.4.19" }, "dependencies": { "xml2js": { @@ -587,8 +642,8 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "requires": { - "sax": "0.6.1", - "xmlbuilder": "9.0.7" + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" } }, "xmlbuilder": { @@ -608,9 +663,9 @@ "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "requires": { - "lru-cache": "4.1.3", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "cryptiles": { @@ -618,7 +673,7 @@ "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-3.1.2.tgz", "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "requires": { - "boom": "5.2.0" + "boom": "5.x.x" }, "dependencies": { "boom": { @@ -626,7 +681,7 @@ "resolved": "http://registry.npm.taobao.org/boom/download/boom-5.2.0.tgz", "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } } } @@ -641,7 +696,7 @@ "resolved": "http://registry.npm.taobao.org/csextends/download/csextends-1.1.1.tgz", "integrity": "sha1-zFPBNJ+vfwrmzfb2xKTZFW08TsE=", "requires": { - "coffee-script": "1.12.7" + "coffee-script": "^1.12.5" } }, "dashdash": { @@ -649,7 +704,7 @@ "resolved": "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "dasherize": { @@ -686,7 +741,7 @@ "resolved": "http://registry.npm.taobao.org/default-user-agent/download/default-user-agent-1.0.0.tgz", "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", "requires": { - "os-name": "1.0.3" + "os-name": "~1.0.3" } }, "delayed-stream": { @@ -748,7 +803,7 @@ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "requires": { - "is-obj": "1.0.1" + "is-obj": "^1.0.0" } }, "dot-qs": { @@ -771,7 +826,7 @@ "resolved": "http://registry.npm.taobao.org/eachr/download/eachr-2.0.4.tgz", "integrity": "sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8=", "requires": { - "typechecker": "2.1.0" + "typechecker": "^2.0.8" } }, "ecc-jsbn": { @@ -780,7 +835,7 @@ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "ecdsa-sig-formatter": { @@ -788,8 +843,8 @@ "resolved": "http://registry.npm.taobao.org/ecdsa-sig-formatter/download/ecdsa-sig-formatter-1.0.9.tgz", "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", "requires": { - "base64url": "2.0.0", - "safe-buffer": "5.1.1" + "base64url": "^2.0.0", + "safe-buffer": "^5.0.1" } }, "editions": { @@ -843,13 +898,13 @@ "resolved": "http://registry.npm.taobao.org/execa/download/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, "expect-ct": { @@ -862,36 +917,36 @@ "resolved": "http://registry.npm.taobao.org/express/download/express-4.16.3.tgz", "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "requires": { - "accepts": "1.3.5", + "accepts": "~1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.4", + "content-type": "~1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.2", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.2", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.3", + "proxy-addr": "~2.0.3", "qs": "6.5.1", - "range-parser": "1.2.0", + "range-parser": "~1.2.0", "safe-buffer": "5.1.1", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.4.0", - "type-is": "1.6.16", + "statuses": "~1.4.0", + "type-is": "~1.6.16", "utils-merge": "1.0.1", - "vary": "1.1.2" + "vary": "~1.1.2" }, "dependencies": { "debug": { @@ -919,7 +974,7 @@ "resolved": "http://registry.npm.taobao.org/extendr/download/extendr-2.1.0.tgz", "integrity": "sha1-MBqgu+pWX00tyPVw8qImEahSe1Y=", "requires": { - "typechecker": "2.0.8" + "typechecker": "~2.0.1" }, "dependencies": { "typechecker": { @@ -934,7 +989,7 @@ "resolved": "http://registry.npm.taobao.org/extract-opts/download/extract-opts-2.2.0.tgz", "integrity": "sha1-H6KOunNSxttID4hc63GkaBC+bX0=", "requires": { - "typechecker": "2.0.8" + "typechecker": "~2.0.1" }, "dependencies": { "typechecker": { @@ -991,7 +1046,7 @@ "resolved": "http://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.0.1.tgz", "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "requires": { - "pend": "1.2.0" + "pend": "~1.2.0" } }, "finalhandler": { @@ -1000,12 +1055,12 @@ "integrity": "sha1-7r9O2EAHnIP0JJA4ydcDAIMBsQU=", "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -1023,7 +1078,7 @@ "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz", "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", "requires": { - "locate-path": "3.0.0" + "locate-path": "^3.0.0" } }, "forever-agent": { @@ -1036,9 +1091,9 @@ "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" } }, "formidable": { @@ -1051,9 +1106,9 @@ "resolved": "http://registry.npm.taobao.org/formstream/download/formstream-1.1.0.tgz", "integrity": "sha1-UfOXDyYTbrCtRDBN5M67UCB7RHk=", "requires": { - "destroy": "1.0.4", - "mime": "1.6.0", - "pause-stream": "0.0.11" + "destroy": "^1.0.4", + "mime": "^1.3.4", + "pause-stream": "~0.0.11" }, "dependencies": { "mime": { @@ -1083,9 +1138,9 @@ "resolved": "http://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.0.tgz", "integrity": "sha1-jMP0fOB+97NZOhG5+yRffjTAQdY=", "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.2" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "fs.realpath": { @@ -1124,20 +1179,19 @@ "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "glob": { "version": "5.0.15", "resolved": "http://registry.npm.taobao.org/glob/download/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "graceful-fs": { @@ -1162,10 +1216,10 @@ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" }, "dependencies": { "source-map": { @@ -1174,7 +1228,7 @@ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } } } @@ -1189,8 +1243,8 @@ "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" } }, "has": { @@ -1198,7 +1252,7 @@ "resolved": "http://registry.npm.taobao.org/has/download/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.0.2" } }, "has-flag": { @@ -1212,10 +1266,10 @@ "resolved": "http://registry.npm.taobao.org/hawk/download/hawk-6.0.2.tgz", "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" + "boom": "4.x.x", + "cryptiles": "3.x.x", + "hoek": "4.x.x", + "sntp": "2.x.x" } }, "he": { @@ -1283,7 +1337,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "statuses": ">= 1.3.1 < 2" }, "dependencies": { "depd": { @@ -1298,9 +1352,9 @@ "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "humanize-ms": { @@ -1308,7 +1362,7 @@ "resolved": "http://registry.npm.taobao.org/humanize-ms/download/humanize-ms-1.2.1.tgz", "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", "requires": { - "ms": "2.0.0" + "ms": "^2.0.0" } }, "i18n": { @@ -1316,12 +1370,12 @@ "resolved": "http://registry.npm.taobao.org/i18n/download/i18n-0.8.3.tgz", "integrity": "sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4=", "requires": { - "debug": "3.1.0", - "make-plural": "3.0.6", - "math-interval-parser": "1.1.0", - "messageformat": "0.3.1", - "mustache": "2.3.0", - "sprintf-js": "1.1.1" + "debug": "*", + "make-plural": "^3.0.3", + "math-interval-parser": "^1.1.0", + "messageformat": "^0.3.1", + "mustache": "*", + "sprintf-js": ">=1.0.3" } }, "iconv-lite": { @@ -1344,8 +1398,8 @@ "resolved": "http://registry.npm.taobao.org/ignorefs/download/ignorefs-1.2.0.tgz", "integrity": "sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y=", "requires": { - "editions": "1.3.4", - "ignorepatterns": "1.1.0" + "editions": "^1.3.3", + "ignorepatterns": "^1.1.0" } }, "ignorepatterns": { @@ -1363,8 +1417,8 @@ "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -1397,8 +1451,8 @@ "resolved": "http://registry.npm.taobao.org/is-expression/download/is-expression-3.0.0.tgz", "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", "requires": { - "acorn": "4.0.13", - "object-assign": "4.1.1" + "acorn": "~4.0.2", + "object-assign": "^4.0.1" }, "dependencies": { "acorn": { @@ -1413,7 +1467,7 @@ "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "is-obj": { @@ -1431,7 +1485,7 @@ "resolved": "http://registry.npm.taobao.org/is-regex/download/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "requires": { - "has": "1.0.1" + "has": "^1.0.1" } }, "is-stream": { @@ -1465,20 +1519,20 @@ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "escodegen": "1.8.1", - "esprima": "2.7.3", - "glob": "5.0.15", - "handlebars": "4.0.11", - "js-yaml": "3.11.0", - "mkdirp": "0.5.0", - "nopt": "3.0.6", - "once": "1.4.0", - "resolve": "1.1.7", - "supports-color": "3.2.3", - "which": "1.3.0", - "wordwrap": "1.0.0" + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" }, "dependencies": { "abbrev": { @@ -1493,11 +1547,11 @@ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" } }, "esprima": { @@ -1525,7 +1579,7 @@ "dev": true, "optional": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } }, "supports-color": { @@ -1534,7 +1588,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -1555,8 +1609,8 @@ "integrity": "sha1-WXwai9VxUvJtYizkEXhRpR9euu8=", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "dependencies": { "esprima": { @@ -1573,6 +1627,11 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, + "jschardet": { + "version": "1.6.0", + "resolved": "http://registry.npm.taobao.org/jschardet/download/jschardet-1.6.0.tgz", + "integrity": "sha1-x9GnHtz/KDnbL57DD8XV69PBpng=" + }, "json-schema": { "version": "0.2.3", "resolved": "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", @@ -1599,7 +1658,7 @@ "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" } }, "jsonwebtoken": { @@ -1607,16 +1666,16 @@ "resolved": "http://registry.npm.taobao.org/jsonwebtoken/download/jsonwebtoken-8.2.0.tgz", "integrity": "sha1-aQ7DqefpXiiENHzj6eudOJqlmLM=", "requires": { - "jws": "3.1.4", - "lodash.includes": "4.3.0", - "lodash.isboolean": "3.0.3", - "lodash.isinteger": "4.0.4", - "lodash.isnumber": "3.0.3", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.once": "4.1.1", - "ms": "2.1.1", - "xtend": "4.0.1" + "jws": "^3.1.4", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "xtend": "^4.0.1" }, "dependencies": { "ms": { @@ -1642,8 +1701,8 @@ "resolved": "http://registry.npm.taobao.org/jstransformer/download/jstransformer-1.0.0.tgz", "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", "requires": { - "is-promise": "2.1.0", - "promise": "7.3.1" + "is-promise": "^2.0.0", + "promise": "^7.0.1" } }, "jwa": { @@ -1654,7 +1713,7 @@ "base64url": "2.0.0", "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.9", - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "jws": { @@ -1662,9 +1721,9 @@ "resolved": "http://registry.npm.taobao.org/jws/download/jws-3.1.4.tgz", "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", "requires": { - "base64url": "2.0.0", - "jwa": "1.1.5", - "safe-buffer": "5.1.1" + "base64url": "^2.0.0", + "jwa": "^1.1.4", + "safe-buffer": "^5.0.1" } }, "kind-of": { @@ -1672,7 +1731,7 @@ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "lazy-cache": { @@ -1685,7 +1744,7 @@ "resolved": "http://registry.npm.taobao.org/lcid/download/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "requires": { - "invert-kv": "1.0.0" + "invert-kv": "^1.0.0" } }, "levn": { @@ -1694,8 +1753,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "linkify-it": { @@ -1703,7 +1762,7 @@ "resolved": "http://registry.npm.taobao.org/linkify-it/download/linkify-it-2.0.3.tgz", "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", "requires": { - "uc.micro": "1.0.5" + "uc.micro": "^1.0.1" } }, "locate-path": { @@ -1711,8 +1770,8 @@ "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", "requires": { - "p-locate": "3.0.0", - "path-exists": "3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, "lodash": { @@ -1726,8 +1785,8 @@ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" } }, "lodash._basecopy": { @@ -1760,9 +1819,9 @@ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", "dev": true, "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" } }, "lodash.includes": { @@ -1813,9 +1872,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, "lodash.once": { @@ -1833,13 +1892,18 @@ "resolved": "http://registry.npm.taobao.org/log4js/download/log4js-3.0.5.tgz", "integrity": "sha1-uAFGv+utaLQw1PNWlVbYpu3+8wM=", "requires": { - "circular-json": "0.5.5", - "date-format": "1.2.0", - "debug": "3.1.0", - "rfdc": "1.1.2", + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", "streamroller": "0.7.0" } }, + "long": { + "version": "2.4.0", + "resolved": "http://registry.npm.taobao.org/long/download/long-2.4.0.tgz", + "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" + }, "longest": { "version": "1.0.1", "resolved": "http://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz", @@ -1850,8 +1914,8 @@ "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.3.tgz", "integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=", "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "make-dir": { @@ -1859,7 +1923,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "requires": { - "pify": "3.0.0" + "pify": "^3.0.0" } }, "make-plural": { @@ -1867,7 +1931,7 @@ "resolved": "http://registry.npm.taobao.org/make-plural/download/make-plural-3.0.6.tgz", "integrity": "sha1-IDOgO6wpC487uRJY9lud9+iwHKc=", "requires": { - "minimist": "1.2.0" + "minimist": "^1.2.0" }, "dependencies": { "minimist": { @@ -1883,11 +1947,11 @@ "resolved": "http://registry.npm.taobao.org/markdown-it/download/markdown-it-8.4.1.tgz", "integrity": "sha1-IG/lmw5OG3inxzJQr5s0pK0Kr0Q=", "requires": { - "argparse": "1.0.10", - "entities": "1.1.1", - "linkify-it": "2.0.3", - "mdurl": "1.0.1", - "uc.micro": "1.0.5" + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" } }, "math-interval-parser": { @@ -1895,7 +1959,7 @@ "resolved": "http://registry.npm.taobao.org/math-interval-parser/download/math-interval-parser-1.1.0.tgz", "integrity": "sha1-2+2lsGsySZc8bfYXD94jhvCv2JM=", "requires": { - "xregexp": "2.0.0" + "xregexp": "^2.0.0" } }, "mdurl": { @@ -1913,7 +1977,7 @@ "resolved": "http://registry.npm.taobao.org/mem/download/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "merge-descriptors": { @@ -1926,11 +1990,11 @@ "resolved": "http://registry.npm.taobao.org/messageformat/download/messageformat-0.3.1.tgz", "integrity": "sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI=", "requires": { - "async": "1.5.2", - "glob": "6.0.4", - "make-plural": "3.0.6", - "nopt": "3.0.6", - "watchr": "2.4.13" + "async": "~1.5.2", + "glob": "~6.0.4", + "make-plural": "~3.0.3", + "nopt": "~3.0.6", + "watchr": "~2.4.13" }, "dependencies": { "glob": { @@ -1938,11 +2002,11 @@ "resolved": "http://registry.npm.taobao.org/glob/download/glob-6.0.4.tgz", "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } @@ -1962,7 +2026,7 @@ "resolved": "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.18.tgz", "integrity": "sha1-bzI/YKg9ERRvgx/xH9ZuL+VQO7g=", "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "mimic-fn": { @@ -1975,7 +2039,7 @@ "resolved": "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -2017,7 +2081,7 @@ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { - "graceful-readlink": "1.0.1" + "graceful-readlink": ">= 1.0.0" } }, "debug": { @@ -2035,12 +2099,12 @@ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "mkdirp": { @@ -2058,7 +2122,7 @@ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } } } @@ -2073,7 +2137,7 @@ "resolved": "http://registry.npm.taobao.org/moment-timezone/download/moment-timezone-0.5.14.tgz", "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", "requires": { - "moment": "2.21.0" + "moment": ">= 2.9.0" } }, "morgan": { @@ -2081,11 +2145,11 @@ "resolved": "http://registry.npm.taobao.org/morgan/download/morgan-1.9.0.tgz", "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", "requires": { - "basic-auth": "2.0.0", + "basic-auth": "~2.0.0", "debug": "2.6.9", - "depd": "1.1.2", - "on-finished": "2.3.0", - "on-headers": "1.0.1" + "depd": "~1.1.1", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" }, "dependencies": { "debug": { @@ -2114,17 +2178,17 @@ "integrity": "sha1-5OBzg5uxCXJmmyQOx3Bh1/9Vz1k=", "requires": { "cardinal": "1.0.0", - "denque": "1.2.3", - "generate-function": "2.0.0", - "iconv-lite": "0.4.19", - "long": "4.0.0", - "lru-cache": "4.1.2", + "denque": "^1.1.1", + "generate-function": "^2.0.0", + "iconv-lite": "^0.4.18", + "long": "^4.0.0", + "lru-cache": "^4.1.1", "named-placeholders": "1.1.1", - "object-assign": "4.1.1", + "object-assign": "^4.1.1", "readable-stream": "2.3.2", - "safe-buffer": "5.1.1", + "safe-buffer": "^5.0.1", "seq-queue": "0.0.5", - "sqlstring": "2.3.1" + "sqlstring": "^2.2.0" }, "dependencies": { "long": { @@ -2137,8 +2201,8 @@ "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.2.tgz", "integrity": "sha1-RSNLLm4vKzPaElYkxGZJKaAiTD8=", "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "process-nextick-args": { @@ -2151,13 +2215,13 @@ "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.2.tgz", "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.0", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" } } } @@ -2187,6 +2251,24 @@ "resolved": "http://registry.npm.taobao.org/nocache/download/nocache-2.0.0.tgz", "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" }, + "node_memcached": { + "version": "1.1.3", + "resolved": "http://registry.npm.taobao.org/node_memcached/download/node_memcached-1.1.3.tgz", + "integrity": "sha1-icFSr4itKIF/ANiRyZBFHV1xLqg=", + "requires": { + "debug": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + } + } + }, "nodemailer": { "version": "4.6.3", "resolved": "http://registry.npm.taobao.org/nodemailer/download/nodemailer-4.6.3.tgz", @@ -2197,2799 +2279,116 @@ "resolved": "http://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "requires": { - "abbrev": "1.1.1" - } - }, - "npm": { - "version": "6.4.1", - "resolved": "http://registry.npm.taobao.org/npm/download/npm-6.4.1.tgz", - "integrity": "sha1-Tzn5M3tVeij67Up3HVyIAta0KIs=", - "requires": { - "JSONStream": "1.3.4", - "abbrev": "1.1.1", - "ansicolors": "0.3.2", - "ansistyles": "0.1.3", - "aproba": "1.2.0", - "archy": "1.0.0", - "bin-links": "1.1.2", - "bluebird": "3.5.1", - "byte-size": "4.0.3", - "cacache": "11.2.0", - "call-limit": "1.1.0", - "chownr": "1.0.1", - "ci-info": "1.4.0", - "cli-columns": "3.1.2", - "cli-table3": "0.5.0", - "cmd-shim": "2.0.2", - "columnify": "1.5.4", - "config-chain": "1.1.11", - "debuglog": "1.0.1", - "detect-indent": "5.0.0", - "detect-newline": "2.1.0", - "dezalgo": "1.0.3", - "editor": "1.0.0", - "figgy-pudding": "3.4.1", - "find-npm-prefix": "1.0.2", - "fs-vacuum": "1.2.10", - "fs-write-stream-atomic": "1.0.10", - "gentle-fs": "2.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "has-unicode": "2.0.1", - "hosted-git-info": "2.7.1", - "iferr": "1.0.2", - "imurmurhash": "0.1.4", - "inflight": "1.0.6", - "inherits": "2.0.3", - "ini": "1.3.5", - "init-package-json": "1.10.3", - "is-cidr": "2.0.6", - "json-parse-better-errors": "1.0.2", - "lazy-property": "1.0.0", - "libcipm": "2.0.2", - "libnpmhook": "4.0.1", - "libnpx": "10.2.0", - "lock-verify": "2.0.2", - "lockfile": "1.0.4", - "lodash._baseindexof": "3.1.0", - "lodash._baseuniq": "4.6.0", - "lodash._bindcallback": "3.0.1", - "lodash._cacheindexof": "3.0.2", - "lodash._createcache": "3.1.2", - "lodash._getnative": "3.9.1", - "lodash.clonedeep": "4.5.0", - "lodash.restparam": "3.6.1", - "lodash.union": "4.6.0", - "lodash.uniq": "4.5.0", - "lodash.without": "4.4.0", - "lru-cache": "4.1.3", - "meant": "1.0.1", - "mississippi": "3.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "node-gyp": "3.8.0", - "nopt": "4.0.1", - "normalize-package-data": "2.4.0", - "npm-audit-report": "1.3.1", - "npm-cache-filename": "1.0.2", - "npm-install-checks": "3.0.0", - "npm-lifecycle": "2.1.0", - "npm-package-arg": "6.1.0", - "npm-packlist": "1.1.11", - "npm-pick-manifest": "2.1.0", - "npm-profile": "3.0.2", - "npm-registry-client": "8.6.0", - "npm-registry-fetch": "1.1.0", - "npm-user-validate": "1.0.0", - "npmlog": "4.1.2", - "once": "1.4.0", - "opener": "1.5.0", - "osenv": "0.1.5", - "pacote": "8.1.6", - "path-is-inside": "1.0.2", - "promise-inflight": "1.0.1", - "qrcode-terminal": "0.12.0", - "query-string": "6.1.0", - "qw": "1.0.1", - "read": "1.0.7", - "read-cmd-shim": "1.0.1", - "read-installed": "4.0.3", - "read-package-json": "2.0.13", - "read-package-tree": "5.2.1", - "readable-stream": "2.3.6", - "readdir-scoped-modules": "1.0.2", - "request": "2.88.0", - "retry": "0.12.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.2", - "semver": "5.5.0", - "sha": "2.0.1", - "slide": "1.1.6", - "sorted-object": "2.0.1", - "sorted-union-stream": "2.1.3", - "ssri": "6.0.0", - "stringify-package": "1.0.0", - "tar": "4.4.6", - "text-table": "0.2.0", - "tiny-relative-date": "1.3.0", - "uid-number": "0.0.6", - "umask": "1.1.0", - "unique-filename": "1.1.0", - "unpipe": "1.0.0", - "update-notifier": "2.5.0", - "uuid": "3.3.2", - "validate-npm-package-license": "3.0.4", - "validate-npm-package-name": "3.0.0", - "which": "1.3.1", - "worker-farm": "1.6.0", - "write-file-atomic": "2.3.0" + "abbrev": "1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "http://registry.npm.taobao.org/on-headers/download/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "http://registry.npm.taobao.org/optimist/download/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" }, "dependencies": { - "JSONStream": { - "version": "1.3.4", - "bundled": true, - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - }, - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - } - }, - "agentkeepalive": { - "version": "3.4.1", - "bundled": true, - "requires": { - "humanize-ms": "1.2.1" - } - }, - "ajv": { - "version": "5.5.2", - "bundled": true, - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - }, - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "2.1.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "ansi-styles": { - "version": "3.2.1", - "bundled": true, - "requires": { - "color-convert": "1.9.1" - } - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "asap": { - "version": "2.0.6", - "bundled": true - }, - "asn1": { - "version": "0.2.4", - "bundled": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true - }, - "aws-sign2": { - "version": "0.7.0", - "bundled": true - }, - "aws4": { - "version": "1.8.0", - "bundled": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "bin-links": { - "version": "1.1.2", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "cmd-shim": "2.0.2", - "gentle-fs": "2.0.1", - "graceful-fs": "4.1.11", - "write-file-atomic": "2.3.0" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - }, - "bluebird": { - "version": "3.5.1", - "bundled": true - }, - "boxen": { - "version": "1.3.0", - "bundled": true, - "requires": { - "ansi-align": "2.0.0", - "camelcase": "4.1.0", - "chalk": "2.4.1", - "cli-boxes": "1.0.0", - "string-width": "2.1.1", - "term-size": "1.2.0", - "widest-line": "2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-from": { - "version": "1.0.0", - "bundled": true - }, - "builtin-modules": { - "version": "1.1.1", - "bundled": true - }, - "builtins": { - "version": "1.0.3", - "bundled": true - }, - "byline": { - "version": "5.0.0", - "bundled": true - }, - "byte-size": { - "version": "4.0.3", - "bundled": true - }, - "cacache": { - "version": "11.2.0", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "chownr": "1.0.1", - "figgy-pudding": "3.4.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lru-cache": "4.1.3", - "mississippi": "3.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.6.2", - "ssri": "6.0.0", - "unique-filename": "1.1.0", - "y18n": "4.0.0" - } - }, - "call-limit": { - "version": "1.1.0", - "bundled": true - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "chalk": { - "version": "2.4.1", - "bundled": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true - }, - "ci-info": { - "version": "1.4.0", - "bundled": true - }, - "cidr-regex": { - "version": "2.0.9", - "bundled": true, - "requires": { - "ip-regex": "2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "cli-columns": { - "version": "3.1.2", - "bundled": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "3.0.1" - } - }, - "cli-table3": { - "version": "0.5.0", - "bundled": true, - "requires": { - "colors": "1.1.2", - "object-assign": "4.1.1", - "string-width": "2.1.1" - } - }, - "cliui": { - "version": "4.1.0", - "bundled": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "bundled": true - }, - "cmd-shim": { - "version": "2.0.2", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1" - } - }, - "co": { - "version": "4.6.0", - "bundled": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "color-convert": { - "version": "1.9.1", - "bundled": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "bundled": true - }, - "colors": { - "version": "1.1.2", - "bundled": true, - "optional": true - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "3.0.1", - "wcwidth": "1.0.1" - } - }, - "combined-stream": { - "version": "1.0.6", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "concat-stream": { - "version": "1.6.2", - "bundled": true, - "requires": { - "buffer-from": "1.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - } - }, - "config-chain": { - "version": "1.1.11", - "bundled": true, - "requires": { - "ini": "1.3.5", - "proto-list": "1.2.4" - } - }, - "configstore": { - "version": "3.1.2", - "bundled": true, - "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.3.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "4.1.3", - "shebang-command": "1.2.0", - "which": "1.3.1" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - }, - "cyclist": { - "version": "0.2.2", - "bundled": true - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "decamelize": { - "version": "1.2.0", - "bundled": true - }, - "decode-uri-component": { - "version": "0.2.0", - "bundled": true - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "1.0.4" - } - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true - }, - "detect-newline": { - "version": "2.1.0", - "bundled": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "2.0.6", - "wrappy": "1.0.2" - } - }, - "dot-prop": { - "version": "4.2.0", - "bundled": true, - "requires": { - "is-obj": "1.0.1" - } - }, - "dotenv": { - "version": "5.0.1", - "bundled": true - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "duplexify": { - "version": "3.6.0", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1", - "safer-buffer": "2.1.2" - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "0.4.23" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "1.0.1" - } - }, - "es6-promise": { - "version": "4.2.4", - "bundled": true - }, - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "extend": { - "version": "3.0.2", - "bundled": true - }, - "extsprintf": { - "version": "1.3.0", - "bundled": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "bundled": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "bundled": true - }, - "figgy-pudding": { - "version": "3.4.1", - "bundled": true - }, - "find-npm-prefix": { - "version": "1.0.2", - "bundled": true - }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "requires": { - "locate-path": "2.0.0" - } - }, - "flush-write-stream": { - "version": "1.0.3", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.3.2", - "bundled": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.19" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "requires": { - "minipass": "2.3.3" - } - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "path-is-inside": "1.0.2", - "rimraf": "2.6.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "readable-stream": "2.3.6" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "genfun": { - "version": "4.0.1", - "bundled": true - }, - "gentle-fs": { - "version": "2.0.1", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "fs-vacuum": "1.2.10", - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "path-is-inside": "1.0.2", - "read-cmd-shim": "1.0.1", - "slide": "1.1.6" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "get-caller-file": { - "version": "1.0.2", - "bundled": true - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "global-dirs": { - "version": "0.1.1", - "bundled": true, - "requires": { - "ini": "1.3.5" - } - }, - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "3.0.2", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.1", - "safe-buffer": "5.1.2", - "timed-out": "4.0.1", - "unzip-response": "2.0.1", - "url-parse-lax": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "har-schema": { - "version": "2.0.0", - "bundled": true - }, - "har-validator": { - "version": "5.1.0", - "bundled": true, - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "hosted-git-info": { - "version": "2.7.1", - "bundled": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.2" - } - }, - "https-proxy-agent": { - "version": "2.2.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "2.1.1" - } - }, - "iconv-lite": { - "version": "0.4.23", - "bundled": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "iferr": { - "version": "1.0.2", - "bundled": true - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true - }, - "init-package-json": { - "version": "1.10.3", - "bundled": true, - "requires": { - "glob": "7.1.2", - "npm-package-arg": "6.1.0", - "promzard": "0.3.0", - "read": "1.0.7", - "read-package-json": "2.0.13", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.4", - "validate-npm-package-name": "3.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "bundled": true - }, - "ip": { - "version": "1.1.5", - "bundled": true - }, - "ip-regex": { - "version": "2.1.0", - "bundled": true - }, - "is-builtin-module": { - "version": "1.0.0", - "bundled": true, - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-ci": { - "version": "1.1.0", - "bundled": true, - "requires": { - "ci-info": "1.4.0" - } - }, - "is-cidr": { - "version": "2.0.6", - "bundled": true, - "requires": { - "cidr-regex": "2.0.9" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "requires": { - "global-dirs": "0.1.1", - "is-path-inside": "1.0.1" - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "is-obj": { - "version": "1.0.1", - "bundled": true - }, - "is-path-inside": { - "version": "1.0.1", - "bundled": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "4.0.1" - } - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true - }, - "lcid": { - "version": "1.0.0", - "bundled": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "libcipm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "bin-links": "1.1.2", - "bluebird": "3.5.1", - "find-npm-prefix": "1.0.2", - "graceful-fs": "4.1.11", - "lock-verify": "2.0.2", - "mkdirp": "0.5.1", - "npm-lifecycle": "2.1.0", - "npm-logical-tree": "1.2.1", - "npm-package-arg": "6.1.0", - "pacote": "8.1.6", - "protoduck": "5.0.0", - "read-package-json": "2.0.13", - "rimraf": "2.6.2", - "worker-farm": "1.6.0" - } - }, - "libnpmhook": { - "version": "4.0.1", - "bundled": true, - "requires": { - "figgy-pudding": "3.4.1", - "npm-registry-fetch": "3.1.1" - }, - "dependencies": { - "npm-registry-fetch": { - "version": "3.1.1", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "figgy-pudding": "3.4.1", - "lru-cache": "4.1.3", - "make-fetch-happen": "4.0.1", - "npm-package-arg": "6.1.0" - } - } - } - }, - "libnpx": { - "version": "10.2.0", - "bundled": true, - "requires": { - "dotenv": "5.0.1", - "npm-package-arg": "6.1.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.2", - "update-notifier": "2.5.0", - "which": "1.3.1", - "y18n": "4.0.0", - "yargs": "11.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, - "lock-verify": { - "version": "2.0.2", - "bundled": true, - "requires": { - "npm-package-arg": "6.1.0", - "semver": "5.5.0" - } - }, - "lockfile": { - "version": "1.0.4", - "bundled": true, - "requires": { - "signal-exit": "3.0.2" - } - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "requires": { - "lodash._createset": "4.0.3", - "lodash._root": "3.0.1" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "requires": { - "lodash._getnative": "3.9.1" - } - }, - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.1", - "bundled": true - }, - "lru-cache": { - "version": "4.1.3", - "bundled": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "requires": { - "pify": "3.0.0" - } - }, - "make-fetch-happen": { - "version": "4.0.1", - "bundled": true, - "requires": { - "agentkeepalive": "3.4.1", - "cacache": "11.2.0", - "http-cache-semantics": "3.8.1", - "http-proxy-agent": "2.1.0", - "https-proxy-agent": "2.2.1", - "lru-cache": "4.1.3", - "mississippi": "3.0.0", - "node-fetch-npm": "2.0.2", - "promise-retry": "1.1.1", - "socks-proxy-agent": "4.0.1", - "ssri": "6.0.0" - } - }, - "meant": { - "version": "1.0.1", - "bundled": true - }, - "mem": { - "version": "1.1.0", - "bundled": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "mime-db": { - "version": "1.35.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.19", - "bundled": true, - "requires": { - "mime-db": "1.35.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "minipass": { - "version": "2.3.3", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2", - "yallist": "3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "requires": { - "minipass": "2.3.3" - } - }, - "mississippi": { - "version": "3.0.0", - "bundled": true, - "requires": { - "concat-stream": "1.6.2", - "duplexify": "3.6.0", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.3", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "3.0.0", - "pumpify": "1.5.1", - "stream-each": "1.2.2", - "through2": "2.0.3" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true - }, - "mute-stream": { - "version": "0.0.7", - "bundled": true - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "0.1.12", - "json-parse-better-errors": "1.0.2", - "safe-buffer": "5.1.2" - } - }, - "node-gyp": { - "version": "3.8.0", - "bundled": true, - "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.5", - "request": "2.88.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.1" - }, - "dependencies": { - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1.1.1" - } - }, - "semver": { - "version": "5.3.0", - "bundled": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - } - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "bundled": true, - "requires": { - "hosted-git-info": "2.7.1", - "is-builtin-module": "1.0.0", - "semver": "5.5.0", - "validate-npm-package-license": "3.0.4" - } - }, - "npm-audit-report": { - "version": "1.3.1", - "bundled": true, - "requires": { - "cli-table3": "0.5.0", - "console-control-strings": "1.1.0" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "3.0.0", - "bundled": true, - "requires": { - "semver": "5.5.0" - } - }, - "npm-lifecycle": { - "version": "2.1.0", - "bundled": true, - "requires": { - "byline": "5.0.0", - "graceful-fs": "4.1.11", - "node-gyp": "3.8.0", - "resolve-from": "4.0.0", - "slide": "1.1.6", - "uid-number": "0.0.6", - "umask": "1.1.0", - "which": "1.3.1" - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true - }, - "npm-package-arg": { - "version": "6.1.0", - "bundled": true, - "requires": { - "hosted-git-info": "2.7.1", - "osenv": "0.1.5", - "semver": "5.5.0", - "validate-npm-package-name": "3.0.0" - } - }, - "npm-packlist": { - "version": "1.1.11", - "bundled": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.5" - } - }, - "npm-pick-manifest": { - "version": "2.1.0", - "bundled": true, - "requires": { - "npm-package-arg": "6.1.0", - "semver": "5.5.0" - } - }, - "npm-profile": { - "version": "3.0.2", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "make-fetch-happen": "4.0.1" - } - }, - "npm-registry-client": { - "version": "8.6.0", - "bundled": true, - "requires": { - "concat-stream": "1.6.2", - "graceful-fs": "4.1.11", - "normalize-package-data": "2.4.0", - "npm-package-arg": "6.1.0", - "npmlog": "4.1.2", - "once": "1.4.0", - "request": "2.88.0", - "retry": "0.10.1", - "safe-buffer": "5.1.2", - "semver": "5.5.0", - "slide": "1.1.6", - "ssri": "5.3.0" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true - }, - "ssri": { - "version": "5.3.0", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2" - } - } - } - }, - "npm-registry-fetch": { - "version": "1.1.0", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "figgy-pudding": "2.0.1", - "lru-cache": "4.1.3", - "make-fetch-happen": "3.0.0", - "npm-package-arg": "6.1.0", - "safe-buffer": "5.1.2" - }, - "dependencies": { - "cacache": { - "version": "10.0.4", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "chownr": "1.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lru-cache": "4.1.3", - "mississippi": "2.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.6.2", - "ssri": "5.3.0", - "unique-filename": "1.1.0", - "y18n": "4.0.0" - }, - "dependencies": { - "mississippi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "concat-stream": "1.6.2", - "duplexify": "3.6.0", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.3", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "2.0.1", - "pumpify": "1.5.1", - "stream-each": "1.2.2", - "through2": "2.0.3" - } - } - } - }, - "figgy-pudding": { - "version": "2.0.1", - "bundled": true - }, - "make-fetch-happen": { - "version": "3.0.0", - "bundled": true, - "requires": { - "agentkeepalive": "3.4.1", - "cacache": "10.0.4", - "http-cache-semantics": "3.8.1", - "http-proxy-agent": "2.1.0", - "https-proxy-agent": "2.2.1", - "lru-cache": "4.1.3", - "mississippi": "3.0.0", - "node-fetch-npm": "2.0.2", - "promise-retry": "1.1.1", - "socks-proxy-agent": "3.0.1", - "ssri": "5.3.0" - } - }, - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - } - }, - "ssri": { - "version": "5.3.0", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2" - } - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "2.0.1" - } - }, - "npm-user-validate": { - "version": "1.0.0", - "bundled": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.9.0", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "opener": { - "version": "1.5.0", - "bundled": true - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-locale": { - "version": "2.1.0", - "bundled": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "p-limit": { - "version": "1.2.0", - "bundled": true, - "requires": { - "p-try": "1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-limit": "1.2.0" - } - }, - "p-try": { - "version": "1.0.0", - "bundled": true - }, - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "6.7.1", - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0", - "semver": "5.5.0" - } - }, - "pacote": { - "version": "8.1.6", - "bundled": true, - "requires": { - "bluebird": "3.5.1", - "cacache": "11.2.0", - "get-stream": "3.0.0", - "glob": "7.1.2", - "lru-cache": "4.1.3", - "make-fetch-happen": "4.0.1", - "minimatch": "3.0.4", - "minipass": "2.3.3", - "mississippi": "3.0.0", - "mkdirp": "0.5.1", - "normalize-package-data": "2.4.0", - "npm-package-arg": "6.1.0", - "npm-packlist": "1.1.11", - "npm-pick-manifest": "2.1.0", - "osenv": "0.1.5", - "promise-inflight": "1.0.1", - "promise-retry": "1.1.1", - "protoduck": "5.0.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.2", - "semver": "5.5.0", - "ssri": "6.0.0", - "tar": "4.4.6", - "unique-filename": "1.1.0", - "which": "1.3.1" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true - }, - "pify": { - "version": "3.0.0", - "bundled": true - }, - "prepend-http": { - "version": "1.0.4", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "1.1.2", - "retry": "0.10.1" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1.0.7" - } - }, - "proto-list": { - "version": "1.2.4", - "bundled": true - }, - "protoduck": { - "version": "5.0.0", - "bundled": true, - "requires": { - "genfun": "4.0.1" - } - }, - "prr": { - "version": "1.0.1", - "bundled": true - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "psl": { - "version": "1.1.29", - "bundled": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.5.1", - "bundled": true, - "requires": { - "duplexify": "3.6.0", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "bundled": true - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true - }, - "qs": { - "version": "6.5.2", - "bundled": true - }, - "query-string": { - "version": "6.1.0", - "bundled": true, - "requires": { - "decode-uri-component": "0.2.0", - "strict-uri-encode": "2.0.0" - } - }, - "qw": { - "version": "1.0.1", - "bundled": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true - } - } - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "0.0.7" - } - }, - "read-cmd-shim": { - "version": "1.0.1", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "1.0.1", - "graceful-fs": "4.1.11", - "read-package-json": "2.0.13", - "readdir-scoped-modules": "1.0.2", - "semver": "5.5.0", - "slide": "1.1.6", - "util-extend": "1.0.3" - } - }, - "read-package-json": { - "version": "2.0.13", - "bundled": true, - "requires": { - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "json-parse-better-errors": "1.0.2", - "normalize-package-data": "2.4.0", - "slash": "1.0.0" - } - }, - "read-package-tree": { - "version": "5.2.1", - "bundled": true, - "requires": { - "debuglog": "1.0.1", - "dezalgo": "1.0.3", - "once": "1.4.0", - "read-package-json": "2.0.13", - "readdir-scoped-modules": "1.0.2" - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "readdir-scoped-modules": { - "version": "1.0.2", - "bundled": true, - "requires": { - "debuglog": "1.0.1", - "dezalgo": "1.0.3", - "graceful-fs": "4.1.11", - "once": "1.4.0" - } - }, - "registry-auth-token": { - "version": "3.3.2", - "bundled": true, - "requires": { - "rc": "1.2.7", - "safe-buffer": "5.1.2" - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "1.2.7" - } - }, - "request": { - "version": "2.88.0", - "bundled": true, - "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.8.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.2", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.1.0", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.19", - "oauth-sign": "0.9.0", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.2", - "tough-cookie": "2.4.3", - "tunnel-agent": "0.6.0", - "uuid": "3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true - }, - "retry": { - "version": "0.12.0", - "bundled": true - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "requires": { - "glob": "7.1.2" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "1.2.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true - }, - "semver": { - "version": "5.5.0", - "bundled": true - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "5.5.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "sha": { - "version": "2.0.1", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "readable-stream": "2.3.6" - } - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "slash": { - "version": "1.0.0", - "bundled": true - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "smart-buffer": { - "version": "4.0.1", - "bundled": true - }, - "socks": { - "version": "2.2.0", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "4.0.1" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "2.2.0" - } - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "requires": { - "from2": "1.3.0", - "stream-iterate": "1.2.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "1.1.14" - } - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - }, - "spdx-correct": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "bundled": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "bundled": true - }, - "sshpk": { - "version": "1.14.2", - "bundled": true, - "requires": { - "asn1": "0.2.4", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.2", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.2", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "safer-buffer": "2.1.2", - "tweetnacl": "0.14.5" - } - }, - "ssri": { - "version": "6.0.0", - "bundled": true - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "requires": { - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - } - }, - "stream-shift": { - "version": "1.0.0", - "bundled": true - }, - "strict-uri-encode": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "stringify-package": { - "version": "1.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - }, - "supports-color": { - "version": "5.4.0", - "bundled": true, - "requires": { - "has-flag": "3.0.0" - } - }, - "tar": { - "version": "4.4.6", - "bundled": true, - "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.3.3", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.2", - "yallist": "3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "requires": { - "execa": "0.7.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true - }, - "tough-cookie": { - "version": "2.4.3", - "bundled": true, - "requires": { - "psl": "1.1.29", - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "unique-filename": { - "version": "1.1.0", - "bundled": true, - "requires": { - "unique-slug": "2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "0.1.4" - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "update-notifier": { - "version": "2.5.0", - "bundled": true, - "requires": { - "boxen": "1.3.0", - "chalk": "2.4.1", - "configstore": "3.1.2", - "import-lazy": "2.1.0", - "is-ci": "1.1.0", - "is-installed-globally": "0.1.0", - "is-npm": "1.0.0", - "latest-version": "3.1.0", - "semver-diff": "2.1.0", - "xdg-basedir": "3.0.0" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "1.0.4" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "util-extend": { - "version": "1.0.3", - "bundled": true - }, - "uuid": { - "version": "3.3.2", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "bundled": true, - "requires": { - "builtins": "1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "1.0.3" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "widest-line": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "2.1.1" - } - }, - "worker-farm": { - "version": "1.6.0", - "bundled": true, - "requires": { - "errno": "0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "write-file-atomic": { - "version": "2.3.0", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true - }, - "yargs": { - "version": "11.0.0", - "bundled": true, - "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" - }, - "dependencies": { - "y18n": { - "version": "3.2.1", - "bundled": true - } - } - }, - "yargs-parser": { - "version": "9.0.2", - "bundled": true, - "requires": { - "camelcase": "4.1.0" - } - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "2.0.1" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/on-headers/download/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" - }, - "once": { - "version": "1.4.0", - "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/optimist/download/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - } - }, - "os-name": { - "version": "1.0.3", - "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz", - "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", - "requires": { - "osx-release": "1.1.0", - "win-release": "1.1.1" - } - }, - "osx-release": { - "version": "1.1.0", - "resolved": "http://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz", - "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", - "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { + "wordwrap": { + "version": "0.0.3", + "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "http://registry.npm.taobao.org/optjs/download/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "os-name": { + "version": "1.0.3", + "resolved": "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "requires": { + "osx-release": "^1.0.0", + "win-release": "^1.0.0" + } + }, + "osx-release": { + "version": "1.1.0", + "resolved": "http://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "requires": { + "minimist": "^1.1.0" + }, + "dependencies": { + "minimist": { "version": "1.2.0", "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" @@ -5006,7 +2405,7 @@ "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-2.0.0.tgz", "integrity": "sha1-5iTtVO6MRgp3izyfNnBJb/ileuw=", "requires": { - "p-try": "2.0.0" + "p-try": "^2.0.0" } }, "p-locate": { @@ -5014,7 +2413,7 @@ "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", "requires": { - "p-limit": "2.0.0" + "p-limit": "^2.0.0" } }, "p-try": { @@ -5057,7 +2456,7 @@ "resolved": "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "requires": { - "through": "2.3.8" + "through": "~2.3" } }, "pend": { @@ -5080,6 +2479,11 @@ "resolved": "http://registry.npm.taobao.org/platform/download/platform-1.3.5.tgz", "integrity": "sha1-+2lYxpbgfikY0u7aDwvJRI1zNEQ=" }, + "pomelo-protobuf": { + "version": "0.4.0", + "resolved": "http://registry.npm.taobao.org/pomelo-protobuf/download/pomelo-protobuf-0.4.0.tgz", + "integrity": "sha1-5F6aCkRusYZn4MbhPutT1Hrdvag=" + }, "prelude-ls": { "version": "1.1.2", "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz", @@ -5096,7 +2500,34 @@ "resolved": "http://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz", "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", "requires": { - "asap": "2.0.6" + "asap": "~2.0.3" + } + }, + "protobufjs": { + "version": "4.1.3", + "resolved": "http://registry.npm.taobao.org/protobufjs/download/protobufjs-4.1.3.tgz", + "integrity": "sha1-jjbRsCJsu2jWR+S0TCoUTzfyd54=", + "requires": { + "ascli": "~1", + "bytebuffer": "~4 >=4.1", + "glob": "^5.0.10", + "yargs": "^3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.32.0", + "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } } }, "proxy-addr": { @@ -5104,7 +2535,7 @@ "resolved": "http://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.3.tgz", "integrity": "sha1-NV8mJQWmIWRrMTCnKOtkfiIFU0E=", "requires": { - "forwarded": "0.1.2", + "forwarded": "~0.1.2", "ipaddr.js": "1.6.0" } }, @@ -5118,14 +2549,14 @@ "resolved": "http://registry.npm.taobao.org/pug/download/pug-2.0.1.tgz", "integrity": "sha1-J8FRYStT1ymr6OgoWqxryJNFtdA=", "requires": { - "pug-code-gen": "2.0.1", - "pug-filters": "3.0.1", - "pug-lexer": "4.0.0", - "pug-linker": "3.0.5", - "pug-load": "2.0.11", - "pug-parser": "5.0.0", - "pug-runtime": "2.0.4", - "pug-strip-comments": "1.0.3" + "pug-code-gen": "^2.0.1", + "pug-filters": "^3.0.1", + "pug-lexer": "^4.0.0", + "pug-linker": "^3.0.5", + "pug-load": "^2.0.11", + "pug-parser": "^5.0.0", + "pug-runtime": "^2.0.4", + "pug-strip-comments": "^1.0.3" } }, "pug-attrs": { @@ -5133,9 +2564,9 @@ "resolved": "http://registry.npm.taobao.org/pug-attrs/download/pug-attrs-2.0.3.tgz", "integrity": "sha1-owlflw5kFR972tlX7vVftdeQXRU=", "requires": { - "constantinople": "3.1.2", - "js-stringify": "1.0.2", - "pug-runtime": "2.0.4" + "constantinople": "^3.0.1", + "js-stringify": "^1.0.1", + "pug-runtime": "^2.0.4" } }, "pug-code-gen": { @@ -5143,14 +2574,14 @@ "resolved": "http://registry.npm.taobao.org/pug-code-gen/download/pug-code-gen-2.0.1.tgz", "integrity": "sha1-CVHsgyJddNjPxHan+Zolm199BQw=", "requires": { - "constantinople": "3.1.2", - "doctypes": "1.1.0", - "js-stringify": "1.0.2", - "pug-attrs": "2.0.3", - "pug-error": "1.3.2", - "pug-runtime": "2.0.4", - "void-elements": "2.0.1", - "with": "5.1.1" + "constantinople": "^3.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.1", + "pug-attrs": "^2.0.3", + "pug-error": "^1.3.2", + "pug-runtime": "^2.0.4", + "void-elements": "^2.0.1", + "with": "^5.0.0" } }, "pug-error": { @@ -5163,13 +2594,13 @@ "resolved": "http://registry.npm.taobao.org/pug-filters/download/pug-filters-3.0.1.tgz", "integrity": "sha1-Fj73O/ux8VRNAysrQPRRMOtS3Ms=", "requires": { - "clean-css": "3.4.28", - "constantinople": "3.1.2", + "clean-css": "^3.3.0", + "constantinople": "^3.0.1", "jstransformer": "1.0.0", - "pug-error": "1.3.2", - "pug-walk": "1.1.7", - "resolve": "1.5.0", - "uglify-js": "2.8.29" + "pug-error": "^1.3.2", + "pug-walk": "^1.1.7", + "resolve": "^1.1.6", + "uglify-js": "^2.6.1" } }, "pug-lexer": { @@ -5177,9 +2608,9 @@ "resolved": "http://registry.npm.taobao.org/pug-lexer/download/pug-lexer-4.0.0.tgz", "integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=", "requires": { - "character-parser": "2.2.0", - "is-expression": "3.0.0", - "pug-error": "1.3.2" + "character-parser": "^2.1.1", + "is-expression": "^3.0.0", + "pug-error": "^1.3.2" } }, "pug-linker": { @@ -5187,8 +2618,8 @@ "resolved": "http://registry.npm.taobao.org/pug-linker/download/pug-linker-3.0.5.tgz", "integrity": "sha1-npp65ABWgtAn3uuWsAD4juuDoC8=", "requires": { - "pug-error": "1.3.2", - "pug-walk": "1.1.7" + "pug-error": "^1.3.2", + "pug-walk": "^1.1.7" } }, "pug-load": { @@ -5196,8 +2627,8 @@ "resolved": "http://registry.npm.taobao.org/pug-load/download/pug-load-2.0.11.tgz", "integrity": "sha1-5kjlftET/iwfRdV4WOorrWvAFSc=", "requires": { - "object-assign": "4.1.1", - "pug-walk": "1.1.7" + "object-assign": "^4.1.0", + "pug-walk": "^1.1.7" } }, "pug-parser": { @@ -5205,7 +2636,7 @@ "resolved": "http://registry.npm.taobao.org/pug-parser/download/pug-parser-5.0.0.tgz", "integrity": "sha1-45Stmz/KkxI5QK/4hcBuRKt+aOQ=", "requires": { - "pug-error": "1.3.2", + "pug-error": "^1.3.2", "token-stream": "0.0.1" } }, @@ -5219,7 +2650,7 @@ "resolved": "http://registry.npm.taobao.org/pug-strip-comments/download/pug-strip-comments-1.0.3.tgz", "integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=", "requires": { - "pug-error": "1.3.2" + "pug-error": "^1.3.2" } }, "pug-walk": { @@ -5237,9 +2668,9 @@ "resolved": "https://registry.npmjs.org/qcloudapi-sdk/-/qcloudapi-sdk-0.2.0.tgz", "integrity": "sha512-Hy6a+95zDheaeMbA/N/7AEuAoOhwjR1POPI9xCwfsPc3b24ZzyH1M4PKgO9sq7Rq62+14ZTessHMdXJ+6NaeQg==", "requires": { - "dot-qs": "0.2.0", - "object-assign": "3.0.0", - "request": "2.85.0" + "dot-qs": "^0.2.0", + "object-assign": "^3.0.0", + "request": ">= 2.33.0" }, "dependencies": { "object-assign": { @@ -5256,7 +2687,7 @@ "requires": { "agentkeepalive": "3.3.0", "crc32": "0.2.2", - "encodeurl": "1.0.2", + "encodeurl": "^1.0.1", "formstream": "1.1.0", "mime": "1.3.6", "tunnel-agent": "0.6.0", @@ -5306,13 +2737,13 @@ "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.5.tgz", "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "recursive-readdir": { @@ -5328,7 +2759,7 @@ "resolved": "http://registry.npm.taobao.org/redeyed/download/redeyed-1.0.1.tgz", "integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=", "requires": { - "esprima": "3.0.0" + "esprima": "~3.0.0" }, "dependencies": { "esprima": { @@ -5343,9 +2774,9 @@ "resolved": "http://registry.npm.taobao.org/redis/download/redis-2.8.0.tgz", "integrity": "sha1-ICKI4/WMSfYHnZevehDhMDrhSwI=", "requires": { - "double-ended-queue": "2.1.0-0", - "redis-commands": "1.3.5", - "redis-parser": "2.6.0" + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" } }, "redis-commands": { @@ -5378,28 +2809,28 @@ "resolved": "http://registry.npm.taobao.org/request/download/request-2.85.0.tgz", "integrity": "sha1-WgNhWkfGFCCz65m326IE+DYD4fo=", "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "hawk": "~6.0.2", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "stringstream": "~0.0.5", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" } }, "require-directory": { @@ -5417,7 +2848,7 @@ "resolved": "http://registry.npm.taobao.org/resolve/download/resolve-1.5.0.tgz", "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "retry-as-promised": { @@ -5425,8 +2856,8 @@ "resolved": "http://registry.npm.taobao.org/retry-as-promised/download/retry-as-promised-2.3.2.tgz", "integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=", "requires": { - "bluebird": "3.5.1", - "debug": "2.6.9" + "bluebird": "^3.4.6", + "debug": "^2.6.9" }, "dependencies": { "debug": { @@ -5449,7 +2880,7 @@ "resolved": "http://registry.npm.taobao.org/right-align/download/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "safe-buffer": { @@ -5462,7 +2893,7 @@ "resolved": "http://registry.npm.taobao.org/safefs/download/safefs-3.2.2.tgz", "integrity": "sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw=", "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "*" } }, "sax": { @@ -5475,9 +2906,9 @@ "resolved": "http://registry.npm.taobao.org/scandirectory/download/scandirectory-2.5.0.tgz", "integrity": "sha1-bOA/VKCQtmjjy+2/IO354xBZPnI=", "requires": { - "ignorefs": "1.2.0", - "safefs": "3.2.2", - "taskgroup": "4.3.1" + "ignorefs": "^1.0.0", + "safefs": "^3.1.2", + "taskgroup": "^4.0.5" } }, "semver": { @@ -5491,18 +2922,18 @@ "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=", "requires": { "debug": "2.6.9", - "depd": "1.1.2", - "destroy": "1.0.4", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "etag": "1.8.1", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.2", + "http-errors": "~1.6.2", "mime": "1.4.1", "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.4.0" + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" }, "dependencies": { "debug": { @@ -5530,23 +2961,23 @@ "resolved": "http://registry.npm.taobao.org/sequelize/download/sequelize-4.37.1.tgz", "integrity": "sha1-F6qX8mm3YhAVxz53qmshNPRdp9c=", "requires": { - "bluebird": "3.5.1", - "cls-bluebird": "2.1.0", - "debug": "3.1.0", - "depd": "1.1.2", - "dottie": "2.0.0", - "generic-pool": "3.4.2", + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^3.1.0", + "depd": "^1.1.0", + "dottie": "^2.0.0", + "generic-pool": "^3.4.0", "inflection": "1.12.0", - "lodash": "4.17.5", - "moment": "2.21.0", - "moment-timezone": "0.5.14", - "retry-as-promised": "2.3.2", - "semver": "5.5.0", - "terraformer-wkt-parser": "1.1.2", - "toposort-class": "1.0.1", - "uuid": "3.2.1", - "validator": "9.4.1", - "wkx": "0.4.4" + "lodash": "^4.17.1", + "moment": "^2.20.0", + "moment-timezone": "^0.5.14", + "retry-as-promised": "^2.3.2", + "semver": "^5.5.0", + "terraformer-wkt-parser": "^1.1.2", + "toposort-class": "^1.0.1", + "uuid": "^3.2.1", + "validator": "^9.4.1", + "wkx": "^0.4.1" }, "dependencies": { "debug": { @@ -5579,10 +3010,10 @@ "resolved": "http://registry.npm.taobao.org/serve-favicon/download/serve-favicon-2.4.5.tgz", "integrity": "sha1-SdmkaGMVOpJAaRyJPSsOfYXW1DY=", "requires": { - "etag": "1.8.1", + "etag": "~1.8.1", "fresh": "0.5.2", "ms": "2.0.0", - "parseurl": "1.3.2", + "parseurl": "~1.3.2", "safe-buffer": "5.1.1" } }, @@ -5591,9 +3022,9 @@ "resolved": "http://registry.npm.taobao.org/serve-static/download/serve-static-1.13.2.tgz", "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", "requires": { - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", "send": "0.16.2" } }, @@ -5612,7 +3043,7 @@ "resolved": "http://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -5631,11 +3062,11 @@ "integrity": "sha1-kPVRRVUtAc/CAGZuToGKHJZw7aI=", "dev": true, "requires": { - "should-equal": "1.0.1", - "should-format": "3.0.3", - "should-type": "1.4.0", - "should-type-adaptors": "1.1.0", - "should-util": "1.0.0" + "should-equal": "^1.0.0", + "should-format": "^3.0.2", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" } }, "should-equal": { @@ -5644,7 +3075,7 @@ "integrity": "sha1-C26VFvJgGp+wuy3MNpr6HH4gCvc=", "dev": true, "requires": { - "should-type": "1.4.0" + "should-type": "^1.0.0" } }, "should-format": { @@ -5653,8 +3084,8 @@ "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", "dev": true, "requires": { - "should-type": "1.4.0", - "should-type-adaptors": "1.1.0" + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" } }, "should-type": { @@ -5669,8 +3100,8 @@ "integrity": "sha1-QB5/M7VTMDOUTVzYvytlAneS4no=", "dev": true, "requires": { - "should-type": "1.4.0", - "should-util": "1.0.0" + "should-type": "^1.3.0", + "should-util": "^1.0.0" } }, "should-util": { @@ -5694,7 +3125,7 @@ "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-2.1.0.tgz", "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", "requires": { - "hoek": "4.2.1" + "hoek": "4.x.x" } }, "sprintf-js": { @@ -5712,14 +3143,14 @@ "resolved": "http://registry.npm.taobao.org/sshpk/download/sshpk-1.14.1.tgz", "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" } }, "statuses": { @@ -5732,10 +3163,10 @@ "resolved": "http://registry.npm.taobao.org/streamroller/download/streamroller-0.7.0.tgz", "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", "requires": { - "date-format": "1.2.0", - "debug": "3.1.0", - "mkdirp": "0.5.1", - "readable-stream": "2.3.5" + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" }, "dependencies": { "mkdirp": { @@ -5753,9 +3184,9 @@ "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -5763,7 +3194,7 @@ "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.0.3.tgz", "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "stringstream": { @@ -5776,7 +3207,7 @@ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-eof": { @@ -5790,16 +3221,16 @@ "integrity": "sha1-5KEbnQR/fT7+s7vlNtnsACHRZAM=", "dev": true, "requires": { - "component-emitter": "1.2.1", - "cookiejar": "2.1.1", - "debug": "3.1.0", - "extend": "3.0.1", - "form-data": "2.3.2", - "formidable": "1.2.1", - "methods": "1.1.2", - "mime": "1.6.0", - "qs": "6.5.1", - "readable-stream": "2.3.5" + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" }, "dependencies": { "debug": { @@ -5825,8 +3256,8 @@ "integrity": "sha1-jUu2j9GDDuBwM7HFpamkAhyWUpY=", "dev": true, "requires": { - "methods": "1.1.2", - "superagent": "3.8.2" + "methods": "~1.1.2", + "superagent": "^3.0.0" } }, "supervisor": { @@ -5840,8 +3271,8 @@ "resolved": "http://registry.npm.taobao.org/taskgroup/download/taskgroup-4.3.1.tgz", "integrity": "sha1-feGT/r12gnPEV3MElwJNUSwnkVo=", "requires": { - "ambi": "2.5.0", - "csextends": "1.1.1" + "ambi": "^2.2.0", + "csextends": "^1.0.3" } }, "terraformer": { @@ -5849,7 +3280,7 @@ "resolved": "http://registry.npm.taobao.org/terraformer/download/terraformer-1.0.8.tgz", "integrity": "sha1-UeCtiXRvzyFh3G9lqnDkI3fItZM=", "requires": { - "@types/geojson": "1.0.6" + "@types/geojson": "^1.0.0" } }, "terraformer-wkt-parser": { @@ -5857,7 +3288,7 @@ "resolved": "http://registry.npm.taobao.org/terraformer-wkt-parser/download/terraformer-wkt-parser-1.1.2.tgz", "integrity": "sha1-M2oMj8gglKWv+DKI9prt7NNpvww=", "requires": { - "terraformer": "1.0.8" + "terraformer": "~1.0.5" } }, "through": { @@ -5885,7 +3316,7 @@ "resolved": "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.3.4.tgz", "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" }, "dependencies": { "punycode": { @@ -5900,7 +3331,7 @@ "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -5915,7 +3346,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { @@ -5924,7 +3355,7 @@ "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" } }, "typechecker": { @@ -5947,9 +3378,9 @@ "resolved": "http://registry.npm.taobao.org/uglify-js/download/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" }, "dependencies": { "camelcase": { @@ -5962,8 +3393,8 @@ "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, @@ -5987,9 +3418,9 @@ "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } } @@ -6006,7 +3437,7 @@ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", "requires": { - "crypto-random-string": "1.0.0" + "crypto-random-string": "^1.0.0" } }, "universalify": { @@ -6033,16 +3464,16 @@ "resolved": "http://registry.npm.taobao.org/urllib/download/urllib-2.22.0.tgz", "integrity": "sha1-KWXcSuEnpvtpW32yfTGE8X2Cy0I=", "requires": { - "any-promise": "1.3.0", - "content-type": "1.0.4", - "debug": "2.6.9", - "default-user-agent": "1.0.0", - "digest-header": "0.0.1", - "ee-first": "1.1.1", - "humanize-ms": "1.2.1", - "iconv-lite": "0.4.19", - "qs": "6.5.1", - "statuses": "1.4.0" + "any-promise": "^1.3.0", + "content-type": "^1.0.2", + "debug": "^2.6.0", + "default-user-agent": "^1.0.0", + "digest-header": "^0.0.1", + "ee-first": "~1.1.1", + "humanize-ms": "^1.2.0", + "iconv-lite": "^0.4.15", + "qs": "^6.4.0", + "statuses": "^1.3.1" }, "dependencies": { "debug": { @@ -6065,7 +3496,7 @@ "resolved": "http://registry.npm.taobao.org/utility/download/utility-0.1.11.tgz", "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", "requires": { - "address": "1.0.3" + "address": ">=0.0.1" } }, "utils-merge": { @@ -6093,9 +3524,9 @@ "resolved": "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" } }, "void-elements": { @@ -6108,14 +3539,14 @@ "resolved": "http://registry.npm.taobao.org/watchr/download/watchr-2.4.13.tgz", "integrity": "sha1-10hHu01vkPYf4sdPn2hmKqDgdgE=", "requires": { - "eachr": "2.0.4", - "extendr": "2.1.0", - "extract-opts": "2.2.0", - "ignorefs": "1.2.0", - "safefs": "3.2.2", - "scandirectory": "2.5.0", - "taskgroup": "4.3.1", - "typechecker": "2.1.0" + "eachr": "^2.0.2", + "extendr": "^2.1.0", + "extract-opts": "^2.2.0", + "ignorefs": "^1.0.0", + "safefs": "^3.1.2", + "scandirectory": "^2.5.0", + "taskgroup": "^4.2.0", + "typechecker": "^2.0.8" } }, "which": { @@ -6123,7 +3554,7 @@ "resolved": "http://registry.npm.taobao.org/which/download/which-1.3.0.tgz", "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "which-module": { @@ -6136,16 +3567,21 @@ "resolved": "http://registry.npm.taobao.org/win-release/download/win-release-1.1.1.tgz", "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", "requires": { - "semver": "5.5.0" + "semver": "^5.0.1" } }, + "window-size": { + "version": "0.1.4", + "resolved": "http://registry.npm.taobao.org/window-size/download/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, "with": { "version": "5.1.1", "resolved": "http://registry.npm.taobao.org/with/download/with-5.1.1.tgz", "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", "requires": { - "acorn": "3.3.0", - "acorn-globals": "3.1.0" + "acorn": "^3.1.0", + "acorn-globals": "^3.0.0" } }, "wkx": { @@ -6153,7 +3589,7 @@ "resolved": "http://registry.npm.taobao.org/wkx/download/wkx-0.4.4.tgz", "integrity": "sha1-z3UbZy5LReFi+f0wEkh45z2WybI=", "requires": { - "@types/node": "9.4.7" + "@types/node": "*" } }, "wordwrap": { @@ -6167,8 +3603,8 @@ "resolved": "http://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" } }, "wrappy": { @@ -6181,9 +3617,9 @@ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "signal-exit": "3.0.2" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, "x-xss-protection": { @@ -6196,6 +3632,30 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" }, + "xml2js": { + "version": "0.4.4", + "resolved": "http://registry.npm.taobao.org/xml2js/download/xml2js-0.4.4.tgz", + "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=", + "requires": { + "sax": "0.6.x", + "xmlbuilder": ">=1.0.0" + } + }, + "xmlbuilder": { + "version": "2.6.5", + "resolved": "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-2.6.5.tgz", + "integrity": "sha1-b/etYPty0idk8AehZLd/K/FABSY=", + "requires": { + "lodash": "^3.5.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "http://registry.npm.taobao.org/lodash/download/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, "xregexp": { "version": "2.0.0", "resolved": "http://registry.npm.taobao.org/xregexp/download/xregexp-2.0.0.tgz", @@ -6221,18 +3681,18 @@ "resolved": "http://registry.npm.taobao.org/yargs/download/yargs-12.0.1.tgz", "integrity": "sha1-ZDLlYSO7Tnw1YhFUAemDdAYCYcI=", "requires": { - "cliui": "4.1.0", - "decamelize": "2.0.0", - "find-up": "3.0.0", - "get-caller-file": "1.0.3", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "10.1.0" + "cliui": "^4.0.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" }, "dependencies": { "ansi-regex": { @@ -6245,9 +3705,9 @@ "resolved": "http://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz", "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" } }, "decamelize": { @@ -6268,9 +3728,9 @@ "resolved": "http://registry.npm.taobao.org/os-locale/download/os-locale-2.1.0.tgz", "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "string-width": { @@ -6278,8 +3738,8 @@ "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz", "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { @@ -6287,7 +3747,7 @@ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" } }, "xregexp": { @@ -6302,7 +3762,7 @@ "resolved": "http://registry.npm.taobao.org/yargs-parser/download/yargs-parser-10.1.0.tgz", "integrity": "sha1-cgImW4n36eny5XZeD+c1qQXtuqg=", "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" }, "dependencies": { "camelcase": { @@ -6317,7 +3777,7 @@ "resolved": "http://registry.npm.taobao.org/yauzl/download/yauzl-2.4.1.tgz", "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "requires": { - "fd-slicer": "1.0.1" + "fd-slicer": "~1.0.1" } }, "yazl": { @@ -6325,7 +3785,7 @@ "resolved": "http://registry.npm.taobao.org/yazl/download/yazl-2.4.3.tgz", "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", "requires": { - "buffer-crc32": "0.2.13" + "buffer-crc32": "~0.2.3" } } } From 9df3145243b908f33f981d480b351e201b20d1e8 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 9 Sep 2018 00:24:44 +0800 Subject: [PATCH 159/194] fix chosenman --- core/services/client-manager.js | 25 +++++++++++++++++-------- routes/index.js | 11 ++++++----- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 2851ae6a..6542cce4 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -74,8 +74,8 @@ proto.updateCheckFromCache = function(deploymentKey, appVersion, label, packageH .finally(() => client.quit()); } -proto.getChosenManCacheKey = function(deploymentKey, appVersion, clientUniqueId, rollout) { - return [CHOSEN_MAN, deploymentKey, appVersion, clientUniqueId, rollout].join(':'); +proto.getChosenManCacheKey = function(packageId, rollout, clientUniqueId) { + return [CHOSEN_MAN, packageId, rollout, clientUniqueId].join(':'); } proto.random = function(rollout) { @@ -87,7 +87,7 @@ proto.random = function(rollout) { } } -proto.chosenMan = function (rollout, deploymentKey, appVersion, clientUniqueId) { +proto.chosenMan = function (packageId, rollout, clientUniqueId) { var self = this; if (rollout >= 100) { return Promise.resolve(true); @@ -97,7 +97,7 @@ proto.chosenMan = function (rollout, deploymentKey, appVersion, clientUniqueId) return self.random(rollout); } else { var client = factory.getRedisClient("default"); - var redisCacheKey = self.getChosenManCacheKey(deploymentKey, appVersion, clientUniqueId, rollout); + var redisCacheKey = self.getChosenManCacheKey(packageId, rollout, clientUniqueId); return client.getAsync(redisCacheKey) .then((data) => { if (data == 1) { @@ -120,6 +120,7 @@ proto.chosenMan = function (rollout, deploymentKey, appVersion, clientUniqueId) proto.updateCheck = function(deploymentKey, appVersion, label, packageHash, clientUniqueId) { var rs = { + packageId: 0, downloadURL: "", downloadUrl: "", description: "", @@ -176,6 +177,7 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash, clie if (packages && _.eq(packages.deployment_id, deploymentsVersions.deployment_id) && !_.eq(packages.package_hash, packageHash)) { + rs.packageId = packageId; rs.downloadUrl = rs.downloadURL = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); rs.description = _.get(packages, 'description', ''); rs.isAvailable = _.eq(packages.is_disabled, 1) ? false : true; @@ -248,14 +250,21 @@ proto.reportStatusDeploy = function (deploymentKey, label, clientUniqueId, other var constConfig = require('../const'); var status = _.get(others, "status"); var packageId = packages.id; + var previous_deployment_key = _.get(others, 'previousDeploymentKey'); + var previous_label = _.get(others, 'previousLabelOrAppVersion'); if (_.eq(status, "DeploymentSucceeded")) { return Promise.all([ models.LogReportDeploy.create({ package_id: packageId, client_unique_id: clientUniqueId, - previous_label: _.get(others, 'previousLabelOrAppVersion'), - previous_deployment_key: _.get(others, 'previousDeploymentKey'), + previous_label: previous_label, + previous_deployment_key: previous_deployment_key, status: constConfig.DEPLOYMENT_SUCCEEDED + }) + .then(() => { + if (previous_deployment_key && previous_label) { + + } }), models.PackagesMetrics.addOneOnInstalledById(packageId), models.PackagesMetrics.addOneOnActiveById(packageId), @@ -265,8 +274,8 @@ proto.reportStatusDeploy = function (deploymentKey, label, clientUniqueId, other models.LogReportDeploy.create({ package_id: packageId, client_unique_id: clientUniqueId, - previous_label: _.get(others, 'previousLabelOrAppVersion'), - previous_deployment_key: _.get(others, 'previousDeploymentKey'), + previous_label: previous_label, + previous_deployment_key: previous_deployment_key, status: constConfig.DEPLOYMENT_FAILED }), models.PackagesMetrics.addOneOnInstalledById(packageId), diff --git a/routes/index.js b/routes/index.js index a42f2d5c..d070b551 100644 --- a/routes/index.js +++ b/routes/index.js @@ -47,16 +47,17 @@ router.get('/updateCheck', (req, res, next) => { clientManager.updateCheckFromCache(deploymentKey, appVersion, label, packageHash, clientUniqueId) .then((rs) => { //灰度检测 - return clientManager.chosenMan(rs.rollout, deploymentKey, appVersion, clientUniqueId) + return clientManager.chosenMan(rs.packageId, rs.rollout, clientUniqueId) .then((data)=>{ - if (!data) { - rs.isAvailable = false; - return rs; - } + if (!data) { + rs.isAvailable = false; return rs; + } + return rs; }); }) .then((rs) => { + delete rs.packageId; delete rs.rollout; res.send({"updateInfo":rs}); }) From ddef23d3f662def9287637a62ca3d65cc24361bc Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 9 Sep 2018 01:22:37 +0800 Subject: [PATCH 160/194] fix state bug --- core/services/client-manager.js | 78 ++++++++++++++++++++++----------- models/packages_metrics.js | 38 ---------------- 2 files changed, 53 insertions(+), 63 deletions(-) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 6542cce4..54880869 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -235,7 +235,13 @@ proto.reportStatusDownload = function(deploymentKey, label, clientUniqueId) { return this.getPackagesInfo(deploymentKey, label) .then((packages) => { return Promise.all([ - models.PackagesMetrics.addOneOnDownloadById(packages.id), + models.PackagesMetrics.findOne({where: {package_id: packages.id}}) + .then((metrics)=>{ + if (metrics) { + return metrics.increment('downloaded'); + } + return; + }), models.LogReportDownload.create({ package_id: packages.id, client_unique_id: clientUniqueId @@ -248,40 +254,62 @@ proto.reportStatusDeploy = function (deploymentKey, label, clientUniqueId, other return this.getPackagesInfo(deploymentKey, label) .then((packages) => { var constConfig = require('../const'); - var status = _.get(others, "status"); + var statusText = _.get(others, "status"); + var status = 0; + if (_.eq(statusText, "DeploymentSucceeded")) { + status = constConfig.DEPLOYMENT_SUCCEEDED; + } else if (_.eq(statusText, "DeploymentFailed")) { + status = constConfig.DEPLOYMENT_FAILED; + } var packageId = packages.id; var previous_deployment_key = _.get(others, 'previousDeploymentKey'); var previous_label = _.get(others, 'previousLabelOrAppVersion'); - if (_.eq(status, "DeploymentSucceeded")) { - return Promise.all([ - models.LogReportDeploy.create({ - package_id: packageId, - client_unique_id: clientUniqueId, - previous_label: previous_label, - previous_deployment_key: previous_deployment_key, - status: constConfig.DEPLOYMENT_SUCCEEDED - }) - .then(() => { - if (previous_deployment_key && previous_label) { - - } - }), - models.PackagesMetrics.addOneOnInstalledById(packageId), - models.PackagesMetrics.addOneOnActiveById(packageId), - ]); - } else if (_.eq(status, "DeploymentFailed")) { + if (status > 0) { return Promise.all([ models.LogReportDeploy.create({ package_id: packageId, client_unique_id: clientUniqueId, previous_label: previous_label, previous_deployment_key: previous_deployment_key, - status: constConfig.DEPLOYMENT_FAILED + status: status }), - models.PackagesMetrics.addOneOnInstalledById(packageId), - models.PackagesMetrics.addOneOnFailedById(packageId), - ]); - }else { + models.PackagesMetrics.findOne({where: {package_id: packageId}}) + .then((metrics)=>{ + if (_.isEmpty(metrics)) { + return; + } + if (constConfig.DEPLOYMENT_SUCCEEDED) { + return metrics.increment(['installed', 'active'],{by: 1}); + } else { + return metrics.increment(['installed', 'failed'],{by: 1}); + } + }) + ]) + .then(()=>{ + if (previous_deployment_key && previous_label) { + return models.Deployments.findOne({where: {deployment_key: previous_deployment_key}}) + .then((dep)=>{ + if (_.isEmpty(dep)) { + return; + } + return models.Packages.findOne({where: {deployment_id: dep.id, label: previous_label}}) + .then((p)=>{ + if (_.isEmpty(p)) { + return; + } + return models.PackagesMetrics.findOne({where:{package_id: p.id}}); + }); + }) + .then((metrics)=>{ + if (metrics) { + return metrics.decrement('active'); + } + return; + }); + } + return; + }); + } else { return; } }); diff --git a/models/packages_metrics.js b/models/packages_metrics.js index 3ee99887..d95bce92 100644 --- a/models/packages_metrics.js +++ b/models/packages_metrics.js @@ -22,43 +22,5 @@ module.exports = function(sequelize, DataTypes) { underscored: true, paranoid: true }); - - PackagesMetrics.addOne = function (packageId, fieldName) { - var self = this; - var sql = 'UPDATE packages_metrics SET `' + fieldName + '`=`' + fieldName + '` + 1 WHERE package_id = :package_id'; - return sequelize.query(sql, { replacements: { package_id: packageId}}) - .spread(function(results, metadata) { - if (_.eq(results.affectedRows, 0)) { - var params = { - package_id: packageId, - active: 0, - downloaded: 0, - failed: 0, - installed: 0, - }; - params[fieldName] = 1; - return self.create(params); - }else { - return true; - } - }); - }; - - PackagesMetrics.addOneOnDownloadById = function (packageId) { - return this.addOne(packageId, 'downloaded'); - }; - - PackagesMetrics.addOneOnFailedById = function (packageId) { - return this.addOne(packageId, 'failed'); - }; - - PackagesMetrics.addOneOnInstalledById = function (packageId) { - return this.addOne(packageId, 'installed'); - }; - - PackagesMetrics.addOneOnActiveById = function (packageId) { - return this.addOne(packageId, 'active'); - }; - return PackagesMetrics; }; From 6e5454971eb2357532dc1a85e6f98cdd956d7872 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 9 Sep 2018 01:26:35 +0800 Subject: [PATCH 161/194] docker --- docker/code-push-server/Dockerfile | 2 +- docker/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/code-push-server/Dockerfile b/docker/code-push-server/Dockerfile index 48247992..690f74a5 100644 --- a/docker/code-push-server/Dockerfile +++ b/docker/code-push-server/Dockerfile @@ -1,7 +1,7 @@ FROM node:8.11.4-alpine RUN npm config set registry https://registry.npm.taobao.org/ \ -&& npm i -g code-push-server@0.5.0 pm2@latest --no-optional +&& npm i -g code-push-server@0.5.1 pm2@latest --no-optional COPY ./process.json /process.json diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index d0cef819..732a4100 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: server: - image: tablee/code-push-server:v0.5.0 + image: tablee/code-push-server:v0.5.1 volumes: - data-storage:/data/storage - data-tmp:/data/tmp From 33130ab3c27aa23f26cf34360756fd50b86c37b0 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 9 Sep 2018 01:26:49 +0800 Subject: [PATCH 162/194] 0.5.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index de921ab4..cf9e57ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.5.0", + "version": "0.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5f28e9a8..578ec0b5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.5.0", + "version": "0.5.1", "license": "MIT", "repository": { "type": "git", From cc6320ee671d93ecf6a4ac91560552d3a3a784b3 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 9 Sep 2018 22:12:44 +0800 Subject: [PATCH 163/194] changelog --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1975b1f7..c6903211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog for code-push-server -## 0.4.7 + +## 0.5.x + +## 新特性 +- 针对文本增量更新进行优化,使用google `diff-match-patch` 算法计算差异 + - react-native-code-push Android客户端适配,需要合并https://github.com/Microsoft/react-native-code-push/pull/1393, 才能正常使用文本增量更新功能。 + - react-native-code-push iOS客户端适配 (需要合并https://github.com/Microsoft/react-native-code-push/pull/1399) + - react-native-code-push Windows客户端适配 (进行中) + +## fixbug + +- 修复统计数据激活数 +- 修复灰度发布bug +- rollback后增加计算和最后一次增量更新版本 + +## 如何升级到该版本 + +### 升级数据库 + +`$ npm run upgrade` + +or + +`$ code-push-server-db upgrade` + + +## 0.4.x ### 新特性 @@ -29,7 +55,7 @@ or $ node ./bin/fixMinMaxVersion //出现提示 success ``` -## 0.3.0 +## 0.3.x - 支持灰度发布 - 适配`code-push app add` 命令,应用不再以名字区分平台,而是以类型区分平台 From ad4d3c93c4e1e5ba1287acac1666596a35983c49 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 9 Sep 2018 23:04:53 +0800 Subject: [PATCH 164/194] readme --- README.md | 9 +++++++++ docker/README.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef314629..092054cf 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,15 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use [local/s3/oss/tencentcloud] storage, just modify config.js file, it's simple configure. + +## Advance Feature + +> use google diff-match-patch calculate text file + +- support iOS and Android +- use `"react-native-code-push": "git+https://git@github.com/lisong/react-native-code-push.git"` instead `"react-native-code-push": "x.x.x"` +- change `apps`.`is_use_diff_text` to `1` in mysql codepush database + ## Support Storage mode - local *storage bundle file in local machine* diff --git a/docker/README.md b/docker/README.md index 236aca12..2c06493e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -8,7 +8,7 @@ - docker-compose.yml只提供了应用的一部分参数设置,如需要设置其他配置,可以修改文件config.js。 - mysql部分 - 数据使用docker volume存储方式,容器销毁不会导致数据丢失,除非人为删除volume。 - - 默认应用使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用,只需要给予`select,update,insert`权限即可 + - 应用请勿使用root用户,为了安全可以创建权限相对较小的权限供code-push-server使用,只需要给予`select,update,insert`权限即可。初始化数据库需要使用root或有建表权限用户 - redis部分 - `tryLoginTimes` 登录错误次数限制 - `updateCheckCache` 提升应用性能 From 6e97380e98ab4d147214aa6fbd9cdf8fbdb15d84 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 9 Sep 2018 23:06:01 +0800 Subject: [PATCH 165/194] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 092054cf..ff7e93dc 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in ## Advance Feature -> use google diff-match-patch calculate text file +> use google diff-match-patch calculate text file diff patch - support iOS and Android - use `"react-native-code-push": "git+https://git@github.com/lisong/react-native-code-push.git"` instead `"react-native-code-push": "x.x.x"` From 1c11cd947d2886d67f5f79960ed80f59cc203446 Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 9 Sep 2018 23:08:55 +0800 Subject: [PATCH 166/194] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff7e93dc..5ed029b7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in > use google diff-match-patch calculate text file diff patch - support iOS and Android -- use `"react-native-code-push": "git+https://git@github.com/lisong/react-native-code-push.git"` instead `"react-native-code-push": "x.x.x"` +- use `"react-native-code-push": "git+https://git@github.com/lisong/react-native-code-push.git"` instead `"react-native-code-push": "x.x.x"` in `package.json` - change `apps`.`is_use_diff_text` to `1` in mysql codepush database ## Support Storage mode From 4fc1f8ee247ffd528ccf1720cdd04eaaad926a02 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 16 Sep 2018 19:44:01 +0800 Subject: [PATCH 167/194] add modify password --- core/middleware.js | 4 +-- package.json | 1 + routes/auth.js | 4 +++ views/auth/password.pug | 57 +++++++++++++++++++++++++++++++++++++++++ views/index.pug | 3 ++- views/layout.pug | 2 ++ 6 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 views/auth/password.pug diff --git a/core/middleware.js b/core/middleware.js index 2ac9a232..98c7b4f3 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -85,7 +85,7 @@ middleware.checkToken = function(req, res, next) { authType = 2; authToken = _.trim(_.trimStart(_.get(req, 'query.access_token', null))); } - if (authType == 1) { + if (authToken && authType == 1) { checkAuthToken(authToken) .then((users) => { req.users = users; @@ -99,7 +99,7 @@ middleware.checkToken = function(req, res, next) { next(e); } }); - } else if (authType == 2) { + } else if (authToken && authType == 2) { checkAccessToken(authToken) .then((users) => { req.users = users; diff --git a/package.json b/package.json index 578ec0b5..ea63f74c 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "config", "core", "docs", + "docker", "models", "public", "routes", diff --git a/routes/auth.js b/routes/auth.js index 2db402e9..7bdd96c2 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -6,6 +6,10 @@ var validator = require('validator'); var log4js = require('log4js'); var log = log4js.getLogger("cps:auth"); +router.get('/password', (req, res) => { + res.render('auth/password', { title: 'CodePushServer' }); +}); + router.get('/login', (req, res) => { var codePushWebUrl = _.get(config, 'common.codePushWebUrl'); if (codePushWebUrl && validator.isURL(codePushWebUrl)) { diff --git a/views/auth/password.pug b/views/auth/password.pug new file mode 100644 index 00000000..47fa302c --- /dev/null +++ b/views/auth/password.pug @@ -0,0 +1,57 @@ +extends ../layout + +block content + .container(style="margin-top:30px;") + form#form.col-md-5.col-md-offset-3(method="post") + .form-group + label.sr-only(for="inputEmail") 邮箱地址/用户名 + input#inputEmail.form-control(type="text" name="account" placeholder="邮箱地址/用户名" required autofocus) + .form-group + .col-md-10(style="margin-left:-15px;") + label.sr-only(for="inputToken") token + input#inputToken.form-control(type="text" name="token" placeholder="token" required) + .col-md-2 + a.form-control.btn.btn-link(style="margin-bottom:15px;" target="_blank" href="/auth/login") 获取token + .form-group + label.sr-only(for="inputPassword") 原密码 + input#inputPassword.form-control(type="password" name="oldPassword" placeholder="原密码" required) + .form-group + label.sr-only(for="inputNewPassword") 新密码 + input#inputNewPassword.form-control(type="password" name="newPassword" placeholder="新密码" required) + .form-group + a#submitBtn.btn.btn-lg.btn-primary.btn-block 修改密码 + +block js + script(). + var submit = false; + $('#submitBtn').on('click', function () { + if (submit) { + return ; + } + var token = $('#inputToken').val(); + var oldPassword = $('#inputPassword').val(); + var newPassword = $('#inputNewPassword').val(); + submit = true; + $.ajax({ + type: 'patch', + data: JSON.stringify({oldPassword:oldPassword,newPassword:newPassword}), + contentType: 'application/json;charset=utf-8', + headers: { + Authorization : 'Bearer '+token + }, + url: '/users/password', + dataType: 'json', + success: function (data) { + if (data.status == "OK") { + alert("修改成功"); + location.href = '/auth/login'; + } else if (data.status == 401) { + alert('token invalid'); + } else { + alert(data.message); + } + submit = false; + } + }); + }); + diff --git a/views/index.pug b/views/index.pug index c97cb43a..800da9bd 100644 --- a/views/index.pug +++ b/views/index.pug @@ -7,4 +7,5 @@ block content h1(style="text-align: center;")= title p(style="text-align: center;") Welcome to #{title} .site-notice - a.btn.btn-primary(href="/auth/login" type="button") 登录 \ No newline at end of file + a.btn.btn-primary(href="/auth/login" type="button") 登录 + a.btn.btn-primary.col-md-offset-1(href="/auth/password" type="button") 修改密码 \ No newline at end of file diff --git a/views/layout.pug b/views/layout.pug index a0ba1682..85d88861 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -2,6 +2,8 @@ doctype html html head title= title + meta(name="keywords" content="code-push-server,code-push,react-native,cordova") + meta(name="description" content="CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push") link(rel='stylesheet', href='/js/bootstrap-3.3.7/css/bootstrap.min.css') block css body From 53b24da1ebca0ee646f8c7aad5d6c5d256db89b4 Mon Sep 17 00:00:00 2001 From: tablee Date: Sun, 16 Sep 2018 19:53:01 +0800 Subject: [PATCH 168/194] 0.5.2 --- docker/code-push-server/Dockerfile | 2 +- docker/docker-compose.yml | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/code-push-server/Dockerfile b/docker/code-push-server/Dockerfile index 690f74a5..004406ba 100644 --- a/docker/code-push-server/Dockerfile +++ b/docker/code-push-server/Dockerfile @@ -1,7 +1,7 @@ FROM node:8.11.4-alpine RUN npm config set registry https://registry.npm.taobao.org/ \ -&& npm i -g code-push-server@0.5.1 pm2@latest --no-optional +&& npm i -g code-push-server@0.5.2 pm2@latest --no-optional COPY ./process.json /process.json diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 732a4100..2b625f8f 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: server: - image: tablee/code-push-server:v0.5.1 + image: tablee/code-push-server:v0.5.2 volumes: - data-storage:/data/storage - data-tmp:/data/tmp diff --git a/package.json b/package.json index ea63f74c..b49de407 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.5.1", + "version": "0.5.2", "license": "MIT", "repository": { "type": "git", From f6bb4d766445e24a3d94966372b0faea54342042 Mon Sep 17 00:00:00 2001 From: tablee Date: Mon, 17 Sep 2018 22:10:16 +0800 Subject: [PATCH 169/194] test --- test/api/users/users.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/api/users/users.test.js b/test/api/users/users.test.js index abced1b2..f14e4249 100644 --- a/test/api/users/users.test.js +++ b/test/api/users/users.test.js @@ -176,6 +176,7 @@ describe('api/users/users.test.js', function() { it('should not change password successful when authToken invalid', function(done) { request.patch(`/users/password`) + .set('Authorization', `Basic 11345`) .send({oldPassword: password, newPassword: newPassword}) .end(function(err, res) { should.not.exist(err); From 303f5b7e34210f55038272ff9eb0f3ce24e3fdce Mon Sep 17 00:00:00 2001 From: taichiyi Date: Wed, 19 Sep 2018 13:32:09 +0800 Subject: [PATCH 170/194] fix andriod -> android (#158) --- docs/README.md | 2 +- docs/react-native-code-push.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 10d25ae1..195ae988 100644 --- a/docs/README.md +++ b/docs/README.md @@ -181,7 +181,7 @@ $ curl -X PATCH -H "Authorization: Bearer mytoken" -H "Accept: application/json" ## config react-native project -> Follow the react-native-code-push docs, addition iOS add a new entry named CodePushServerURL, whose value is the key of ourself CodePushServer URL. Andriod use the new CodePush constructor in MainApplication point CodePushServerUrl +> Follow the react-native-code-push docs, addition iOS add a new entry named CodePushServerURL, whose value is the key of ourself CodePushServer URL. Android use the new CodePush constructor in MainApplication point CodePushServerUrl iOS eg. in file Info.plist diff --git a/docs/react-native-code-push.md b/docs/react-native-code-push.md index feab43f1..0b70bf37 100644 --- a/docs/react-native-code-push.md +++ b/docs/react-native-code-push.md @@ -52,7 +52,7 @@ $ react-native link react-native-code-push #连接到项目中,提示输入 ```shell $ code-push login http://YOUR_CODE_PUSH_SERVER_IP:3000 #浏览器中登录获取token,用户名:admin, 密码:123456 $ code-push app add CodePushDemoiOS ios react-native #创建iOS版, 获取Production DeploymentKey -$ code-push app add CodePushDemoAndroid andriod react-native #创建android版,获取获取Production DeploymentKey +$ code-push app add CodePushDemoAndroid android react-native #创建android版,获取获取Production DeploymentKey ``` ## 配置CodePushDemo react-native项目 From 91dbc19fa63b3ca33fe331f141cefa760eeacb24 Mon Sep 17 00:00:00 2001 From: tablee Date: Wed, 19 Sep 2018 21:27:15 +0800 Subject: [PATCH 171/194] fix test --- test/api/init/database.js | 5 +++-- test/api/users/users.test.js | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/api/init/database.js b/test/api/init/database.js index 83232b59..a32c0aea 100644 --- a/test/api/init/database.js +++ b/test/api/init/database.js @@ -12,10 +12,11 @@ describe('api/init/database.js', function() { var connection = mysql.createConnection({ host: config.db.host, user: config.db.username, - password: config.db.password + password: config.db.password, + multipleStatements: true }); connection.connect(); - connection.query(`CREATE DATABASE IF NOT EXISTS ${config.db.database}`, function(err, rows, fields) { + connection.query(`DROP DATABASE IF EXISTS ${config.db.database};CREATE DATABASE IF NOT EXISTS ${config.db.database}`, function(err, rows, fields) { should.not.exist(err); done(); }); diff --git a/test/api/users/users.test.js b/test/api/users/users.test.js index f14e4249..2b936dbf 100644 --- a/test/api/users/users.test.js +++ b/test/api/users/users.test.js @@ -180,7 +180,9 @@ describe('api/users/users.test.js', function() { .send({oldPassword: password, newPassword: newPassword}) .end(function(err, res) { should.not.exist(err); - res.status.should.equal(401); + var rs = JSON.parse(res.text); + res.status.should.equal(200); + rs.should.containEql({status:401}); done(); }); }); From 39a31a208b727554f75ca6d6355e15a00b0a492c Mon Sep 17 00:00:00 2001 From: lisong Date: Thu, 20 Sep 2018 14:59:57 +0800 Subject: [PATCH 172/194] Update tokens.pug --- views/tokens.pug | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/views/tokens.pug b/views/tokens.pug index 81829751..ad770b56 100644 --- a/views/tokens.pug +++ b/views/tokens.pug @@ -53,7 +53,10 @@ block js $.ajax({ type: 'post', data: postParams, - url: '/accessKeys?access_token='+access_token, + headers: { + Authorization : 'Bearer '+access_token + }, + url: '/accessKeys', dataType: 'json', success: function (data) { submit = false; From dcce15f1067dd994073decda02b3f44960366e9d Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 20 Sep 2018 22:15:25 +0800 Subject: [PATCH 173/194] remove query.access_token --- core/middleware.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/middleware.js b/core/middleware.js index 98c7b4f3..fc4054f2 100644 --- a/core/middleware.js +++ b/core/middleware.js @@ -74,16 +74,17 @@ middleware.checkToken = function(req, res, next) { var authType = 1; var authToken = null; if (_.eq(authArr[0], 'Bearer')) { - authType = 1; authToken = authArr[1]; //Bearer + if (authToken && authToken.length > 64) { + authType = 2; + } else { + authType = 1; + } } else if(_.eq(authArr[0], 'Basic')) { authType = 2; var b = new Buffer(authArr[1], 'base64'); var user = _.split(b.toString(), ':'); authToken = _.get(user, '1'); - } else { - authType = 2; - authToken = _.trim(_.trimStart(_.get(req, 'query.access_token', null))); } if (authToken && authType == 1) { checkAuthToken(authToken) From 19ed355006a812dd9fe7776e54e7185963c1c2ec Mon Sep 17 00:00:00 2001 From: lisong Date: Sun, 23 Sep 2018 09:48:34 +0800 Subject: [PATCH 174/194] Update config.js --- config/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.js b/config/config.js index 551cb643..07c2deec 100644 --- a/config/config.js +++ b/config/config.js @@ -53,7 +53,7 @@ config.development = { // Binary files download host address which Code Push Server listen to. the files storage in storageDir. downloadUrl: process.env.LOCAL_DOWNLOAD_URL || "http://127.0.0.1:3000/download", // public static download spacename. - public: process.env.PUBLIC || '/download' + public: '/download' }, jwt: { // Recommended: 63 random alpha-numeric characters From f568e66b0087f3c1a70937fdc0aa33d35f72d5fc Mon Sep 17 00:00:00 2001 From: tablee Date: Fri, 19 Oct 2018 21:20:10 +0800 Subject: [PATCH 175/194] add notice --- docs/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/README.md b/docs/README.md index 195ae988..dc455f8c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,6 +18,9 @@ $ sudo npm i -g pm2 - [Microsoft Windows](https://dev.mysql.com/doc/refman/8.0/en/windows-installation.html) - [Others](https://dev.mysql.com/doc/refman/8.0/en/installing.html) +> notice. mysql8.x default auth caching_sha2_pasword not support in node-mysql2 see [issue](https://github.com/mysqljs/mysql/pull/1962) + + ## GET code-push-server FROM NPM From 7e1dc99210144a5c9e92e8f9baa57a68adb77015 Mon Sep 17 00:00:00 2001 From: tablee Date: Tue, 23 Oct 2018 21:44:54 +0800 Subject: [PATCH 176/194] add account --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5ed029b7..59fefeb0 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,11 @@ $ code-push login http://api.code-push.com #登录 - [docker](https://github.com/lisong/code-push-server/blob/master/docker/README.md) (recommend) - [manual operation](https://github.com/lisong/code-push-server/blob/master/docs/README.md) +## DEFAULT ACCOUNT AND PASSWORD + +- account: `admin` +- password: `123456` + ## HOW TO USE - [normal](https://github.com/lisong/code-push-server/blob/master/docs/react-native-code-push.md) From bab6c663833d4248b87c65d21a12457d2fe0c3ba Mon Sep 17 00:00:00 2001 From: lisong Date: Thu, 22 Nov 2018 15:16:16 +0800 Subject: [PATCH 177/194] Update README.md --- README.md | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 59fefeb0..d5f8914f 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,6 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in China, we can use this to build our's. I use [qiniu](http://www.qiniu.com/) to store the files, because it's simple and quick! Or you can use [local/s3/oss/tencentcloud] storage, just modify config.js file, it's simple configure. -## Advance Feature - -> use google diff-match-patch calculate text file diff patch - -- support iOS and Android -- use `"react-native-code-push": "git+https://git@github.com/lisong/react-native-code-push.git"` instead `"react-native-code-push": "x.x.x"` in `package.json` -- change `apps`.`is_use_diff_text` to `1` in mysql codepush database - ## Support Storage mode - local *storage bundle file in local machine* @@ -85,6 +77,26 @@ $ code-push login http://api.code-push.com #登录 [modify password](https://github.com/lisong/code-push-server/issues/43) + +# UPDATE TIME LINE + +- targetBinaryVersion support + - `*` + - `1.2.3` + - `1.2`/`1.2.*` + - `>=1.2.3<1.3.7` + - `~1.2.3` + - `^1.2.3` + + +## Advance Feature + +> use google diff-match-patch calculate text file diff patch + +- support iOS and Android +- use `"react-native-code-push": "git+https://git@github.com/lisong/react-native-code-push.git"` instead `"react-native-code-push": "x.x.x"` in `package.json` +- change `apps`.`is_use_diff_text` to `1` in mysql codepush database + ## License MIT License [read](https://github.com/lisong/code-push-server/blob/master/LICENSE) From 501962487700c8902095897ad2748dc6bb6dca39 Mon Sep 17 00:00:00 2001 From: lisong Date: Mon, 3 Dec 2018 11:30:36 +0800 Subject: [PATCH 178/194] Update README.md --- docker/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/README.md b/docker/README.md index 2c06493e..d1fb6da1 100644 --- a/docker/README.md +++ b/docker/README.md @@ -45,11 +45,11 @@ $ cd code-push-server/docker $ vim docker-compose.yml ``` -*将`DOWNLOAD_URL`中`YOU_MACHINE_IP`替换成本机ip* +*将`DOWNLOAD_URL`中`YOU_MACHINE_IP`替换成本机外网ip或者域名* -*将`MYSQL_HOST`中`YOU_MACHINE_IP`替换成本机ip* +*将`MYSQL_HOST`中`YOU_MACHINE_IP`替换成本机内网ip* -*将`REDIS_HOST`中`YOU_MACHINE_IP`替换成本机ip* +*将`REDIS_HOST`中`YOU_MACHINE_IP`替换成本机内网ip* ## jwt.tokenSecret修改 From aa647a509c5c7e1162c121ec9b597728e841a8cb Mon Sep 17 00:00:00 2001 From: lisong Date: Wed, 12 Dec 2018 16:24:07 +0800 Subject: [PATCH 179/194] Update package-manager.js fix isDisabled error --- core/services/package-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/services/package-manager.js b/core/services/package-manager.js index 1b9b8b0c..fe259c7c 100644 --- a/core/services/package-manager.js +++ b/core/services/package-manager.js @@ -583,9 +583,9 @@ proto.promotePackage = function (sourceDeploymentInfo, destDeploymentInfo, param create_params.isMandatory = sourcePack.is_mandatory } if (_.isBoolean(params.isDisabled)) { - create_params.isMandatory = params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; + create_params.isDisabled = params.isDisabled ? constConfig.IS_DISABLED_YES : constConfig.IS_DISABLED_NO; } else { - create_params.isMandatory = sourcePack.is_disabled + create_params.isDisabled = sourcePack.is_disabled } return self.createPackage( destDeploymentInfo.id, From f364988e84d7a27be01b133a96792c45e0938829 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 13 Dec 2018 20:27:50 +0800 Subject: [PATCH 180/194] 0.5.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cf9e57ee..550ccad8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.5.1", + "version": "0.5.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b49de407..fafcc600 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.5.2", + "version": "0.5.3", "license": "MIT", "repository": { "type": "git", From 42f8e7672db9d8a1f84133c961c2373b03fbfb60 Mon Sep 17 00:00:00 2001 From: tablee Date: Thu, 13 Dec 2018 20:28:11 +0800 Subject: [PATCH 181/194] 0.5.4 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 550ccad8..ef06fecf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "code-push-server", - "version": "0.5.3", + "version": "0.5.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fafcc600..6e60a383 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-push-server", "description": "CodePush service is hotupdate services which adapter react-native-code-push and cordova-plugin-code-push", - "version": "0.5.3", + "version": "0.5.4", "license": "MIT", "repository": { "type": "git", From 2e90e36f94b1303492d011e4975f76bb617f1116 Mon Sep 17 00:00:00 2001 From: lisong Date: Mon, 21 Jan 2019 16:11:55 +0800 Subject: [PATCH 182/194] =?UTF-8?q?=E8=AE=BE=E7=BD=AEAccess-Control-Allow-?= =?UTF-8?q?Headers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index cfc415a3..7c7d20cf 100644 --- a/app.js +++ b/app.js @@ -32,16 +32,16 @@ app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); //use nginx in production -if (app.get('env') === 'development') { +//if (app.get('env') === 'development') { log.debug("set Access-Control Header"); app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); + res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CodePush-Plugin-Version, X-CodePush-Plugin-Name, X-CodePush-SDK-Version"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,PATCH,DELETE,OPTIONS"); log.debug("use set Access-Control Header"); next(); }); -} +//} log.debug("config common.storageType value: " + _.get(config, 'common.storageType')); From 6e6dcd5dba23ba3d1a45d52e68fb538c17a045a3 Mon Sep 17 00:00:00 2001 From: Roc Date: Fri, 15 Mar 2019 16:05:11 +0800 Subject: [PATCH 183/194] ignore .codepushrelease and other system generated files in calculating folder hash (#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 谢谢! --- core/utils/security.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/utils/security.js b/core/utils/security.js index 4bbc7095..7cb15791 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -146,6 +146,25 @@ security.uploadPackageType = function (directoryPath) { }); } +// some files are ignored in calc hash in client sdk +// https://github.com/Microsoft/react-native-code-push/pull/974/files#diff-21b650f88429c071b217d46243875987R15 +security.isHashIgnored = function (relativePath) { + if (!relativePath) { + return true; + } + + + const IgnoreMacOSX = '__MACOSX/'; + const IgnoreDSStore = '.DS_Store'; + const IgnoreCodePushMetadata = '.codepushrelease'; + + return relativePath.startsWith(IgnoreMacOSX) + || relativePath === IgnoreDSStore + || relativePath.endsWith(IgnoreDSStore) + || relativePath === IgnoreCodePushMetadata + || relativePath.endsWith(IgnoreCodePushMetadata); +} + security.calcAllFileSha256 = function (directoryPath) { return new Promise((resolve, reject) => { var recursive = require("recursive-readdir"); @@ -156,6 +175,12 @@ security.calcAllFileSha256 = function (directoryPath) { log.error(error); reject(new AppError.AppError(error.message)); } else { + // filter files that should be ignored + files = files.filter((file) => { + var relative = path.relative(directoryPath, file); + return !security.isHashIgnored(relative); + }); + if (files.length == 0) { log.debug(`calcAllFileSha256 empty files in directoryPath:`, directoryPath); reject(new AppError.AppError("empty files")); From 3489c47bfc3a2ca87750aa22c6c39684742e587c Mon Sep 17 00:00:00 2001 From: Roc Date: Thu, 28 Mar 2019 20:36:19 +0800 Subject: [PATCH 184/194] fix code signing issue with diff package - keep .codepushrelease in manifest json but ignores it in package hash as it needs to be included in diff package (#184) --- core/utils/security.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/core/utils/security.js b/core/utils/security.js index 7cb15791..b6bab402 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -61,7 +61,9 @@ security.stringSha256Sync = function (contents) { security.packageHashSync = function (jsonData) { var sortedArr = security.sortJsonToArr(jsonData); - var manifestData = _.map(sortedArr, (v) => { + var manifestData = _.filter(sortedArr, (v) => { + return !security.isPackageHashIgnored(v.path); + }).map((v) => { return v.path + ':' + v.hash; }); log.debug('packageHashSync manifestData:', manifestData); @@ -153,18 +155,28 @@ security.isHashIgnored = function (relativePath) { return true; } - const IgnoreMacOSX = '__MACOSX/'; const IgnoreDSStore = '.DS_Store'; - const IgnoreCodePushMetadata = '.codepushrelease'; return relativePath.startsWith(IgnoreMacOSX) || relativePath === IgnoreDSStore - || relativePath.endsWith(IgnoreDSStore) - || relativePath === IgnoreCodePushMetadata - || relativePath.endsWith(IgnoreCodePushMetadata); + || relativePath.endsWith(IgnoreDSStore); +} + +security.isPackageHashIgnored = function (relativePath) { + if (!relativePath) { + return true; + } + + // .codepushrelease contains code sign JWT + // it should be ignored in package hash but need to be included in package manifest + const IgnoreCodePushMetadata = '.codepushrelease'; + return relativePath === IgnoreCodePushMetadata + || relativePath.endsWith(IgnoreCodePushMetadata) + || security.isHashIgnored(relativePath); } + security.calcAllFileSha256 = function (directoryPath) { return new Promise((resolve, reject) => { var recursive = require("recursive-readdir"); From 991599cc953894570a8816f22890be109b1e803e Mon Sep 17 00:00:00 2001 From: Roc Date: Fri, 5 Apr 2019 20:33:58 +0800 Subject: [PATCH 185/194] allows spaces in targetBinaryVersion format and (#183) --- README.md | 3 ++- core/utils/common.js | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d5f8914f..5d72439a 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,8 @@ $ code-push login http://api.code-push.com #登录 - `*` - `1.2.3` - `1.2`/`1.2.*` - - `>=1.2.3<1.3.7` + - `1.2.3 - 1.2.7` + - `>=1.2.3 <1.2.7` - `~1.2.3` - `^1.2.3` diff --git a/core/utils/common.js b/core/utils/common.js index 0a4acd9c..e7f7db08 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -69,13 +69,13 @@ common.validatorVersion = function (versionNo) { flag = true; min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); max = _.toString((parseInt(data[1])+1)) + _.padStart(0, 5, '0') + _.padStart('0', 10, '0'); - } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})-([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { - // "1.2.3-1.2.7" + } else if (data = versionNo.match(/^([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})\s?-\s?([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + // "1.2.3 - 1.2.7" flag = true; min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); max = data[4] + _.padStart(data[5], 5, '0') + _.padStart((parseInt(data[6])+1), 10, '0'); - } else if (data = versionNo.match(/^>=([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})<([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { - //">=1.2.3<1.2.7" + } else if (data = versionNo.match(/^>=([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})\s?<([0-9]{1,3}).([0-9]{1,5}).([0-9]{1,10})$/)) { + // ">=1.2.3 <1.2.7" flag = true; min = data[1] + _.padStart(data[2], 5, '0') + _.padStart(data[3], 10, '0'); max = data[4] + _.padStart(data[5], 5, '0') + _.padStart(data[6], 10, '0'); From 74d0c4512d14c838e665a31c4a135bc22b239b96 Mon Sep 17 00:00:00 2001 From: chunge66 Date: Thu, 11 Jul 2019 21:17:33 +0800 Subject: [PATCH 186/194] Add storage logic for upyun cdn (#207) --- config/config.js | 8 ++++++ core/utils/common.js | 40 ++++++++++++++++++++++++++ docs/process.json | 8 ++++++ package-lock.json | 68 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 5 files changed, 125 insertions(+) diff --git a/config/config.js b/config/config.js index 07c2deec..f92b0ee7 100644 --- a/config/config.js +++ b/config/config.js @@ -20,6 +20,14 @@ config.development = { bucketName: "", downloadUrl: "" // Binary files download host address. }, + // Config for upyun (https://www.upyun.com/) storage when storageType value is "upyun" + upyun: { + storageDir: process.evv.UPYUN_STORAGE_DIR, + serviceName: process.env.UPYUN_SERVICE_NAME, + operatorName: process.env.UPYUN_OPERATOR_NAME, + operatorPass: process.env.UPYUN_OPERATOR_PASS, + downloadUrl: process.env.DOWNLOAD_URL, + }, // Config for Amazon s3 (https://aws.amazon.com/cn/s3/) storage when storageType value is "s3". s3: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, diff --git a/core/utils/common.js b/core/utils/common.js index e7f7db08..6d221535 100644 --- a/core/utils/common.js +++ b/core/utils/common.js @@ -7,6 +7,7 @@ var config = require('../config'); var _ = require('lodash'); var validator = require('validator'); var qiniu = require("qiniu"); +var upyun = require('upyun'); var common = {}; var AppError = require('../app-error'); var jschardet = require("jschardet"); @@ -225,6 +226,8 @@ common.uploadFileToStorage = function (key, filePath) { return common.uploadFileToOSS(key, filePath); } else if (storageType === 'qiniu') { return common.uploadFileToQiniu(key, filePath); + } else if (storageType === 'upyun') { + return common.uploadFileToUpyun(key, filePath); } else if (storageType === 'tencentcloud') { return common.uploadFileToTencentCloud(key, filePath); } @@ -350,6 +353,43 @@ common.uploadFileToQiniu = function (key, filePath) { }); }; +common.uploadFileToUpyun = function (key, filePath) { + var serviceName = _.get(config, "upyun.serviceName"); + var operatorName = _.get(config, "upyun.operatorName"); + var operatorPass = _.get(config, "upyun.operatorPass", ""); + var storageDir = _.get(config, "upyun.storageDir", ""); + var service = new upyun.Service(serviceName, operatorName, operatorPass); + var client = new upyun.Client(service); + return ( + new Promise((resolve, reject) => { + client.makeDir(storageDir).then(result => { + if(!storageDir) { + reject(new AppError.AppError('Please config the upyun remoteDir!')); + return; + } + let remotePath = storageDir + '/' + key; + log.debug('uploadFileToUpyun remotePath:', remotePath); + log.debug('uploadFileToUpyun mkDir result:', result); + client.putFile(remotePath, fs.createReadStream(filePath)).then(data => { + log.debug('uploadFileToUpyun putFile response:', data); + if(data) { + resolve(key) + } else { + log.debug('uploadFileToUpyun putFile failed!', data); + reject(new AppError.AppError('Upload file to upyun failed!')); + } + }).catch(e1 => { + log.debug('uploadFileToUpyun putFile exception e1:', e1); + reject(new AppError.AppError(JSON.stringify(e1))); + }) + }).catch(e => { + log.debug('uploadFileToUpyun putFile exception e:', e); + reject(new AppError.AppError(JSON.stringify(e))); + }); + }) + ); +}; + common.uploadFileToS3 = function (key, filePath) { var AWS = require('aws-sdk'); return ( diff --git a/docs/process.json b/docs/process.json index de88022b..8ef0e3e1 100644 --- a/docs/process.json +++ b/docs/process.json @@ -10,6 +10,14 @@ "NODE_ENV" : "production", "PORT" : 3000, "CONFIG_FILE" : "/path/to/production/config.js" + + // Must set add config when STORAGE_TYPE is upyun + // "STORAGE_TYPE" : "upyun", + // "DOWNLOAD_URL" : "", + // "UPYUN_STORAGE_DIR" : "", + // "UPYUN_SERVICE_NAME" : "", + // "UPYUN_OPERATOR_NAME" : "", + // "UPYUN_OPERATOR_PASS" : "" } } ] diff --git a/package-lock.json b/package-lock.json index ef06fecf..79668d14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -255,6 +255,22 @@ "resolved": "http://registry.npm.taobao.org/aws4/download/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" + } + } + }, "babel-runtime": { "version": "6.26.0", "resolved": "http://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz", @@ -285,6 +301,11 @@ "resolved": "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base-64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", + "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=" + }, "base64-js": { "version": "1.2.3", "resolved": "http://registry.npm.taobao.org/base64-js/download/base64-js-1.2.3.tgz", @@ -452,6 +473,11 @@ "is-regex": "^1.0.3" } }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, "circular-json": { "version": "0.5.5", "resolved": "http://registry.npm.taobao.org/circular-json/download/circular-json-0.5.5.tgz", @@ -668,6 +694,11 @@ "which": "^1.2.9" } }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, "cryptiles": { "version": "3.1.2", "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-3.1.2.tgz", @@ -1081,6 +1112,14 @@ "locate-path": "^3.0.0" } }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", @@ -1314,6 +1353,11 @@ "resolved": "http://registry.npm.taobao.org/hide-powered-by/download/hide-powered-by-1.0.0.tgz", "integrity": "sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=" }, + "hmacsha1": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hmacsha1/-/hmacsha1-1.0.0.tgz", + "integrity": "sha1-wbeuA6TqEWNICQrxT4FIwSk4qRc=" + }, "hoek": { "version": "4.2.1", "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-4.2.1.tgz", @@ -1962,6 +2006,16 @@ "xregexp": "^2.0.0" } }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, "mdurl": { "version": "1.0.1", "resolved": "http://registry.npm.taobao.org/mdurl/download/mdurl-1.0.1.tgz", @@ -3450,6 +3504,20 @@ "resolved": "http://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "upyun": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/upyun/-/upyun-3.3.9.tgz", + "integrity": "sha512-UqvSKvvFgbQwLI+yjTO0WUnmS2i2KIvX4N2Je6ZTRN4cja17DHX7ARd13DO6h65/JOQJPs/Nua2zlnixNFIdWA==", + "requires": { + "axios": "^0.18.0", + "base-64": "^0.1.0", + "form-data": "^2.1.4", + "hmacsha1": "^1.0.0", + "is-promise": "^2.1.0", + "md5": "^2.2.1", + "mime-types": "^2.1.15" + } + }, "url": { "version": "0.10.3", "resolved": "http://registry.npm.taobao.org/url/download/url-0.10.3.tgz", diff --git a/package.json b/package.json index 6e60a383..1e3fc19a 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "nodemailer": "^4.0.1", "pug": "^2.0.1", "qiniu": "^7.1.3", + "upyun": "^3.3.9", "rand-token": "^0.4.0", "recursive-readdir": "^2.1.1", "redis": "^2.6.2", From 8ff23fad50866e881c735ef8f4588dab5fc410bf Mon Sep 17 00:00:00 2001 From: opu Date: Fri, 12 Jul 2019 23:41:34 +0800 Subject: [PATCH 187/194] fix bug (#208) --- core/services/client-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index 54880869..db1d084b 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -278,7 +278,7 @@ proto.reportStatusDeploy = function (deploymentKey, label, clientUniqueId, other if (_.isEmpty(metrics)) { return; } - if (constConfig.DEPLOYMENT_SUCCEEDED) { + if (_.eq(status, constConfig.DEPLOYMENT_SUCCEEDED)) { return metrics.increment(['installed', 'active'],{by: 1}); } else { return metrics.increment(['installed', 'failed'],{by: 1}); From 07d3fc7b983f67192e864d227acbf30479d6997b Mon Sep 17 00:00:00 2001 From: chunge66 Date: Tue, 16 Jul 2019 19:31:01 +0800 Subject: [PATCH 188/194] Fix db init failed by upyun config error (#210) --- .gitignore | 6 +++++- config/config.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c4fa1f63..c8f8d743 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,8 @@ pids # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git node_modules -coverage \ No newline at end of file +coverage + +# vs code +.history +.idea \ No newline at end of file diff --git a/config/config.js b/config/config.js index f92b0ee7..0789b5ee 100644 --- a/config/config.js +++ b/config/config.js @@ -22,7 +22,7 @@ config.development = { }, // Config for upyun (https://www.upyun.com/) storage when storageType value is "upyun" upyun: { - storageDir: process.evv.UPYUN_STORAGE_DIR, + storageDir: process.env.UPYUN_STORAGE_DIR, serviceName: process.env.UPYUN_SERVICE_NAME, operatorName: process.env.UPYUN_OPERATOR_NAME, operatorPass: process.env.UPYUN_OPERATOR_PASS, From 03ae6f674c8320a023063c0d396a01c3f825b4f9 Mon Sep 17 00:00:00 2001 From: lisong Date: Fri, 23 Aug 2019 09:49:03 +0800 Subject: [PATCH 189/194] Update README.md --- docs/README.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docs/README.md b/docs/README.md index dc455f8c..9419e94d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -236,15 +236,3 @@ edit config.xml. add code below. ``` - -## Use [CodePush Web](https://github.com/lisong/code-push-web) manage apps - -> add codePushWebUrl config in config.js - -eg. - -```javascript -"common": { - "codePushWebUrl": "Your CodePush Web address", -} -``` From 758a99a8a0d746788a22c4d83a6133369f3540a4 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 24 Aug 2019 11:54:26 +0800 Subject: [PATCH 190/194] adoptor --- app.js | 2 ++ routes/indexV1.js | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 routes/indexV1.js diff --git a/app.js b/app.js index 7c7d20cf..ee93e3cc 100644 --- a/app.js +++ b/app.js @@ -9,6 +9,7 @@ var _ = require('lodash'); var fs = require('fs'); var routes = require('./routes/index'); +var indexV1 = require('./routes/indexV1'); var auth = require('./routes/auth'); var accessKeys = require('./routes/accessKeys'); var account = require('./routes/account'); @@ -72,6 +73,7 @@ if (_.get(config, 'common.storageType') === 'local') { } app.use('/', routes); +app.use('/v0.1/public/codepush', indexV1); app.use('/auth', auth); app.use('/accessKeys', accessKeys); app.use('/account', account); diff --git a/routes/indexV1.js b/routes/indexV1.js new file mode 100644 index 00000000..fc9e825f --- /dev/null +++ b/routes/indexV1.js @@ -0,0 +1,89 @@ +var express = require('express'); +var router = express.Router(); +var Promise = require('bluebird'); +var AppError = require('../core/app-error'); +var middleware = require('../core/middleware'); +var ClientManager = require('../core/services/client-manager'); +var _ = require('lodash'); +var log4js = require('log4js'); +var log = log4js.getLogger("cps:indexV1"); + +router.get('/update_check', (req, res, next) => { + var deploymentKey = _.get(req, "query.deployment_key"); + var appVersion = _.get(req, "query.app_version"); + var label = _.get(req, "query.label"); + var packageHash = _.get(req, "query.package_hash") + var isCompanion = _.get(req, "query.is_companion") + var clientUniqueId = _.get(req, "query.client_unique_id") + var clientManager = new ClientManager(); + log.debug('req.query', req.query); + clientManager.updateCheckFromCache(deploymentKey, appVersion, label, packageHash, clientUniqueId) + .then((rs) => { + //灰度检测 + return clientManager.chosenMan(rs.packageId, rs.rollout, clientUniqueId) + .then((data)=>{ + if (!data) { + rs.isAvailable = false; + return rs; + } + return rs; + }); + }) + .then((rs) => { + delete rs.packageId; + delete rs.rollout; + var update_info = { + download_url : rs.downloadUrl; + description : rs.description; + is_available : rs.isAvailable; + is_disabled : rs.isDisabled; + target_binary_range: rs.targetBinaryRange; + label: rs.label; + package_hash: rs.packageHash; + package_size: rs.packageSize; + should_run_binary_version: rs.shouldRunBinaryVersion; + update_app_version: rs.updateAppVersion; + is_mandatory: rs.isMandatory; + }; + res.send({"update_info": update_info}); + }) + .catch((e) => { + if (e instanceof AppError.AppError) { + res.status(404).send(e.message); + } else { + next(e); + } + }); +}); + +router.post('/report_status/download', (req, res) => { + log.debug('req.body', req.body); + var clientUniqueId = _.get(req, "body.client_unique_id"); + var label = _.get(req, "body.label"); + var deploymentKey = _.get(req, "body.deployment_key"); + var clientManager = new ClientManager(); + clientManager.reportStatusDownload(deploymentKey, label, clientUniqueId) + .catch((err) => { + if (!err instanceof AppError.AppError) { + console.error(err.stack) + } + }); + res.send('OK'); +}); + +router.post('/report_status/deploy', (req, res) => { + log.debug('req.body', req.body); + var clientUniqueId = _.get(req, "body.client_unique_id"); + var label = _.get(req, "body.label"); + var deploymentKey = _.get(req, "body.deployment_key"); + var clientManager = new ClientManager(); + clientManager.reportStatusDeploy(deploymentKey, label, clientUniqueId, req.body) + .catch((err) => { + if (!err instanceof AppError.AppError) { + console.error(err.stack) + } + }); + res.send('OK'); +}); + +module.exports = router; From a0415ad054d8d8bfdafa56e2edba80df23864156 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 24 Aug 2019 16:51:52 +0800 Subject: [PATCH 191/194] adaptor code-push 3.0.1 --- core/services/client-manager.js | 4 ++++ routes/indexV1.js | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/core/services/client-manager.js b/core/services/client-manager.js index db1d084b..87a16625 100644 --- a/core/services/client-manager.js +++ b/core/services/client-manager.js @@ -125,8 +125,10 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash, clie downloadUrl: "", description: "", isAvailable: false, + isDisabled: true, isMandatory: false, appVersion: appVersion, + targetBinaryRange: "", packageHash: "", label: "", packageSize: 0, @@ -178,9 +180,11 @@ proto.updateCheck = function(deploymentKey, appVersion, label, packageHash, clie && _.eq(packages.deployment_id, deploymentsVersions.deployment_id) && !_.eq(packages.package_hash, packageHash)) { rs.packageId = packageId; + rs.targetBinaryRange = deploymentsVersions.app_version; rs.downloadUrl = rs.downloadURL = common.getBlobDownloadUrl(_.get(packages, 'blob_url')); rs.description = _.get(packages, 'description', ''); rs.isAvailable = _.eq(packages.is_disabled, 1) ? false : true; + rs.isDisabled = _.eq(packages.is_disabled, 1) ? true : false; rs.isMandatory = _.eq(packages.is_mandatory, 1) ? true : false; rs.appVersion = appVersion; rs.packageHash = _.get(packages, 'package_hash', ''); diff --git a/routes/indexV1.js b/routes/indexV1.js index fc9e825f..1720f1a8 100644 --- a/routes/indexV1.js +++ b/routes/indexV1.js @@ -33,17 +33,17 @@ router.get('/update_check', (req, res, next) => { delete rs.packageId; delete rs.rollout; var update_info = { - download_url : rs.downloadUrl; - description : rs.description; - is_available : rs.isAvailable; - is_disabled : rs.isDisabled; - target_binary_range: rs.targetBinaryRange; - label: rs.label; - package_hash: rs.packageHash; - package_size: rs.packageSize; - should_run_binary_version: rs.shouldRunBinaryVersion; - update_app_version: rs.updateAppVersion; - is_mandatory: rs.isMandatory; + download_url : rs.downloadUrl, + description : rs.description, + is_available : rs.isAvailable, + is_disabled : rs.isDisabled, + target_binary_range: rs.targetBinaryRange, + label: rs.label, + package_hash: rs.packageHash, + package_size: rs.packageSize, + should_run_binary_version: rs.shouldRunBinaryVersion, + update_app_version: rs.updateAppVersion, + is_mandatory: rs.isMandatory, }; res.send({"update_info": update_info}); }) From 6fd2da1daa675e9be7b9eb768bd33f769e174bf0 Mon Sep 17 00:00:00 2001 From: tablee Date: Sat, 24 Aug 2019 17:48:32 +0800 Subject: [PATCH 192/194] fixbug --- routes/apps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/apps.js b/routes/apps.js index 8edc39a9..8fd7d832 100644 --- a/routes/apps.js +++ b/routes/apps.js @@ -171,7 +171,7 @@ router.get('/:appName/deployments/:deploymentName/history', return deployments.getDeploymentHistory(deploymentInfo.id); }) .then((rs) => { - res.send({history: rs}); + res.send({history: _.pullAll(rs, [null, false])}); }) .catch((e) => { if (e instanceof AppError.AppError) { From 34426986e721b1e4f59fd56fc28b7a85c1bcab70 Mon Sep 17 00:00:00 2001 From: opu Date: Sun, 17 Nov 2019 19:50:18 +0800 Subject: [PATCH 193/194] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=94=B1=E4=BA=8E=20?= =?UTF-8?q?code-push=20=E7=9A=84=20release=20=E5=91=BD=E4=BB=A4=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E7=83=AD=E6=9B=B4=E6=96=B0=E5=8F=AF=E8=83=BD=E5=AF=BC?= =?UTF-8?q?=E8=87=B4hash=E5=80=BC=E4=B8=8D=E5=90=8Cbug=20(#236)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3q --- core/utils/security.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/utils/security.js b/core/utils/security.js index b6bab402..a4054acd 100644 --- a/core/utils/security.js +++ b/core/utils/security.js @@ -69,7 +69,7 @@ security.packageHashSync = function (jsonData) { log.debug('packageHashSync manifestData:', manifestData); var manifestString = JSON.stringify(manifestData.sort()); manifestString = _.replace(manifestString, /\\\//g, '/'); - log.debug('packageHashSync manifestString:', manifestData); + log.debug('packageHashSync manifestString:', manifestString); return security.stringSha256Sync(manifestString); } @@ -202,6 +202,10 @@ security.calcAllFileSha256 = function (directoryPath) { var data = {}; _.forIn(results, (value, key) => { var relativePath = path.relative(directoryPath, key); + var matchresult = relativePath.match(/(\/|\\).*/); + if (matchresult) { + relativePath = path.join('CodePush', matchresult[0]); + } relativePath = slash(relativePath); data[relativePath] = value; }); From 0dde12b08719c870ece46861a821ad923ee3c7ef Mon Sep 17 00:00:00 2001 From: lisong Date: Tue, 1 Aug 2023 17:13:14 +0800 Subject: [PATCH 194/194] Update README.md --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 5d72439a..1611e8db 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,6 @@ CodePush Server is a CodePush progam server! microsoft CodePush cloud is slow in - oss *storage bundle file in [aliyun](https://www.aliyun.com/product/oss)* - tencentcloud *storage bundle file in [tencentcloud](https://cloud.tencent.com/product/cos)* -## qq交流群 - -- QQ群: 628921445 -- QQ群: 535491067 - ## 正确使用code-push热更新 - 苹果App允许使用热更新[Apple's developer agreement](https://developer.apple.com/programs/ios/information/iOS_Program_Information_4_3_15.pdf), 为了不影响用户体验,规定必须使用静默更新。 Google Play不能使用静默更新,必须弹框告知用户App有更新。中国的android市场必须采用静默更新(如果弹框提示,App会被“请上传最新版本的二进制应用包”原因驳回)。