From eb493c1248bb473657716fcf4da5510e8699a74b Mon Sep 17 00:00:00 2001 From: leeyeh Date: Tue, 20 Sep 2016 20:09:33 +0800 Subject: [PATCH 001/122] chore(package): upgrade leancloud-storage to v2.0.0 --- lib/cloud.js | 12 +-- lib/http-request.js | 173 ++++++++++++++++++------------------ lib/leanengine.js | 4 +- lib/storage-extra.js | 1 - middleware/fetch-user.js | 10 +-- package.json | 4 +- test/cookie-session-test.js | 3 +- test/function_test.js | 76 ++++++++-------- test/hook_test.js | 16 ++-- test/storage-extra_test.js | 28 +++--- 10 files changed, 158 insertions(+), 169 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index eca05ab..8cc93f8 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -33,7 +33,7 @@ Cloud.run = function(name, data, options) { return originalCloudRun.apply(null, arguments); } - return AV.Promise.as().then(function() { + return AV.Promise.resolve().then(function() { if (options.sessionToken) { return AV.User.become(options.sessionToken); } @@ -60,7 +60,7 @@ Cloud.run = function(name, data, options) { }).catch(function(err) { console.log('Run function \'' + name + '\' failed with error:', err); throw err; - })._thenRunCallbacks(options); + }); }; var originalCloudRpc = AV.Cloud.rpc; @@ -118,14 +118,14 @@ AV.Insight.on = function(action, func) { Cloud.logInByIdAndSessionToken = function(uid, sessionToken, fetchUser, cb) { if (fetchUser) { - AV.User.become(sessionToken, { - success: function(user) { + AV.User.become(sessionToken).then( + function(user) { return cb(null, user); }, - error: function(user, err) { + function(err) { return cb(err); } - }); + ); } else { var user = new AV.User(); user.id = uid; diff --git a/lib/http-request.js b/lib/http-request.js index 48d96d3..1242566 100644 --- a/lib/http-request.js +++ b/lib/http-request.js @@ -36,7 +36,7 @@ var HTTPResponse = function HTTPResponse(buffer, headers, response, status, text }; module.exports = function(options) { - var body, contentLen, contentType, headers, hostname, httpResponse, http_module, method, params, parsedRes, path, port, promise, request, requestOptions, search, text, theBody, url; + var body, contentLen, contentType, headers, hostname, httpResponse, http_module, method, params, parsedRes, path, port, request, requestOptions, search, text, theBody, url; options = options || {}; options.agent = false; url = options.url; @@ -44,98 +44,101 @@ module.exports = function(options) { if (/^https.*/.exec(url)) { http_module = https; } - promise = new Promise(); - params = options.params; - headers = options.headers || {}; - method = options.method || 'GET'; - body = options.body; - text = options.text ? options.text : true; - delete options.params; - delete options.body; - delete options.url; - delete options.text; - parsedRes = urlParser.parse(url); - hostname = parsedRes.hostname; - port = parsedRes.port || 80; - if ((/^https.*/.exec(url)) && (!parsedRes.port)) { - port = 443; - } - path = parsedRes.path; - search = parsedRes.search; - if (params) { - path = !search ? path + '?' : path + '&'; - if (utils.typeOf(params) === 'string') { - params = qs.parse(params); + return new Promise(function(resolve, reject) { + params = options.params; + headers = options.headers || {}; + method = options.method || 'GET'; + body = options.body; + text = options.text ? options.text : true; + delete options.params; + delete options.body; + delete options.url; + delete options.text; + parsedRes = urlParser.parse(url); + hostname = parsedRes.hostname; + port = parsedRes.port || 80; + if ((/^https.*/.exec(url)) && (!parsedRes.port)) { + port = 443; } - params = qs.stringify(params); - path = path + params; - } - contentType = headers['Content-Type']; - if ((method === 'POST') && (!contentType)) { - headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; - } - theBody = castBody(body, headers['Content-Type']); - contentLen = theBody ? theBody.length : 0; - if (!headers['Content-Length']) { - headers['Content-Length'] = contentLen; - } - requestOptions = { - host: hostname, - port: port, - method: method, - headers: headers, - path: path - }; - requestOptions = util._extend(requestOptions, options); - httpResponse = new HTTPResponse(); - request = http_module.request(requestOptions, function(res) { - var chunkList, contentLength, encoding, matches, responseContentType; - httpResponse.status = res.statusCode; - httpResponse.headers = res.headers; - responseContentType = res.headers['content-type'] || ''; - encoding = (matches = responseContentType.match(/.*charset=(.*)/i)) ? matches[1].trim().replace(/'|"/gm, '') : 'utf8'; - if (encoding.toLowerCase() === 'utf-8') { - encoding = 'utf8'; + path = parsedRes.path; + search = parsedRes.search; + if (params) { + path = !search ? path + '?' : path + '&'; + if (utils.typeOf(params) === 'string') { + params = qs.parse(params); + } + params = qs.stringify(params); + path = path + params; } - if (text) { - httpResponse.text = ''; + contentType = headers['Content-Type']; + if ((method === 'POST') && (!contentType)) { + headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; } - chunkList = []; - contentLength = 0; - res.on('data', function(chunk) { - contentLength += chunk.length; - return chunkList.push(chunk); - }); - return res.on('end', function() { - var chunk, pos, _i, _len; - httpResponse.buffer = new Buffer(contentLength); - pos = 0; - for (_i = 0, _len = chunkList.length; _i < _len; _i++) { - chunk = chunkList[_i]; - chunk.copy(httpResponse.buffer, pos); - pos += chunk.length; + theBody = castBody(body, headers['Content-Type']); + contentLen = theBody ? theBody.length : 0; + if (!headers['Content-Length']) { + headers['Content-Length'] = contentLen; + } + requestOptions = { + host: hostname, + port: port, + method: method, + headers: headers, + path: path + }; + requestOptions = util._extend(requestOptions, options); + httpResponse = new HTTPResponse(); + request = http_module.request(requestOptions, function(res) { + var chunkList, contentLength, encoding, matches, responseContentType; + httpResponse.status = res.statusCode; + httpResponse.headers = res.headers; + responseContentType = res.headers['content-type'] || ''; + encoding = (matches = responseContentType.match(/.*charset=(.*)/i)) ? matches[1].trim().replace(/'|"/gm, '') : 'utf8'; + if (encoding.toLowerCase() === 'utf-8') { + encoding = 'utf8'; } if (text) { - httpResponse.text = iconvlite.decode(httpResponse.buffer, encoding); - } - trySetData(httpResponse); - if (httpResponse.status < 200 || httpResponse.status >= 400) { - return promise.reject(httpResponse); - } else { - return promise.resolve(httpResponse); + httpResponse.text = ''; } + chunkList = []; + contentLength = 0; + res.on('data', function(chunk) { + contentLength += chunk.length; + return chunkList.push(chunk); + }); + return res.on('end', function() { + var chunk, pos, _i, _len; + httpResponse.buffer = new Buffer(contentLength); + pos = 0; + for (_i = 0, _len = chunkList.length; _i < _len; _i++) { + chunk = chunkList[_i]; + chunk.copy(httpResponse.buffer, pos); + pos += chunk.length; + } + if (text) { + httpResponse.text = iconvlite.decode(httpResponse.buffer, encoding); + } + trySetData(httpResponse); + if (httpResponse.status < 200 || httpResponse.status >= 400) { + var error = new Error('falsey response status'); + error.httpResponse = httpResponse; + return reject(error); + } else { + return resolve(httpResponse); + } + }); }); + request.setTimeout(options.timeout || 10000, function() { + return request.abort(); + }); + request.on('error', function(e) { + httpResponse.text = util.inspect(e); + httpResponse.status = 500; + e.httpResponse = httpResponse; + return reject(e); + }); + request.end(theBody); }); - request.setTimeout(options.timeout || 10000, function() { - return request.abort(); - }); - request.on('error', function(e) { - httpResponse.text = util.inspect(e); - httpResponse.status = 500; - return promise.reject(httpResponse); - }); - request.end(theBody); - return promise._thenRunCallbacks(options); }; function castBody(body, contentType) { diff --git a/lib/leanengine.js b/lib/leanengine.js index 6868c9a..7bdb034 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -407,8 +407,6 @@ var encodeResult = function(result) { } }; -var decodeParams = function(params) { - return AV._decode('', params); -}; +var decodeParams = AV._decode; module.exports = AV; diff --git a/lib/storage-extra.js b/lib/storage-extra.js index dc80d51..567693f 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -3,7 +3,6 @@ var AV = require('leancloud-storage'); var utils = require('./utils'); AV._config.disableCurrentUser = true; -AV.Promise.setPromisesAPlusCompliant(true); if (process.env.LEANCLOUD_REGION) { AV._config.region = process.env.LEANCLOUD_REGION; diff --git a/middleware/fetch-user.js b/middleware/fetch-user.js index 2b64ca9..c4aa4cc 100644 --- a/middleware/fetch-user.js +++ b/middleware/fetch-user.js @@ -3,15 +3,13 @@ var utils = require('../lib/utils'); module.exports = function(AV) { return function(req, res, next) { if (req.AV.sessionToken && req.AV.sessionToken !== '') { - AV.User.become(req.AV.sessionToken, { - success: function(user) { + AV.User.become(req.AV.sessionToken).then( + function(user) { req.AV.user = user; next(); }, - error: function(user, err) { - next(err); - } - }); + next + ); } else { return next(); } diff --git a/package.json b/package.json index 70d31bf..b6d22b8 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "connect": "3.2.0", "connect-timeout": "^1.7.0", "cookies": "0.5.0", - "debug": "2.0.0", + "debug": "^2.0.0", "iconv-lite": "^0.4.8", - "leancloud-storage": "1.5.4", + "leancloud-storage": "^2.1.3", "on-headers": "1.0.0", "underscore": "^1.8.3" }, diff --git a/test/cookie-session-test.js b/test/cookie-session-test.js index 95b5d8e..0956366 100644 --- a/test/cookie-session-test.js +++ b/test/cookie-session-test.js @@ -59,10 +59,11 @@ describe('webhosting', function() { password: 'admin' }) .expect(302, function(err, res) { + if (err) return done(err); res.headers.location.should.equal('/profile'); res.headers['set-cookie'][0].indexOf('avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; path=/; expires=').should.equal(0); res.headers['set-cookie'][1].indexOf('avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0; path=/; expires=').should.equal(0); - done(err); + done(); }); }); diff --git a/test/function_test.js b/test/function_test.js index d324a35..51bbdfd 100644 --- a/test/function_test.js +++ b/test/function_test.js @@ -47,8 +47,8 @@ AV.Cloud.define('complexObject', function(request, response) { var query = new AV.Query(ComplexObject); query.include('fileColumn'); query.ascending('createdAt'); - query.find({ - success: function(results) { + query.find().then( + function(results) { response.success({ foo: 'bar', i: 123, @@ -61,29 +61,29 @@ AV.Cloud.define('complexObject', function(request, response) { avObjects: results, }); } - }); + ); }); AV.Cloud.define('bareAVObject', function(request, response) { var query = new AV.Query(ComplexObject); query.include('fileColumn'); query.ascending('createdAt'); - query.find({ - success: function(results) { + query.find().then( + function(results) { response.success(results[0]); } - }); + ); }); AV.Cloud.define('AVObjects', function(request, response) { var query = new AV.Query(ComplexObject); query.include('fileColumn'); query.ascending('createdAt'); - query.find({ - success: function(results) { + query.find().then( + function(results) { response.success(results); } - }); + ); }); AV.Cloud.define('testAVObjectParams', function(request, response) { @@ -137,32 +137,32 @@ AV.Cloud.define('testRun', function(request, response) { return response.error('Should be run on remote'); } - AV.Cloud.run('hello', {name: '李四'}, { - success: function(data) { + AV.Cloud.run('hello', {name: '李四'}).then( + function(data) { assert.deepEqual(data, {action: "hello", name: '李四'}); response.success(); } - }); + ); }); AV.Cloud.define('testRun_options_callback', function(request, response) { - AV.Cloud.run('choice', {choice: true}, { - success: function(data) { + AV.Cloud.run('choice', {choice: true}).then( + function(data) { assert.equal('OK~', data); - AV.Cloud.run('choice', {choice: false}, { - success: function(data) { + AV.Cloud.run('choice', {choice: false}).then( + function(data) { assert.ifError(data); }, - error: function(err) { + function(err) { assert.equal('OMG...', err); response.success(); } - }); + ); }, - error: function(err) { + function(err) { assert.ifError(err); } - }); + ); }); AV.Cloud.define('testRun_promise', function(request, response) { @@ -182,38 +182,34 @@ AV.Cloud.define('testRun_promise', function(request, response) { AV.Cloud.define('testRunWithUser', function(request, response) { AV.Cloud.run('testUser', {}, { - user: request.user, - success: function(data) { - assert.equal('ok', data); - response.success(); - } + user: request.user + }).then(function(data) { + assert.equal('ok', data); + response.success(); }); }); AV.Cloud.define('testRunWithAVObject', function(request, response) { AV.Cloud.run('complexObject', {}, { - user: request.user, - success: function(datas) { - response.success(datas); - } + user: request.user + }).then(function(datas) { + response.success(datas); }); }); AV.Cloud.define('testRunWithSessionToken', function(request, response) { AV.Cloud.run('testUser', {}, { - sessionToken: request.sessionToken, - success: function(datas) { - response.success(datas); - } + sessionToken: request.sessionToken + }).then(function(datas) { + response.success(datas); }); }); AV.Cloud.define('testRpcRemote', function(request, response) { AV.Cloud.rpc('testRun', {shouldRemote: true}, { remote: true, - success: function(datas) { - response.success(datas); - } + }).then(function(datas) { + response.success(datas); }); }); @@ -241,14 +237,14 @@ AV.Cloud.define("userMatching", function(req, res) { setTimeout(function() { // 为了更加靠谱的验证串号问题,走一次网络 IO var query = new AV.Query(TestObject); - query.get('55069f5be4b0c93838ed9b17', { - success: function(obj) { + query.get('55069f5be4b0c93838ed9b17').then( + function(obj) { assert.equal(obj.get('foo'), 'bar'); res.success({reqUser: req.user, currentUser: AV.User.current()}); - }, error: function() { + }, function() { res.success({reqUser: req.user, currentUser: AV.User.current()}); } - }); + ); }, Math.floor((Math.random() * 2000) + 1)); }); diff --git a/test/hook_test.js b/test/hook_test.js index b26813c..f49deaf 100644 --- a/test/hook_test.js +++ b/test/hook_test.js @@ -82,11 +82,11 @@ AV.Cloud.afterUpdate("TestClass", function(request) { assert(request.object.updatedKeys.indexOf('foo') != -1); should.exist(request.object.get('__after')); request.object.set('bizTime', bizTime); - request.object.save(null, { - success: function(obj) { + request.object.save().then( + function(obj) { assert.equal(bizTime, obj.get('bizTime')); } - }); + ); }); AV.Cloud.beforeDelete("TestClass", function(request, response) { @@ -176,7 +176,7 @@ describe('hook', function() { object: { file: { __type: 'File', - id: '55543fc2e4b0846760bd92f3', + objectId: '55543fc2e4b0846760bd92f3', url: 'http://ac-4h2h4okw.clouddn.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg' }, __before: '1464591343092,9761baef9f36ee98ecd582ee142dabe31fbae17a' @@ -335,9 +335,9 @@ describe('hook', function() { .set('Content-Type', 'application/json') .send({ "object": { - "id": "5403e36be4b0b77b5746b292", + "objectId": "5403e36be4b0b77b5746b292", "post": { - "id": "5403e36be4b0b77b5746b291" + "objectId": "5403e36be4b0b77b5746b291" }, __after: '1464591343092,d9e59a2ffffa2fab568c6aa5372ea6fb58eed29d' } @@ -362,7 +362,7 @@ describe('hook', function() { .send({ "object": { "post": { - "id": "5403e36be4b0b77b5746b291" + "objectId": "5403e36be4b0b77b5746b291" }, __after: '1464591343092,0a94f5bad8e437471fa3038caaa3f419f376222d' } @@ -385,7 +385,7 @@ describe('hook', function() { .send({ "object": { "post": { - "id": "5403e36be4b0b77b5746b291" + "objectId": "5403e36be4b0b77b5746b291" }, __after: '1464591343092,8dfcc1e306877697c43d8503ad24273641a9e802' } diff --git a/test/storage-extra_test.js b/test/storage-extra_test.js index c0f39a8..805c63f 100644 --- a/test/storage-extra_test.js +++ b/test/storage-extra_test.js @@ -25,37 +25,31 @@ after(function() { }); describe('storage-extra', function() { - it('httpRequest', function(done) { - AV.Cloud.httpRequest({ + it('httpRequest', function() { + return AV.Cloud.httpRequest({ url: 'http://localhost:3333/hello', - params: { name : '张三' }, - success: function(res) { + params: { name : '张三' } + }).then( + function(res) { res.status.should.equal(200); res.text.should.equal('Hello, 张三'); - done(); - }, - error: function(httpResponse) { - throw httpResponse.text; } - }); + ); }); - it('httpRequest', function(done) { + it('httpRequest', function() { AV.Cloud.httpRequest({ url: 'http://localhost:3333/hello', method: 'POST', body: { name: "张三" - }, - success: function(res) { + } + }).then( + function(res) { res.status.should.equal(200); res.text.should.equal('Hello, 张三'); - done(); - }, - error: function(httpResponse) { - throw httpResponse.text; } - }); + ); }); it('signDisableHook', function() { From ebcfe33fd11117aa8e5dbb2061682dd7a3f6eed6 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 6 Feb 2017 16:49:08 +0800 Subject: [PATCH 002/122] :arrow_up: Upgrading dependencies --- CHANGELOG.md | 5 ++++ middleware/cookie-session.js | 2 +- package.json | 52 +++++++++++++++--------------------- test/function_test.js | 4 +-- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c2dc46..9f83c07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 更新日志 +## v2.0.0 + +* **存在不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0) +* **不兼容改动** 仅兼容至 Node.js 4.3 以上版本 + ## v1.2.3 * 升级 JavaScript SDK 到 [leancloud-storage 1.5.0](https://github.com/leancloud/javascript-sdk/releases) diff --git a/middleware/cookie-session.js b/middleware/cookie-session.js index 24d6bb0..c0f5a2f 100644 --- a/middleware/cookie-session.js +++ b/middleware/cookie-session.js @@ -31,7 +31,7 @@ module.exports = function(AV) { debug('session options %j', opts); return function cookieSession(req, res, next) { - var cookies = req.sessionCookies = new Cookies(req, res, keys); + var cookies = req.sessionCookies = new Cookies(req, res, {keys: keys}); var responseUser; // 兼容 connect diff --git a/package.json b/package.json index b6d22b8..196a621 100644 --- a/package.json +++ b/package.json @@ -1,53 +1,45 @@ { "name": "leanengine", - "version": "1.2.4", + "version": "2.0.0-rc.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", "url": "https://github.com/leancloud/leanengine-node-sdk" }, "dependencies": { - "body-parser": "1.9.0", - "connect": "3.2.0", - "connect-timeout": "^1.7.0", - "cookies": "0.5.0", - "debug": "^2.0.0", - "iconv-lite": "^0.4.8", - "leancloud-storage": "^2.1.3", - "on-headers": "1.0.0", + "body-parser": "^1.16.0", + "connect": "^3.5.0", + "connect-timeout": "^1.8.0", + "cookies": "^0.6.2", + "debug": "^2.6.0", + "iconv-lite": "^0.4.15", + "leancloud-storage": "^2.1.0", + "on-headers": "^1.0.1", "underscore": "^1.8.3" }, "devDependencies": { - "blanket": "^1.2.1", - "expect.js": "0.2.0", - "express": "4.9.7", - "koa": "^1.2.0", - "koa-bodyparser": "^2.2.0", - "mocha": "2.3.3", - "rewire": "^2.5.1", - "should": "10.0.0", - "supertest": "0.14.0" + "blanket": "^1.2.3", + "express": "^4.14.1", + "koa": "^1.2.4", + "koa-bodyparser": "^2.3.0", + "mocha": "^3.2.0", + "should": "^11.2.0", + "supertest": "^3.0.0" }, - "keywords": [ - "LeanCloud", - "LeanEngine", - "cloud", - "BaaS" - ], + "keywords": ["LeanCloud", "LeanEngine", "cloud", "BaaS"], "config": { "blanket": { "pattern": "//^((?!(node_modules|test)).)*$/" } }, + "engines": { + "node": ">=4.3.0" + }, "license": "MIT", "author": { - "name": "wchen", - "email": "wchen@leancloud.rocks" - }, - "bugs": { - "url": "https://github.com/leancloud/leanengine-node-sdk/issues" + "name": "LeanCloud", + "email": "support@leancloud.rocks" }, - "homepage": "https://github.com/leancloud/leanengine-node-sdk", "scripts": { "test": "node_modules/mocha/bin/mocha -R spec --timeout=10000", "test-koa": "FRAMEWORK=koa node_modules/mocha/bin/mocha -R spec --timeout=10000 test test/koa", diff --git a/test/function_test.js b/test/function_test.js index 51bbdfd..2c89430 100644 --- a/test/function_test.js +++ b/test/function_test.js @@ -348,9 +348,9 @@ describe('functions', function() { __type: 'Date', iso: '2015-05-14T06:24:47.000Z' }); - result.avObject.fileColumn.should.eql({ + result.avObject.fileColumn.should.containEql({ __type: 'File', - id: '55543fc2e4b0846760bd92f3', + objectId: '55543fc2e4b0846760bd92f3', name: 'ttt.jpg', url: 'http://ac-4h2h4okw.clouddn.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg' }); From f4752ae7a036d1f6a2a5b714a4e231079a1acb59 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 6 Feb 2017 17:11:03 +0800 Subject: [PATCH 003/122] :fire: Remove AV.Cloud.httpRequest --- API.md | 46 ---------- CHANGELOG.md | 1 + lib/cloud.js | 3 - lib/http-request.js | 182 ------------------------------------- test/storage-extra_test.js | 28 ------ 5 files changed, 1 insertion(+), 259 deletions(-) delete mode 100644 lib/http-request.js diff --git a/API.md b/API.md index b3291c7..655115e 100644 --- a/API.md +++ b/API.md @@ -154,52 +154,6 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 这些 Hook 需要用 `AV.Cloud.define` 来定义,详见文档 [实时通信概览:云引擎 Hook](https://leancloud.cn/docs/realtime_v2.html#云引擎_Hook) -### AV.Cloud.httpRequest - -注意:该 API 已不再维护且可能在之后的版本中去除,请使用 [request](https://www.npmjs.com/package/request) 发起 HTTP 请求。 - -```javascript -AV.Cloud.httpRequest(options: object); -``` - -options 的属性包括: - -* `url`:被请求的 Url, 例如 `https://api.leancloud.cn/1.1/ping`。 -* `success: function(response: Response)`:成功回调,接受一个 HTTP 响应作为参数。 -* `error: function(response: Response)`:失败回调,接受一个 HTTP 响应作为参数。 -* `method: string`:HTTP 方法,默认为 `GET`。 -* `params`:Query String,可以是对象 `{q : 'Sean Plott'}` 也可以是字符串 `q=Sean Plott`。 -* `headers: object`:HTTP 头,例如 `{'Content-Type': 'application/json'}`。 -* `body: object`:HTTP 请求正文,默认使用 urlencode 编码,如果指定了 `Content-Type` 为 `application/json` 则发送 JSON 格式的正文;不适用于 `GET` 或 `HEAD` 请求。 -* `timeout: number`:超时时间,单位秒,默认 `10000`。 - -Response 的属性包括: - -* `status: number`:HTTP 响应状态码。 -* `headers: object`:HTTP 响应头。 -* `text: string`:HTTP 响应正文。 -* `buffer: Buffer`:HTTP 响应正文。 -* `data` 解析后的 HTTP 响应正文,例如对于 `Content-Type` 为 `application/json` 时,会将响应正文解析为一个对象。 - -示例: - -```javascript -AV.Cloud.httpRequest({ - method: 'POST', - url: 'http://www.example.com/create_post', - body: { - title: 'Vote for Pedro', - body: 'If you vote for Pedro, your wildest dreams will come true' - }, - success: function(httpResponse) { - console.log(httpResponse.text); - }, - error: function(httpResponse) { - console.error('Request failed with response code ' + httpResponse.status); - } -}); -``` - ## Middlewares ### cookie-session diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f83c07..108be04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * **存在不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0) * **不兼容改动** 仅兼容至 Node.js 4.3 以上版本 +* **不兼容** 移除 `AV.Cloud.httpRequest` ## v1.2.3 diff --git a/lib/cloud.js b/lib/cloud.js index 8cc93f8..c29cb10 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -134,9 +134,6 @@ Cloud.logInByIdAndSessionToken = function(uid, sessionToken, fetchUser, cb) { } }; -// 增加 Cloud.httpRequest 的支持 -Cloud.httpRequest = require('./http-request'); - function defineClassHook(className, hook, func) { debug('define class hook: %s %s', hook, className); Cloud.__code[hook + className] = func; diff --git a/lib/http-request.js b/lib/http-request.js deleted file mode 100644 index 1242566..0000000 --- a/lib/http-request.js +++ /dev/null @@ -1,182 +0,0 @@ -var http = require('http'); -var https = require('https'); -var urlParser = require('url'); -var qs = require('querystring'); -var util = require('util'); -var iconvlite = require('iconv-lite'); - -var Promise = require('leancloud-storage').Promise; -var utils = require('./utils'); - -var mimeTypes = [ - { - pattern: /^text\/plain.*/i, - process: function(res) { - return res.text; - } - }, { - pattern: /^application\/json.*/i, - process: function(res) { - return JSON.parse(res.text); - } - }, { - pattern: /^application\/x-www-form-urlencoded/i, - process: function(res) { - return qs.parse(res.buffer); - } - } -]; - -var HTTPResponse = function HTTPResponse(buffer, headers, response, status, text) { - this.buffer = buffer; - this.headers = headers || {}; - this.response = response; - this.status = status; - this.text = text; -}; - -module.exports = function(options) { - var body, contentLen, contentType, headers, hostname, httpResponse, http_module, method, params, parsedRes, path, port, request, requestOptions, search, text, theBody, url; - options = options || {}; - options.agent = false; - url = options.url; - http_module = http; - if (/^https.*/.exec(url)) { - http_module = https; - } - return new Promise(function(resolve, reject) { - params = options.params; - headers = options.headers || {}; - method = options.method || 'GET'; - body = options.body; - text = options.text ? options.text : true; - delete options.params; - delete options.body; - delete options.url; - delete options.text; - parsedRes = urlParser.parse(url); - hostname = parsedRes.hostname; - port = parsedRes.port || 80; - if ((/^https.*/.exec(url)) && (!parsedRes.port)) { - port = 443; - } - path = parsedRes.path; - search = parsedRes.search; - if (params) { - path = !search ? path + '?' : path + '&'; - if (utils.typeOf(params) === 'string') { - params = qs.parse(params); - } - params = qs.stringify(params); - path = path + params; - } - contentType = headers['Content-Type']; - if ((method === 'POST') && (!contentType)) { - headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; - } - theBody = castBody(body, headers['Content-Type']); - contentLen = theBody ? theBody.length : 0; - if (!headers['Content-Length']) { - headers['Content-Length'] = contentLen; - } - requestOptions = { - host: hostname, - port: port, - method: method, - headers: headers, - path: path - }; - requestOptions = util._extend(requestOptions, options); - httpResponse = new HTTPResponse(); - request = http_module.request(requestOptions, function(res) { - var chunkList, contentLength, encoding, matches, responseContentType; - httpResponse.status = res.statusCode; - httpResponse.headers = res.headers; - responseContentType = res.headers['content-type'] || ''; - encoding = (matches = responseContentType.match(/.*charset=(.*)/i)) ? matches[1].trim().replace(/'|"/gm, '') : 'utf8'; - if (encoding.toLowerCase() === 'utf-8') { - encoding = 'utf8'; - } - if (text) { - httpResponse.text = ''; - } - chunkList = []; - contentLength = 0; - res.on('data', function(chunk) { - contentLength += chunk.length; - return chunkList.push(chunk); - }); - return res.on('end', function() { - var chunk, pos, _i, _len; - httpResponse.buffer = new Buffer(contentLength); - pos = 0; - for (_i = 0, _len = chunkList.length; _i < _len; _i++) { - chunk = chunkList[_i]; - chunk.copy(httpResponse.buffer, pos); - pos += chunk.length; - } - if (text) { - httpResponse.text = iconvlite.decode(httpResponse.buffer, encoding); - } - trySetData(httpResponse); - if (httpResponse.status < 200 || httpResponse.status >= 400) { - var error = new Error('falsey response status'); - error.httpResponse = httpResponse; - return reject(error); - } else { - return resolve(httpResponse); - } - }); - }); - request.setTimeout(options.timeout || 10000, function() { - return request.abort(); - }); - request.on('error', function(e) { - httpResponse.text = util.inspect(e); - httpResponse.status = 500; - e.httpResponse = httpResponse; - return reject(e); - }); - request.end(theBody); - }); -}; - -function castBody(body, contentType) { - if (!body) { - return body; - } else if (typeof body === 'string') { - return body; - } else if (Buffer.isBuffer(body)) { - return body; - } else if (typeof body === 'object') { - if (/^application\/json.*/i.test(contentType)) { - return new Buffer(JSON.stringify(body)); - } else if ((!contentType) || /^application\/x-www-form-urlencoded/i.test(contentType)) { - return qs.stringify(body); - } - throw new Error('Invalid request body.'); - } else { - throw new Error('Invalid request body.'); - } -} - -function trySetData(httpRes) { - var contentType, e, type; - contentType = httpRes.headers['content-type']; - mimeTypes.some(function(mimeType) { - if (mimeType.pattern.exec(contentType)) { - type = mimeType; - return true; - } - }); - if (type) { - try { - httpRes.data = type.process(httpRes); - } catch (_error) { - e = _error; - httpRes.data = httpRes.buffer; - } - } else { - httpRes.data = httpRes.buffer; - } -} diff --git a/test/storage-extra_test.js b/test/storage-extra_test.js index 805c63f..1f11a2d 100644 --- a/test/storage-extra_test.js +++ b/test/storage-extra_test.js @@ -25,35 +25,7 @@ after(function() { }); describe('storage-extra', function() { - it('httpRequest', function() { - return AV.Cloud.httpRequest({ - url: 'http://localhost:3333/hello', - params: { name : '张三' } - }).then( - function(res) { - res.status.should.equal(200); - res.text.should.equal('Hello, 张三'); - } - ); - }); - - it('httpRequest', function() { - AV.Cloud.httpRequest({ - url: 'http://localhost:3333/hello', - method: 'POST', - body: { - name: "张三" - } - }).then( - function(res) { - res.status.should.equal(200); - res.text.should.equal('Hello, 张三'); - } - ); - }); - it('signDisableHook', function() { utils.signHook(config.masterKey, '__before_for_TestClass', 1453711871302).should.equal('1453711871302,a9611dbc226eed1a5f4aa0e4fa20e2d014aeaeb8'); }); - }); From f13a774b21804c91356e720f40945218725602e7 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 6 Feb 2017 18:08:53 +0800 Subject: [PATCH 004/122] :rotating_light: Print warning while call saveCurrentUser without sessionToken --- middleware/cookie-session.js | 6 +++++- test/cookie-session-test.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/middleware/cookie-session.js b/middleware/cookie-session.js index c0f5a2f..5f36e20 100644 --- a/middleware/cookie-session.js +++ b/middleware/cookie-session.js @@ -31,7 +31,7 @@ module.exports = function(AV) { debug('session options %j', opts); return function cookieSession(req, res, next) { - var cookies = req.sessionCookies = new Cookies(req, res, {keys: keys}); + var cookies = new Cookies(req, res, {keys: keys}); var responseUser; // 兼容 connect @@ -43,6 +43,10 @@ module.exports = function(AV) { req.sessionKey = name; res.saveCurrentUser = function(user) { + if (!user || !user.getSessionToken()) { + console.trace('LeanEngine: saveCurrentUser: User 对象上没有 sessionToken, 无法正确保存用户状态'); + } + responseUser = user; }; diff --git a/test/cookie-session-test.js b/test/cookie-session-test.js index 0956366..2e65b5a 100644 --- a/test/cookie-session-test.js +++ b/test/cookie-session-test.js @@ -34,7 +34,7 @@ app.post('/login', function(req, res) { }); app.post('/logout', function(req, res) { - res.saveCurrentUser(null); + res.clearCurrentUser(); res.send(); }); From 4231f91745937d8588b7b9a3ced269ce694e5a12 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 7 Feb 2017 14:57:55 +0800 Subject: [PATCH 005/122] :rotating_light: Throw exception if function already exists in `Cloud.define` --- lib/cloud.js | 17 +++++++++++++---- lib/leanengine.js | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index c29cb10..344b119 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -3,7 +3,7 @@ var debug = require('debug')('AV:LeanEngine'); var utils = require('./utils'); var Cloud = module.exports = { - __code: {} + functions: {} }; Cloud.define = function(name, options, func) { @@ -18,7 +18,11 @@ Cloud.define = function(name, options, func) { func.fetchUser = false; } - Cloud.__code[name] = func; + if (Cloud.functions[name]) { + throw new Error(`LeanEngine: ${name} already defined`); + } else { + Cloud.functions[name] = func; + } }; var originalCloudRun = AV.Cloud.run; @@ -55,7 +59,7 @@ Cloud.run = function(name, data, options) { } }); - Cloud.__code[name](request, response); + Cloud.functions[name](request, response); }); }).catch(function(err) { console.log('Run function \'' + name + '\' failed with error:', err); @@ -136,7 +140,12 @@ Cloud.logInByIdAndSessionToken = function(uid, sessionToken, fetchUser, cb) { function defineClassHook(className, hook, func) { debug('define class hook: %s %s', hook, className); - Cloud.__code[hook + className] = func; + + if (Cloud.functions[hook + className]) { + throw new Error(`LeanEngine: ${hook} of ${className} already defined`); + } else { + Cloud.functions[hook + className] = func; + } } function className(clazz) { diff --git a/lib/leanengine.js b/lib/leanengine.js index 7bdb034..4d47c14 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -91,7 +91,7 @@ function createCloudFunctionRouter(options) { cloudFunctions.use('/_ops/metadatas', function(req, res) { if (req.AV.authMasterKey) { - return resp(res, Object.keys(Cloud.__code)); + return resp(res, Object.keys(Cloud.functions)); } else { return utils.unauthResp(res); } @@ -145,7 +145,7 @@ function createCloudFunctionRouter(options) { }); }; - if (Cloud.__code[splited[1]] && Cloud.__code[splited[1]].fetchUser === false) { + if (Cloud.functions[splited[1]] && Cloud.functions[splited[1]].fetchUser === false) { handleCloudfunction(); } else { fetchUser(handleCloudfunction); @@ -239,7 +239,7 @@ var call = function(funcName, params, user, req, options, cb) { options = {}; } - if (!Cloud.__code[funcName]) { + if (!Cloud.functions[funcName]) { var err = new Error("LeanEngine not found function named '" + funcName + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); err.statusCode = 404; return cb(err); @@ -262,7 +262,7 @@ var call = function(funcName, params, user, req, options, cb) { cb(err, result); }); - Cloud.__code[funcName](request, response); + Cloud.functions[funcName](request, response); } catch (err) { console.warn('Execute \'' + funcName + '\' failed with error: ' + (err.stack || err)); err.statusCode = 500; @@ -271,7 +271,7 @@ var call = function(funcName, params, user, req, options, cb) { }; var classHook = function(className, hook, object, user, req, cb) { - if (!Cloud.__code[hook + className]) { + if (!Cloud.functions[hook + className]) { var err = new Error("LeanEngine could not find hook '" + hook + className + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); err.statusCode = 404; return cb(err); @@ -297,11 +297,11 @@ var classHook = function(className, hook, object, user, req, cb) { if (hook.indexOf('__after_') === 0) { setHookMark('__after', obj); // after 的 hook 不需要 response 参数,并且请求默认返回 ok - Cloud.__code[hook + className](request); + Cloud.functions[hook + className](request); return cb(null, 'ok'); } else { setHookMark('__before', obj); - Cloud.__code[hook + className](request, utils.prepareResponseObject(req.res, function(err) { + Cloud.functions[hook + className](request, utils.prepareResponseObject(req.res, function(err) { if (err) { cb(new Error(err)); } else if ('__before_delete_for_' === hook) { @@ -342,7 +342,7 @@ var onVerified = function(req, type, user) { req: req }); - Cloud.__code['__on_verified_' + type](request); + Cloud.functions['__on_verified_' + type](request); } catch (err) { console.warn('Execute onVerified ' + type + ' failed with error: ' + (err.stack || err)); } @@ -364,7 +364,7 @@ var onLogin = function(req, user, cb) { } }); - Cloud.__code.__on_login__User(request, response); + Cloud.functions['__on_login__User'](request, response); } catch (err) { console.warn('Execute onLogin failed with error: ' + (err.stack || err)); } @@ -372,7 +372,7 @@ var onLogin = function(req, user, cb) { var onCompleteBigQueryJob = function(data) { try { - Cloud.__code.__on_complete_bigquery_job(null, data); + Cloud.functions['__on_complete_bigquery_job'](null, data); } catch (err) { console.warn('Execute onCompleteBigQueryJob failed with error: ' + (err.stack || err)); } From eece0841662696e93d1253a03f9da369b84f42ad Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 7 Feb 2017 14:58:13 +0800 Subject: [PATCH 006/122] :hammer: Rewrite tests --- .jshintrc | 14 - .travis.yml | 4 +- CHANGELOG.md | 7 +- package.json | 2 +- ...rization_test.js => authorization-test.js} | 28 +- test/cookie-session-test.js | 10 +- ...rent-user_test.js => current-user-test.js} | 12 +- test/{function_test.js => function-test.js} | 292 ++---------------- test/{hook_test.js => hook-test.js} | 118 +------ test/https-redirect-test.js | 4 +- test/koa/cookie-session-test.js | 6 +- test/koa/https-redirect-test.js | 4 +- ...ge-extra_test.js => storage-extra-test.js} | 4 +- test/{config.js => utils/app-info.js} | 10 +- test/utils/functions.js | 236 ++++++++++++++ test/utils/hooks.js | 117 +++++++ test/utils/index.js | 14 + 17 files changed, 437 insertions(+), 445 deletions(-) delete mode 100644 .jshintrc rename test/{authorization_test.js => authorization-test.js} (88%) rename test/{current-user_test.js => current-user-test.js} (94%) rename test/{function_test.js => function-test.js} (66%) rename test/{hook_test.js => hook-test.js} (82%) rename test/{storage-extra_test.js => storage-extra-test.js} (76%) rename test/{config.js => utils/app-info.js} (57%) create mode 100644 test/utils/functions.js create mode 100644 test/utils/hooks.js create mode 100644 test/utils/index.js diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index e67a2ee..0000000 --- a/.jshintrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "strict": true, - "undef": true, - "unused": true, - "node": true, - "globals" : { - "describe" : false, - "it" : false, - "before" : false, - "beforeEach" : false, - "after" : false, - "afterEach" : false - } -} diff --git a/.travis.yml b/.travis.yml index 9d678ee..cde3a99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: node_js node_js: - - 0.12 - 4 - 6 + - node script: - npm test - - node -v | grep 'v0.12' || npm run test-koa + - npm run test-koa diff --git a/CHANGELOG.md b/CHANGELOG.md index 108be04..262ddf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,10 @@ ## v2.0.0 -* **存在不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0) -* **不兼容改动** 仅兼容至 Node.js 4.3 以上版本 -* **不兼容** 移除 `AV.Cloud.httpRequest` +* **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0) +* **不兼容改动** 仅兼容至 Node.js 4.4 以上版本 +* **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常 +* **不兼容改动** 移除 `AV.Cloud.httpRequest` ## v1.2.3 diff --git a/package.json b/package.json index 196a621..3305842 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ } }, "engines": { - "node": ">=4.3.0" + "node": ">=4.4.0" }, "license": "MIT", "author": { diff --git a/test/authorization_test.js b/test/authorization-test.js similarity index 88% rename from test/authorization_test.js rename to test/authorization-test.js index dbafcd9..15f1f2c 100644 --- a/test/authorization_test.js +++ b/test/authorization-test.js @@ -1,28 +1,18 @@ 'use strict'; -var config = require('./config'), - AV = require('..'); -var appId = config.appId; -var appKey = config.appKey; -var masterKey = config.masterKey; - -AV.init(config); +var request = require('supertest'); -var app; +const AV = require('..'); +const utils = require('./utils') +const appInfo = require('./utils/app-info'); -if (process.env.FRAMEWORK == 'koa') { - var koa = require('koa')(); - koa.use(AV.koa()); - app = koa.listen(); -} else { - app = AV.express(); -} +require('./utils/functions'); -AV.Cloud.define('foo', function(request, response) { - response.success("bar"); -}); +var appId = appInfo.appId; +var appKey = appInfo.appKey; +var masterKey = appInfo.masterKey; -var request = require('supertest'); +const app = utils.app(); describe('authorization', function() { it('ok', function(done) { diff --git a/test/cookie-session-test.js b/test/cookie-session-test.js index 2e65b5a..c3b1a03 100644 --- a/test/cookie-session-test.js +++ b/test/cookie-session-test.js @@ -5,13 +5,11 @@ var bodyParser = require('body-parser'); var request = require('supertest'); var should = require('should'); -var AV = require('..'); -var config = require('./config'); +const AV = require('..'); +const appInfo = require('./utils/app-info'); var app = express(); -AV.init(config); - app.use(AV.express()); app.use(bodyParser.json()); app.use(AV.Cloud.CookieSession({secret: 'my secret', maxAge: 3600000, fetchUser: true})); @@ -42,7 +40,7 @@ app.get('/profile', function(req, res) { res.send(req.currentUser); }); -describe('webhosting', function() { +describe('cookie-session', function() { it('index', function(done) { request(app).get('/') .expect(200, function(err, res) { @@ -53,6 +51,8 @@ describe('webhosting', function() { }); it('loign', function(done) { + this.timeout(20000); + request(app).post('/login') .send({ username: 'admin', diff --git a/test/current-user_test.js b/test/current-user-test.js similarity index 94% rename from test/current-user_test.js rename to test/current-user-test.js index 68f4dfd..84cb405 100644 --- a/test/current-user_test.js +++ b/test/current-user-test.js @@ -5,15 +5,13 @@ var assert = require('assert'); var bodyParser = require('body-parser'); var AV = require('..'); -var config = require('./config'); +const appInfo = require('./utils/app-info'); var request = require('supertest'); -var appId = config.appId; -var appKey = config.appKey; -var masterKey = config.masterKey; -var sessionTokenAdmin = config.sessionToken_admin; - -AV.init(config); +var appId = appInfo.appId; +var appKey = appInfo.appKey; +var masterKey = appInfo.masterKey; +var sessionTokenAdmin = appInfo.sessionTokenAdmin; describe('current user', function() { var app = express(); diff --git a/test/function_test.js b/test/function-test.js similarity index 66% rename from test/function_test.js rename to test/function-test.js index 2c89430..f15be19 100644 --- a/test/function_test.js +++ b/test/function-test.js @@ -1,272 +1,22 @@ 'use strict'; -var config = require('./config'), - AV = require('..'), - should = require('should'), - fs = require('fs'), - request = require('supertest'), - assert = require('assert'), - _ = require('underscore'); - -var appId = config.appId; -var appKey = config.appKey; -var masterKey = config.masterKey; - -AV.init(config); - -var app; - -if (process.env.FRAMEWORK == 'koa') { - var koa = require('koa')(); - koa.use(AV.koa()); - app = koa.listen(); -} else { - app = AV.express(); -} - -var TestObject = AV.Object.extend('TestObject'); -var ComplexObject = AV.Object.extend('ComplexObject'); - -AV.Cloud.define('foo', function(request, response) { - assert.ok(request.meta.remoteAddress); - response.success("bar"); -}); - -AV.Cloud.define('hello', function(request, response) { - response.success({action: "hello", name: request.params.name}); -}); - -AV.Cloud.define('choice', function(req, res) { - if (req.params.choice) { - res.success('OK~'); - } else { - res.error('OMG...'); - } -}); - -AV.Cloud.define('complexObject', function(request, response) { - var query = new AV.Query(ComplexObject); - query.include('fileColumn'); - query.ascending('createdAt'); - query.find().then( - function(results) { - response.success({ - foo: 'bar', - i: 123, - obj: { - a: 'b', - as: [1, 2, 3], - }, - t: new Date('2015-05-14T09:21:18.273Z'), - avObject: results[0], - avObjects: results, - }); - } - ); -}); - -AV.Cloud.define('bareAVObject', function(request, response) { - var query = new AV.Query(ComplexObject); - query.include('fileColumn'); - query.ascending('createdAt'); - query.find().then( - function(results) { - response.success(results[0]); - } - ); -}); - -AV.Cloud.define('AVObjects', function(request, response) { - var query = new AV.Query(ComplexObject); - query.include('fileColumn'); - query.ascending('createdAt'); - query.find().then( - function(results) { - response.success(results); - } - ); -}); - -AV.Cloud.define('testAVObjectParams', function(request, response) { - request.params.avObject.should.be.instanceof(AV.Object); - request.params.avObject.get('name').should.be.equal('avObject'); - request.params.avObject.get('pointerColumn').should.be.instanceof(AV.User); - request.params.avFile.should.be.instanceof(AV.File); +const request = require('supertest'); +const should = require('should'); +const assert = require('assert'); - request.params.avObjects.forEach(function(object) { - object.should.be.instanceof(AV.Object); - object.get('name').should.be.equal('avObjects'); - }); - - response.success(); -}); - -AV.Cloud.define('testBareAVObjectParams', function(request, response) { - request.params.should.be.instanceof(AV.Object); - request.params.get('name').should.be.equal('avObject'); - request.params.get('avFile').should.be.instanceof(AV.File); - request.params.get('avFile').name().should.be.equal('hello.txt'); - response.success(); -}); +const AV = require('..'); +const utils = require('./utils') +const appInfo = require('./utils/app-info'); -AV.Cloud.define('testAVObjectsArrayParams', function(request, response) { - request.params.forEach(function(object) { - object.get('name').should.be.equal('avObject'); - object.get('avFile').should.be.instanceof(AV.File); - object.get('avFile').name().should.be.equal('hello.txt'); - }); - response.success(); -}); - -AV.Cloud.define('testUser', function(request, response) { - assert.equal(request.user.className, '_User'); - assert.equal(request.user.id, '54fd6a03e4b06c41e00b1f40'); - assert.equal(request.user.get('username'), 'admin'); - response.success('ok'); -}); +require('./utils/functions'); +require('./utils/hooks'); -AV.Cloud.define('dontFetchUser', {fetchUser: false}, function(req, res) { - should.not.exist(res.user); - should.not.exist(res.currentUser); - req.sessionToken.should.be.equal(sessionToken_admin); - res.success(); -}); - -AV.Cloud.define('testRun', function(request, response) { - if (request.params.shouldRemote && process.env.NODE_ENV != 'production') { - return response.error('Should be run on remote'); - } - - AV.Cloud.run('hello', {name: '李四'}).then( - function(data) { - assert.deepEqual(data, {action: "hello", name: '李四'}); - response.success(); - } - ); -}); - -AV.Cloud.define('testRun_options_callback', function(request, response) { - AV.Cloud.run('choice', {choice: true}).then( - function(data) { - assert.equal('OK~', data); - AV.Cloud.run('choice', {choice: false}).then( - function(data) { - assert.ifError(data); - }, - function(err) { - assert.equal('OMG...', err); - response.success(); - } - ); - }, - function(err) { - assert.ifError(err); - } - ); -}); - -AV.Cloud.define('testRun_promise', function(request, response) { - AV.Cloud.run('choice', {choice: true}).then(function(data) { - assert.equal('OK~', data); - AV.Cloud.run('choice', {choice: false}).then(function(data) { - assert.ifError(data); - }, function(err) { - assert.equal('OMG...', err); - response.success(); - }); - }, - function(err) { - assert.ifError(err); - }); -}); - -AV.Cloud.define('testRunWithUser', function(request, response) { - AV.Cloud.run('testUser', {}, { - user: request.user - }).then(function(data) { - assert.equal('ok', data); - response.success(); - }); -}); - -AV.Cloud.define('testRunWithAVObject', function(request, response) { - AV.Cloud.run('complexObject', {}, { - user: request.user - }).then(function(datas) { - response.success(datas); - }); -}); - -AV.Cloud.define('testRunWithSessionToken', function(request, response) { - AV.Cloud.run('testUser', {}, { - sessionToken: request.sessionToken - }).then(function(datas) { - response.success(datas); - }); -}); - -AV.Cloud.define('testRpcRemote', function(request, response) { - AV.Cloud.rpc('testRun', {shouldRemote: true}, { - remote: true, - }).then(function(datas) { - response.success(datas); - }); -}); - -AV.Cloud.define('readDir', function(request, response) { - fs.readdir('.', function(err, dir) { - dir.should.containEql('package.json'); - response.success(dir); - }); -}); - -AV.Cloud.onVerified('sms', function(request) { - assert.equal(request.object.className, '_User'); - assert.equal(request.object.id, '54fd6a03e4b06c41e00b1f40'); - assert.equal(request.object.get('username'), 'admin'); -}); - -AV.Cloud.define('testThrowError', function(request, response) { - /* jshint ignore:start */ - noThisMethod(); - /* jshint ignore:end */ - response.success(); -}); - -AV.Cloud.define("userMatching", function(req, res) { - setTimeout(function() { - // 为了更加靠谱的验证串号问题,走一次网络 IO - var query = new AV.Query(TestObject); - query.get('55069f5be4b0c93838ed9b17').then( - function(obj) { - assert.equal(obj.get('foo'), 'bar'); - res.success({reqUser: req.user, currentUser: AV.User.current()}); - }, function() { - res.success({reqUser: req.user, currentUser: AV.User.current()}); - } - ); - }, Math.floor((Math.random() * 2000) + 1)); -}); - -AV.Cloud.define('testTimeout', function(req, res) { - setTimeout(function() { - res.success('ok'); - }, req.params.delay); -}); - -AV.Cloud.define('_messageReceived', function(request, response) { - response.success('ok'); -}); - -AV.Insight.on('end', function(err, result) { - assert.deepEqual({ - "id" : "job id", - "status": "OK/ERROR", - "message": "当 status 为 ERROR 时的错误消息" - }, _.omit(result, '__sign')); -}); +const appId = appInfo.appId; +const appKey = appInfo.appKey; +const masterKey = appInfo.masterKey; +const sessionTokenAdmin = appInfo.sessionTokenAdmin; -var sessionToken_admin = config.sessionToken_admin; +const app = utils.app(); describe('functions', function() { it('ping', function(done) { @@ -544,7 +294,7 @@ describe('functions', function() { .post('/1/functions/testUser') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionToken_admin) + .set('x-avoscloud-session-token', sessionTokenAdmin) .expect(200, done); }); @@ -553,7 +303,7 @@ describe('functions', function() { .post('/1/functions/dontFetchUser') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionToken_admin) + .set('x-avoscloud-session-token', sessionTokenAdmin) .expect(200, done); }); @@ -577,7 +327,7 @@ describe('functions', function() { .post('/1/functions/testRunWithUser') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionToken_admin) + .set('x-avoscloud-session-token', sessionTokenAdmin) .expect(200, done); }); @@ -587,7 +337,7 @@ describe('functions', function() { .post('/1/functions/testRun_options_callback') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionToken_admin) + .set('x-avoscloud-session-token', sessionTokenAdmin) .expect(200, done); }); @@ -597,7 +347,7 @@ describe('functions', function() { .post('/1/functions/testRun_promise') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionToken_admin) + .set('x-avoscloud-session-token', sessionTokenAdmin) .expect(200, done); }); @@ -606,7 +356,7 @@ describe('functions', function() { .post('/1/functions/testRunWithSessionToken') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionToken_admin) + .set('x-avoscloud-session-token', sessionTokenAdmin) .expect(200, done); }); @@ -665,7 +415,7 @@ describe('functions', function() { }); it('timeoutTest', function(done) { - this.timeout(17000); + this.timeout(20000); request(app) .post('/1.1/functions/testTimeout') .set('X-AVOSCloud-Application-Id', appId) @@ -713,7 +463,7 @@ describe('functions', function() { }); }; for (var i = 0; i <= 4; i++) { - doRequest(sessionToken_admin, 'admin', cb); + doRequest(sessionTokenAdmin, 'admin', cb); doRequest('0hgr13u12tmgyv4x594682sv5', 'zhangsan', cb); doRequest(null, null, cb); } diff --git a/test/hook_test.js b/test/hook-test.js similarity index 82% rename from test/hook_test.js rename to test/hook-test.js index f49deaf..cd94e37 100644 --- a/test/hook_test.js +++ b/test/hook-test.js @@ -1,14 +1,14 @@ 'use strict'; -var config = require('./config'), - AV = require('..'), - should = require('should'), // jshint ignore:line + +var AV = require('..'), + should = require('should'), assert = require('assert'); -var appId = config.appId; -var appKey = config.appKey; -var masterKey = config.masterKey; +const appInfo = require('./utils/app-info'); -AV.init(config); +var appId = appInfo.appId; +var appKey = appInfo.appKey; +var masterKey = appInfo.masterKey; var app; @@ -20,110 +20,10 @@ if (process.env.FRAMEWORK == 'koa') { app = AV.express(); } -AV.Cloud.beforeSave("TestClass", function(request, response) { - if (request.user) { - assert.equal(request.user.className, '_User'); - } - assert.equal(request.object.className, 'TestClass'); - request.object.set('user', request.user); - should.exist(request.object.get('__before')); - response.success(); -}); - -AV.Cloud.beforeSave("TestReview", function(request, response){ - if (request.object.get("stars") < 1) { - response.error("you cannot give less than one star"); - } else if (request.object.get("stars") > 5) { - response.error("you cannot give more than five stars"); - } else { - var comment = request.object.get("comment"); - if (comment && comment.length > 140) { - // Truncate and add a ... - request.object.set("comment", comment.substring(0, 137) + "..."); - } - response.success(); - } -}); - -AV.Cloud.beforeUpdate("TestReview", function(request, response) { - if (request.object.updatedKeys.indexOf('comment') != -1) { - if (request.object.get('comment').length <= 50) { - response.success(); - } else { - response.error('comment must short than 50'); - } - } else { - response.success(); - } -}); - -AV.Cloud.beforeSave("ErrorObject", function(request, response) { - var a = {}; - a.noThisMethod(); - response.success(); -}); - -AV.Cloud.beforeSave('ContainsFile', function(request, response) { - request.object.get('file').url().should.be.equal('http://ac-4h2h4okw.clouddn.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg'); - response.success(); -}); - -AV.Cloud.afterSave("TestReview", function(request) { - assert.equal(request.object.className, 'TestReview'); - assert.equal(request.object.id, '5403e36be4b0b77b5746b292'); -}); - -AV.Cloud.afterSave("TestError", function() { - noThisMethod(); // jshint ignore:line -}); - -AV.Cloud.afterUpdate("TestClass", function(request) { - var bizTime = new Date(); - assert(request.object.updatedKeys.indexOf('foo') != -1); - should.exist(request.object.get('__after')); - request.object.set('bizTime', bizTime); - request.object.save().then( - function(obj) { - assert.equal(bizTime, obj.get('bizTime')); - } - ); -}); - -AV.Cloud.beforeDelete("TestClass", function(request, response) { - assert.equal(request.object.className, 'TestClass'); - if (request.object.get('foo') === 'important') { - return response.error('important note'); - } - response.success(); -}); - -AV.Cloud.beforeSave("HookMarkTest", function(request, response) { - should.exist(request.object.get('__before')); - response.success(request.object); -}); - -AV.Cloud.afterSave("HookMarkTest", function(request) { - should.exist(request.object.get('__after')); -}); - -AV.Cloud.onVerified('sms', function(request) { - assert.equal(request.object.id, '54fd6a03e4b06c41e00b1f40'); -}); - -AV.Cloud.onLogin(function(request, response) { - // 因为此时用户还没有登录,所以用户信息是保存在 request.object 对象中 - assert(request.object); - if (request.object.get('username') == 'noLogin') { - // 如果是 error 回调,则用户无法登录 - response.error('Forbidden'); - } else { - // 如果是 success 回调,则用户可以登录 - response.success(); - } -}); - var request = require('supertest'); +request('./utils/hooks'); + describe('hook', function() { it('beforeSave', function(done) { request(app) diff --git a/test/https-redirect-test.js b/test/https-redirect-test.js index de781b7..89c497b 100644 --- a/test/https-redirect-test.js +++ b/test/https-redirect-test.js @@ -4,9 +4,7 @@ var express = require('express'); var request = require('supertest'); require('should'); -var config = require('./config'); - -AV.init(config); +const appInfo = require('./utils/app-info'); var app = express(); diff --git a/test/koa/cookie-session-test.js b/test/koa/cookie-session-test.js index 1440a97..fc8ab0d 100644 --- a/test/koa/cookie-session-test.js +++ b/test/koa/cookie-session-test.js @@ -3,13 +3,11 @@ var bodyParser = require('koa-bodyparser'); var request = require('supertest'); var should = require('should'); -var AV = require('../..'); -var config = require('../config'); +const AV = require('../..'); +const appInfo = require('../utils/app-info'); var app = koa(); -AV.init(config); - app.use(AV.koa()); app.use(bodyParser()); app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true})); diff --git a/test/koa/https-redirect-test.js b/test/koa/https-redirect-test.js index 26d35cd..eb07d78 100644 --- a/test/koa/https-redirect-test.js +++ b/test/koa/https-redirect-test.js @@ -5,9 +5,7 @@ var request = require('supertest'); require('should'); var AV = require('../..'); -var config = require('../config'); - -AV.init(config); +const appInfo = require('../utils/app-info'); var app = koa(); diff --git a/test/storage-extra_test.js b/test/storage-extra-test.js similarity index 76% rename from test/storage-extra_test.js rename to test/storage-extra-test.js index 1f11a2d..86537c1 100644 --- a/test/storage-extra_test.js +++ b/test/storage-extra-test.js @@ -4,7 +4,7 @@ var AV = require('../lib/storage-extra.js'); var express = require('express'); var bodyParser = require('body-parser'); var app = express(); -var config = require('./config'); +const appInfo = require('./utils/app-info'); var utils = require('../lib/utils'); app.use(bodyParser.json()); @@ -26,6 +26,6 @@ after(function() { describe('storage-extra', function() { it('signDisableHook', function() { - utils.signHook(config.masterKey, '__before_for_TestClass', 1453711871302).should.equal('1453711871302,a9611dbc226eed1a5f4aa0e4fa20e2d014aeaeb8'); + utils.signHook(appInfo.masterKey, '__before_for_TestClass', 1453711871302).should.equal('1453711871302,a9611dbc226eed1a5f4aa0e4fa20e2d014aeaeb8'); }); }); diff --git a/test/config.js b/test/utils/app-info.js similarity index 57% rename from test/config.js rename to test/utils/app-info.js index 1f15971..457bfdd 100644 --- a/test/config.js +++ b/test/utils/app-info.js @@ -1,6 +1,12 @@ -module.exports = { +const AV = require('../..'); + +const appInfo = { appId: '4h2h4okwiyn8b6cle0oig00vitayum8ephrlsvg7xo8o19ne', appKey: '3xjj1qw91cr3ygjq9lt0g8c3qpet38rrxtwmmp0yffyoy2t4', masterKey: '3v7z633lzfec9qzx8sjql6zimvdpmtwypcchr2gelu5mrzb0', - sessionToken_admin: 'w2jrtkbehp38otqmhbqu7ybs9' + sessionTokenAdmin: 'w2jrtkbehp38otqmhbqu7ybs9' }; + +AV.init(appInfo); + +module.exports = appInfo; diff --git a/test/utils/functions.js b/test/utils/functions.js new file mode 100644 index 0000000..f7c3c86 --- /dev/null +++ b/test/utils/functions.js @@ -0,0 +1,236 @@ +const assert = require('assert'); +const should = require('should'); +const fs = require('fs'); + +const AV = require('../..'); + +const sessionTokenAdmin = require('./app-info').sessionTokenAdmin; + +const TestObject = AV.Object.extend('TestObject'); +const ComplexObject = AV.Object.extend('ComplexObject'); + +AV.Cloud.define('foo', function(request, response) { + assert.ok(request.meta.remoteAddress); + response.success("bar"); +}); + +AV.Cloud.define('hello', function(request, response) { + response.success({action: "hello", name: request.params.name}); +}); + +AV.Cloud.define('choice', function(req, res) { + if (req.params.choice) { + res.success('OK~'); + } else { + res.error('OMG...'); + } +}); + +AV.Cloud.define('complexObject', function(request, response) { + var query = new AV.Query(ComplexObject); + query.include('fileColumn'); + query.ascending('createdAt'); + query.find().then( + function(results) { + response.success({ + foo: 'bar', + i: 123, + obj: { + a: 'b', + as: [1, 2, 3], + }, + t: new Date('2015-05-14T09:21:18.273Z'), + avObject: results[0], + avObjects: results, + }); + } + ); +}); + +AV.Cloud.define('bareAVObject', function(request, response) { + var query = new AV.Query(ComplexObject); + query.include('fileColumn'); + query.ascending('createdAt'); + query.find().then( + function(results) { + response.success(results[0]); + } + ); +}); + +AV.Cloud.define('AVObjects', function(request, response) { + var query = new AV.Query(ComplexObject); + query.include('fileColumn'); + query.ascending('createdAt'); + query.find().then( + function(results) { + response.success(results); + } + ); +}); + +AV.Cloud.define('testAVObjectParams', function(request, response) { + request.params.avObject.should.be.instanceof(AV.Object); + request.params.avObject.get('name').should.be.equal('avObject'); + request.params.avObject.get('pointerColumn').should.be.instanceof(AV.User); + + request.params.avFile.should.be.instanceof(AV.File); + + request.params.avObjects.forEach(function(object) { + object.should.be.instanceof(AV.Object); + object.get('name').should.be.equal('avObjects'); + }); + + response.success(); +}); + +AV.Cloud.define('testBareAVObjectParams', function(request, response) { + request.params.should.be.instanceof(AV.Object); + request.params.get('name').should.be.equal('avObject'); + request.params.get('avFile').should.be.instanceof(AV.File); + request.params.get('avFile').name().should.be.equal('hello.txt'); + response.success(); +}); + +AV.Cloud.define('testAVObjectsArrayParams', function(request, response) { + request.params.forEach(function(object) { + object.get('name').should.be.equal('avObject'); + object.get('avFile').should.be.instanceof(AV.File); + object.get('avFile').name().should.be.equal('hello.txt'); + }); + response.success(); +}); + +AV.Cloud.define('testUser', function(request, response) { + assert.equal(request.user.className, '_User'); + assert.equal(request.user.id, '54fd6a03e4b06c41e00b1f40'); + assert.equal(request.user.get('username'), 'admin'); + response.success('ok'); +}); + +AV.Cloud.define('dontFetchUser', {fetchUser: false}, function(req, res) { + should.not.exist(res.user); + should.not.exist(res.currentUser); + req.sessionToken.should.be.equal(sessionTokenAdmin); + res.success(); +}); + +AV.Cloud.define('testRun', function(request, response) { + if (request.params.shouldRemote && process.env.NODE_ENV != 'production') { + return response.error('Should be run on remote'); + } + + AV.Cloud.run('hello', {name: '李四'}).then( + function(data) { + assert.deepEqual(data, {action: "hello", name: '李四'}); + response.success(); + } + ); +}); + +AV.Cloud.define('testRun_options_callback', function(request, response) { + AV.Cloud.run('choice', {choice: true}).then( + function(data) { + assert.equal('OK~', data); + AV.Cloud.run('choice', {choice: false}).then( + function(data) { + assert.ifError(data); + }, + function(err) { + assert.equal('OMG...', err); + response.success(); + } + ); + }, + function(err) { + assert.ifError(err); + } + ); +}); + +AV.Cloud.define('testRun_promise', function(request, response) { + AV.Cloud.run('choice', {choice: true}).then(function(data) { + assert.equal('OK~', data); + AV.Cloud.run('choice', {choice: false}).then(function(data) { + assert.ifError(data); + }, function(err) { + assert.equal('OMG...', err); + response.success(); + }); + }, + function(err) { + assert.ifError(err); + }); +}); + +AV.Cloud.define('testRunWithUser', function(request, response) { + AV.Cloud.run('testUser', {}, { + user: request.user + }).then(function(data) { + assert.equal('ok', data); + response.success(); + }); +}); + +AV.Cloud.define('testRunWithAVObject', function(request, response) { + AV.Cloud.run('complexObject', {}, { + user: request.user + }).then(function(datas) { + response.success(datas); + }); +}); + +AV.Cloud.define('testRunWithSessionToken', function(request, response) { + AV.Cloud.run('testUser', {}, { + sessionToken: request.sessionToken + }).then(function(datas) { + response.success(datas); + }); +}); + +AV.Cloud.define('testRpcRemote', function(request, response) { + AV.Cloud.rpc('testRun', {shouldRemote: true}, { + remote: true, + }).then(function(datas) { + response.success(datas); + }); +}); + +AV.Cloud.define('readDir', function(request, response) { + fs.readdir('.', function(err, dir) { + dir.should.containEql('package.json'); + response.success(dir); + }); +}); + +AV.Cloud.define('testThrowError', function(request, response) { + /* jshint ignore:start */ + noThisMethod(); + /* jshint ignore:end */ + response.success(); +}); + +AV.Cloud.define("userMatching", function(req, res) { + setTimeout(function() { + // 为了更加靠谱的验证串号问题,走一次网络 IO + var query = new AV.Query(TestObject); + query.get('55069f5be4b0c93838ed9b17').then( + function(obj) { + assert.equal(obj.get('foo'), 'bar'); + res.success({reqUser: req.user, currentUser: AV.User.current()}); + }, function() { + res.success({reqUser: req.user, currentUser: AV.User.current()}); + } + ); + }, Math.floor((Math.random() * 2000) + 1)); +}); + +AV.Cloud.define('testTimeout', function(req, res) { + setTimeout(function() { + res.success('ok'); + }, req.params.delay); +}); + +AV.Cloud.define('_messageReceived', function(request, response) { + response.success('ok'); +}); diff --git a/test/utils/hooks.js b/test/utils/hooks.js new file mode 100644 index 0000000..f98792f --- /dev/null +++ b/test/utils/hooks.js @@ -0,0 +1,117 @@ +const assert = require('assert'); +const should = require('should'); +const _ = require('underscore'); + +const AV = require('../..'); + +AV.Cloud.beforeSave("TestClass", function(request, response) { + if (request.user) { + assert.equal(request.user.className, '_User'); + } + assert.equal(request.object.className, 'TestClass'); + request.object.set('user', request.user); + should.exist(request.object.get('__before')); + response.success(); +}); + +AV.Cloud.beforeSave("TestReview", function(request, response){ + if (request.object.get("stars") < 1) { + response.error("you cannot give less than one star"); + } else if (request.object.get("stars") > 5) { + response.error("you cannot give more than five stars"); + } else { + var comment = request.object.get("comment"); + if (comment && comment.length > 140) { + // Truncate and add a ... + request.object.set("comment", comment.substring(0, 137) + "..."); + } + response.success(); + } +}); + +AV.Cloud.beforeUpdate("TestReview", function(request, response) { + if (request.object.updatedKeys.indexOf('comment') != -1) { + if (request.object.get('comment').length <= 50) { + response.success(); + } else { + response.error('comment must short than 50'); + } + } else { + response.success(); + } +}); + +AV.Cloud.beforeSave("ErrorObject", function(request, response) { + var a = {}; + a.noThisMethod(); + response.success(); +}); + +AV.Cloud.beforeSave('ContainsFile', function(request, response) { + request.object.get('file').url().should.be.equal('http://ac-4h2h4okw.clouddn.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg'); + response.success(); +}); + +AV.Cloud.afterSave("TestReview", function(request) { + assert.equal(request.object.className, 'TestReview'); + assert.equal(request.object.id, '5403e36be4b0b77b5746b292'); +}); + +AV.Cloud.afterSave("TestError", function() { + noThisMethod(); // jshint ignore:line +}); + +AV.Cloud.afterUpdate("TestClass", function(request) { + var bizTime = new Date(); + assert(request.object.updatedKeys.indexOf('foo') != -1); + should.exist(request.object.get('__after')); + request.object.set('bizTime', bizTime); + request.object.save().then( + function(obj) { + assert.equal(bizTime, obj.get('bizTime')); + } + ); +}); + +AV.Cloud.beforeDelete("TestClass", function(request, response) { + assert.equal(request.object.className, 'TestClass'); + if (request.object.get('foo') === 'important') { + return response.error('important note'); + } + response.success(); +}); + +AV.Cloud.beforeSave("HookMarkTest", function(request, response) { + should.exist(request.object.get('__before')); + response.success(request.object); +}); + +AV.Cloud.afterSave("HookMarkTest", function(request) { + should.exist(request.object.get('__after')); +}); + +AV.Cloud.onLogin(function(request, response) { + // 因为此时用户还没有登录,所以用户信息是保存在 request.object 对象中 + assert(request.object); + if (request.object.get('username') == 'noLogin') { + // 如果是 error 回调,则用户无法登录 + response.error('Forbidden'); + } else { + // 如果是 success 回调,则用户可以登录 + response.success(); + } +}); + +AV.Cloud.onVerified('sms', function(request) { + assert.equal(request.object.className, '_User'); + assert.equal(request.object.id, '54fd6a03e4b06c41e00b1f40'); + assert.equal(request.object.get('username'), 'admin'); +}); + +AV.Insight.on('end', function(err, result) { + assert.deepEqual({ + "id" : "job id", + "status": "OK/ERROR", + "message": "当 status 为 ERROR 时的错误消息" + }, _.omit(result, '__sign')); +}); diff --git a/test/utils/index.js b/test/utils/index.js new file mode 100644 index 0000000..f5e6282 --- /dev/null +++ b/test/utils/index.js @@ -0,0 +1,14 @@ +const koa = require('koa'); +const request = require('supertest'); + +const AV = require('../..'); + +exports.app = function() { + if (process.env.FRAMEWORK == 'koa') { + var app = koa(); + app.use(AV.koa()); + return app.listen(); + } else { + return AV.express(); + } +} From 3310478024851cc3710a6e0f389d33d09957fffd Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 10 Feb 2017 15:18:50 +0800 Subject: [PATCH 007/122] :boom: AV.Cloud is no longer a express middleware --- CHANGELOG.md | 5 +++-- lib/leanengine.js | 19 ------------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 262ddf0..0179b04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ ## v2.0.0 -* **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0) +* **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0)(请检查 JS SDK 2.0 引入的不兼容改动) * **不兼容改动** 仅兼容至 Node.js 4.4 以上版本 * **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常 -* **不兼容改动** 移除 `AV.Cloud.httpRequest` +* **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块) +* **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`) ## v1.2.3 diff --git a/lib/leanengine.js b/lib/leanengine.js index 4d47c14..61e0515 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -34,25 +34,6 @@ AV.koa = function(options) { return require('../middleware/koa')(AV); }; -// override AV.Cloud to a connect app -if (!AV._old_Cloud) { - AV._old_Cloud = AV.Cloud; - var defaultMiddleware; - - AV.Cloud = function() { - if (!defaultMiddleware) { - console.error('Use AV.Cloud as a middleware is deprecated, use AV.express() instead'); - defaultMiddleware = AV.express(); - } - - defaultMiddleware.apply(this, arguments); - }; - - for (var key in AV._old_Cloud) { - AV.Cloud[key] = AV._old_Cloud[key]; - } -} - var Cloud = _.extend(AV.Cloud, require('./cloud')); // Don't reject unauthorized ssl. From e0e6fddf86e2e1a49da7d929a6e318df37ba79d0 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 17 Mar 2017 14:51:42 +0800 Subject: [PATCH 008/122] :sparkles: Add promise support to cloud functions --- CHANGELOG.md | 33 ++++++++++++++--- lib/cloud.js | 20 ++++++++++- lib/leanengine.js | 68 ++++++++++++++++++++++++++---------- middleware/domain-wrapper.js | 21 ----------- package.json | 8 +++-- test/function-test.js | 45 ++++++++++++++++++++++++ test/utils/functions.js | 29 ++++++++++++++- 7 files changed, 176 insertions(+), 48 deletions(-) delete mode 100644 middleware/domain-wrapper.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0179b04..315f1b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,34 @@ ## v2.0.0 -* **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0)(请检查 JS SDK 2.0 引入的不兼容改动) -* **不兼容改动** 仅兼容至 Node.js 4.4 以上版本 -* **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常 -* **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块) -* **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`) +- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0)(请检查 JS SDK 2.0 引入的不兼容改动) +- **不兼容改动** 仅兼容至 Node.js 4.4 以上版本 +- **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常 +- **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块) +- **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`) +- **不兼容改动** 移除基于 [domain](https://nodejs.org/api/domain.html),开发者需要自行捕捉云函数异步代码中的异常。 + +新增云函数和 Class Hook 的 Promise 模式,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 + +```javascript +AV.Cloud.define(function(request) { + return new AV.Query('Post').find().then( posts => { + if (posts.length > 0) { + return posts[0]; + } else { + throw new AV.Cloud.Error('posts is empty'); + } + }); +}); +``` + +如果传入 `AV.Cloud.define` 的函数有两个参数(`request` 和 `response`)则继续兼容原定义方式,需要使用 `response.success()` 发送响应。我们会继续兼容这种用法到下一个大版本,希望用户尽快迁移到 Promise 风格的云函数上。 + +## v1.2.4 + +暂时地锁定 leancloud-storage 的版本,控制 [1.5.5](https://github.com/leancloud/javascript-sdk/releases/tag/v1.5.5) 中 disableCurrentUser 变动的影响。 + +- 锁定 leancloud-storage 的版本到 1.5.4 ## v1.2.3 diff --git a/lib/cloud.js b/lib/cloud.js index 344b119..c569225 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -1,6 +1,7 @@ var AV = require('./storage-extra'); var debug = require('debug')('AV:LeanEngine'); var utils = require('./utils'); +var _ = require('underscore'); var Cloud = module.exports = { functions: {} @@ -37,7 +38,7 @@ Cloud.run = function(name, data, options) { return originalCloudRun.apply(null, arguments); } - return AV.Promise.resolve().then(function() { + return Promise.resolve().then(function() { if (options.sessionToken) { return AV.User.become(options.sessionToken); } @@ -120,6 +121,23 @@ AV.Insight.on = function(action, func) { Cloud.define('__on_complete_bigquery_job', func); }; +Cloud.Error = class CloudError extends Error { + constructor(message, extra = {}) { + super() + + Error.captureStackTrace(this, this.constructor) + + if (!extra.status) { + extra.status = 400; + } + + _.extend(this, { + name: 'CloudError', + message: message + }, extra) + } +} + Cloud.logInByIdAndSessionToken = function(uid, sessionToken, fetchUser, cb) { if (fetchUser) { AV.User.become(sessionToken).then( diff --git a/lib/leanengine.js b/lib/leanengine.js index 61e0515..1ec19f1 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -67,7 +67,6 @@ function createCloudFunctionRouter(options) { cloudFunctions.use(bodyParser.json({limit: '20mb'})); cloudFunctions.use(bodyParser.text({limit: '20mb'})); cloudFunctions.use(require('../middleware/cors')()); - cloudFunctions.use(require('../middleware/domain-wrapper')()); cloudFunctions.use(require('../middleware/parse-leancloud-headers')(AV, {restrict: true})); cloudFunctions.use('/_ops/metadatas', function(req, res) { @@ -208,7 +207,7 @@ var respBare = function(res, data) { var respError = function(res, err) { res.setHeader('Content-Type', 'application/json; charset=UTF-8'); - res.statusCode = err.statusCode || 400; + res.statusCode = err.status || err.statusCode || 400; res.end(JSON.stringify({ code: err.code || 1, error: err && (err.message || err.responseText || err) || 'null message' @@ -220,34 +219,57 @@ var call = function(funcName, params, user, req, options, cb) { options = {}; } - if (!Cloud.functions[funcName]) { + const cloudFunction = Cloud.functions[funcName] + + if (!cloudFunction) { var err = new Error("LeanEngine not found function named '" + funcName + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); err.statusCode = 404; return cb(err); } - try { - if (options.decodeAVObject) { - params = decodeParams(params); - } - var request = utils.prepareRequestObject({ - user: user, - params: params, - req: req - }); + if (options.decodeAVObject) { + params = decodeParams(params); + } + + const request = utils.prepareRequestObject({ + user: user, + params: params, + req: req + }); - var response = utils.prepareResponseObject(req.res, function(err, result) { + if (cloudFunction.length == 2) { + const response = utils.prepareResponseObject(req.res, function(err, result) { if (!err && options.decodeAVObject) { result = encodeResult(result); } cb(err, result); }); - Cloud.functions[funcName](request, response); - } catch (err) { - console.warn('Execute \'' + funcName + '\' failed with error: ' + (err.stack || err)); - err.statusCode = 500; - return cb(err); + try { + cloudFunction(request, response); + } catch (err) { + console.warn('Execute \'' + funcName + '\' failed with error: ' + (err.stack || err)); + err.statusCode = 500; + return cb(err); + } + } else { + promiseTry(cloudFunction.bind(null, request)).then( result => { + if (options.decodeAVObject) { + cb(null, encodeResult(result)) + } else { + cb(null, result) + } + }).catch( (err) => { + if (!err.status) { + err.status = 500; + } + + if (err.status == 500) { + console.warn('Execute \'' + funcName + '\' failed with error: ' + (err.stack || err)); + } + + cb(err); + }); } }; @@ -390,4 +412,14 @@ var encodeResult = function(result) { var decodeParams = AV._decode; +function promiseTry(func) { + return new Promise((resolve, reject) => { + try { + Promise.resolve(func()).then(resolve, reject); + } catch (err) { + reject(err); + } + }); +} + module.exports = AV; diff --git a/middleware/domain-wrapper.js b/middleware/domain-wrapper.js deleted file mode 100644 index 9e19f3c..0000000 --- a/middleware/domain-wrapper.js +++ /dev/null @@ -1,21 +0,0 @@ -var domain = require('domain'); - -module.exports = function() { - return function(req, res, next) { - if (process.domain) { - return next(); - } - var d = domain.create(); - d.add(req); - d.add(res); - d.on('error', function(err) { - console.error('LeanEngine function uncaughtException url=%s, msg=%s', req.originalUrl, err.stack || err.message || err); - if(!res.finished) { - res.statusCode = 500; - res.setHeader('content-type', 'application/json; charset=UTF-8'); - res.end(JSON.stringify({code: 1, error: 'LeanEngine function uncaughtException'})); - } - }); - d.run(next); - }; -}; diff --git a/package.json b/package.json index 3305842..08e6138 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "connect-timeout": "^1.8.0", "cookies": "^0.6.2", "debug": "^2.6.0", - "iconv-lite": "^0.4.15", "leancloud-storage": "^2.1.0", "on-headers": "^1.0.1", "underscore": "^1.8.3" @@ -26,7 +25,12 @@ "should": "^11.2.0", "supertest": "^3.0.0" }, - "keywords": ["LeanCloud", "LeanEngine", "cloud", "BaaS"], + "keywords": [ + "LeanCloud", + "LeanEngine", + "cloud", + "BaaS" + ], "config": { "blanket": { "pattern": "//^((?!(node_modules|test)).)*$/" diff --git a/test/function-test.js b/test/function-test.js index f15be19..7a3f07b 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -36,6 +36,51 @@ describe('functions', function() { .expect({result: "bar"}, done); }); + it('get object (promise)', function(done) { + request(app) + .post('/1.1/functions/getObjectPromise') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .expect(200, (err, res) => { + res.body.result.foo.should.be.equal('bar'); + done(err); + }); + }); + + it('client error (promise)', function(done) { + request(app) + .post('/1.1/functions/choicePromise') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .expect(400, (err, res) => { + res.body.code.should.be.equal(1); + res.body.error.should.be.equal('OMG...'); + done(err); + }); + }); + + it('customized error code (promise)', function(done) { + request(app) + .post('/1.1/functions/clientErrorPromise') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .expect(400, (err, res) => { + res.body.code.should.be.equal(400); + done(err); + }); + }); + + it('server error (promise)', function(done) { + request(app) + .post('/1.1/functions/serverErrorPromise') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .expect(500, (err, res) => { + res.body.error.should.be.match(/noThisMethod is not defined/); + done(err); + }); + }); + // 测试 api version 1.1 的有效性 it('version_1.1', function(done) { request(app) diff --git a/test/utils/functions.js b/test/utils/functions.js index f7c3c86..6be905e 100644 --- a/test/utils/functions.js +++ b/test/utils/functions.js @@ -18,6 +18,21 @@ AV.Cloud.define('hello', function(request, response) { response.success({action: "hello", name: request.params.name}); }); +AV.Cloud.define('getObjectPromise', function() { + var query = new AV.Query(TestObject); + return query.get('55069f5be4b0c93838ed9b17').then( object => { + return object; + }); +}); + +AV.Cloud.define('choicePromise', function(req) { + if (req.params.choice) { + return 'OK~' + } else { + throw new AV.Cloud.Error('OMG...'); + } +}); + AV.Cloud.define('choice', function(req, res) { if (req.params.choice) { res.success('OK~'); @@ -210,6 +225,14 @@ AV.Cloud.define('testThrowError', function(request, response) { response.success(); }); +AV.Cloud.define('clientErrorPromise', function(request) { + throw new AV.Cloud.Error('some message', {code: 400}); +}); + +AV.Cloud.define('serverErrorPromise', function(request) { + noThisMethod(); +}); + AV.Cloud.define("userMatching", function(req, res) { setTimeout(function() { // 为了更加靠谱的验证串号问题,走一次网络 IO @@ -227,7 +250,11 @@ AV.Cloud.define("userMatching", function(req, res) { AV.Cloud.define('testTimeout', function(req, res) { setTimeout(function() { - res.success('ok'); + try { + res.success('ok'); + } catch (err) { + console.error(err); + } }, req.params.delay); }); From 06fdfaf34aa364b1f3ae5a9fc4b03df3be704b60 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 17 Mar 2017 15:07:35 +0800 Subject: [PATCH 009/122] :lipstick: No longer print error in AV.Cloud.run --- CHANGELOG.md | 1 + lib/cloud.js | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 315f1b4..5cb9b24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块) - **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`) - **不兼容改动** 移除基于 [domain](https://nodejs.org/api/domain.html),开发者需要自行捕捉云函数异步代码中的异常。 +- **不兼容改动** `AV.Cloud.run` 在运行失败时不再向标准输出打印日志,请从返回的 Promise 中获取错误。 新增云函数和 Class Hook 的 Promise 模式,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 diff --git a/lib/cloud.js b/lib/cloud.js index c569225..fdd8e4b 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -62,9 +62,6 @@ Cloud.run = function(name, data, options) { Cloud.functions[name](request, response); }); - }).catch(function(err) { - console.log('Run function \'' + name + '\' failed with error:', err); - throw err; }); }; From b9c1e705eb353e61430fb22c0b7b2dc1c9ee02f9 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 17 Mar 2017 15:34:34 +0800 Subject: [PATCH 010/122] :sparkles: Add AV.Cloud.LeanCloudHeaders --- lib/leanengine.js | 10 ++- middleware/leancloud-headers-koa.js | 12 +++ middleware/leancloud-headers.js | 112 ++++++++++++++++++++++++++ middleware/parse-leancloud-headers.js | 110 ------------------------- 4 files changed, 133 insertions(+), 111 deletions(-) create mode 100644 middleware/leancloud-headers-koa.js create mode 100644 middleware/leancloud-headers.js delete mode 100644 middleware/parse-leancloud-headers.js diff --git a/lib/leanengine.js b/lib/leanengine.js index 1ec19f1..8275cde 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -57,6 +57,14 @@ AV.Cloud.HttpsRedirect = function(options) { } } +AV.Cloud.LeanCloudHeaders = function(options) { + if (options && options.framework == 'koa') { + return require('../middleware/leancloud-heaedrs-koa')(AV)(options); + } else { + return require('../middleware/leancloud-heaedrs')(AV)(options); + } +} + function createCloudFunctionRouter(options) { options = options || {}; @@ -67,7 +75,7 @@ function createCloudFunctionRouter(options) { cloudFunctions.use(bodyParser.json({limit: '20mb'})); cloudFunctions.use(bodyParser.text({limit: '20mb'})); cloudFunctions.use(require('../middleware/cors')()); - cloudFunctions.use(require('../middleware/parse-leancloud-headers')(AV, {restrict: true})); + cloudFunctions.use(require('../middleware/leancloud-headers')(AV)({restrict: true})); cloudFunctions.use('/_ops/metadatas', function(req, res) { if (req.AV.authMasterKey) { diff --git a/middleware/leancloud-headers-koa.js b/middleware/leancloud-headers-koa.js new file mode 100644 index 0000000..e01d622 --- /dev/null +++ b/middleware/leancloud-headers-koa.js @@ -0,0 +1,12 @@ +const leancloudHeaders = require('./leancloud-headers'); + +module.exports = function(AV) { + return function(options) { + var middleware = leancloudHeaders(AV, options); + + return function *(next) { + yield middleware.bind(null, this.req, this.res); + yield next; + } + }; +}; diff --git a/middleware/leancloud-headers.js b/middleware/leancloud-headers.js new file mode 100644 index 0000000..22c9f3c --- /dev/null +++ b/middleware/leancloud-headers.js @@ -0,0 +1,112 @@ +var crypto = require('crypto'); + +var utils = require('../lib/utils'); + +module.exports = function(AV) { + return function(options) { + options = options || {}; + + return function(req, res, next) { + var appId, appKey, masterKey, contentType, param, prod, prodHeader, prodValue, sessionToken; + contentType = req.headers['content-type']; + if (/^text\/plain.*/i.test(contentType)) { + if (req.body && req.body !== '') { + req.body = JSON.parse(req.body); + } + appId = req.body._ApplicationId; + appKey = req.body._ApplicationKey; + masterKey = req.body._MasterKey; + prodValue = req.body._ApplicationProduction; + sessionToken = req.body._SessionToken; + for (param in req.body) { + // remove _* but keep __* + if (param.charAt(0) === '_' && param.charAt(1) !== '_') { + delete req.body[param]; + } + } + prod = 1; + if (prodValue === 0 || prodValue === false) { + prod = 0; + } + req.AV = { + id: appId, + key: appKey, + masterKey: masterKey, + prod: prod, + sessionToken: sessionToken + }; + } else { + appId = req.headers['x-lc-id'] || + req.headers['x-avoscloud-application-id'] || + req.headers['x-uluru-application-id']; + appKey = req.headers['x-lc-key'] || + req.headers['x-avoscloud-application-key'] || + req.headers['x-uluru-application-key']; + masterKey = req.headers['x-avoscloud-master-key'] || req.headers['x-uluru-master-key']; + prodHeader = req.headers['x-lc-prod'] || + req.headers['x-avoscloud-application-production'] || + req.headers['x-uluru-application-production']; + sessionToken = req.headers['x-lc-session'] || + req.headers['x-uluru-session-token'] || + req.headers['x-avoscloud-session-token']; + prod = 1; + if (prodHeader === '0' || prodHeader === 'false') { + prod = 0; + } + if (appKey && (appKey.indexOf(',master') > 0)) { + masterKey = appKey.slice(0, appKey.indexOf(',')); + appKey = null; + } + req.sessionToken = sessionToken; + req.AV = { + id: appId, + key: appKey, + masterKey: masterKey, + prod: prod, + sessionToken: sessionToken + }; + } + + if (options.restrict) { + var key, master, requestSign, sign, timestamp, validSign, _ref; + if (!req.AV.id) { + return utils.unauthResp(res); + } + if (AV.applicationId === req.AV.id && + (AV.applicationKey === req.AV.key || + AV.masterKey === req.AV.key || + AV.masterKey === req.AV.masterKey)) { + if (AV.masterKey === req.AV.masterKey) { + req.AV.authMasterKey = true; + } + return next(); + } + requestSign = req.headers['x-lc-sign'] || req.headers['x-avoscloud-request-sign']; + if (requestSign) { + _ref = requestSign.split(','); + sign = _ref[0]; + timestamp = _ref[1]; + master = _ref[2]; + key = master === 'master' ? AV.masterKey : AV.applicationKey; + validSign = signByKey(timestamp, key); + if (validSign === sign.toLowerCase()) { + if (master === 'master') { + req.AV.authMasterKey = true; + req.AV.masterKey = key; + } else { + req.AV.key = key; + } + return next(); + } + } + return utils.unauthResp(res); + } else { + return next(); + } + }; + } +} + +function signByKey(timestamp, key) { + return crypto.createHash('md5').update('' + timestamp + key).digest('hex'); +} diff --git a/middleware/parse-leancloud-headers.js b/middleware/parse-leancloud-headers.js deleted file mode 100644 index e773467..0000000 --- a/middleware/parse-leancloud-headers.js +++ /dev/null @@ -1,110 +0,0 @@ -var crypto = require('crypto'); - -var utils = require('../lib/utils'); - -module.exports = function(AV, options) { - options = options || {}; - - return function(req, res, next) { - var appId, appKey, masterKey, contentType, param, prod, prodHeader, prodValue, sessionToken; - contentType = req.headers['content-type']; - if (/^text\/plain.*/i.test(contentType)) { - if (req.body && req.body !== '') { - req.body = JSON.parse(req.body); - } - appId = req.body._ApplicationId; - appKey = req.body._ApplicationKey; - masterKey = req.body._MasterKey; - prodValue = req.body._ApplicationProduction; - sessionToken = req.body._SessionToken; - for (param in req.body) { - // remove _* but keep __* - if (param.charAt(0) === '_' && param.charAt(1) !== '_') { - delete req.body[param]; - } - } - prod = 1; - if (prodValue === 0 || prodValue === false) { - prod = 0; - } - req.AV = { - id: appId, - key: appKey, - masterKey: masterKey, - prod: prod, - sessionToken: sessionToken - }; - } else { - appId = req.headers['x-lc-id'] || - req.headers['x-avoscloud-application-id'] || - req.headers['x-uluru-application-id']; - appKey = req.headers['x-lc-key'] || - req.headers['x-avoscloud-application-key'] || - req.headers['x-uluru-application-key']; - masterKey = req.headers['x-avoscloud-master-key'] || req.headers['x-uluru-master-key']; - prodHeader = req.headers['x-lc-prod'] || - req.headers['x-avoscloud-application-production'] || - req.headers['x-uluru-application-production']; - sessionToken = req.headers['x-lc-session'] || - req.headers['x-uluru-session-token'] || - req.headers['x-avoscloud-session-token']; - prod = 1; - if (prodHeader === '0' || prodHeader === 'false') { - prod = 0; - } - if (appKey && (appKey.indexOf(',master') > 0)) { - masterKey = appKey.slice(0, appKey.indexOf(',')); - appKey = null; - } - req.sessionToken = sessionToken; - req.AV = { - id: appId, - key: appKey, - masterKey: masterKey, - prod: prod, - sessionToken: sessionToken - }; - } - - if (options.restrict) { - var key, master, requestSign, sign, timestamp, validSign, _ref; - if (!req.AV.id) { - return utils.unauthResp(res); - } - if (AV.applicationId === req.AV.id && - (AV.applicationKey === req.AV.key || - AV.masterKey === req.AV.key || - AV.masterKey === req.AV.masterKey)) { - if (AV.masterKey === req.AV.masterKey) { - req.AV.authMasterKey = true; - } - return next(); - } - requestSign = req.headers['x-lc-sign'] || req.headers['x-avoscloud-request-sign']; - if (requestSign) { - _ref = requestSign.split(','); - sign = _ref[0]; - timestamp = _ref[1]; - master = _ref[2]; - key = master === 'master' ? AV.masterKey : AV.applicationKey; - validSign = signByKey(timestamp, key); - if (validSign === sign.toLowerCase()) { - if (master === 'master') { - req.AV.authMasterKey = true; - req.AV.masterKey = key; - } else { - req.AV.key = key; - } - return next(); - } - } - return utils.unauthResp(res); - } else { - return next(); - } - }; -}; - -function signByKey(timestamp, key) { - return crypto.createHash('md5').update('' + timestamp + key).digest('hex'); -} From 5e67b40f34ae57fcfb67165356f6e728c772dfaa Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 17 Mar 2017 15:47:48 +0800 Subject: [PATCH 011/122] :truck: Move test/koa/* to test/* --- package.json | 2 +- test/authorization-test.js | 8 ++++---- ...okie-session-test.js => cookie-session-koa-test.js} | 4 ++-- test/cookie-session-test.js | 2 +- test/current-user-test.js | 2 +- test/function-test.js | 10 +++++----- test/{utils => helpers}/app-info.js | 0 test/{utils => helpers}/functions.js | 0 test/{utils => helpers}/hooks.js | 0 test/{utils => helpers}/index.js | 0 test/hook-test.js | 4 ++-- ...tps-redirect-test.js => https-redirect-koa-test.js} | 6 +++--- test/https-redirect-test.js | 2 +- test/storage-extra-test.js | 2 +- 14 files changed, 21 insertions(+), 21 deletions(-) rename test/{koa/cookie-session-test.js => cookie-session-koa-test.js} (97%) rename test/{utils => helpers}/app-info.js (100%) rename test/{utils => helpers}/functions.js (100%) rename test/{utils => helpers}/hooks.js (100%) rename test/{utils => helpers}/index.js (100%) rename test/{koa/https-redirect-test.js => https-redirect-koa-test.js} (87%) diff --git a/package.json b/package.json index 08e6138..7ba4041 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ }, "scripts": { "test": "node_modules/mocha/bin/mocha -R spec --timeout=10000", - "test-koa": "FRAMEWORK=koa node_modules/mocha/bin/mocha -R spec --timeout=10000 test test/koa", + "test-koa": "FRAMEWORK=koa node_modules/mocha/bin/mocha -R spec --timeout=10000", "test-cov": "node_modules/mocha/bin/mocha --require blanket -R html-cov > coverage.html" } } diff --git a/test/authorization-test.js b/test/authorization-test.js index 15f1f2c..48f4645 100644 --- a/test/authorization-test.js +++ b/test/authorization-test.js @@ -3,16 +3,16 @@ var request = require('supertest'); const AV = require('..'); -const utils = require('./utils') -const appInfo = require('./utils/app-info'); +const helpers = require('./helpers') +const appInfo = require('./helpers/app-info'); -require('./utils/functions'); +require('./helpers/functions'); var appId = appInfo.appId; var appKey = appInfo.appKey; var masterKey = appInfo.masterKey; -const app = utils.app(); +const app = helpers.app(); describe('authorization', function() { it('ok', function(done) { diff --git a/test/koa/cookie-session-test.js b/test/cookie-session-koa-test.js similarity index 97% rename from test/koa/cookie-session-test.js rename to test/cookie-session-koa-test.js index fc8ab0d..58e8f1d 100644 --- a/test/koa/cookie-session-test.js +++ b/test/cookie-session-koa-test.js @@ -3,8 +3,8 @@ var bodyParser = require('koa-bodyparser'); var request = require('supertest'); var should = require('should'); -const AV = require('../..'); -const appInfo = require('../utils/app-info'); +const AV = require('..'); +const appInfo = require('./helpers/app-info'); var app = koa(); diff --git a/test/cookie-session-test.js b/test/cookie-session-test.js index c3b1a03..9c433c5 100644 --- a/test/cookie-session-test.js +++ b/test/cookie-session-test.js @@ -6,7 +6,7 @@ var request = require('supertest'); var should = require('should'); const AV = require('..'); -const appInfo = require('./utils/app-info'); +const appInfo = require('./helpers/app-info'); var app = express(); diff --git a/test/current-user-test.js b/test/current-user-test.js index 84cb405..71c1f75 100644 --- a/test/current-user-test.js +++ b/test/current-user-test.js @@ -5,7 +5,7 @@ var assert = require('assert'); var bodyParser = require('body-parser'); var AV = require('..'); -const appInfo = require('./utils/app-info'); +const appInfo = require('./helpers/app-info'); var request = require('supertest'); var appId = appInfo.appId; diff --git a/test/function-test.js b/test/function-test.js index 7a3f07b..c4460cb 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -5,18 +5,18 @@ const should = require('should'); const assert = require('assert'); const AV = require('..'); -const utils = require('./utils') -const appInfo = require('./utils/app-info'); +const helpers = require('./helpers') +const appInfo = require('./helpers/app-info'); -require('./utils/functions'); -require('./utils/hooks'); +require('./helpers/functions'); +require('./helpers/hooks'); const appId = appInfo.appId; const appKey = appInfo.appKey; const masterKey = appInfo.masterKey; const sessionTokenAdmin = appInfo.sessionTokenAdmin; -const app = utils.app(); +const app = helpers.app(); describe('functions', function() { it('ping', function(done) { diff --git a/test/utils/app-info.js b/test/helpers/app-info.js similarity index 100% rename from test/utils/app-info.js rename to test/helpers/app-info.js diff --git a/test/utils/functions.js b/test/helpers/functions.js similarity index 100% rename from test/utils/functions.js rename to test/helpers/functions.js diff --git a/test/utils/hooks.js b/test/helpers/hooks.js similarity index 100% rename from test/utils/hooks.js rename to test/helpers/hooks.js diff --git a/test/utils/index.js b/test/helpers/index.js similarity index 100% rename from test/utils/index.js rename to test/helpers/index.js diff --git a/test/hook-test.js b/test/hook-test.js index cd94e37..ce1d067 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -4,7 +4,7 @@ var AV = require('..'), should = require('should'), assert = require('assert'); -const appInfo = require('./utils/app-info'); +const appInfo = require('./helpers/app-info'); var appId = appInfo.appId; var appKey = appInfo.appKey; @@ -22,7 +22,7 @@ if (process.env.FRAMEWORK == 'koa') { var request = require('supertest'); -request('./utils/hooks'); +request('./helpers/hooks'); describe('hook', function() { it('beforeSave', function(done) { diff --git a/test/koa/https-redirect-test.js b/test/https-redirect-koa-test.js similarity index 87% rename from test/koa/https-redirect-test.js rename to test/https-redirect-koa-test.js index eb07d78..19300a6 100644 --- a/test/koa/https-redirect-test.js +++ b/test/https-redirect-koa-test.js @@ -4,8 +4,8 @@ var koa = require('koa'); var request = require('supertest'); require('should'); -var AV = require('../..'); -const appInfo = require('../utils/app-info'); +var AV = require('..'); +const appInfo = require('./helpers/app-info'); var app = koa(); @@ -18,7 +18,7 @@ app.use(function *(next) { var server = app.listen(); -describe('https-redirect', function() { +describe('https-redirect-koa', function() { it('should redirect', function(done) { request(server) .get('/test') diff --git a/test/https-redirect-test.js b/test/https-redirect-test.js index 89c497b..19dbc64 100644 --- a/test/https-redirect-test.js +++ b/test/https-redirect-test.js @@ -4,7 +4,7 @@ var express = require('express'); var request = require('supertest'); require('should'); -const appInfo = require('./utils/app-info'); +const appInfo = require('./helpers/app-info'); var app = express(); diff --git a/test/storage-extra-test.js b/test/storage-extra-test.js index 86537c1..b56175b 100644 --- a/test/storage-extra-test.js +++ b/test/storage-extra-test.js @@ -4,7 +4,7 @@ var AV = require('../lib/storage-extra.js'); var express = require('express'); var bodyParser = require('body-parser'); var app = express(); -const appInfo = require('./utils/app-info'); +const appInfo = require('./helpers/app-info'); var utils = require('../lib/utils'); app.use(bodyParser.json()); From 1a8c94e66aabd29ab4c23219741ed6056fcb7ff0 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 17 Mar 2017 16:16:11 +0800 Subject: [PATCH 012/122] :memo: Update documents --- API.md | 58 +++++++++++++++++++++++++++++++++------------------- CHANGELOG.md | 22 ++++++++++++++++---- README.md | 16 +-------------- 3 files changed, 56 insertions(+), 40 deletions(-) diff --git a/API.md b/API.md index 655115e..a65f847 100644 --- a/API.md +++ b/API.md @@ -49,7 +49,7 @@ AV.Cloud.define(name: string, func: function) AV.Cloud.define(name: string, options: object, func: function) ``` -定义云函数有两种签名,其中 options 是一个可选的参数,`func` 的签名:`function(request: Request, response: Response)`。 +定义云函数有两种签名,其中 `options` 是一个可选的参数,`func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,Promise 的值即为云函数的响应。在 Promise 中可以抛出使用 `AV.Cloud.Error` 构造的异常表示错误,如果抛出其他类型的异常则视作服务器端错误,会打印错误到标准输出。 `options` 的属性包括: @@ -63,10 +63,18 @@ AV.Cloud.define(name: string, options: object, func: function) * `meta: {remoteAddress}`:`meta.remoteAddress` 是客户端的 IP. * `sessionToken?: string`:客户端发来的 sessionToken(`X-LC-Session` 头)。 -`Response` 上的属性包括: +1.x 兼容模式:在早期版本中,云函数和 after 类的 Hook 是接受两个参数(`request` 和 `response`)的,我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上。 -* `success: function(result?)`:向客户端发送结果,可以是包括 AV.Object 在内的各种数据类型或数组,客户端解析方式见各 SDK 文档。 -* `error: function(err?: string)`:向客户端返回一个错误。 +### AV.Cloud.Error + +```javascript +new AV.Cloud.Error(message: string, options?) +``` + +继承自 `Error`,用于在云函数和 Class Hook 中表示客户端错误,其中第二个参数支持: + +- `status?: number`:设置 HTTP 响应代码(默认 500) +- `code?: number`:设置响应正文中的错误代码(默认 1) ### AV.Cloud.run @@ -98,11 +106,9 @@ AV.Cloud.run(name: string, data: object, options?: object): Promise * AV.Cloud.beforeDelete * AV.Cloud.afterDelete -这些函数的签名:`function(className: string, func: function)`。 - -before 类 Hook 的 `func` 签名:`function(request: Request, response: Response)`,before 类 Hook 需要在执行完成后调用 `response.success` 或 `response.error` 接受或拒绝这次操作。 +这些函数的签名:`function(className: string, func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数。在 before 类 Hook 中如果没有抛出异常则视作接受这次操作。如果抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误;抛出其他类型的异常视作服务器端错误,会打印到标准输出。 -after 类 Hook 的 `func` 签名:`function(request: Request)`。 +在 Promise 中可以抛出使用 `AV.Cloud.Error` 构造的异常表示错误,如果抛出其他类型的异常则视作服务器端错误,返回 500 响应并打印错误到标准输出。 `Request` 上的属性包括: @@ -110,11 +116,6 @@ after 类 Hook 的 `func` 签名:`function(request: Request)`。 * `currentUser?: AV.User`:发起操作的用户。 * `user?: AV.User`:同 `currentUser`. -`Response` 上的属性包括: - -* `success: function()`:允许这个操作,请在 15 秒内调用 `success`, 否则会认为操作被拒绝。 -* `error: function(err: string)`:向客户端返回一个错误并拒绝这个操作。 - LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调用者的确是 LeanCloud 或本地调试时的命令行工具。 更多有关 Hook 函数的内容请参考文档 [云函数开发指南:Hook 函数](https://leancloud.cn/docs/leanengine_cloudfunction_guide-node.html#Hook_函数)。 @@ -124,20 +125,13 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * AV.Cloud.onVerified * AV.Cloud.onLogin -这两个函数的签名:`function(func: function)`,`func` 签名:`function(request: Request, response: Response)`,Hook 需要在执行完成后调用 `response.success` 或 `response.error` 接受或拒绝这次操作。 +这两个函数的签名:`function(func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,如果没有抛出异常则视作接受这次操作。 `Request` 上的属性包括: * `currentUser: AV.User`:被操作的用户。 * `user: AV.User`:同 `currentUser`. -`Response` 上的属性包括: - -* `success: function()`:允许这个操作,请在 15 秒内调用 `success`, 否则会认为操作被拒绝。 -* `error: function(err: string)`:向客户端返回一个错误并拒绝这个操作。 - -更多有关 Hook 函数的内容请参考文档 [云函数开发指南:Hook 函数](https://leancloud.cn/docs/leanengine_cloudfunction_guide-node.html#Hook_函数)。 - ### 实时通信 Hook 函数 包括: @@ -156,6 +150,28 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 ## Middlewares +### leancloud-headers + +该中间件会将 `X-LC` 系列的头解析为 request.AV 上的属性,在 Express 中: + +```javascript +app.use(AV.Cloud.LeanCloudHeaders()); +``` + +在 Koa 中(添加 `framework: 'koa'` 参数): + +```javascript +app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa'})); +``` + +express 的 `Request`(或 koa 的 `ctx.request`)上会有这些属性可用: + +* `AV.id?`:App ID +* `AV.key?`:App Key +* `AV.masterKey?`:App Master Key +* `AV.prod`:`0` 或 `1` +* `AV.sessionToken?`:Session Token + ### cookie-session 该中间件提供了在 Express 或 Koa 中维护用户状态的能力,在 Express 中: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cb9b24..2e090fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,10 @@ - **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常 - **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块) - **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`) -- **不兼容改动** 移除基于 [domain](https://nodejs.org/api/domain.html),开发者需要自行捕捉云函数异步代码中的异常。 -- **不兼容改动** `AV.Cloud.run` 在运行失败时不再向标准输出打印日志,请从返回的 Promise 中获取错误。 +- **不兼容改动** 移除基于 [domain](https://nodejs.org/api/domain.html) 的异常处理,开发者需要自行捕捉云函数异步代码中的异常。 +- **不兼容改动** `AV.Cloud.run` 不再支持 Backbone 风格的回调(`success` 和 `error`)、在运行失败时不再向标准输出打印日志,请从返回的 Promise 中获取错误。 -新增云函数和 Class Hook 的 Promise 模式,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 +**新增云函数和 Class Hook 的 Promise 模式**,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 ```javascript AV.Cloud.define(function(request) { @@ -24,7 +24,21 @@ AV.Cloud.define(function(request) { }); ``` -如果传入 `AV.Cloud.define` 的函数有两个参数(`request` 和 `response`)则继续兼容原定义方式,需要使用 `response.success()` 发送响应。我们会继续兼容这种用法到下一个大版本,希望用户尽快迁移到 Promise 风格的云函数上。 +如果传入 `AV.Cloud.define` 的函数有两个参数(`request` 和 `response`)则继续兼容原定义方式,需要使用 `response.success()` 发送响应。我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上。 + +**新增了 LeanCloudHeaders 中间件**,用于在 Express 或 Koa 应用中解析 `X-LC` 开头的头,获取 Session Token 等信息: + +```javascript +// 注册中间件 +app.use(AV.Cloud.LeanCloudHeaders()); + +// 获取 Session Token +app.get('/', (req, res) => { + res.json({ + sessionToken: req.AV.sessionToken + }) +}); +``` ## v1.2.4 diff --git a/README.md b/README.md index 26493a0..73774d3 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,12 @@ # LeanEngine Node.js SDK -[![Build Status](https://travis-ci.org/leancloud/leanengine-node-sdk.svg?branch=master)](https://travis-ci.org/leancloud/leanengine-node-sdk) - ## 安装 ```bash npm install leanengine --save ``` -建议使用 Node.js 4.0 以上的版本(可在 `package.json` 中设置 `engines.node` 为 `4.x`)。 +建议使用 Node.js 6.0 以上的版本(可在 `package.json` 中设置 `engines.node` 为 `6.x`)。 ## 文档 @@ -34,15 +32,3 @@ npm install leanengine --save ```bash npm install leanengine@0.x --save ``` - -## 贡献者 - -在此表示感谢! - -* [filod](https://github.com/filod) - -## 许可协议 - -许可协议: MIT - -作者: wchen (wchen@leancloud.rocks) From 4418ea07fd7efddb7bd62fe6de1fd41772fc7168 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 20 Mar 2017 13:49:08 +0800 Subject: [PATCH 013/122] :ok_hand: Fix API.md --- API.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/API.md b/API.md index a65f847..0ea35d5 100644 --- a/API.md +++ b/API.md @@ -49,7 +49,7 @@ AV.Cloud.define(name: string, func: function) AV.Cloud.define(name: string, options: object, func: function) ``` -定义云函数有两种签名,其中 `options` 是一个可选的参数,`func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,Promise 的值即为云函数的响应。在 Promise 中可以抛出使用 `AV.Cloud.Error` 构造的异常表示错误,如果抛出其他类型的异常则视作服务器端错误,会打印错误到标准输出。 +定义云函数有两种签名,其中 `options` 是一个可选的参数,`func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,Promise 的值即为云函数的响应。在 Promise 中可以抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误,如参数不合法;如果抛出其他类型的异常则视作服务器端错误,会打印错误到标准输出。 `options` 的属性包括: @@ -63,7 +63,7 @@ AV.Cloud.define(name: string, options: object, func: function) * `meta: {remoteAddress}`:`meta.remoteAddress` 是客户端的 IP. * `sessionToken?: string`:客户端发来的 sessionToken(`X-LC-Session` 头)。 -1.x 兼容模式:在早期版本中,云函数和 after 类的 Hook 是接受两个参数(`request` 和 `response`)的,我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上。 +1.x 兼容模式:在早期版本中,云函数和 before 类的 Hook 是接受两个参数(`request` 和 `response`)的,我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上。 ### AV.Cloud.Error @@ -73,7 +73,7 @@ new AV.Cloud.Error(message: string, options?) 继承自 `Error`,用于在云函数和 Class Hook 中表示客户端错误,其中第二个参数支持: -- `status?: number`:设置 HTTP 响应代码(默认 500) +- `status?: number`:设置 HTTP 响应代码(默认 400) - `code?: number`:设置响应正文中的错误代码(默认 1) ### AV.Cloud.run @@ -106,9 +106,7 @@ AV.Cloud.run(name: string, data: object, options?: object): Promise * AV.Cloud.beforeDelete * AV.Cloud.afterDelete -这些函数的签名:`function(className: string, func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数。在 before 类 Hook 中如果没有抛出异常则视作接受这次操作。如果抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误;抛出其他类型的异常视作服务器端错误,会打印到标准输出。 - -在 Promise 中可以抛出使用 `AV.Cloud.Error` 构造的异常表示错误,如果抛出其他类型的异常则视作服务器端错误,返回 500 响应并打印错误到标准输出。 +这些函数的签名:`function(className: string, func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数。在 before 类 Hook 中如果没有抛出异常则视作接受这次操作。如果抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误,拒绝本次操作;如果抛出其他类型的异常则视作服务器端错误,返回 500 响应并打印错误到标准输出。 `Request` 上的属性包括: From 27b9028738b419b26dff4107dbea9469faae33ec Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 20 Mar 2017 14:57:29 +0800 Subject: [PATCH 014/122] :sparkles: Add promise support to hook functions --- lib/cloud.js | 6 ++- lib/leanengine.js | 100 ++++++++++++++++++++++++++++-------------- package.json | 2 +- test/helpers/hooks.js | 20 +++++++++ test/hook-test.js | 75 ++++++++++++++++++++++++++++++- 5 files changed, 167 insertions(+), 36 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index fdd8e4b..39b88a8 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -1,3 +1,5 @@ +'use strict'; + var AV = require('./storage-extra'); var debug = require('debug')('AV:LeanEngine'); var utils = require('./utils'); @@ -119,9 +121,11 @@ AV.Insight.on = function(action, func) { }; Cloud.Error = class CloudError extends Error { - constructor(message, extra = {}) { + constructor(message, extra) { super() + extra = extra || {} + Error.captureStackTrace(this, this.constructor) if (!extra.status) { diff --git a/lib/leanengine.js b/lib/leanengine.js index 8275cde..de638db 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -227,7 +227,7 @@ var call = function(funcName, params, user, req, options, cb) { options = {}; } - const cloudFunction = Cloud.functions[funcName] + const cloudFunction = Cloud.functions[funcName]; if (!cloudFunction) { var err = new Error("LeanEngine not found function named '" + funcName + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); @@ -267,7 +267,7 @@ var call = function(funcName, params, user, req, options, cb) { } else { cb(null, result) } - }).catch( (err) => { + }).catch( err => { if (!err.status) { err.status = 500; } @@ -282,7 +282,10 @@ var call = function(funcName, params, user, req, options, cb) { }; var classHook = function(className, hook, object, user, req, cb) { - if (!Cloud.functions[hook + className]) { + const hookFunction = Cloud.functions[hook + className]; + const isBeforeHook = hook.indexOf('__before_') === 0 + + if (!hookFunction) { var err = new Error("LeanEngine could not find hook '" + hook + className + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); err.statusCode = 404; return cb(err); @@ -293,42 +296,73 @@ var classHook = function(className, hook, object, user, req, cb) { className: className })); - // for beforeUpdate + // for beforeUpdate and afterUpdate if (object._updatedKeys) { obj.updatedKeys = object._updatedKeys; } - try { - var request = utils.prepareRequestObject({ - user: user, - object: obj, - req: req - }); + const request = utils.prepareRequestObject({ + user: user, + object: obj, + req: req + }); - if (hook.indexOf('__after_') === 0) { - setHookMark('__after', obj); - // after 的 hook 不需要 response 参数,并且请求默认返回 ok - Cloud.functions[hook + className](request); - return cb(null, 'ok'); - } else { - setHookMark('__before', obj); - Cloud.functions[hook + className](request, utils.prepareResponseObject(req.res, function(err) { - if (err) { - cb(new Error(err)); - } else if ('__before_delete_for_' === hook) { - cb(null, {}, true); - } else { - cb(null, obj, true); - } - })); - } - } catch (err) { - console.warn('Execute \'' + hook + className + '\' failed with error: ' + (err.stack || err)); - if (hook.indexOf('__after__') === 0) { - return cb(null, 'ok'); + if (isBeforeHook) { + setHookMark('__before', obj); + } else { + setHookMark('__after', obj); + } + + if (isBeforeHook && hookFunction.length === 2) { + try { + if (!isBeforeHook) { + Cloud.functions[hook + className](request); + return cb(null, 'ok'); + } else { + Cloud.functions[hook + className](request, utils.prepareResponseObject(req.res, function(err) { + if (err) { + cb(new Error(err)); + } else if ('__before_delete_for_' === hook) { + cb(null, {}, true); + } else { + cb(null, obj, true); + } + })); + } + } catch (err) { + console.warn('Execute \'' + hook + className + '\' failed with error: ' + (err.stack || err)); + + if (!isBeforeHook) { + cb(null, 'ok'); + } else { + err.statusCode = 500; + cb(err); + } } - err.statusCode = 500; - return cb(err); + } else { + promiseTry(hookFunction.bind(null, request)).then( () => { + if (!isBeforeHook) { + cb(null, 'ok'); + } else if (hook === '__before_delete_for_') { + cb(null, {}, true); + } else { + cb(null, obj, true); + } + }).catch( err => { + if (!err.status) { + err.status = 500; + } + + if (err.status == 500) { + console.warn('Execute \'' + hook + className + '\' failed with error: ' + (err.stack || err)); + } + + if (isBeforeHook) { + cb(err); + } else { + cb(null, 'ok'); + } + }); } }; diff --git a/package.json b/package.json index 7ba4041..4732118 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ } }, "engines": { - "node": ">=4.4.0" + "node": ">=4.4.7" }, "license": "MIT", "author": { diff --git a/test/helpers/hooks.js b/test/helpers/hooks.js index f98792f..2da7d6e 100644 --- a/test/helpers/hooks.js +++ b/test/helpers/hooks.js @@ -14,6 +14,26 @@ AV.Cloud.beforeSave("TestClass", function(request, response) { response.success(); }); +AV.Cloud.beforeSave('TestPromise', function(request) { + assert.equal(request.object.className, 'TestPromise'); +}); + +AV.Cloud.beforeSave('TestPromiseClientError', function(request) { + throw new AV.Cloud.Error('OMG...'); +}); + +AV.Cloud.beforeSave('TestPromiseServerError', function(request) { + return Promise.resolve().then( () => { + noThisMethod(); + }); +}); + +AV.Cloud.afterSave('TestPromiseServerError', function(request) { + return Promise.resolve().then( () => { + noThisMethod(); + }); +}); + AV.Cloud.beforeSave("TestReview", function(request, response){ if (request.object.get("stars") < 1) { response.error("you cannot give less than one star"); diff --git a/test/hook-test.js b/test/hook-test.js index ce1d067..1605731 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -22,7 +22,7 @@ if (process.env.FRAMEWORK == 'koa') { var request = require('supertest'); -request('./helpers/hooks'); +require('./helpers/hooks'); describe('hook', function() { it('beforeSave', function(done) { @@ -47,6 +47,79 @@ describe('hook', function() { }); }); + it('beforeSave (promise)', done => { + request(app) + .post('/1/functions/TestPromise/beforeSave') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('Content-Type', 'application/json') + .send({ + object: { + stars: 1, + __before: '1464591343092,f444ef023b39542b285b2fce86df4b83acf308fe' + }, + }) + .expect(200) + .end(function(err, res) { + res.body.stars.should.equal(1); + done(err); + }); + }); + + it('client error in beforeSave (promise)', (done) => { + request(app) + .post('/1/functions/TestPromiseClientError/beforeSave') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('Content-Type', 'application/json') + .send({ + object: { + stars: 1, + __before: '1464591343092,920600126c77d422e168594b807d93ff85d96a10' + }, + }) + .expect(400) + .end(function(err, res) { + res.body.error.should.equal('OMG...'); + done(err); + }); + }); + + it('server error in beforeSave (promise)', done => { + request(app) + .post('/1/functions/TestPromiseServerError/beforeSave') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('Content-Type', 'application/json') + .send({ + object: { + stars: 1, + __before: '1464591343092,8c4dbae1d25e34669a0688699030a26b9ddfdfd0' + }, + }) + .expect(500) + .end(function(err, res) { + res.body.error.should.be.match(/noThisMethod is not defined/); + done(err); + }); + }); + + it('error in afterSave (promise)', done => { + request(app) + .post('/1/functions/TestPromiseServerError/afterSave') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('Content-Type', 'application/json') + .send({ + object: { + stars: 1, + __after: '1464591343092,d636deff46791816be194997af054f06511aa664' + }, + }) + .expect(200) + .end(done); + }); + it('beforeSave should fail without sign', function(done) { request(app) .post('/1/functions/TestReview/beforeSave') From 724251078d297d25c9efb0ebfdb8709d3858e756 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 20 Mar 2017 17:35:54 +0800 Subject: [PATCH 015/122] :sparkles: Add TypeScript declaration file --- API.md | 3 +- leanengine.d.ts | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 + 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 leanengine.d.ts diff --git a/API.md b/API.md index 0ea35d5..fc7bc59 100644 --- a/API.md +++ b/API.md @@ -184,9 +184,8 @@ app.use(AV.Cloud.CookieSession({secret: 'my secret', maxAge: 3600000, fetchUser: app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true})); ``` -参数包括: +其他参数包括: -* `koa?: boolean`:返回一个 koa(而不是 express)中间件。 * `secret: string`:对 Cookie 进行签名的密钥,请选用一个随机字符串。 * `name?: string`:Cookie 名称,默认为 `avos.sess`。 * `maxAge?: number`:Cookie 过期时间。 diff --git a/leanengine.d.ts b/leanengine.d.ts new file mode 100644 index 0000000..8b2db47 --- /dev/null +++ b/leanengine.d.ts @@ -0,0 +1,115 @@ +import {Promise} from 'es6-promise'; +import {Request, RequestHandler} from 'express'; +import {User as LCUser, Object as LCObject} from 'leancloud-storage'; + +declare namespace Express { + export interface Request { + AV: { + id: string, + key: string, + masterKey: string, + prod: number, + sessionToken: string + }; + + currentUser?: LCUser; + sessionToken?: string; + } + + export interface Response { + saveCurrentUser(user: LCUser); + clearCurrentUser(); + } +} + +declare module 'leanengine' { + interface InitializeOptions { + appId: string, + appKey: string, + masterKey: string + } + + interface MiddlewareOptions { + timeout?: string + } + + export function init(options: InitializeOptions): void; + + export function express(options?: MiddlewareOptions): RequestHandler; + export function koa(options?: MiddlewareOptions): Function; + + export class Object { + disableBeforeHook(): void; + disableAfterHook(): void; + } + + export namespace Cloud { + interface DefineOptions { + fetchUser?: boolean + } + + interface RunOptions { + remote?: boolean, + user?: LCUser, + sessionToken?: string, + req?: Request + } + + interface MiddlewareOptions { + framework?: string + } + + interface CookieSessionOptions extends MiddlewareOptions { + secret: string + fetchUser?: boolean + } + + interface CloudFunctionRequestMeta { + remoteAddress: string + } + + interface CloudFunctionRequest { + meta: CloudFunctionRequestMeta, + params: Object, + currentUser?: LCUser, + sessionToken?: string + } + + interface ClassHookRequest { + object: LCObject, + currentUser?: LCUser + } + + interface UserHookRequest { + currentUser: LCUser + } + + type CloudFunction = (request: CloudFunctionRequest) => Promise; + type ClassHookFunction = (request: ClassHookRequest) => Promise; + type UserHookFunction = (request: UserHookRequest) => Promise; + + export class Error { + constructor(message: string, options?: {status?: number, code?: number}) + } + + export function define(name: string, options: DefineOptions, handler: CloudFunction); + export function define(name: string, handler: CloudFunction); + + export function run(name: string, params: Object, options?: RunOptions): Promise; + export function rpc(name: string, params: Object, options?: RunOptions): Promise; + + export function beforeSave(className: string, handler: ClassHookFunction): void; + export function afterSave(className: string, handler: ClassHookFunction): void; + export function beforeUpdate(className: string, handler: ClassHookFunction): void; + export function afterUpdate(className: string, handler: ClassHookFunction): void; + export function beforeDelete(className: string, handler: ClassHookFunction): void; + export function afterDelete(className: string, handler: ClassHookFunction): void; + + export function onVerified(handler: UserHookFunction): void; + export function onLogin(handler: UserHookFunction): void; + + export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; + export function CookieSession(options?: CookieSessionOptions): RequestHandler; + export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; + } +} diff --git a/package.json b/package.json index 4732118..e05d9c9 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,8 @@ "pattern": "//^((?!(node_modules|test)).)*$/" } }, + "typings": "./leanengine.d.ts", + "types": "./leanengine.d.ts", "engines": { "node": ">=4.4.7" }, From c614b9b5e0dfdd9b57f91b1955c7a055d69bbdf6 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 21 Mar 2017 13:59:28 +0800 Subject: [PATCH 016/122] :sparkles: Add promise support to user hook --- CHANGELOG.md | 14 ++++---- leanengine.d.ts | 6 ++++ lib/leanengine.js | 79 +++++++++++++++++++++++++++++-------------- test/helpers/hooks.js | 2 +- 4 files changed, 68 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e090fa..9ce1fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,17 @@ ## v2.0.0 -- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0)(请检查 JS SDK 2.0 引入的不兼容改动) -- **不兼容改动** 仅兼容至 Node.js 4.4 以上版本 -- **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常 -- **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块) -- **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`) +- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0)(请检查 JS SDK 2.0 引入的不兼容改动)。 +- **不兼容改动** 仅兼容至 Node.js 4.4 以上版本。 +- **不兼容改动** 重复定义云函数或 Hook 时会抛出一个异常。 +- **不兼容改动** 移除 `AV.Cloud.httpRequest`(请改用 `request` 模块)。 +- **不兼容改动** 移除 `app.use(AV.Cloud)` 的用法(请改用 `app.use(AV.express())`)。 - **不兼容改动** 移除基于 [domain](https://nodejs.org/api/domain.html) 的异常处理,开发者需要自行捕捉云函数异步代码中的异常。 - **不兼容改动** `AV.Cloud.run` 不再支持 Backbone 风格的回调(`success` 和 `error`)、在运行失败时不再向标准输出打印日志,请从返回的 Promise 中获取错误。 +- **不兼容改动** `AV.Insight.on` 注册的回调函数改为只接受一个 `result` 参数(去掉了 err 参数,请从 `result.status` 判断成功或失败)。 +- 新增 TypeScript 类型定义文件,位于 `leanengine.d.ts`。 -**新增云函数和 Class Hook 的 Promise 模式**,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 +**新增云函数、Class Hook 和 User Hook 的 Promise 模式**,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 ```javascript AV.Cloud.define(function(request) { diff --git a/leanengine.d.ts b/leanengine.d.ts index 8b2db47..77f1c04 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -43,6 +43,12 @@ declare module 'leanengine' { disableAfterHook(): void; } + export namespace Insight { + type InsightHandler = (result: Object) => Promise; + + export function on(event: string, handler: InsightHandler): Promise; + } + export namespace Cloud { interface DefineOptions { fetchUser?: boolean diff --git a/lib/leanengine.js b/lib/leanengine.js index de638db..720ab54 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -380,28 +380,34 @@ var setHookMark = function(hookAction, obj) { }; var onVerified = function(req, type, user) { - try { - var request = utils.prepareRequestObject({ - user: user, - object: user, - req: req - }); + const request = utils.prepareRequestObject({ + user: user, + object: user, + req: req + }); - Cloud.functions['__on_verified_' + type](request); - } catch (err) { - console.warn('Execute onVerified ' + type + ' failed with error: ' + (err.stack || err)); - } + promiseTry(Cloud.functions['__on_verified_' + type].bind(null, request)).catch( err => { + if (!err.status) { + err.status = 500; + } + + if (err.status == 500) { + console.warn('Execute onVerified ' + type + ' failed with error: ' + (err.stack || err)); + } + }); }; var onLogin = function(req, user, cb) { - try { - var request = utils.prepareRequestObject({ - user: user, - object: user, - req: req - }); + const request = utils.prepareRequestObject({ + user: user, + object: user, + req: req + }); + + const onLoginHook = Cloud.functions['__on_login__User']; - var response = utils.prepareResponseObject(req.res, function(err) { + if (onLoginHook.length === 2) { + const response = utils.prepareResponseObject(req.res, function(err) { if (err) { cb(new Error(err)); } else { @@ -409,18 +415,39 @@ var onLogin = function(req, user, cb) { } }); - Cloud.functions['__on_login__User'](request, response); - } catch (err) { - console.warn('Execute onLogin failed with error: ' + (err.stack || err)); + try { + onLoginHook(request, response); + } catch (err) { + console.warn('Execute onLogin failed with error: ' + (err.stack || err)); + cb(err); + } + } else { + promiseTry(onLoginHook.bind(this, request)).then( () => { + cb(null, 'ok'); + }).catch( err => { + if (!err.status) { + err.status = 500; + } + + if (err.status == 500) { + console.warn('Execute onLogin failed with error: ' + (err.stack || err)); + } + + cb(err); + }); } }; -var onCompleteBigQueryJob = function(data) { - try { - Cloud.functions['__on_complete_bigquery_job'](null, data); - } catch (err) { - console.warn('Execute onCompleteBigQueryJob failed with error: ' + (err.stack || err)); - } +var onCompleteBigQueryJob = function(result) { + promiseTry(Cloud.functions['__on_complete_bigquery_job'].bind(null, result)).catch( err => { + if (!err.status) { + err.status = 500; + } + + if (err.status == 500) { + console.warn('Execute onCompleteBigQueryJob failed with error: ' + (err.stack || err)); + } + }); }; var hookNameMapping = { diff --git a/test/helpers/hooks.js b/test/helpers/hooks.js index 2da7d6e..5c4d38a 100644 --- a/test/helpers/hooks.js +++ b/test/helpers/hooks.js @@ -128,7 +128,7 @@ AV.Cloud.onVerified('sms', function(request) { assert.equal(request.object.get('username'), 'admin'); }); -AV.Insight.on('end', function(err, result) { +AV.Insight.on('end', function(result) { assert.deepEqual({ "id" : "job id", "status": "OK/ERROR", From 89d8aabdc730a848266e4cb5dfba5bba31a9a3cb Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 22 Mar 2017 16:11:57 +0800 Subject: [PATCH 017/122] :hammer: Use promise internally; verify hook key --- CHANGELOG.md | 3 + lib/cloud.js | 4 +- lib/leanengine.js | 489 ++++++++++++++------------------------ lib/storage-extra.js | 8 - lib/utils.js | 1 + test/function-test.js | 102 +------- test/helpers/app-info.js | 1 + test/helpers/functions.js | 35 --- test/helpers/hooks.js | 13 +- test/hook-test.js | 186 +++++---------- 10 files changed, 259 insertions(+), 583 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ce1fe4..87a0d11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - **不兼容改动** 移除基于 [domain](https://nodejs.org/api/domain.html) 的异常处理,开发者需要自行捕捉云函数异步代码中的异常。 - **不兼容改动** `AV.Cloud.run` 不再支持 Backbone 风格的回调(`success` 和 `error`)、在运行失败时不再向标准输出打印日志,请从返回的 Promise 中获取错误。 - **不兼容改动** `AV.Insight.on` 注册的回调函数改为只接受一个 `result` 参数(去掉了 err 参数,请从 `result.status` 判断成功或失败)。 +- **不兼容改动** 一些错误提示被调整过,如果你依赖于对错误信息进行字符串匹配,请注意测试你的错误处理逻辑。 - 新增 TypeScript 类型定义文件,位于 `leanengine.d.ts`。 **新增云函数、Class Hook 和 User Hook 的 Promise 模式**,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 @@ -26,6 +27,8 @@ AV.Cloud.define(function(request) { }); ``` +对于原本不需要响应的 after 类 Hook(还包括 onVerified),现在也会按照同样的方式等待 Promise 完成再发送响应、结束链接,如果你希望收到请求后立刻结束链接,请不要在这类 Hook 中返回 Promise(或提前返回一个已经 resolve 的 Promise)。 + 如果传入 `AV.Cloud.define` 的函数有两个参数(`request` 和 `response`)则继续兼容原定义方式,需要使用 `response.success()` 发送响应。我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上。 **新增了 LeanCloudHeaders 中间件**,用于在 Express 或 Koa 应用中解析 `X-LC` 开头的头,获取 Session Token 等信息: diff --git a/lib/cloud.js b/lib/cloud.js index 39b88a8..f684feb 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -126,8 +126,6 @@ Cloud.Error = class CloudError extends Error { extra = extra || {} - Error.captureStackTrace(this, this.constructor) - if (!extra.status) { extra.status = 400; } @@ -136,6 +134,8 @@ Cloud.Error = class CloudError extends Error { name: 'CloudError', message: message }, extra) + + Error.captureStackTrace(this, this.constructor) } } diff --git a/lib/leanengine.js b/lib/leanengine.js index 720ab54..034037a 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -11,6 +11,22 @@ var utils = require('./utils'); var NODE_ENV = process.env.NODE_ENV || 'development'; +const REALTIME_HOOKS = [ + '_messageReceived', '_receiversOffline', '_messageSent', '_conversationStart', + '_conversationStarted', '_conversationAdd', '_conversationRemove', '_conversationUpdate' +]; + +const hookNameMapping = { + beforeSave: '__before_save_for_', + beforeUpdate: '__before_update_for_', + afterSave: '__after_save_for_', + afterUpdate: '__after_update_for_', + beforeDelete: '__before_delete_for_', + afterDelete: '__after_delete_for_', + onVerified: '__on_verified_', + onLogin: '__on_login_' +}; + AV.express = function(options) { var router = connect(); @@ -79,114 +95,56 @@ function createCloudFunctionRouter(options) { cloudFunctions.use('/_ops/metadatas', function(req, res) { if (req.AV.authMasterKey) { - return resp(res, Object.keys(Cloud.functions)); + return responseJson(res, {result: Object.keys(Cloud.functions)}); } else { return utils.unauthResp(res); } }); - var fetchUserMiddleware = require('../middleware/fetch-user')(AV); - cloudFunctions.use(function(req, res, next) { - if (req.url === '/') { - return respError(res, 'no function or class name'); - } + promiseTry( () => { + if (req.url === '/') { + throw new Cloud.Error(`No function name or class name: ${req.originalUrl}`, {status: 404, printToLog: true}); + } - var fetchUser = function(callback) { - fetchUserMiddleware(req, res, function(err) { - if (err) { - next(err); - } else { - callback(); - } - }); - }; + const [__, functionOrClass, hookName] = req.url.split('/'); - var sendResponse = function(err, data, isBare) { - if (err) { - return respError(res, err); - } - if (isBare) { - return respBare(res, data); + if (!hookName) { + return callCloudFunction(req, functionOrClass); + } else if (functionOrClass === 'onVerified') { + return callUserHook(req, 'onVerified', hookName); + } else if (functionOrClass === '_User' && hookName === 'onLogin') { + return callUserHook(req, 'onLogin', '_User'); + } else if ((functionOrClass === 'BigQuery' || functionOrClass === 'Insight') && hookName === 'onComplete') { + return onCompleteBigQueryJob(req); } else { - return resp(res, data); - } - }; - - var splited = req.url.split('/'); - if (splited.length == 2) { // cloud function - if (_.contains([ - '_messageReceived', '_receiversOffline', '_messageSent', '_conversationStart', '_conversationStarted', - '_conversationAdd', '_conversationRemove', '_conversationUpdate' - ], splited[1])) { - if (!utils.verifyHookSign(AV.masterKey, splited[1], req.body.__sign)) { - console.error('LeanEngine: verifyHookSign failed on', (req.originalUrl || req.url), 'from', utils.getRemoteAddress(req)); - return utils.unauthResp(res); - } + return callClassHook(req, functionOrClass, hookName); } + }).then( response => { + responseJson(res, response); + }).catch( err => { + var statusCode; - var handleCloudfunction = function() { - call(splited[1], req.body, req.AV.user, req, { - decodeAVObject: req.rpcCall - }, function(err, data) { - sendResponse(err, data); - }); - }; - - if (Cloud.functions[splited[1]] && Cloud.functions[splited[1]].fetchUser === false) { - handleCloudfunction(); + if (err instanceof Error) { + statusCode = err.status || err.statusCode || 500; } else { - fetchUser(handleCloudfunction); + statusCode = 400; } - } else if (splited.length == 3) { // class hook - var userObj = new AV.User(); - if (splited[1] === 'onVerified') { - if (utils.verifyHookSign(AV.masterKey, '__on_verified_' + splited[2], req.body.object.__sign)) { - userObj._finishFetch(req.body.object, true); - onVerified(req, splited[2], userObj); - sendResponse(null, 'ok'); - } else { - console.error('LeanEngine: verifyHookSign failed on', (req.originalUrl || req.url), 'from', utils.getRemoteAddress(req)); - return utils.unauthResp(res); - } - } else if (splited[1] === '_User' && splited[2] === 'onLogin') { - if (utils.verifyHookSign(AV.masterKey, '__on_login__User', req.body.object.__sign)) { - userObj._finishFetch(req.body.object, true); - onLogin(req, userObj, sendResponse); - } else { - console.error('LeanEngine: verifyHookSign failed on', (req.originalUrl || req.url), 'from', utils.getRemoteAddress(req)); - return utils.unauthResp(res); - } - } else if ((splited[1] === 'BigQuery' || splited[1] === 'Insight' ) && splited[2] === 'onComplete') { - if (utils.verifyHookSign(AV.masterKey, '__on_complete_bigquery_job', req.body.__sign)) { - onCompleteBigQueryJob(req.body); - sendResponse(null, 'ok'); - } else { - console.error('LeanEngine: verifyHookSign failed on', (req.originalUrl || req.url), 'from', utils.getRemoteAddress(req)); - return utils.unauthResp(res); - } - } else { - var verified = false; - - if (splited[2].indexOf('after') === 0) { - verified = utils.verifyHookSign(AV.masterKey, '__after_for_' + splited[1], req.body.object.__after); - } else { - verified = utils.verifyHookSign(AV.masterKey, '__before_for_' + splited[1], req.body.object.__before); - } - if (!verified) { - console.error('LeanEngine: verifyHookSign failed on', (req.originalUrl || req.url), 'from', utils.getRemoteAddress(req)); - return utils.unauthResp(res); - } + if (statusCode === 500 || err.printToLog) { + console.warn(`LeanEngine: ${req.url}: ${statusCode}: ${err.stack || err.message}`); + } - if (req.body.user) { - userObj._finishFetch(req.body.user, true); - req.AV.user = userObj; - } + if (!res.headersSent) { + res.setHeader('Content-Type', 'application/json; charset=UTF-8'); + res.statusCode = statusCode; - classHook(splited[1], hookNameMapping[splited[2]], req.body.object, userObj, req, sendResponse); + res.end(JSON.stringify({ + code: err.code || 1, + error: err.message || err.responseText || err || 'unknown error' + })); } - } + }); }); cloudFunctions.use(function(err, req, res, next) { // jshint ignore:line @@ -195,271 +153,154 @@ function createCloudFunctionRouter(options) { err.code = 124; // https://leancloud.cn/docs/error_code.html#_124 err.message = 'The request timed out on the server.'; } - respError(res, err); + responseError(res, err); }); return cloudFunctions; } -var resp = function(res, data) { - res.setHeader('Content-Type', 'application/json; charset=UTF-8'); - res.statusCode = 200; - return res.end(JSON.stringify({result: data})); -}; - -var respBare = function(res, data) { - res.setHeader('Content-Type', 'application/json; charset=UTF-8'); - res.statusCode = 200; - return res.end(JSON.stringify(data)); -}; - -var respError = function(res, err) { - res.setHeader('Content-Type', 'application/json; charset=UTF-8'); - res.statusCode = err.status || err.statusCode || 400; - res.end(JSON.stringify({ - code: err.code || 1, - error: err && (err.message || err.responseText || err) || 'null message' - })); -}; - -var call = function(funcName, params, user, req, options, cb) { - if (!options) { - options = {}; - } - +function callCloudFunction(req, funcName) { const cloudFunction = Cloud.functions[funcName]; if (!cloudFunction) { - var err = new Error("LeanEngine not found function named '" + funcName + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); - err.statusCode = 404; - return cb(err); + throw new Cloud.Error(`No such cloud function '${funcName}'`, {status: 404, printToLog: true}); } - if (options.decodeAVObject) { - params = decodeParams(params); + if (_.contains(REALTIME_HOOKS, funcName)) { + checkHookKey(req); } - const request = utils.prepareRequestObject({ - user: user, - params: params, - req: req - }); + var params = req.body; - if (cloudFunction.length == 2) { - const response = utils.prepareResponseObject(req.res, function(err, result) { - if (!err && options.decodeAVObject) { - result = encodeResult(result); - } - cb(err, result); - }); + if (req.rpcCall) { + params = decodeParams(params); + } - try { - cloudFunction(request, response); - } catch (err) { - console.warn('Execute \'' + funcName + '\' failed with error: ' + (err.stack || err)); - err.statusCode = 500; - return cb(err); + return promiseTry( () => { + if (cloudFunction.fetchUser !== false && req.AV.sessionToken && req.AV.sessionToken !== '') { + return AV.User.become(req.AV.sessionToken); } - } else { - promiseTry(cloudFunction.bind(null, request)).then( result => { - if (options.decodeAVObject) { - cb(null, encodeResult(result)) - } else { - cb(null, result) - } - }).catch( err => { - if (!err.status) { - err.status = 500; - } + }).then( user => { + const request = utils.prepareRequestObject({req, user, params}); - if (err.status == 500) { - console.warn('Execute \'' + funcName + '\' failed with error: ' + (err.stack || err)); - } + if (cloudFunction.length === 2) { + return new Promise( (resolve, reject) => { + const response = utils.prepareResponseObject(req.res, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); - cb(err); - }); - } -}; + cloudFunction(request, response); + }); + } else { + return cloudFunction(request); + } + }).then( result => { + if (req.rpcCall) { + return {result: encodeResult(result)}; + } else { + return {result}; + } + }); +} + +function callClassHook(req, className, hookName) { + const hookFunction = Cloud.functions[hookNameMapping[hookName] + className]; + const hookType = hookName.indexOf('before') === 0 ? 'before' : 'after'; -var classHook = function(className, hook, object, user, req, cb) { - const hookFunction = Cloud.functions[hook + className]; - const isBeforeHook = hook.indexOf('__before_') === 0 + checkHookKey(req); if (!hookFunction) { - var err = new Error("LeanEngine could not find hook '" + hook + className + "' for app '" + AV.applicationId + "' on " + NODE_ENV + "."); - err.statusCode = 404; - return cb(err); + throw new Cloud.Error(`No ${hookName} hook of '${className}'`, {status: 404, printToLog: true}); } - var obj = decodeParams(_.extend({}, object, { + const object = decodeParams(_.extend({}, req.body.object, { __type: 'Object', className: className })); - // for beforeUpdate and afterUpdate - if (object._updatedKeys) { - obj.updatedKeys = object._updatedKeys; + if (req.body.object._updatedKeys) { + object.updatedKeys = req.body.object._updatedKeys; } - const request = utils.prepareRequestObject({ - user: user, - object: obj, - req: req - }); - - if (isBeforeHook) { - setHookMark('__before', obj); + if (hookType === 'before') { + object.disableBeforeHook(); } else { - setHookMark('__after', obj); + object.disableAfterHook(); } - if (isBeforeHook && hookFunction.length === 2) { - try { - if (!isBeforeHook) { - Cloud.functions[hook + className](request); - return cb(null, 'ok'); - } else { - Cloud.functions[hook + className](request, utils.prepareResponseObject(req.res, function(err) { - if (err) { - cb(new Error(err)); - } else if ('__before_delete_for_' === hook) { - cb(null, {}, true); - } else { - cb(null, obj, true); - } - })); - } - } catch (err) { - console.warn('Execute \'' + hook + className + '\' failed with error: ' + (err.stack || err)); + const user = decodeUser(req.body.user); + const request = utils.prepareRequestObject({req, object, user}); - if (!isBeforeHook) { - cb(null, 'ok'); - } else { - err.statusCode = 500; - cb(err); - } + return new Promise( (resolve, reject) => { + if (hookType == 'before' && hookFunction.length == 2) { + hookFunction(request, utils.prepareResponseObject(req.res, err => { + if (err) { + reject(err); + } else if (hookName === 'beforeDelete') { + resolve({}); + } else { + resolve(object); + } + })); + } else { + promiseTry(hookFunction.bind(null, request)).then( () => { + if (hookType === 'after') { + resolve({result: 'ok'}); + } else { + resolve(object); + } + }).catch(reject); } - } else { - promiseTry(hookFunction.bind(null, request)).then( () => { - if (!isBeforeHook) { - cb(null, 'ok'); - } else if (hook === '__before_delete_for_') { - cb(null, {}, true); - } else { - cb(null, obj, true); - } - }).catch( err => { - if (!err.status) { - err.status = 500; - } + }); +} - if (err.status == 500) { - console.warn('Execute \'' + hook + className + '\' failed with error: ' + (err.stack || err)); - } +function callUserHook(req, hookName, verifType) { + const userHookFunction = Cloud.functions[hookNameMapping[hookName] + verifType]; - if (isBeforeHook) { - cb(err); - } else { - cb(null, 'ok'); - } - }); - } -}; + checkHookKey(req); -var setHookMark = function(hookAction, obj) { - var sign = obj.get(hookAction); - if(sign) { - obj.set(hookAction, sign); - } else { - if(hookAction.indexOf('__before') === 0) { - obj.disableBeforeHook(); - } else if(hookAction.indexOf('__after') === 0) { - obj.disableAfterHook(); - } + if (!userHookFunction) { + throw new Cloud.Error(`No such hook: ${hookName}`, {status: 404, printToLog: true}); } -}; - -var onVerified = function(req, type, user) { - const request = utils.prepareRequestObject({ - user: user, - object: user, - req: req - }); - promiseTry(Cloud.functions['__on_verified_' + type].bind(null, request)).catch( err => { - if (!err.status) { - err.status = 500; - } - - if (err.status == 500) { - console.warn('Execute onVerified ' + type + ' failed with error: ' + (err.stack || err)); - } - }); -}; + const user = decodeUser(req.body.object); -var onLogin = function(req, user, cb) { const request = utils.prepareRequestObject({ + req: req, user: user, - object: user, - req: req + object: user }); - const onLoginHook = Cloud.functions['__on_login__User']; - - if (onLoginHook.length === 2) { - const response = utils.prepareResponseObject(req.res, function(err) { - if (err) { - cb(new Error(err)); - } else { - cb(null, 'ok'); - } - }); - - try { - onLoginHook(request, response); - } catch (err) { - console.warn('Execute onLogin failed with error: ' + (err.stack || err)); - cb(err); + return new Promise( (resolve, reject) => { + if (hookName === 'onLogin' && userHookFunction.length === 2) { + userHookFunction(request, utils.prepareResponseObject(req.res, err => { + if (err) { + reject(err); + } else { + resolve({result: 'ok'}); + } + })); + } else { + promiseTry(userHookFunction.bind(null, request)).then( () => { + resolve({result: 'ok'}); + }).catch(reject); } - } else { - promiseTry(onLoginHook.bind(this, request)).then( () => { - cb(null, 'ok'); - }).catch( err => { - if (!err.status) { - err.status = 500; - } + }); +} - if (err.status == 500) { - console.warn('Execute onLogin failed with error: ' + (err.stack || err)); - } +function onCompleteBigQueryJob(req) { + checkHookKey(req); - cb(err); - }); - } -}; + return promiseTry(Cloud.functions['__on_complete_bigquery_job'].bind(null, req.body)); +} -var onCompleteBigQueryJob = function(result) { - promiseTry(Cloud.functions['__on_complete_bigquery_job'].bind(null, result)).catch( err => { - if (!err.status) { - err.status = 500; - } +const decodeParams = AV._decode; - if (err.status == 500) { - console.warn('Execute onCompleteBigQueryJob failed with error: ' + (err.stack || err)); - } - }); -}; - -var hookNameMapping = { - beforeSave: '__before_save_for_', - beforeUpdate: '__before_update_for_', - afterSave: '__after_save_for_', - afterUpdate: '__after_update_for_', - beforeDelete: '__before_delete_for_', - afterDelete: '__after_delete_for_' -}; - -var encodeResult = function(result) { +function encodeResult(result) { var encodeAVObject = function(object) { if (object && object._toFullJSON){ object = object._toFullJSON([]); @@ -479,10 +320,38 @@ var encodeResult = function(result) { } }; -var decodeParams = AV._decode; +function responseJson(res, data) { + res.setHeader('Content-Type', 'application/json; charset=UTF-8'); + return res.end(JSON.stringify(data)); +} + +function responseError(res, err) { + res.setHeader('Content-Type', 'application/json; charset=UTF-8'); + res.statusCode = err.status || err.statusCode || 400; + res.end(JSON.stringify({ + code: err.code || 1, + error: err && (err.message || err.responseText || err) || 'null message' + })); +} + +function checkHookKey(req) { + if (req.headers['x-lc-hook-key'] !== AV.hookKey) { + throw new Cloud.Error(`Hook key check failed, request from ${utils.getRemoteAddress(req)}`, { + status: 401, code: 401, printToLog: true + }); + } +} + +function decodeUser(requestUser) { + if (requestUser) { + const user = new AV.User(); + user._finishFetch(requestUser, true); + return user; + } +} function promiseTry(func) { - return new Promise((resolve, reject) => { + return new Promise( (resolve, reject) => { try { Promise.resolve(func()).then(resolve, reject); } catch (err) { diff --git a/lib/storage-extra.js b/lib/storage-extra.js index 567693f..61eb07d 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -16,12 +16,4 @@ AV._config.userAgent = 'AVOS Cloud Code Node ' + require('../package').version; AV.Cloud.__prod = process.env.NODE_ENV === 'production' ? 1 : 0; AV.setProduction(AV.Cloud.__prod); -AV.Object.prototype.disableBeforeHook = function() { - this.set('__before', utils.signHook(AV.masterKey, '__before_for_' + this.className, new Date().getTime())); -}; - -AV.Object.prototype.disableAfterHook = function() { - this.set('__after', utils.signHook(AV.masterKey, '__after_for_' + this.className, new Date().getTime())); -}; - module.exports = AV; diff --git a/lib/utils.js b/lib/utils.js index b79765e..bcaf66e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,5 @@ 'use strict'; + var crypto = require('crypto'); exports.typeOf = function(obj) { diff --git a/test/function-test.js b/test/function-test.js index c4460cb..f72387a 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -14,6 +14,7 @@ require('./helpers/hooks'); const appId = appInfo.appId; const appKey = appInfo.appKey; const masterKey = appInfo.masterKey; +const hookKey = appInfo.hookKey; const sessionTokenAdmin = appInfo.sessionTokenAdmin; const app = helpers.app(); @@ -305,6 +306,7 @@ describe('functions', function() { .post('/1/functions/_messageReceived') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .send({ __sign: '1464591343092,6ac315b96655d04e3a49d758f5a8ae55208c98f0' }) @@ -328,8 +330,8 @@ describe('functions', function() { .set('X-AVOSCloud-Application-Key', appKey) .expect(404) .expect({ - "code": 1, - "error": "LeanEngine not found function named 'noThisMethod' for app '" + appId + "' on development." + code: 1, + error: `No such cloud function 'noThisMethod'` }, done); }); @@ -376,16 +378,6 @@ describe('functions', function() { .expect(200, done); }); - // 测试调用 run 方法 options callback - it('testRun_options_callback', function(done) { - request(app) - .post('/1/functions/testRun_options_callback') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .set('x-avoscloud-session-token', sessionTokenAdmin) - .expect(200, done); - }); - // 测试调用 run 方法,返回值是 promise 类型 it('testRun_promise', function(done) { request(app) @@ -422,40 +414,15 @@ describe('functions', function() { .expect(200, done); }); - // 测试 onVerified hook 的有效性 - it('onVerified', function(done) { - request(app) - .post("/1/functions/onVerified/sms") - .set('X-Uluru-Application-Id', appId) - .set('X-Uluru-Application-Key', appKey) - .send({ - object: { - objectId: '54fd6a03e4b06c41e00b1f40', - username: 'admin', - __sign: '1464591343092,b0c8463a3c12bf4241820c52963515d9a363b6bc' - } - }) - .expect(200) - .expect({ result: 'ok'}, done); - }); - // 测试抛出异常时的处理 it('throw Error', function(done) { - var stderr_write = process.stderr.write; - var strings = []; - global.process.stderr.write = function(string) { - strings.push(string); - }; request(app) .post('/1/functions/testThrowError') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) - .expect(500) - .expect({result: 'ok'}, function() { - assert.deepEqual('Execute \'testThrowError\' failed with error: ReferenceError: noThisMethod is not defined', strings[0].split('\n')[0]); - assert.equal(1, strings.length); - global.process.stderr.write = stderr_write; - done(); + .expect(500, (err, res) => { + res.body.error.should.be.equal('noThisMethod is not defined'); + done(err) }); }); @@ -477,43 +444,6 @@ describe('functions', function() { }); }); - // 用户串号测试 - it('user_matching_func', function(done) { - this.timeout(30000); - var count = 0; - var cb = function(err) { - if (err) { - throw err; - } - count++; - if (count === 10) { - return done(); - } - }; - var doRequest = function(sessionToken, username, cb) { - var r = request(app) - .post('/1.1/functions/userMatching') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey); - if (sessionToken) { - r.set('X-AVOSCloud-session-token', sessionToken); - } - r.end(function(err, res) { - if (username) { - res.body.result.reqUser.username.should.equal(username); - } else { - should.not.exist(res.body.reqUser); - } - return cb(err); - }); - }; - for (var i = 0; i <= 4; i++) { - doRequest(sessionTokenAdmin, 'admin', cb); - doRequest('0hgr13u12tmgyv4x594682sv5', 'zhangsan', cb); - doRequest(null, null, cb); - } - }); - it('_metadatas', function(done) { request(app) .get('/1/functions/_ops/metadatas') @@ -528,8 +458,7 @@ describe('functions', function() { 'testRunWithUser', 'readDir', '__on_verified_sms', - 'testThrowError', - 'userMatching' ]); + 'testThrowError']); done(); }); }); @@ -543,19 +472,4 @@ describe('functions', function() { .expect('access-control-allow-origin', 'http://foo.bar') .expect(200, done); }); - - it('onCompleteBigqueryJob', function(done) { - request(app) - .post('/1.1/functions/BigQuery/onComplete') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .send({ - id : "job id", - status: "OK/ERROR", - message: "当 status 为 ERROR 时的错误消息", - __sign: '1464591343092,44c8f6a8a0520bc4636d890935aee0977ef34dd6' - }) - .expect(200, done); - }); - }); diff --git a/test/helpers/app-info.js b/test/helpers/app-info.js index 457bfdd..7bbe604 100644 --- a/test/helpers/app-info.js +++ b/test/helpers/app-info.js @@ -4,6 +4,7 @@ const appInfo = { appId: '4h2h4okwiyn8b6cle0oig00vitayum8ephrlsvg7xo8o19ne', appKey: '3xjj1qw91cr3ygjq9lt0g8c3qpet38rrxtwmmp0yffyoy2t4', masterKey: '3v7z633lzfec9qzx8sjql6zimvdpmtwypcchr2gelu5mrzb0', + hookKey: 'qlkcRqv9v5J5A11Byr3mzori', sessionTokenAdmin: 'w2jrtkbehp38otqmhbqu7ybs9' }; diff --git a/test/helpers/functions.js b/test/helpers/functions.js index 6be905e..d23740d 100644 --- a/test/helpers/functions.js +++ b/test/helpers/functions.js @@ -143,26 +143,6 @@ AV.Cloud.define('testRun', function(request, response) { ); }); -AV.Cloud.define('testRun_options_callback', function(request, response) { - AV.Cloud.run('choice', {choice: true}).then( - function(data) { - assert.equal('OK~', data); - AV.Cloud.run('choice', {choice: false}).then( - function(data) { - assert.ifError(data); - }, - function(err) { - assert.equal('OMG...', err); - response.success(); - } - ); - }, - function(err) { - assert.ifError(err); - } - ); -}); - AV.Cloud.define('testRun_promise', function(request, response) { AV.Cloud.run('choice', {choice: true}).then(function(data) { assert.equal('OK~', data); @@ -233,21 +213,6 @@ AV.Cloud.define('serverErrorPromise', function(request) { noThisMethod(); }); -AV.Cloud.define("userMatching", function(req, res) { - setTimeout(function() { - // 为了更加靠谱的验证串号问题,走一次网络 IO - var query = new AV.Query(TestObject); - query.get('55069f5be4b0c93838ed9b17').then( - function(obj) { - assert.equal(obj.get('foo'), 'bar'); - res.success({reqUser: req.user, currentUser: AV.User.current()}); - }, function() { - res.success({reqUser: req.user, currentUser: AV.User.current()}); - } - ); - }, Math.floor((Math.random() * 2000) + 1)); -}); - AV.Cloud.define('testTimeout', function(req, res) { setTimeout(function() { try { diff --git a/test/helpers/hooks.js b/test/helpers/hooks.js index 5c4d38a..5d08800 100644 --- a/test/helpers/hooks.js +++ b/test/helpers/hooks.js @@ -10,7 +10,6 @@ AV.Cloud.beforeSave("TestClass", function(request, response) { } assert.equal(request.object.className, 'TestClass'); request.object.set('user', request.user); - should.exist(request.object.get('__before')); response.success(); }); @@ -84,7 +83,6 @@ AV.Cloud.afterSave("TestError", function() { AV.Cloud.afterUpdate("TestClass", function(request) { var bizTime = new Date(); assert(request.object.updatedKeys.indexOf('foo') != -1); - should.exist(request.object.get('__after')); request.object.set('bizTime', bizTime); request.object.save().then( function(obj) { @@ -101,15 +99,6 @@ AV.Cloud.beforeDelete("TestClass", function(request, response) { response.success(); }); -AV.Cloud.beforeSave("HookMarkTest", function(request, response) { - should.exist(request.object.get('__before')); - response.success(request.object); -}); - -AV.Cloud.afterSave("HookMarkTest", function(request) { - should.exist(request.object.get('__after')); -}); - AV.Cloud.onLogin(function(request, response) { // 因为此时用户还没有登录,所以用户信息是保存在 request.object 对象中 assert(request.object); @@ -133,5 +122,5 @@ AV.Insight.on('end', function(result) { "id" : "job id", "status": "OK/ERROR", "message": "当 status 为 ERROR 时的错误消息" - }, _.omit(result, '__sign')); + }, result); }); diff --git a/test/hook-test.js b/test/hook-test.js index 1605731..ac0e83e 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -9,6 +9,7 @@ const appInfo = require('./helpers/app-info'); var appId = appInfo.appId; var appKey = appInfo.appKey; var masterKey = appInfo.masterKey; +var hookKey = appInfo.hookKey; var app; @@ -30,19 +31,18 @@ describe('hook', function() { .post('/1/functions/TestReview/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { comment: '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890', - stars: 1, - __before: '1464591343092,f1f51166c96d5642e411762987cd506da8769627' + stars: 1 }, }) .expect(200) .end(function(err, res) { res.body.stars.should.equal(1); res.body.comment.should.equal('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567...'); - should.exist(res.body.__before); done(); }); }); @@ -52,11 +52,11 @@ describe('hook', function() { .post('/1/functions/TestPromise/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { - stars: 1, - __before: '1464591343092,f444ef023b39542b285b2fce86df4b83acf308fe' + stars: 1 }, }) .expect(200) @@ -71,11 +71,11 @@ describe('hook', function() { .post('/1/functions/TestPromiseClientError/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { - stars: 1, - __before: '1464591343092,920600126c77d422e168594b807d93ff85d96a10' + stars: 1 }, }) .expect(400) @@ -90,11 +90,11 @@ describe('hook', function() { .post('/1/functions/TestPromiseServerError/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { - stars: 1, - __before: '1464591343092,8c4dbae1d25e34669a0688699030a26b9ddfdfd0' + stars: 1 }, }) .expect(500) @@ -109,14 +109,14 @@ describe('hook', function() { .post('/1/functions/TestPromiseServerError/afterSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { - stars: 1, - __after: '1464591343092,d636deff46791816be194997af054f06511aa664' + stars: 1 }, }) - .expect(200) + .expect(500) .end(done); }); @@ -134,7 +134,7 @@ describe('hook', function() { }) .expect(401) .end(function(err, res) { - res.body.error.should.equal('Unauthorized.'); + res.body.error.should.match(/Hook key check failed/); done(); }); }); @@ -144,6 +144,7 @@ describe('hook', function() { .post('/1/functions/ContainsFile/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { @@ -151,8 +152,7 @@ describe('hook', function() { __type: 'File', objectId: '55543fc2e4b0846760bd92f3', url: 'http://ac-4h2h4okw.clouddn.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg' - }, - __before: '1464591343092,9761baef9f36ee98ecd582ee142dabe31fbae17a' + } } }) .expect(200, done); @@ -163,11 +163,11 @@ describe('hook', function() { .post('/1/functions/TestReview/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { - "stars": 0, - __before: '1464591343092,f1f51166c96d5642e411762987cd506da8769627' + "stars": 0 } }) .expect(400) @@ -179,6 +179,7 @@ describe('hook', function() { .post('/1/functions/TestClass/beforeSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "user": { @@ -189,9 +190,7 @@ describe('hook', function() { "createdAt": "2013-12-16T16:37:50.059Z", "updatedAt": "2013-12-16T16:37:50.059Z" }, - "object": { - __before: '1464591343092,3f878d2fff4dc8b651c313546220c95d9a847261' - } + "object": {} }) .expect(200) .end(function(err, res) { @@ -200,7 +199,6 @@ describe('hook', function() { "className": "_User", "objectId": "52aebbdee4b0c8b6fa455aa7" }); - should.exist(res.body.__before); done(); }); }); @@ -216,18 +214,18 @@ describe('hook', function() { .post("/1.1/functions/ErrorObject/beforeSave") .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .send({ object: { - foo: 'bar', - __before: '1464591343092,87f14f124be9bcdca1cd28d82887882ad4ee2cbc' + foo: 'bar' } }) .expect(500, function(err, res) { res.body.code.should.be.equal(1); - res.body.error.should.be.match(/(undefined|a\.noThisMethod) is not a function/); + res.body.error.should.be.equal('a.noThisMethod is not a function'); console.warn = ori; warnLogs.some(function(log) { - return log[0].trim().match(/Execute '__before_save_for_ErrorObject' failed with error: TypeError: (undefined|a\.noThisMethod) is not a function/); + return log[0].trim().match(/LeanEngine: \/ErrorObject\/beforeSave: 500: TypeError: a\.noThisMethod is not a function/); }).should.equal(true); done(); }); @@ -238,14 +236,14 @@ describe('hook', function() { .post("/1.1/functions/NoThisObject/beforeSave") .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .send({ object: { - foo: 'bar', - __before: '1464591343092,a5092e1168c90846dcfbd4a1044d757ae4e22d74' + foo: 'bar' } }) .expect(404) - .expect({ code: 1, error: "LeanEngine could not find hook '__before_save_for_NoThisObject' for app '" + appId + "' on development." }, done); + .expect({ code: 1, error: `No beforeSave hook of 'NoThisObject'` }, done); }); it('beforeUpdate', function(done) { @@ -253,13 +251,13 @@ describe('hook', function() { .post('/1/functions/TestReview/beforeUpdate') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "_updatedKeys": ['comment'], "comment": "a short comment", - "stars": 1, - __before: '1464591343092,f1f51166c96d5642e411762987cd506da8769627' + "stars": 1 } }) .expect(200, done); @@ -270,13 +268,13 @@ describe('hook', function() { .post('/1/functions/TestReview/beforeUpdate') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "_updatedKeys": ['star'], "comment": "a short comment", - "stars": 1, - __before: '1464591343092,f1f51166c96d5642e411762987cd506da8769627' + "stars": 1 } }) .expect(200, done); @@ -287,13 +285,13 @@ describe('hook', function() { .post('/1/functions/TestReview/beforeUpdate') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "_updatedKeys": ['comment'], "comment": "a looooooooooooooooooooooooooooooooooooooog comment", - "stars": 1, - __before: '1464591343092,f1f51166c96d5642e411762987cd506da8769627' + "stars": 1 } }) .expect(400) @@ -305,14 +303,14 @@ describe('hook', function() { .post('/1/functions/TestReview/afterSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "objectId": "5403e36be4b0b77b5746b292", "post": { "objectId": "5403e36be4b0b77b5746b291" - }, - __after: '1464591343092,d9e59a2ffffa2fab568c6aa5372ea6fb58eed29d' + } } }) .expect(200) @@ -331,18 +329,18 @@ describe('hook', function() { .post('/1/functions/TestError/afterSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "post": { "objectId": "5403e36be4b0b77b5746b291" - }, - __after: '1464591343092,0a94f5bad8e437471fa3038caaa3f419f376222d' + } } }) .expect(200) .expect({result: 'ok'}, function() { - assert.deepEqual('Execute \'__after_save_for_TestError\' failed with error: ReferenceError: noThisMethod is not defined', strings[0].split('\n')[0]); + assert.deepEqual(`LeanEngine: /TestError/afterSave: 500: ReferenceError: noThisMethod is not defined`, strings[0].split('\n')[0]); assert.equal(1, strings.length); global.process.stderr.write = stderr_write; done(); @@ -354,17 +352,17 @@ describe('hook', function() { .post('/1/functions/NoThisClass/afterSave') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "post": { "objectId": "5403e36be4b0b77b5746b291" - }, - __after: '1464591343092,8dfcc1e306877697c43d8503ad24273641a9e802' + } } }) .expect(404) - .expect({ code: 1, error: "LeanEngine could not find hook \'__after_save_for_NoThisClass\' for app \'" + appId + "\' on development." }, done); + .expect({ code: 1, error: `No afterSave hook of 'NoThisClass'` }, done); }); it('afterUpdate', function(done) { @@ -372,13 +370,13 @@ describe('hook', function() { .post('/1/functions/TestClass/afterUpdate') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { "_updatedKeys": ['foo'], objectId: '556904d8e4b09419960c14bd', - foo: 'bar', - __after: '1464591343092,3261f123d432ff33040d65af3957811179637d97' + foo: 'bar' } }) .expect(200, function(err, res) { @@ -394,12 +392,12 @@ describe('hook', function() { .post('/1/functions/TestClass/beforeDelete') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { objectId: '55690242e4b09419960c01f5', - foo: 'bar', - __before: '1464591343092,3f878d2fff4dc8b651c313546220c95d9a847261' + foo: 'bar' } }) .expect(200) @@ -411,12 +409,12 @@ describe('hook', function() { .post('/1/functions/TestClass/beforeDelete') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ object: { objectId: '55690242e4b09419960c01f6', - foo: 'important', - __before: '1464591343092,3f878d2fff4dc8b651c313546220c95d9a847261' + foo: 'important' } }) .expect(400) @@ -428,12 +426,12 @@ describe('hook', function() { .post('/1/functions/onVerified/sms') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "objectId": '54fd6a03e4b06c41e00b1f40', - "username": 'admin', - __sign: '1464591343092,b0c8463a3c12bf4241820c52963515d9a363b6bc' + "username": 'admin' }, }) .expect(200) @@ -447,12 +445,12 @@ describe('hook', function() { .post('/1/functions/_User/onLogin') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "objectId": '54fd6a03e4b06c41e00b1f40', - "username": 'admin', - __sign: '1464591343092,0a890df4759cb6b781670b1eed5faa0e77cd27de' + "username": 'admin' } }) .expect(200) @@ -466,12 +464,12 @@ describe('hook', function() { .post('/1/functions/_User/onLogin') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) .set('Content-Type', 'application/json') .send({ "object": { "objectId": '55068ea4e4b0c93838ece36d', - "username": 'noLogin', - __sign: '1464591343092,0a890df4759cb6b781670b1eed5faa0e77cd27de' + "username": 'noLogin' } }) .expect(400) @@ -499,73 +497,17 @@ describe('hook', function() { }); }); - describe('hookMark', function() { - it('before', function(done) { - request(app) - .post('/1/functions/HookMarkTest/beforeSave') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .set('Content-Type', 'application/json') - .send({ - "object": { - "foo": "bar", - __before: '1464591343092,89bd1b16aa5732ac41eadac8658789b156cd4f44' - } - }) - .expect(200) - .end(function(err, res) { - res.body.__before.should.equal('1464591343092,89bd1b16aa5732ac41eadac8658789b156cd4f44'); - done(); - }); - }); - - it('before_no_attrib', function(done) { - request(app) - .post('/1/functions/HookMarkTest/beforeSave') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .set('Content-Type', 'application/json') - .send({ - "object": { - "foo": "bar", - __before: '1464591343092,89bd1b16aa5732ac41eadac8658789b156cd4f44' - } - }) - .expect(200) - .end(function(err, res) { - should.exist(res.body.__before); - done(); - }); - }); - - it('after', function(done) { - request(app) - .post('/1/functions/HookMarkTest/afterSave') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .set('Content-Type', 'application/json') - .send({ - "object": { - "foo": "bar", - "__after": '1464591343092,14e0b7a09eb7c6e00f2ab6b7a7bb2d22ff60eedc' - } - }) - .expect(200, done); - }); - - it('after_no_attrib', function(done) { - request(app) - .post('/1/functions/HookMarkTest/afterSave') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .set('Content-Type', 'application/json') - .send({ - "object": { - "foo": "bar", - "__after": '1464591343092,14e0b7a09eb7c6e00f2ab6b7a7bb2d22ff60eedc' - } - }) - .expect(200, done); - }); + it('onCompleteBigqueryJob', function(done) { + request(app) + .post('/1.1/functions/BigQuery/onComplete') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) + .send({ + id : "job id", + status: "OK/ERROR", + message: "当 status 为 ERROR 时的错误消息" + }) + .expect(200, done); }); }); From 4cc4c34dc4f210dc15b97b49e8d972defff105fd Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 22 Mar 2017 16:18:56 +0800 Subject: [PATCH 018/122] :sparkles: Add printFullStack option --- leanengine.d.ts | 3 ++- lib/leanengine.js | 16 ++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index 77f1c04..792d17d 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -30,7 +30,8 @@ declare module 'leanengine' { } interface MiddlewareOptions { - timeout?: string + timeout?: string, + printFullStack?: boolean } export function init(options: InitializeOptions): void; diff --git a/lib/leanengine.js b/lib/leanengine.js index 034037a..5398b94 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -104,7 +104,7 @@ function createCloudFunctionRouter(options) { cloudFunctions.use(function(req, res, next) { promiseTry( () => { if (req.url === '/') { - throw new Cloud.Error(`No function name or class name: ${req.originalUrl}`, {status: 404, printToLog: true}); + throw new Cloud.Error(`No function name or class name: ${req.originalUrl}`, {status: 404, printToLog: true, printFullStack: false}); } const [__, functionOrClass, hookName] = req.url.split('/'); @@ -132,7 +132,11 @@ function createCloudFunctionRouter(options) { } if (statusCode === 500 || err.printToLog) { - console.warn(`LeanEngine: ${req.url}: ${statusCode}: ${err.stack || err.message}`); + if (options.printFullStack !== false && err.printFullStack !== false) { + console.warn(`LeanEngine: ${req.url}: ${statusCode}: ${err.stack || err.message}`); + } else { + console.warn(`LeanEngine: ${req.url}: ${statusCode}: ${err.name}: ${err.message}`); + } } if (!res.headersSent) { @@ -163,7 +167,7 @@ function callCloudFunction(req, funcName) { const cloudFunction = Cloud.functions[funcName]; if (!cloudFunction) { - throw new Cloud.Error(`No such cloud function '${funcName}'`, {status: 404, printToLog: true}); + throw new Cloud.Error(`No such cloud function '${funcName}'`, {status: 404, printToLog: true, printFullStack: false}); } if (_.contains(REALTIME_HOOKS, funcName)) { @@ -214,7 +218,7 @@ function callClassHook(req, className, hookName) { checkHookKey(req); if (!hookFunction) { - throw new Cloud.Error(`No ${hookName} hook of '${className}'`, {status: 404, printToLog: true}); + throw new Cloud.Error(`No ${hookName} hook of '${className}'`, {status: 404, printToLog: true, printFullStack: false}); } const object = decodeParams(_.extend({}, req.body.object, { @@ -264,7 +268,7 @@ function callUserHook(req, hookName, verifType) { checkHookKey(req); if (!userHookFunction) { - throw new Cloud.Error(`No such hook: ${hookName}`, {status: 404, printToLog: true}); + throw new Cloud.Error(`No such hook: ${hookName}`, {status: 404, printToLog: true, printFullStack: false}); } const user = decodeUser(req.body.object); @@ -337,7 +341,7 @@ function responseError(res, err) { function checkHookKey(req) { if (req.headers['x-lc-hook-key'] !== AV.hookKey) { throw new Cloud.Error(`Hook key check failed, request from ${utils.getRemoteAddress(req)}`, { - status: 401, code: 401, printToLog: true + status: 401, code: 401, printToLog: true, printFullStack: false }); } } From eecc1acc250c6cf9f6883ecee0426f118af8865e Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 22 Mar 2017 17:10:34 +0800 Subject: [PATCH 019/122] :sparkles: Add realtime hook define function --- CHANGELOG.md | 1 + leanengine.d.ts | 8 +++++++ lib/cloud.js | 6 ++++- lib/leanengine.js | 22 +++--------------- lib/utils.js | 47 +++++++++++++++----------------------- package.json | 2 +- test/helpers/functions.js | 2 +- test/storage-extra-test.js | 31 ------------------------- 8 files changed, 38 insertions(+), 81 deletions(-) delete mode 100644 test/storage-extra-test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 87a0d11..271f4be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - **不兼容改动** `AV.Insight.on` 注册的回调函数改为只接受一个 `result` 参数(去掉了 err 参数,请从 `result.status` 判断成功或失败)。 - **不兼容改动** 一些错误提示被调整过,如果你依赖于对错误信息进行字符串匹配,请注意测试你的错误处理逻辑。 - 新增 TypeScript 类型定义文件,位于 `leanengine.d.ts`。 +- 新增 `AV.Cloud.onIMMessageReceived` 系列方法,用于更方便地定义实时通讯 Hook 函数。 **新增云函数、Class Hook 和 User Hook 的 Promise 模式**,会使用 Promise 的值作为响应内容。如果在 Promise 中抛了使用新增的 `AV.Cloud.Error` 构造的异常则作为错误返回给客户端,`AV.Cloud.Error` 的第二个参数可以指定 HTTP Status Code 和 Error Code(`AV.Cloud.Error('posts is empty', {status: 422, code: 422})`);如果抛出了其他错误类型则视作服务器端错误,返回 500 响应并打印错误到标准输出。 diff --git a/leanengine.d.ts b/leanengine.d.ts index 792d17d..74bf5aa 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -115,6 +115,14 @@ declare module 'leanengine' { export function onVerified(handler: UserHookFunction): void; export function onLogin(handler: UserHookFunction): void; + export function onIMMessageReceived(handler: CloudFunction): void; + export function onIMReceiversOffline(handler: CloudFunction): void; + export function onIMMessageSent(handler: CloudFunction): void; + export function onIMConversationStart(handler: CloudFunction): void; + export function onIMConversationStarted(handler: CloudFunction): void; + export function onIMConversationAdd(handler: CloudFunction): void; + export function onIMConversationUpdate(handler: CloudFunction): void; + export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; export function CookieSession(options?: CookieSessionOptions): RequestHandler; export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; diff --git a/lib/cloud.js b/lib/cloud.js index f684feb..107e58b 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -112,6 +112,10 @@ Cloud.onLogin = function(func) { Cloud.define('__on_login__User', func); }; +_.each(utils.realtimeHookMapping, (metadataName, hookName) => { + Cloud[hookName] = Cloud.define.bind(null, metadataName); +}); + if (!AV.Insight) { AV.Insight = {}; } @@ -168,7 +172,7 @@ function defineClassHook(className, hook, func) { } function className(clazz) { - if (utils.typeOf(clazz) === 'string') { + if (_.isString(clazz)) { return clazz; } else if (clazz.className) { return clazz.className; diff --git a/lib/leanengine.js b/lib/leanengine.js index 5398b94..7706219 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -11,22 +11,6 @@ var utils = require('./utils'); var NODE_ENV = process.env.NODE_ENV || 'development'; -const REALTIME_HOOKS = [ - '_messageReceived', '_receiversOffline', '_messageSent', '_conversationStart', - '_conversationStarted', '_conversationAdd', '_conversationRemove', '_conversationUpdate' -]; - -const hookNameMapping = { - beforeSave: '__before_save_for_', - beforeUpdate: '__before_update_for_', - afterSave: '__after_save_for_', - afterUpdate: '__after_update_for_', - beforeDelete: '__before_delete_for_', - afterDelete: '__after_delete_for_', - onVerified: '__on_verified_', - onLogin: '__on_login_' -}; - AV.express = function(options) { var router = connect(); @@ -170,7 +154,7 @@ function callCloudFunction(req, funcName) { throw new Cloud.Error(`No such cloud function '${funcName}'`, {status: 404, printToLog: true, printFullStack: false}); } - if (_.contains(REALTIME_HOOKS, funcName)) { + if (_.contains(_.values(utils.realtimeHookMapping), funcName)) { checkHookKey(req); } @@ -212,7 +196,7 @@ function callCloudFunction(req, funcName) { } function callClassHook(req, className, hookName) { - const hookFunction = Cloud.functions[hookNameMapping[hookName] + className]; + const hookFunction = Cloud.functions[utils.hookNameMapping[hookName] + className]; const hookType = hookName.indexOf('before') === 0 ? 'before' : 'after'; checkHookKey(req); @@ -263,7 +247,7 @@ function callClassHook(req, className, hookName) { } function callUserHook(req, hookName, verifType) { - const userHookFunction = Cloud.functions[hookNameMapping[hookName] + verifType]; + const userHookFunction = Cloud.functions[utils.hookNameMapping[hookName] + verifType]; checkHookKey(req); diff --git a/lib/utils.js b/lib/utils.js index bcaf66e..363d6db 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -2,22 +2,25 @@ var crypto = require('crypto'); -exports.typeOf = function(obj) { - var classToType; - if (obj === void 0 || obj === null) { - return String(obj); - } - classToType = { - '[object Boolean]': 'boolean', - '[object Number]': 'number', - '[object String]': 'string', - '[object Function]': 'function', - '[object Array]': 'array', - '[object Date]': 'date', - '[object RegExp]': 'regexp', - '[object Object]': 'object' - }; - return classToType[Object.prototype.toString.call(obj)]; +exports.hookNameMapping = { + beforeSave: '__before_save_for_', + beforeUpdate: '__before_update_for_', + afterSave: '__after_save_for_', + afterUpdate: '__after_update_for_', + beforeDelete: '__before_delete_for_', + afterDelete: '__after_delete_for_', + onVerified: '__on_verified_', + onLogin: '__on_login_' +}; + +exports.realtimeHookMapping = { + onIMMessageReceived: '_messageReceived', + onIMReceiversOffline: '_receiversOffline', + onIMMessageSent: '_messageSent', + onIMConversationStart: '_conversationStart', + onIMConversationStarted: '_conversationStarted', + onIMConversationAdd: '_conversationAdd', + onIMConversationUpdate: '_conversationUpdate' }; exports.unauthResp = function(res) { @@ -26,18 +29,6 @@ exports.unauthResp = function(res) { return res.end(JSON.stringify({ code: 401, error: 'Unauthorized.' })); }; -exports.signHook = function(masterKey, hookName, ts) { - return ts + ',' + crypto.createHmac('sha1', masterKey).update(hookName + ':' + ts).digest('hex'); -}; - -exports.verifyHookSign = function(masterKey, hookName, sign) { - if (sign) { - return exports.signHook(masterKey, hookName, sign.split(',')[0]) === sign; - } else { - return false; - } -}; - /* options: req, user, params, object*/ exports.prepareRequestObject = function(options) { var req = options.req; diff --git a/package.json b/package.json index e05d9c9..b28fdf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.0-rc.0", + "version": "2.0.0-beta", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", diff --git a/test/helpers/functions.js b/test/helpers/functions.js index d23740d..7729d3d 100644 --- a/test/helpers/functions.js +++ b/test/helpers/functions.js @@ -223,6 +223,6 @@ AV.Cloud.define('testTimeout', function(req, res) { }, req.params.delay); }); -AV.Cloud.define('_messageReceived', function(request, response) { +AV.Cloud.onIMMessageReceived(function(request, response) { response.success('ok'); }); diff --git a/test/storage-extra-test.js b/test/storage-extra-test.js deleted file mode 100644 index b56175b..0000000 --- a/test/storage-extra-test.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -var AV = require('../lib/storage-extra.js'); - -var express = require('express'); -var bodyParser = require('body-parser'); -var app = express(); -const appInfo = require('./helpers/app-info'); -var utils = require('../lib/utils'); - -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: false })); - -app.get('/hello', function (req, res) { - res.send('Hello, ' + req.query.name); -}); - -app.post('/hello', function (req, res) { - res.send('Hello, ' + req.body.name); -}); - -var server = app.listen(3333, function () {}); - -after(function() { - server.close(); -}); - -describe('storage-extra', function() { - it('signDisableHook', function() { - utils.signHook(appInfo.masterKey, '__before_for_TestClass', 1453711871302).should.equal('1453711871302,a9611dbc226eed1a5f4aa0e4fa20e2d014aeaeb8'); - }); -}); From 9a2509a32b2bbb8aed6f29ba886c4ace58b7b497 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 23 Mar 2017 14:12:30 +0800 Subject: [PATCH 020/122] :bookmark: Release 2.0.0-beta.0 --- API.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/API.md b/API.md index fc7bc59..b3ae99e 100644 --- a/API.md +++ b/API.md @@ -63,7 +63,7 @@ AV.Cloud.define(name: string, options: object, func: function) * `meta: {remoteAddress}`:`meta.remoteAddress` 是客户端的 IP. * `sessionToken?: string`:客户端发来的 sessionToken(`X-LC-Session` 头)。 -1.x 兼容模式:在早期版本中,云函数和 before 类的 Hook 是接受两个参数(`request` 和 `response`)的,我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上。 +1.x 兼容模式:在早期版本中,云函数和 before 类的 Hook 是接受两个参数(`request` 和 `response`)的,**我们会继续兼容这种用法到下一个大版本,希望开发者尽快迁移到 Promise 风格的云函数上**。 ### AV.Cloud.Error @@ -106,7 +106,7 @@ AV.Cloud.run(name: string, data: object, options?: object): Promise * AV.Cloud.beforeDelete * AV.Cloud.afterDelete -这些函数的签名:`function(className: string, func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数。在 before 类 Hook 中如果没有抛出异常则视作接受这次操作。如果抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误,拒绝本次操作;如果抛出其他类型的异常则视作服务器端错误,返回 500 响应并打印错误到标准输出。 +这些函数的签名:`function(className: string, func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数。在 before 类 Hook 中如果没有抛出异常则视作接受这次操作。如果抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误,拒绝本次操作;如果抛出其他类型的异常则视作服务器端错误,返回 500 响应并打印错误到标准输出,也会拒绝本次操作。 `Request` 上的属性包括: diff --git a/package.json b/package.json index b28fdf5..fbba52d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.0-beta", + "version": "2.0.0-beta.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 4fa1989056e8505994f964e5522f47fcc74bfd0c Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 23 Mar 2017 17:24:21 +0800 Subject: [PATCH 021/122] :bug: Fix compatibility of Node.js 4.x --- lib/leanengine.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/leanengine.js b/lib/leanengine.js index 7706219..20fe293 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -91,7 +91,9 @@ function createCloudFunctionRouter(options) { throw new Cloud.Error(`No function name or class name: ${req.originalUrl}`, {status: 404, printToLog: true, printFullStack: false}); } - const [__, functionOrClass, hookName] = req.url.split('/'); + const urlParams = req.url.split('/'); + const functionOrClass = urlParams[1]; + const hookName = urlParams[2]; if (!hookName) { return callCloudFunction(req, functionOrClass); From e828051e34af890b2c659929b30309575419fba7 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Mar 2017 16:41:58 +0800 Subject: [PATCH 022/122] :green_heart: Fix koa support --- lib/leanengine.js | 3 ++- middleware/koa.js | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/leanengine.js b/lib/leanengine.js index 20fe293..05477f9 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -31,7 +31,7 @@ AV.express = function(options) { }; AV.koa = function(options) { - return require('../middleware/koa')(AV); + return require('../middleware/koa')(AV)(options); }; var Cloud = _.extend(AV.Cloud, require('./cloud')); @@ -312,6 +312,7 @@ function encodeResult(result) { function responseJson(res, data) { res.setHeader('Content-Type', 'application/json; charset=UTF-8'); + res.statusCode = 200; return res.end(JSON.stringify(data)); } diff --git a/middleware/koa.js b/middleware/koa.js index e1ae24c..2ad01f7 100644 --- a/middleware/koa.js +++ b/middleware/koa.js @@ -1,8 +1,10 @@ module.exports = function(AV) { - var middleware = AV.express(); + return function(options) { + const middleware = AV.express(options); - return function *(next) { - yield middleware.bind(null, this.req, this.res); - yield next; + return function *(next) { + yield middleware.bind(null, this.req, this.res); + yield next; + } } }; From 29d8641250e779ab981061bcf8617aabc47ad2ee Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Mar 2017 16:49:59 +0800 Subject: [PATCH 023/122] :bookmark: Release 2.0.0-beta.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbba52d..62b1137 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.0-beta.0", + "version": "2.0.0-beta.1", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 474ed1b2cf77f35699a3392738747460e6cada96 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 27 Mar 2017 15:59:34 +0800 Subject: [PATCH 024/122] :bulb: Add Cloud.onIMConversationRemove --- API.md | 17 +++++++++-------- leanengine.d.ts | 1 + lib/leanengine.js | 2 +- lib/utils.js | 1 + 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/API.md b/API.md index b3ae99e..af2a8fb 100644 --- a/API.md +++ b/API.md @@ -134,17 +134,18 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 包括: -* `_messageReceived` -* `_receiversOffline` -* `_messageSent` -* `_conversationStart` -* `_conversationAdd` -* `_conversationRemove` -* `_conversationUpdate` +* `onIMMessageReceived` +* `onIMReceiversOffline` +* `onIMMessageSent` +* `onIMConversationStart` +* `onIMConversationStarted` +* `onIMConversationAdd` +* `onIMConversationRemove` +* `onIMConversationUpdate` LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调用者的确是 LeanCloud 或本地调试时的命令行工具。 -这些 Hook 需要用 `AV.Cloud.define` 来定义,详见文档 [实时通信概览:云引擎 Hook](https://leancloud.cn/docs/realtime_v2.html#云引擎_Hook) +这些 Hook 函数签名是 `function(func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,详见文档 [实时通信概览:云引擎 Hook](https://leancloud.cn/docs/realtime_v2.html#云引擎_Hook) ## Middlewares diff --git a/leanengine.d.ts b/leanengine.d.ts index 74bf5aa..299c8e4 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -121,6 +121,7 @@ declare module 'leanengine' { export function onIMConversationStart(handler: CloudFunction): void; export function onIMConversationStarted(handler: CloudFunction): void; export function onIMConversationAdd(handler: CloudFunction): void; + export function onIMConversationRemove(handler: CloudFunction): void; export function onIMConversationUpdate(handler: CloudFunction): void; export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; diff --git a/lib/leanengine.js b/lib/leanengine.js index 05477f9..4b5f612 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -139,7 +139,7 @@ function createCloudFunctionRouter(options) { cloudFunctions.use(function(err, req, res, next) { // jshint ignore:line if(req.timedout) { - console.error('LeanEngine function timeout, url=%s, timeout=%d', req.originalUrl, err.timeout); + console.error(`LeanEngine: ${req.originalUrl}: function timeout (${err.timeout}ms)`); err.code = 124; // https://leancloud.cn/docs/error_code.html#_124 err.message = 'The request timed out on the server.'; } diff --git a/lib/utils.js b/lib/utils.js index 363d6db..d1e8e81 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -20,6 +20,7 @@ exports.realtimeHookMapping = { onIMConversationStart: '_conversationStart', onIMConversationStarted: '_conversationStarted', onIMConversationAdd: '_conversationAdd', + onIMConversationRemove: '_conversationRemove', onIMConversationUpdate: '_conversationUpdate' }; From ca4e62ac780af278c6018623cb330bee15091f06 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 11 Apr 2017 17:33:05 +0800 Subject: [PATCH 025/122] :bookmark: Release 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 62b1137..ff42dbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.0-beta.1", + "version": "2.0.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From f8b4bd03fa46c5b95d7a40856ec103c205f34750 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 11 Apr 2017 17:40:11 +0800 Subject: [PATCH 026/122] :memo: Update README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 73774d3..d8b796c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ npm install leanengine --save 见 [Releases](https://github.com/leancloud/leanengine-node-sdk/releases) +安装 1.x 版本(建议尽快升级,见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0)): + +``` +npm install leanengine@1.x --save +``` + 安装早期的 0.x 版本(请尽快 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html)): ```bash From 3bbb43c5b82350d567d66f0d6b725ea733dfaf53 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 14 Apr 2017 14:32:53 +0800 Subject: [PATCH 027/122] :green_heart: Add X-LC-Hook-Key to Access-Control-Allow-Headers --- middleware/cors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware/cors.js b/middleware/cors.js index e9262a8..150036b 100644 --- a/middleware/cors.js +++ b/middleware/cors.js @@ -6,7 +6,7 @@ module.exports = function() { res.statusCode = 200; res.setHeader('Access-Control-Max-Age','86400'); res.setHeader('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS'); - res.setHeader('Access-Control-Allow-Headers', 'X-LC-Id, X-LC-Key, X-LC-Session, X-LC-Sign, X-LC-Prod, X-LC-UA, X-Uluru-Application-Key, X-Uluru-Application-Id, X-Uluru-Application-Production, X-Uluru-Client-Version, X-Uluru-Session-Token, X-AVOSCloud-Application-Key, X-AVOSCloud-Application-Id, X-AVOSCloud-Application-Production, X-AVOSCloud-Client-Version, X-AVOSCloud-Session-Token, X-AVOSCloud-Super-Key, X-Requested-With, Content-Type, X-AVOSCloud-Request-sign'); + res.setHeader('Access-Control-Allow-Headers', 'X-LC-Id, X-LC-Key, X-LC-Session, X-LC-Sign, X-LC-Prod, X-LC-UA, X-Uluru-Application-Key, X-Uluru-Application-Id, X-Uluru-Application-Production, X-Uluru-Client-Version, X-Uluru-Session-Token, X-AVOSCloud-Application-Key, X-AVOSCloud-Application-Id, X-AVOSCloud-Application-Production, X-AVOSCloud-Client-Version, X-AVOSCloud-Session-Token, X-AVOSCloud-Super-Key, X-Requested-With, Content-Type, X-AVOSCloud-Request-sign, X-LC-Hook-Key'); res.setHeader('Content-Length', 0); res.end(); } else { From e05d17fc15ce1ff6d3e9fda5e7e4f9de30668303 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 14 Apr 2017 15:44:01 +0800 Subject: [PATCH 028/122] :bookmark: Release 2.0.1 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 271f4be..0289ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## v2.0.1 + +- 补充 CORS 头,兼容最新版本的命令行工具的本地调试。 + ## v2.0.0 - **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage 2.1.0](https://github.com/leancloud/javascript-sdk/releases/tag/v2.0.0)(请检查 JS SDK 2.0 引入的不兼容改动)。 diff --git a/package.json b/package.json index ff42dbc..6a4d57a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.0", + "version": "2.0.1", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From a1d533b148698caeb88a9f3570e47b8800368a25 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 25 Apr 2017 12:18:25 +0800 Subject: [PATCH 029/122] :bug: Fix promise support of Cloud.run --- lib/cloud.js | 36 +++++++++++++++++++++--------------- test/helpers/functions.js | 8 ++------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index 107e58b..30ccd12 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -47,23 +47,29 @@ Cloud.run = function(name, data, options) { }).then(function(user) { user = user || options.user; - return new Promise(function(resolve, reject) { - var request = utils.prepareRequestObject({ - user: user, - params: data, - req: options.req - }); - - var response = utils.prepareResponseObject(options.req && options.req.res, function(err, result) { - if (err) { - reject(err); - } else { - resolve(result); - } - }); + const cloudFunction = Cloud.functions[name]; - Cloud.functions[name](request, response); + const request = utils.prepareRequestObject({ + user: user, + params: data, + req: options.req }); + + if (cloudFunction.length === 2) { + return new Promise( (resolve, reject) => { + const response = utils.prepareResponseObject(options.req && options.req.res, function(err, result) { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + + cloudFunction(request, response); + }); + } else { + return cloudFunction(request); + } }); }; diff --git a/test/helpers/functions.js b/test/helpers/functions.js index 7729d3d..68a4a66 100644 --- a/test/helpers/functions.js +++ b/test/helpers/functions.js @@ -143,18 +143,14 @@ AV.Cloud.define('testRun', function(request, response) { ); }); -AV.Cloud.define('testRun_promise', function(request, response) { - AV.Cloud.run('choice', {choice: true}).then(function(data) { +AV.Cloud.define('testRun_promise', function(request) { + return AV.Cloud.run('choice', {choice: true}).then(function(data) { assert.equal('OK~', data); AV.Cloud.run('choice', {choice: false}).then(function(data) { assert.ifError(data); }, function(err) { assert.equal('OMG...', err); - response.success(); }); - }, - function(err) { - assert.ifError(err); }); }); From 527d2f3290cb3f33ace0d7fd004aae4b91a69376 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 10 May 2017 18:05:10 +0800 Subject: [PATCH 030/122] :heavy_plus_sign: Use leancloud-cors-headers --- middleware/cors.js | 6 ++++-- package.json | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/middleware/cors.js b/middleware/cors.js index 150036b..79f81b7 100644 --- a/middleware/cors.js +++ b/middleware/cors.js @@ -1,3 +1,5 @@ +const leancloudHeaders = require('leancloud-cors-headers'); + module.exports = function() { return function(req, res, next) { res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*'); @@ -5,8 +7,8 @@ module.exports = function() { if (req.method.toLowerCase() === 'options') { res.statusCode = 200; res.setHeader('Access-Control-Max-Age','86400'); - res.setHeader('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS'); - res.setHeader('Access-Control-Allow-Headers', 'X-LC-Id, X-LC-Key, X-LC-Session, X-LC-Sign, X-LC-Prod, X-LC-UA, X-Uluru-Application-Key, X-Uluru-Application-Id, X-Uluru-Application-Production, X-Uluru-Client-Version, X-Uluru-Session-Token, X-AVOSCloud-Application-Key, X-AVOSCloud-Application-Id, X-AVOSCloud-Application-Production, X-AVOSCloud-Client-Version, X-AVOSCloud-Session-Token, X-AVOSCloud-Super-Key, X-Requested-With, Content-Type, X-AVOSCloud-Request-sign, X-LC-Hook-Key'); + res.setHeader('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, DELETE, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', leancloudHeaders); res.setHeader('Content-Length', 0); res.end(); } else { diff --git a/package.json b/package.json index 6a4d57a..8440432 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.1", + "version": "2.0.2", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", @@ -12,6 +12,7 @@ "connect-timeout": "^1.8.0", "cookies": "^0.6.2", "debug": "^2.6.0", + "leancloud-cors-headers": "^0.1.0", "leancloud-storage": "^2.1.0", "on-headers": "^1.0.1", "underscore": "^1.8.3" From 53c000c7c048f8a8ccbd66415f94f7d079598961 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 10 May 2017 18:11:43 +0800 Subject: [PATCH 031/122] :rotating_light: Fix Access-Control-Allow-Headers to single line --- middleware/cors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware/cors.js b/middleware/cors.js index 79f81b7..da897c7 100644 --- a/middleware/cors.js +++ b/middleware/cors.js @@ -8,7 +8,7 @@ module.exports = function() { res.statusCode = 200; res.setHeader('Access-Control-Max-Age','86400'); res.setHeader('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, DELETE, OPTIONS'); - res.setHeader('Access-Control-Allow-Headers', leancloudHeaders); + res.setHeader('Access-Control-Allow-Headers', leancloudHeaders.join(', ')); res.setHeader('Content-Length', 0); res.end(); } else { From 1040a8875dbaabbf68952b4d12586d0b56fe35c6 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 10 May 2017 18:12:29 +0800 Subject: [PATCH 032/122] :bookmark: Release 2.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8440432..bb3b11e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.2", + "version": "2.0.3", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 76bd526b801976f12f5c980c1eb66c49f51684ee Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 6 Jun 2017 17:43:52 +0800 Subject: [PATCH 033/122] :bug: Throw explicit error in AV.Cloud.run --- lib/cloud.js | 8 ++++++-- test/function-test.js | 8 ++++++++ test/helpers/functions.js | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index 30ccd12..94fe71f 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -30,7 +30,7 @@ Cloud.define = function(name, options, func) { var originalCloudRun = AV.Cloud.run; -Cloud.run = function(name, data, options) { +Cloud.run = function(funcName, data, options) { options = options || {}; if (options.remote) { @@ -47,7 +47,11 @@ Cloud.run = function(name, data, options) { }).then(function(user) { user = user || options.user; - const cloudFunction = Cloud.functions[name]; + const cloudFunction = Cloud.functions[funcName]; + + if (!cloudFunction) { + throw new Cloud.Error(`No such cloud function '${funcName}'`, {status: 404, printToLog: true, printFullStack: false}); + } const request = utils.prepareRequestObject({ user: user, diff --git a/test/function-test.js b/test/function-test.js index f72387a..a3ab553 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -388,6 +388,14 @@ describe('functions', function() { .expect(200, done); }); + it('run undefined function', function(done) { + request(app) + .post('/1/functions/testRunUndefinedFunction') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .expect(404, done); + }); + it('testRunWithSessionToken', function(done) { request(app) .post('/1/functions/testRunWithSessionToken') diff --git a/test/helpers/functions.js b/test/helpers/functions.js index 68a4a66..04b5e9d 100644 --- a/test/helpers/functions.js +++ b/test/helpers/functions.js @@ -154,6 +154,10 @@ AV.Cloud.define('testRun_promise', function(request) { }); }); +AV.Cloud.define('testRunUndefinedFunction', function(request) { + return AV.Cloud.run('undefinedFunction'); +}); + AV.Cloud.define('testRunWithUser', function(request, response) { AV.Cloud.run('testUser', {}, { user: request.user From 03905a69ad783956f74208bf3a5425adfd861a43 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 27 Jun 2017 16:05:41 +0800 Subject: [PATCH 034/122] :bug: Fix Cloud.run in remote mode --- CHANGELOG.md | 8 ++++++++ lib/cloud.js | 2 +- package.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0289ccb..583207c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # 更新日志 +## v2.0.4 + +- 修复使用 remote 模式调用 `Cloud.run` 时,user 参数处理不正确的问题。 + +## v2.0.3 + +- 修复 `Cloud.run` 对 Promise 的支持。 + ## v2.0.1 - 补充 CORS 头,兼容最新版本的命令行工具的本地调试。 diff --git a/lib/cloud.js b/lib/cloud.js index 30ccd12..0c7714b 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -35,7 +35,7 @@ Cloud.run = function(name, data, options) { if (options.remote) { if (options.user) { - options.sessionToken = options.sessionToken || options.getSessionToken(); + options.sessionToken = options.sessionToken || options.user.getSessionToken(); } return originalCloudRun.apply(null, arguments); } diff --git a/package.json b/package.json index bb3b11e..40fd3ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.3", + "version": "2.0.4", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 7879cbc740983d2d6b685a131fde71d83985c3f4 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 23 Mar 2017 13:29:55 +0800 Subject: [PATCH 035/122] :arrow_up: Upgrade to leancloud-storage 3.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 40fd3ae..82b003b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "2.0.4", + "version": "3.0.0-alpha", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", @@ -13,7 +13,7 @@ "cookies": "^0.6.2", "debug": "^2.6.0", "leancloud-cors-headers": "^0.1.0", - "leancloud-storage": "^2.1.0", + "leancloud-storage": "^3.0.0-beta.1", "on-headers": "^1.0.1", "underscore": "^1.8.3" }, From b63a00fddd49bcbabfeab7ba7803bab91c0ca939 Mon Sep 17 00:00:00 2001 From: leeyeh Date: Thu, 23 Mar 2017 16:27:26 +0800 Subject: [PATCH 036/122] :construction: update test case for leancloud-storage v3 --- lib/leanengine.js | 6 +++--- test/function-test.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/leanengine.js b/lib/leanengine.js index 4b5f612..56a0061 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -233,7 +233,7 @@ function callClassHook(req, className, hookName) { } else if (hookName === 'beforeDelete') { resolve({}); } else { - resolve(object); + resolve(object._toFullJSON()); } })); } else { @@ -292,8 +292,8 @@ const decodeParams = AV._decode; function encodeResult(result) { var encodeAVObject = function(object) { - if (object && object._toFullJSON){ - object = object._toFullJSON([]); + if (object && object.toFullJSON){ + object = object.toFullJSON(); } return _.mapObject(object, function(value) { diff --git a/test/function-test.js b/test/function-test.js index a3ab553..4e6ad40 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -118,7 +118,7 @@ describe('functions', function() { iso: '2015-05-14T09:21:18.273Z' }); - result.avObject.__type.should.equal('Object'); + result.avObject.__type.should.equal('Pointer'); result.avObject.className.should.equal('ComplexObject'); result.avObject.numberColumn.should.equal(1.23); result.avObject.arrayColumn.should.eql([1, 2, 3]); @@ -152,7 +152,7 @@ describe('functions', function() { }); result.avObjects.forEach(function(object) { - object.__type.should.equal('Object'); + object.__type.should.equal('Pointer'); object.className.should.equal('ComplexObject'); }); @@ -282,7 +282,7 @@ describe('functions', function() { .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) .expect(200, function(err, res) { - res.body.result.avObjects[0].__type.should.equal('Object'); + res.body.result.avObjects[0].__type.should.equal('Pointer'); res.body.result.avObjects[0].className.should.equal('ComplexObject'); done(); }); From 34d74f22915d1e1833d464bf768446ab36b6a6a8 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Mar 2017 16:47:33 +0800 Subject: [PATCH 037/122] :arrow_down: Lock leancloud-storage to 3.0.0-beta.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 82b003b..a6b2500 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "cookies": "^0.6.2", "debug": "^2.6.0", "leancloud-cors-headers": "^0.1.0", - "leancloud-storage": "^3.0.0-beta.1", + "leancloud-storage": "3.0.0-beta.1", "on-headers": "^1.0.1", "underscore": "^1.8.3" }, From 7e90335f7f8a2ed660320d6937972f1ec2256088 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Mar 2017 16:48:21 +0800 Subject: [PATCH 038/122] :bookmark: Release 3.0.0-alpha.0 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 583207c..63f04a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## v3.0.0 + +- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage v3.0.0-beta.1](https://github.com/leancloud/javascript-sdk/releases/tag/v3.0.0-beta.1)(请检查 JS SDK 3.0 引入的不兼容改动)。 + ## v2.0.4 - 修复使用 remote 模式调用 `Cloud.run` 时,user 参数处理不正确的问题。 diff --git a/package.json b/package.json index a6b2500..6d00e1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.0-alpha", + "version": "3.0.0-alpha.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From bfeb0db2c2d41b94872417605b2723c0d33966ff Mon Sep 17 00:00:00 2001 From: leeyeh Date: Thu, 13 Apr 2017 15:07:15 +0800 Subject: [PATCH 039/122] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20to=20lea?= =?UTF-8?q?ncloud-storage=203.0.0-beta.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/storage-extra.js | 3 +-- package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/storage-extra.js b/lib/storage-extra.js index 61eb07d..a365560 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -1,6 +1,5 @@ 'use strict'; var AV = require('leancloud-storage'); -var utils = require('./utils'); AV._config.disableCurrentUser = true; @@ -9,7 +8,7 @@ if (process.env.LEANCLOUD_REGION) { } if (process.env.LC_API_SERVER) { - AV._config.APIServerURL = process.env.LC_API_SERVER; + AV.setServerURLs(process.env.LC_API_SERVER); } AV._config.userAgent = 'AVOS Cloud Code Node ' + require('../package').version; diff --git a/package.json b/package.json index 6d00e1b..af8e77e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "cookies": "^0.6.2", "debug": "^2.6.0", "leancloud-cors-headers": "^0.1.0", - "leancloud-storage": "3.0.0-beta.1", + "leancloud-storage": "3.0.0-beta.2", "on-headers": "^1.0.1", "underscore": "^1.8.3" }, From 59e05bc368395b1d1de50fd88f30174027f466d0 Mon Sep 17 00:00:00 2001 From: leeyeh Date: Wed, 24 May 2017 16:25:31 +0800 Subject: [PATCH 040/122] =?UTF-8?q?=F0=9F=90=9B=20remove=20extra=20meta=20?= =?UTF-8?q?data=20in=20hook=20callbacks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/leanengine.js | 2 +- test/hook-test.js | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/leanengine.js b/lib/leanengine.js index 56a0061..f87a0ab 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -233,7 +233,7 @@ function callClassHook(req, className, hookName) { } else if (hookName === 'beforeDelete') { resolve({}); } else { - resolve(object._toFullJSON()); + resolve(_.omit(object._toFullJSON(), ['__type', 'className'])); } })); } else { diff --git a/test/hook-test.js b/test/hook-test.js index ac0e83e..4e2d58c 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -194,10 +194,12 @@ describe('hook', function() { }) .expect(200) .end(function(err, res) { - res.body.user.should.eql({ - "__type": "Pointer", - "className": "_User", - "objectId": "52aebbdee4b0c8b6fa455aa7" + res.body.should.eql({ + 'user': { + "__type": "Pointer", + "className": "_User", + "objectId": "52aebbdee4b0c8b6fa455aa7" + } }); done(); }); From c3089c9092fa0d97a78c8b1b87bd8d9830aeaec7 Mon Sep 17 00:00:00 2001 From: leeyeh Date: Fri, 16 Jun 2017 15:20:54 +0800 Subject: [PATCH 041/122] :arrow_up: Upgrade to leancloud-storage 3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af8e77e..74556df 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "cookies": "^0.6.2", "debug": "^2.6.0", "leancloud-cors-headers": "^0.1.0", - "leancloud-storage": "3.0.0-beta.2", + "leancloud-storage": "3.0.0", "on-headers": "^1.0.1", "underscore": "^1.8.3" }, From cee61a722861c93cf39828da30ae75983b1992ce Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Jun 2017 15:02:42 +0800 Subject: [PATCH 042/122] :bug: Fix https-redirect in koa --- middleware/https-redirect.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/middleware/https-redirect.js b/middleware/https-redirect.js index 5a32e75..fdc73b7 100644 --- a/middleware/https-redirect.js +++ b/middleware/https-redirect.js @@ -5,8 +5,12 @@ var endsWith = require('../lib/utils').endsWith; module.exports = function(AV) { return function() { return function(req, res, next) { - if ((AV.Cloud.__prod || endsWith(req.get('host'), '.leanapp.cn')) && (!req.secure)) { - return res.redirect('https://' + req.get('host') + req.originalUrl); + if ((AV.Cloud.__prod || endsWith(req.headers.host, '.leanapp.cn')) && (!req.secure)) { + const url = `https://${req.headers.host}${req.originalUrl || req.url}`; + + res.statusCode = 302; + res.setHeader('Location', url); + res.end(`Found. Redirecting to ${url}`); } else { return next(); } From 093b117a817ae1415a10b9827dc2cbb09b80813f Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Jun 2017 15:03:04 +0800 Subject: [PATCH 043/122] :sparkles: Add support to koa2 --- lib/frameworks.js | 75 +++++++++++++++++++++++++++++ lib/leanengine.js | 63 ++++++++++++------------ middleware/cookie-session-koa.js | 17 ------- middleware/https-redirect-koa.js | 13 ----- middleware/koa.js | 10 ---- middleware/leancloud-headers-koa.js | 12 ----- 6 files changed, 105 insertions(+), 85 deletions(-) create mode 100644 lib/frameworks.js delete mode 100644 middleware/cookie-session-koa.js delete mode 100644 middleware/https-redirect-koa.js delete mode 100644 middleware/koa.js delete mode 100644 middleware/leancloud-headers-koa.js diff --git a/lib/frameworks.js b/lib/frameworks.js new file mode 100644 index 0000000..b328357 --- /dev/null +++ b/lib/frameworks.js @@ -0,0 +1,75 @@ +function express(middleware) { + return middleware; +} + +function koa(middleware) { + return function*(next) { + yield middleware.bind(null, this.req, this.res); + + if (this.req.currentUser) { + this.request.currentUser = this.req.currentUser; + this.currentUser = this.req.currentUser; + } + + if (this.req.sessionToken) { + this.request.sessionToken = this.req.sessionToken; + this.sessionToken = this.req.sessionToken; + } + + if (this.res.saveCurrentUser) { + this.response.saveCurrentUser = this.res.saveCurrentUser; + this.saveCurrentUser = this.res.saveCurrentUser; + } + + if (this.res.clearCurrentUser) { + this.response.clearCurrentUser = this.res.clearCurrentUser; + this.clearCurrentUser = this.res.clearCurrentUser; + } + + yield next; + }; +} + +function koa2(middleware) { + return function(ctx, next) { + return new Promise( (resolve, reject) => { + middleware(ctx.req, ctx.res, err => { + if (ctx.req.currentUser) { + ctx.currentUser = ctx.req.currentUser; + } + + if (ctx.req.sessionToken) { + ctx.sessionToken = ctx.req.sessionToken; + } + + if (ctx.res.saveCurrentUser) { + ctx.saveCurrentUser = ctx.res.saveCurrentUser; + } + + if (ctx.res.clearCurrentUser) { + ctx.clearCurrentUser = ctx.res.clearCurrentUser; + } + + if (err) { + reject(err); + } else { + resolve(next()); + } + }); + }); + }; +} + +const converters = {express, koa, koa2}; + +module.exports = function(middleware, framework) { + if (framework) { + if (converters[framework] !== -1) { + return converters[framework](middleware); + } else { + throw new Error(`Unsupported framework: ${framework}`); + } + } else { + return express(middleware); + } +}; diff --git a/lib/leanengine.js b/lib/leanengine.js index f87a0ab..8e51320 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -8,30 +8,20 @@ var _ = require('underscore'); var AV = require('./storage-extra'); var utils = require('./utils'); +var frameworks = require('./frameworks'); var NODE_ENV = process.env.NODE_ENV || 'development'; AV.express = function(options) { - var router = connect(); - - router.use(require('../middleware/health-check')()); - - ['1', '1.1'].forEach(function(apiVersion) { - router.use('/' + apiVersion + '/call', function(req, res, next) { - req.rpcCall = true; - next(); - }); - - ['functions', 'call'].forEach(function(urlEndpoint) { - router.use('/' + apiVersion + '/' + urlEndpoint, createCloudFunctionRouter(options)); - }); - }); - - return router; + return frameworks(createRootRouter(options), 'express'); }; AV.koa = function(options) { - return require('../middleware/koa')(AV)(options); + return frameworks(createRootRouter(options), 'koa'); +}; + +AV.koa2 = function(options) { + return frameworks(createRootRouter(options), 'koa2'); }; var Cloud = _.extend(AV.Cloud, require('./cloud')); @@ -42,27 +32,34 @@ if (https.globalAgent && https.globalAgent.options) { } AV.Cloud.CookieSession = function(options) { - if (options && options.framework == 'koa') { - return require('../middleware/cookie-session-koa')(AV)(options); - } else { - return require('../middleware/cookie-session')(AV)(options); - } + return frameworks(require('../middleware/cookie-session')(AV)(options), options && options.framework); }; AV.Cloud.HttpsRedirect = function(options) { - if (options && options.framework == 'koa') { - return require('../middleware/https-redirect-koa')(AV)(options); - } else { - return require('../middleware/https-redirect')(AV)(options); - } -} + return frameworks(require('../middleware/https-redirect')(AV)(options), options && options.framework); +}; AV.Cloud.LeanCloudHeaders = function(options) { - if (options && options.framework == 'koa') { - return require('../middleware/leancloud-heaedrs-koa')(AV)(options); - } else { - return require('../middleware/leancloud-heaedrs')(AV)(options); - } + return frameworks(require('../middleware/leancloud-heaedrs')(AV)(options), options && options.framework); +}; + +function createRootRouter(options) { + var router = connect(); + + router.use(require('../middleware/health-check')()); + + ['1', '1.1'].forEach(function(apiVersion) { + router.use('/' + apiVersion + '/call', function(req, res, next) { + req.rpcCall = true; + next(); + }); + + ['functions', 'call'].forEach(function(urlEndpoint) { + router.use('/' + apiVersion + '/' + urlEndpoint, createCloudFunctionRouter(options)); + }); + }); + + return router; } function createCloudFunctionRouter(options) { diff --git a/middleware/cookie-session-koa.js b/middleware/cookie-session-koa.js deleted file mode 100644 index 8c08c18..0000000 --- a/middleware/cookie-session-koa.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = function(AV) { - return function (options) { - var middleware = require('./cookie-session')(AV)(options); - - return function *(next) { - yield middleware.bind(null, this.req, this.res); - - this.request.currentUser = this.req.currentUser; - this.request.sessionToken = this.req.sessionToken; - - this.response.saveCurrentUser = this.res.saveCurrentUser; - this.response.clearCurrentUser = this.res.clearCurrentUser; - - yield next; - } - }; -}; diff --git a/middleware/https-redirect-koa.js b/middleware/https-redirect-koa.js deleted file mode 100644 index 9adc831..0000000 --- a/middleware/https-redirect-koa.js +++ /dev/null @@ -1,13 +0,0 @@ -var endsWith = require('../lib/utils').endsWith; - -module.exports = function(AV) { - return function() { - return function *(next) { - if ((AV.Cloud.__prod || endsWith(this.request.hostname, '.leanapp.cn')) && (!this.request.secure)) { - this.response.redirect('https://' + this.request.hostname + this.request.originalUrl); - } else { - yield next; - } - } - } -}; diff --git a/middleware/koa.js b/middleware/koa.js deleted file mode 100644 index 2ad01f7..0000000 --- a/middleware/koa.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = function(AV) { - return function(options) { - const middleware = AV.express(options); - - return function *(next) { - yield middleware.bind(null, this.req, this.res); - yield next; - } - } -}; diff --git a/middleware/leancloud-headers-koa.js b/middleware/leancloud-headers-koa.js deleted file mode 100644 index e01d622..0000000 --- a/middleware/leancloud-headers-koa.js +++ /dev/null @@ -1,12 +0,0 @@ -const leancloudHeaders = require('./leancloud-headers'); - -module.exports = function(AV) { - return function(options) { - var middleware = leancloudHeaders(AV, options); - - return function *(next) { - yield middleware.bind(null, this.req, this.res); - yield next; - } - }; -}; From 64df0c90bfb09260bce38b5c399fd97e0b336f60 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Jun 2017 15:03:40 +0800 Subject: [PATCH 044/122] :truck: Rename test/helpers to test/fixtures --- test/authorization-test.js | 7 +++--- test/cookie-session-koa-test.js | 2 +- test/cookie-session-test.js | 2 +- test/current-user-test.js | 2 +- test/{helpers => fixtures}/app-info.js | 0 .../index.js => fixtures/frameworks.js} | 3 +-- test/{helpers => fixtures}/functions.js | 0 test/{helpers => fixtures}/hooks.js | 0 test/function-test.js | 9 ++++---- test/hook-test.js | 23 ++++++------------- test/https-redirect-koa-test.js | 4 ++-- test/https-redirect-test.js | 2 +- 12 files changed, 21 insertions(+), 33 deletions(-) rename test/{helpers => fixtures}/app-info.js (100%) rename test/{helpers/index.js => fixtures/frameworks.js} (76%) rename test/{helpers => fixtures}/functions.js (100%) rename test/{helpers => fixtures}/hooks.js (100%) diff --git a/test/authorization-test.js b/test/authorization-test.js index 48f4645..9d117e5 100644 --- a/test/authorization-test.js +++ b/test/authorization-test.js @@ -3,16 +3,15 @@ var request = require('supertest'); const AV = require('..'); -const helpers = require('./helpers') -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); -require('./helpers/functions'); +require('./fixtures/functions'); var appId = appInfo.appId; var appKey = appInfo.appKey; var masterKey = appInfo.masterKey; -const app = helpers.app(); +const app = require('./fixtures/frameworks')(); describe('authorization', function() { it('ok', function(done) { diff --git a/test/cookie-session-koa-test.js b/test/cookie-session-koa-test.js index 58e8f1d..efb6598 100644 --- a/test/cookie-session-koa-test.js +++ b/test/cookie-session-koa-test.js @@ -4,7 +4,7 @@ var request = require('supertest'); var should = require('should'); const AV = require('..'); -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); var app = koa(); diff --git a/test/cookie-session-test.js b/test/cookie-session-test.js index 9c433c5..01261a5 100644 --- a/test/cookie-session-test.js +++ b/test/cookie-session-test.js @@ -6,7 +6,7 @@ var request = require('supertest'); var should = require('should'); const AV = require('..'); -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); var app = express(); diff --git a/test/current-user-test.js b/test/current-user-test.js index 71c1f75..8ce6ab3 100644 --- a/test/current-user-test.js +++ b/test/current-user-test.js @@ -5,7 +5,7 @@ var assert = require('assert'); var bodyParser = require('body-parser'); var AV = require('..'); -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); var request = require('supertest'); var appId = appInfo.appId; diff --git a/test/helpers/app-info.js b/test/fixtures/app-info.js similarity index 100% rename from test/helpers/app-info.js rename to test/fixtures/app-info.js diff --git a/test/helpers/index.js b/test/fixtures/frameworks.js similarity index 76% rename from test/helpers/index.js rename to test/fixtures/frameworks.js index f5e6282..b999a40 100644 --- a/test/helpers/index.js +++ b/test/fixtures/frameworks.js @@ -1,9 +1,8 @@ const koa = require('koa'); -const request = require('supertest'); const AV = require('../..'); -exports.app = function() { +module.exports = function() { if (process.env.FRAMEWORK == 'koa') { var app = koa(); app.use(AV.koa()); diff --git a/test/helpers/functions.js b/test/fixtures/functions.js similarity index 100% rename from test/helpers/functions.js rename to test/fixtures/functions.js diff --git a/test/helpers/hooks.js b/test/fixtures/hooks.js similarity index 100% rename from test/helpers/hooks.js rename to test/fixtures/hooks.js diff --git a/test/function-test.js b/test/function-test.js index 4e6ad40..4cc1788 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -5,11 +5,10 @@ const should = require('should'); const assert = require('assert'); const AV = require('..'); -const helpers = require('./helpers') -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); -require('./helpers/functions'); -require('./helpers/hooks'); +require('./fixtures/functions'); +require('./fixtures/hooks'); const appId = appInfo.appId; const appKey = appInfo.appKey; @@ -17,7 +16,7 @@ const masterKey = appInfo.masterKey; const hookKey = appInfo.hookKey; const sessionTokenAdmin = appInfo.sessionTokenAdmin; -const app = helpers.app(); +const app = require('./fixtures/frameworks')(); describe('functions', function() { it('ping', function(done) { diff --git a/test/hook-test.js b/test/hook-test.js index 4e2d58c..865c640 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -1,29 +1,20 @@ 'use strict'; -var AV = require('..'), - should = require('should'), - assert = require('assert'); +var AV = require('..'); +var should = require('should'); +var assert = require('assert'); +var request = require('supertest'); -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); var appId = appInfo.appId; var appKey = appInfo.appKey; var masterKey = appInfo.masterKey; var hookKey = appInfo.hookKey; -var app; - -if (process.env.FRAMEWORK == 'koa') { - var koa = require('koa')(); - koa.use(AV.koa()); - app = koa.listen(); -} else { - app = AV.express(); -} - -var request = require('supertest'); +const app = require('./fixtures/frameworks')(); -require('./helpers/hooks'); +require('./fixtures/hooks'); describe('hook', function() { it('beforeSave', function(done) { diff --git a/test/https-redirect-koa-test.js b/test/https-redirect-koa-test.js index 19300a6..c2c5697 100644 --- a/test/https-redirect-koa-test.js +++ b/test/https-redirect-koa-test.js @@ -5,7 +5,7 @@ var request = require('supertest'); require('should'); var AV = require('..'); -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); var app = koa(); @@ -26,7 +26,7 @@ describe('https-redirect-koa', function() { .expect(302) .end(function(err, res) { res.headers.location.should.equal('https://stg-abc.leanapp.cn/test'); - res.text.should.match('Redirecting to https://stg-abc.leanapp.cn/test.'); + res.text.should.endWith('Redirecting to https://stg-abc.leanapp.cn/test'); done(); }); }); diff --git a/test/https-redirect-test.js b/test/https-redirect-test.js index 19dbc64..3cd957c 100644 --- a/test/https-redirect-test.js +++ b/test/https-redirect-test.js @@ -4,7 +4,7 @@ var express = require('express'); var request = require('supertest'); require('should'); -const appInfo = require('./helpers/app-info'); +const appInfo = require('./fixtures/app-info'); var app = express(); From 3a3ec202d8036b17bab5a0e72b5b29a789542b6e Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Jun 2017 16:47:31 +0800 Subject: [PATCH 045/122] :white_check_mark: Rewrite tests --- .gitignore | 1 + README.md | 14 +++-------- lib/leanengine.js | 2 +- package.json | 9 ++++--- test/authorization-test.js | 2 +- test/{ => express}/cookie-session-test.js | 4 ++-- test/{ => express}/current-user-test.js | 4 ++-- test/{ => express}/https-redirect-test.js | 4 ++-- test/fixtures/{frameworks.js => app.js} | 4 ++-- test/function-test.js | 2 +- test/hook-test.js | 2 +- test/{ => koa}/cookie-session-koa-test.js | 6 ++--- test/{ => koa}/https-redirect-koa-test.js | 6 ++--- test/koa2/koa2-test.js | 29 +++++++++++++++++++++++ 14 files changed, 55 insertions(+), 34 deletions(-) rename test/{ => express}/cookie-session-test.js (97%) rename test/{ => express}/current-user-test.js (97%) rename test/{ => express}/https-redirect-test.js (91%) rename test/fixtures/{frameworks.js => app.js} (78%) rename test/{ => koa}/cookie-session-koa-test.js (96%) rename test/{ => koa}/https-redirect-koa-test.js (89%) create mode 100644 test/koa2/koa2-test.js diff --git a/.gitignore b/.gitignore index b832735..fedf8ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *~ *.swp coverage.html +package-lock.json node_modules/ diff --git a/README.md b/README.md index d8b796c..39079ca 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,6 @@ npm install leanengine --save 见 [Releases](https://github.com/leancloud/leanengine-node-sdk/releases) -安装 1.x 版本(建议尽快升级,见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0)): - -``` -npm install leanengine@1.x --save -``` - -安装早期的 0.x 版本(请尽快 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html)): - -```bash -npm install leanengine@0.x --save -``` +- `npm install leanengine@2.x --save` +- `npm install leanengine@1.x --save`,升级说明见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0) +- `npm install leanengine@0.x --save` 升级说明见 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html) diff --git a/lib/leanengine.js b/lib/leanengine.js index 8e51320..2e2593f 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -40,7 +40,7 @@ AV.Cloud.HttpsRedirect = function(options) { }; AV.Cloud.LeanCloudHeaders = function(options) { - return frameworks(require('../middleware/leancloud-heaedrs')(AV)(options), options && options.framework); + return frameworks(require('../middleware/leancloud-headers')(AV)(options), options && options.framework); }; function createRootRouter(options) { diff --git a/package.json b/package.json index 74556df..63813f7 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,6 @@ "devDependencies": { "blanket": "^1.2.3", "express": "^4.14.1", - "koa": "^1.2.4", - "koa-bodyparser": "^2.3.0", "mocha": "^3.2.0", "should": "^11.2.0", "supertest": "^3.0.0" @@ -48,8 +46,9 @@ "email": "support@leancloud.rocks" }, "scripts": { - "test": "node_modules/mocha/bin/mocha -R spec --timeout=10000", - "test-koa": "FRAMEWORK=koa node_modules/mocha/bin/mocha -R spec --timeout=10000", - "test-cov": "node_modules/mocha/bin/mocha --require blanket -R html-cov > coverage.html" + "test": "npm run test-express && npm run test-koa1 && npm run test-koa2", + "test-express": "mocha test test/express", + "test-koa1": "env FRAMEWORK=koa npm install koa@1 koa-bodyparser@2 && mocha test test/koa", + "test-koa2": "env FRAMEWORK=koa npm install koa@2 koa-bodyparser@4 && mocha test test/koa test/koa2" } } diff --git a/test/authorization-test.js b/test/authorization-test.js index 9d117e5..bc5ed7e 100644 --- a/test/authorization-test.js +++ b/test/authorization-test.js @@ -11,7 +11,7 @@ var appId = appInfo.appId; var appKey = appInfo.appKey; var masterKey = appInfo.masterKey; -const app = require('./fixtures/frameworks')(); +const app = require('./fixtures/app')(); describe('authorization', function() { it('ok', function(done) { diff --git a/test/cookie-session-test.js b/test/express/cookie-session-test.js similarity index 97% rename from test/cookie-session-test.js rename to test/express/cookie-session-test.js index 01261a5..dcdb464 100644 --- a/test/cookie-session-test.js +++ b/test/express/cookie-session-test.js @@ -5,8 +5,8 @@ var bodyParser = require('body-parser'); var request = require('supertest'); var should = require('should'); -const AV = require('..'); -const appInfo = require('./fixtures/app-info'); +const AV = require('../..'); +const appInfo = require('../fixtures/app-info'); var app = express(); diff --git a/test/current-user-test.js b/test/express/current-user-test.js similarity index 97% rename from test/current-user-test.js rename to test/express/current-user-test.js index 8ce6ab3..e1114cc 100644 --- a/test/current-user-test.js +++ b/test/express/current-user-test.js @@ -4,8 +4,8 @@ var express = require('express'); var assert = require('assert'); var bodyParser = require('body-parser'); -var AV = require('..'); -const appInfo = require('./fixtures/app-info'); +var AV = require('../..'); +const appInfo = require('../fixtures/app-info'); var request = require('supertest'); var appId = appInfo.appId; diff --git a/test/https-redirect-test.js b/test/express/https-redirect-test.js similarity index 91% rename from test/https-redirect-test.js rename to test/express/https-redirect-test.js index 3cd957c..7d14f39 100644 --- a/test/https-redirect-test.js +++ b/test/express/https-redirect-test.js @@ -1,10 +1,10 @@ 'use strict'; -var AV = require('..'); +var AV = require('../..'); var express = require('express'); var request = require('supertest'); require('should'); -const appInfo = require('./fixtures/app-info'); +const appInfo = require('../fixtures/app-info'); var app = express(); diff --git a/test/fixtures/frameworks.js b/test/fixtures/app.js similarity index 78% rename from test/fixtures/frameworks.js rename to test/fixtures/app.js index b999a40..5553368 100644 --- a/test/fixtures/frameworks.js +++ b/test/fixtures/app.js @@ -1,10 +1,10 @@ -const koa = require('koa'); +const Koa = require('koa'); const AV = require('../..'); module.exports = function() { if (process.env.FRAMEWORK == 'koa') { - var app = koa(); + var app = new Koa(); app.use(AV.koa()); return app.listen(); } else { diff --git a/test/function-test.js b/test/function-test.js index 4cc1788..735b31a 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -16,7 +16,7 @@ const masterKey = appInfo.masterKey; const hookKey = appInfo.hookKey; const sessionTokenAdmin = appInfo.sessionTokenAdmin; -const app = require('./fixtures/frameworks')(); +const app = require('./fixtures/app')(); describe('functions', function() { it('ping', function(done) { diff --git a/test/hook-test.js b/test/hook-test.js index 865c640..6b5b629 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -12,7 +12,7 @@ var appKey = appInfo.appKey; var masterKey = appInfo.masterKey; var hookKey = appInfo.hookKey; -const app = require('./fixtures/frameworks')(); +const app = require('./fixtures/app')(); require('./fixtures/hooks'); diff --git a/test/cookie-session-koa-test.js b/test/koa/cookie-session-koa-test.js similarity index 96% rename from test/cookie-session-koa-test.js rename to test/koa/cookie-session-koa-test.js index efb6598..7fe1495 100644 --- a/test/cookie-session-koa-test.js +++ b/test/koa/cookie-session-koa-test.js @@ -3,10 +3,10 @@ var bodyParser = require('koa-bodyparser'); var request = require('supertest'); var should = require('should'); -const AV = require('..'); -const appInfo = require('./fixtures/app-info'); +const AV = require('../..'); +const appInfo = require('../fixtures/app-info'); -var app = koa(); +var app = new koa(); app.use(AV.koa()); app.use(bodyParser()); diff --git a/test/https-redirect-koa-test.js b/test/koa/https-redirect-koa-test.js similarity index 89% rename from test/https-redirect-koa-test.js rename to test/koa/https-redirect-koa-test.js index c2c5697..ffbd28e 100644 --- a/test/https-redirect-koa-test.js +++ b/test/koa/https-redirect-koa-test.js @@ -4,10 +4,10 @@ var koa = require('koa'); var request = require('supertest'); require('should'); -var AV = require('..'); -const appInfo = require('./fixtures/app-info'); +var AV = require('../..'); +const appInfo = require('../fixtures/app-info'); -var app = koa(); +var app = new koa(); app.proxy = true; app.use(AV.Cloud.HttpsRedirect({framework: 'koa'})); diff --git a/test/koa2/koa2-test.js b/test/koa2/koa2-test.js new file mode 100644 index 0000000..91eb0cc --- /dev/null +++ b/test/koa2/koa2-test.js @@ -0,0 +1,29 @@ +const bodyParser = require('koa-bodyparser'); +const Koa = require('koa'); +const request = require('supertest'); +const should = require('should'); + +const AV = require('../..'); +const appInfo = require('../fixtures/app-info'); + +const app = new Koa(); + +app.use(AV.koa2()); +app.use(bodyParser()); +app.use(AV.Cloud.HttpsRedirect({framework: 'koa2'})); +app.use(AV.Cloud.CookieSession({framework: 'koa2', secret: 'my secret', maxAge: 3600000, fetchUser: true})); +app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa2'})); + +const server = app.listen(); + +describe('koa2', function() { + it('health-check', done => { + request(server) + .get('/__engine/1/ping') + .expect(200, (err, res) => { + should.exist(res.body.runtime); + should.exist(res.body.version); + done(err); + }); + }); +}); From 4d855a90f2c11f10eefa0d69ff0c67e4514a7af5 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Jun 2017 17:18:12 +0800 Subject: [PATCH 046/122] :bookmark: Release 3.0.0-alpha.1 --- API.md | 42 ++++++++++++++++-------------------------- CHANGELOG.md | 10 +++++++++- README.md | 2 +- leanengine.d.ts | 1 + package.json | 4 ++-- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/API.md b/API.md index af2a8fb..6e7e525 100644 --- a/API.md +++ b/API.md @@ -17,22 +17,16 @@ app.use(AV.express()); app.listen(process.env.LEANCLOUD_APP_PORT); ``` -## AV.express +## 路由框架 -```javascript -AV.express(options?: object) -``` - -初始化一个 LeanEngine 中间件,可被挂载到 express 应用上。 - -## AV.koa +目前 Node SDK 支持 express、koa、koa2 三种路由框架,可以通过下面的 3 种方法创建中间件并挂载到你的路由框架上: ```javascript +AV.express(options?: object) AV.koa(options?: object) +AV.koa2(options?: object) ``` -初始化一个 LeanEngine 中间件,可被挂载到 koa 应用上。 - ## AV.Object * `AV.Object#disableBeforeHook()` @@ -149,21 +143,23 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 ## Middlewares -### leancloud-headers - -该中间件会将 `X-LC` 系列的头解析为 request.AV 上的属性,在 Express 中: +因为 Node SDK 同时支持多种路由框架,需要你在创建中间件时指定类型,默认为 express: ```javascript -app.use(AV.Cloud.LeanCloudHeaders()); +app.use(AV.Cloud.LeanCloudHeaders({framework: 'express'})); +app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa'})); +app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa2'})); ``` -在 Koa 中(添加 `framework: 'koa'` 参数): +### leancloud-headers + +该中间件会将 `X-LC` 系列的头解析为 request.AV 上的属性,在 Express 中: ```javascript -app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa'})); +app.use(AV.Cloud.LeanCloudHeaders()); ``` -express 的 `Request`(或 koa 的 `ctx.request`)上会有这些属性可用: +express 的 `Request`(或 koa 的 `ctx`)上会有这些属性可用: * `AV.id?`:App ID * `AV.key?`:App Key @@ -179,12 +175,6 @@ express 的 `Request`(或 koa 的 `ctx.request`)上会有这些属性可用 app.use(AV.Cloud.CookieSession({secret: 'my secret', maxAge: 3600000, fetchUser: true})); ``` -在 Koa 中(添加 `framework: 'koa'` 参数): - -```javascript -app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true})); -``` - 其他参数包括: * `secret: string`:对 Cookie 进行签名的密钥,请选用一个随机字符串。 @@ -193,12 +183,12 @@ app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3 * `fetchUser?: boolean`:是否自动查询用户信息,默认为 `false`,即不自动查询,这种情况下只能访问用户的 `id` 和 `sessionToken`. * `httpOnly?: boolean`: 不允许客户端读写该 Cookie,默认 `false`. -express 的 `Request`(或 koa 的 `ctx.request`)上会有这些属性可用: +express 的 `Request`(或 koa 的 `ctx`)上会有这些属性可用: * `currentUser?: AV.User`:和当前客户端关联的用户信息(根据 Cookie),如未开启 `cookie-session` 的 `fetchUser` 选项则只可以访问 `id` 和 `sessionToken`. * `sessionToken?: string`:和当前客户端关联的 `sessionToken`(根据 Cookie)。 -express 的 `Response`(或 koa 的 `ctx.response`)上会有这些属性可用: +express 的 `Response`(或 koa 的 `ctx`)上会有这些属性可用: * `saveCurrentUser(user: AV.User)`:将当前客户端与特定用户关联(会写入 Cookie)。 * `clearCurrentUser()`:清除当前客户端关联的用户(删除 Cookie)。 @@ -214,7 +204,7 @@ app.enable('trust proxy'); app.use(AV.Cloud.HttpsRedirect()); ``` -Koa 中(添加 `framework: 'koa'` 参数): +Koa 中: ```javascript app.proxy = true; diff --git a/CHANGELOG.md b/CHANGELOG.md index 63f04a9..62333a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,15 @@ ## v3.0.0 -- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage v3.0.0-beta.1](https://github.com/leancloud/javascript-sdk/releases/tag/v3.0.0-beta.1)(请检查 JS SDK 3.0 引入的不兼容改动)。 +- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage v3.0.0-beta.1](https://github.com/leancloud/javascript-sdk/releases/tag/v3.0.0)(请检查 JS SDK 3.0 引入的不兼容改动)。 + +**新增 Koa2 支持**: + +```javascript +var app = new Koa(); +app.use(AV.koa2()); +app.use(AV.Cloud.HttpsRedirect({framework: 'koa2'})); +``` ## v2.0.4 diff --git a/README.md b/README.md index 39079ca..6b2a5d7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ npm install leanengine --save ## 项目示例 -* 上手示例: +* 项目模板: * Todo 列表示例: * 微信公众平台: * 微博 OAuth 授权验证: diff --git a/leanengine.d.ts b/leanengine.d.ts index 299c8e4..4142f10 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -38,6 +38,7 @@ declare module 'leanengine' { export function express(options?: MiddlewareOptions): RequestHandler; export function koa(options?: MiddlewareOptions): Function; + export function koa2(options?: MiddlewareOptions): Function; export class Object { disableBeforeHook(): void; diff --git a/package.json b/package.json index 63813f7..1bd96f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.0-alpha.0", + "version": "3.0.0-alpha.1", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", @@ -13,7 +13,7 @@ "cookies": "^0.6.2", "debug": "^2.6.0", "leancloud-cors-headers": "^0.1.0", - "leancloud-storage": "3.0.0", + "leancloud-storage": "^3.0.0", "on-headers": "^1.0.1", "underscore": "^1.8.3" }, From 4ff21255e7e0f38b692ba7557b17276a2c4facf0 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 10 Jul 2017 14:02:38 +0800 Subject: [PATCH 047/122] :heavy_minus_sign: Defined leancloud-storage as peer dependency --- .travis.yml | 1 - CHANGELOG.md | 4 ++-- README.md | 7 ++++--- package.json | 6 ++++-- test/fixtures/app.js | 11 +++++------ 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index cde3a99..1c7bd2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,3 @@ node_js: script: - npm test - - npm run test-koa diff --git a/CHANGELOG.md b/CHANGELOG.md index 62333a5..0d74c85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ ## v3.0.0 -- **不兼容改动** 升级 JavaScript SDK 到 [leancloud-storage v3.0.0-beta.1](https://github.com/leancloud/javascript-sdk/releases/tag/v3.0.0)(请检查 JS SDK 3.0 引入的不兼容改动)。 +- **不兼容改动** 指定 JavaScript SDK 为 peerDependency, 同时仅支持 [leancloud-storage v3.0.0](https://github.com/leancloud/javascript-sdk/releases/tag/v3.0.0) 以上版本。你需要运行 `npm install leancloud-storage@3 --save` 来额外安装 JS SDK,同时请检查 JS SDK 3.0 引入的其他不兼容改动。 -**新增 Koa2 支持**: +**新增 Koa2 支持(建议使用 Node 7.0 以上版本)**: ```javascript var app = new Koa(); diff --git a/README.md b/README.md index 6b2a5d7..b0cdf8a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ ```bash npm install leanengine --save +npm install leancloud-storage@3 --save ``` 建议使用 Node.js 6.0 以上的版本(可在 `package.json` 中设置 `engines.node` 为 `6.x`)。 @@ -27,6 +28,6 @@ npm install leanengine --save 见 [Releases](https://github.com/leancloud/leanengine-node-sdk/releases) -- `npm install leanengine@2.x --save` -- `npm install leanengine@1.x --save`,升级说明见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0) -- `npm install leanengine@0.x --save` 升级说明见 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html) +- `npm install leanengine@2 --save` +- `npm install leanengine@1 --save`,升级说明见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0) +- `npm install leanengine@0 --save` 升级说明见 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html) diff --git a/package.json b/package.json index 1bd96f5..90c50d0 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "cookies": "^0.6.2", "debug": "^2.6.0", "leancloud-cors-headers": "^0.1.0", - "leancloud-storage": "^3.0.0", "on-headers": "^1.0.1", "underscore": "^1.8.3" }, @@ -24,6 +23,9 @@ "should": "^11.2.0", "supertest": "^3.0.0" }, + "peerDependency": { + "leancloud-storage": "^3.0.0" + }, "keywords": [ "LeanCloud", "LeanEngine", @@ -46,7 +48,7 @@ "email": "support@leancloud.rocks" }, "scripts": { - "test": "npm run test-express && npm run test-koa1 && npm run test-koa2", + "test": "npm install leancloud-storage@3 && npm run test-express && npm run test-koa1 && npm run test-koa2", "test-express": "mocha test test/express", "test-koa1": "env FRAMEWORK=koa npm install koa@1 koa-bodyparser@2 && mocha test test/koa", "test-koa2": "env FRAMEWORK=koa npm install koa@2 koa-bodyparser@4 && mocha test test/koa test/koa2" diff --git a/test/fixtures/app.js b/test/fixtures/app.js index 5553368..e817ff9 100644 --- a/test/fixtures/app.js +++ b/test/fixtures/app.js @@ -1,13 +1,12 @@ -const Koa = require('koa'); - const AV = require('../..'); module.exports = function() { if (process.env.FRAMEWORK == 'koa') { - var app = new Koa(); - app.use(AV.koa()); - return app.listen(); + const Koa = require('koa'); + var app = new Koa(); + app.use(AV.koa()); + return app.listen(); } else { - return AV.express(); + return AV.express(); } } From 2e9d3717e275eceffa4cc06cfa5eba905836e472 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 10 Jul 2017 14:03:13 +0800 Subject: [PATCH 048/122] :bookmark: Release 3.0.0-alpha.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90c50d0..ab510f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.0-alpha.1", + "version": "3.0.0-alpha.2", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From baa5500dd0e686b956a6c384cb26fcf9264d9674 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 19 Jul 2017 11:20:03 +0800 Subject: [PATCH 049/122] :bookmark: Release 3.0.0 --- README.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b0cdf8a..d2d468c 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,6 @@ npm install leancloud-storage@3 --save 见 [Releases](https://github.com/leancloud/leanengine-node-sdk/releases) -- `npm install leanengine@2 --save` -- `npm install leanengine@1 --save`,升级说明见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0) +- `npm install leanengine@2 --save` 升级说明见 [v3.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v3.0.0) +- `npm install leanengine@1 --save` 升级说明见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0) - `npm install leanengine@0 --save` 升级说明见 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html) diff --git a/package.json b/package.json index ab510f9..9aa71a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.0-alpha.2", + "version": "3.0.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From c7a46414d7a21369c64ca2227862084d0a788e7f Mon Sep 17 00:00:00 2001 From: leeyeh Date: Tue, 1 Aug 2017 18:41:40 +0800 Subject: [PATCH 050/122] =?UTF-8?q?=F0=9F=90=9B=20Fix=20ts=20error=20by=20?= =?UTF-8?q?export=20the=20AV=20namespace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix https://leanticket.cn/tickets/13350 --- leanengine.d.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index 299c8e4..ce10fc0 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -1,6 +1,6 @@ import {Promise} from 'es6-promise'; import {Request, RequestHandler} from 'express'; -import {User as LCUser, Object as LCObject} from 'leancloud-storage'; +import {User, Object as LCObject} from 'leancloud-storage'; declare namespace Express { export interface Request { @@ -12,17 +12,18 @@ declare namespace Express { sessionToken: string }; - currentUser?: LCUser; + currentUser?: User; sessionToken?: string; } export interface Response { - saveCurrentUser(user: LCUser); + saveCurrentUser(user: User); clearCurrentUser(); } } -declare module 'leanengine' { +declare namespace AV { + interface InitializeOptions { appId: string, appKey: string, @@ -39,7 +40,7 @@ declare module 'leanengine' { export function express(options?: MiddlewareOptions): RequestHandler; export function koa(options?: MiddlewareOptions): Function; - export class Object { + export class Object extends LCObject { disableBeforeHook(): void; disableAfterHook(): void; } @@ -57,7 +58,7 @@ declare module 'leanengine' { interface RunOptions { remote?: boolean, - user?: LCUser, + user?: User, sessionToken?: string, req?: Request } @@ -78,17 +79,17 @@ declare module 'leanengine' { interface CloudFunctionRequest { meta: CloudFunctionRequestMeta, params: Object, - currentUser?: LCUser, + currentUser?: User, sessionToken?: string } interface ClassHookRequest { - object: LCObject, - currentUser?: LCUser + object: Object, + currentUser?: User } interface UserHookRequest { - currentUser: LCUser + currentUser: User } type CloudFunction = (request: CloudFunctionRequest) => Promise; @@ -129,3 +130,5 @@ declare module 'leanengine' { export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; } } + +export = AV; \ No newline at end of file From 62974181b5f68911fd033de18c536a54d80cf37a Mon Sep 17 00:00:00 2001 From: Lee Yeh Date: Mon, 14 Aug 2017 15:54:20 +0800 Subject: [PATCH 051/122] =?UTF-8?q?=F0=9F=90=9B=20Use=20leancloud-storage/?= =?UTF-8?q?live-query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prevent https://leanticket.cn/tickets/13597#599148ea5c497d0057a57641 --- lib/storage-extra.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/storage-extra.js b/lib/storage-extra.js index a365560..f61bfce 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -1,5 +1,5 @@ 'use strict'; -var AV = require('leancloud-storage'); +var AV = require('leancloud-storage/live-query'); AV._config.disableCurrentUser = true; From 66ecfb9639f2b1be1ea9c57437211e6aa2c36764 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 24 Aug 2017 14:33:01 +0800 Subject: [PATCH 052/122] :bookmark: Release 3.0.1 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d74c85..bbf41a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 更新日志 +## v3.0.1 + +- 默认加载 JavaScript 中的 LiveQuery 特性。 +- 修复 TypeScript 定义文件中的 AV.Object. + ## v3.0.0 - **不兼容改动** 指定 JavaScript SDK 为 peerDependency, 同时仅支持 [leancloud-storage v3.0.0](https://github.com/leancloud/javascript-sdk/releases/tag/v3.0.0) 以上版本。你需要运行 `npm install leancloud-storage@3 --save` 来额外安装 JS SDK,同时请检查 JS SDK 3.0 引入的其他不兼容改动。 diff --git a/package.json b/package.json index 9aa71a3..324c070 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.0", + "version": "3.0.1", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From e924f59cfacd560030158c6e2d0da482155c7098 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 28 Aug 2017 14:55:13 +0800 Subject: [PATCH 053/122] :bug: Fix promise style before hook #119 --- CHANGELOG.md | 4 ++++ lib/leanengine.js | 2 +- package.json | 2 +- test/function-test.js | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbf41a9..0872036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## v3.0.2 + +- 修复 Promise 写法的 beforeHook 无法正确工作的问题。 + ## v3.0.1 - 默认加载 JavaScript 中的 LiveQuery 特性。 diff --git a/lib/leanengine.js b/lib/leanengine.js index 2e2593f..cab616b 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -238,7 +238,7 @@ function callClassHook(req, className, hookName) { if (hookType === 'after') { resolve({result: 'ok'}); } else { - resolve(object); + resolve(_.omit(object._toFullJSON(), ['__type', 'className'])); } }).catch(reject); } diff --git a/package.json b/package.json index 324c070..86d365e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.1", + "version": "3.0.2", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", diff --git a/test/function-test.js b/test/function-test.js index 735b31a..976cc17 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -362,7 +362,8 @@ describe('functions', function() { .set('x-avoscloud-session-token', '00000000000000000000') .expect(400) .end(function(err, res) { - res.body.should.eql({ code: 211, error: 'Could not find user' }); + res.body.code.should.be.equal(211); + res.body.error.should.be.match(/Could not find user/); done(); }); }); From 15ab23dde1a77b7b0b00e7873f1e3691028a956d Mon Sep 17 00:00:00 2001 From: Lee Yeh Date: Thu, 21 Sep 2017 03:13:09 -0500 Subject: [PATCH 054/122] =?UTF-8?q?=F0=9F=90=9B=20Fix=20useragent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/storage-extra.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/storage-extra.js b/lib/storage-extra.js index f61bfce..334e4b9 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -11,7 +11,7 @@ if (process.env.LC_API_SERVER) { AV.setServerURLs(process.env.LC_API_SERVER); } -AV._config.userAgent = 'AVOS Cloud Code Node ' + require('../package').version; +AV._sharedConfig.userAgent = 'AVOS Cloud Code Node ' + require('../package').version; AV.Cloud.__prod = process.env.NODE_ENV === 'production' ? 1 : 0; AV.setProduction(AV.Cloud.__prod); From 0c1110a5b77a8077a9e8b20df6c14680e06c2661 Mon Sep 17 00:00:00 2001 From: wchen Date: Fri, 10 Nov 2017 17:58:30 +0800 Subject: [PATCH 055/122] fix: add LEANCLOUD_API_SERVER env support --- lib/storage-extra.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/storage-extra.js b/lib/storage-extra.js index 334e4b9..e6ed6d8 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -11,6 +11,10 @@ if (process.env.LC_API_SERVER) { AV.setServerURLs(process.env.LC_API_SERVER); } +if (process.env.LEANCLOUD_API_SERVER) { + AV.setServerURLs(process.env.LEANCLOUD_API_SERVER); +} + AV._sharedConfig.userAgent = 'AVOS Cloud Code Node ' + require('../package').version; AV.Cloud.__prod = process.env.NODE_ENV === 'production' ? 1 : 0; AV.setProduction(AV.Cloud.__prod); From f223837c3e26565c93d8171adf34cfe38c58a826 Mon Sep 17 00:00:00 2001 From: leeyeh Date: Tue, 5 Dec 2017 21:53:38 +0800 Subject: [PATCH 056/122] =?UTF-8?q?=F0=9F=90=9B=20Fix=20ts=20definition=20?= =?UTF-8?q?namespace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- leanengine.d.ts | 189 ++++++++++++++++++++++++------------------------ 1 file changed, 93 insertions(+), 96 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index e8a366c..c7d85e9 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -1,6 +1,7 @@ import {Promise} from 'es6-promise'; import {Request, RequestHandler} from 'express'; import {User, Object as LCObject} from 'leancloud-storage'; +export * from 'leancloud-storage'; declare namespace Express { export interface Request { @@ -22,114 +23,110 @@ declare namespace Express { } } -declare namespace AV { - interface InitializeOptions { - appId: string, - appKey: string, - masterKey: string +interface InitializeOptions { + appId: string, + appKey: string, + masterKey: string +} + +interface MiddlewareOptions { + timeout?: string, + printFullStack?: boolean +} + +export function init(options: InitializeOptions): void; + +export function express(options?: MiddlewareOptions): RequestHandler; +export function koa(options?: MiddlewareOptions): Function; +export function koa2(options?: MiddlewareOptions): Function; + +export class Object extends LCObject { + disableBeforeHook(): void; + disableAfterHook(): void; +} + +export namespace Insight { + type InsightHandler = (result: Object) => Promise; + + export function on(event: string, handler: InsightHandler): Promise; +} + +export namespace Cloud { + interface DefineOptions { + fetchUser?: boolean + } + + interface RunOptions { + remote?: boolean, + user?: User, + sessionToken?: string, + req?: Request } interface MiddlewareOptions { - timeout?: string, - printFullStack?: boolean + framework?: string } - export function init(options: InitializeOptions): void; + interface CookieSessionOptions extends MiddlewareOptions { + secret: string + fetchUser?: boolean + } - export function express(options?: MiddlewareOptions): RequestHandler; - export function koa(options?: MiddlewareOptions): Function; - export function koa2(options?: MiddlewareOptions): Function; + interface CloudFunctionRequestMeta { + remoteAddress: string + } - export class Object extends LCObject { - disableBeforeHook(): void; - disableAfterHook(): void; + interface CloudFunctionRequest { + meta: CloudFunctionRequestMeta, + params: Object, + currentUser?: User, + sessionToken?: string } - export namespace Insight { - type InsightHandler = (result: Object) => Promise; + interface ClassHookRequest { + object: Object, + currentUser?: User + } - export function on(event: string, handler: InsightHandler): Promise; + interface UserHookRequest { + currentUser: User } - export namespace Cloud { - interface DefineOptions { - fetchUser?: boolean - } - - interface RunOptions { - remote?: boolean, - user?: User, - sessionToken?: string, - req?: Request - } - - interface MiddlewareOptions { - framework?: string - } - - interface CookieSessionOptions extends MiddlewareOptions { - secret: string - fetchUser?: boolean - } - - interface CloudFunctionRequestMeta { - remoteAddress: string - } - - interface CloudFunctionRequest { - meta: CloudFunctionRequestMeta, - params: Object, - currentUser?: User, - sessionToken?: string - } - - interface ClassHookRequest { - object: Object, - currentUser?: User - } - - interface UserHookRequest { - currentUser: User - } - - type CloudFunction = (request: CloudFunctionRequest) => Promise; - type ClassHookFunction = (request: ClassHookRequest) => Promise; - type UserHookFunction = (request: UserHookRequest) => Promise; - - export class Error { - constructor(message: string, options?: {status?: number, code?: number}) - } - - export function define(name: string, options: DefineOptions, handler: CloudFunction); - export function define(name: string, handler: CloudFunction); - - export function run(name: string, params: Object, options?: RunOptions): Promise; - export function rpc(name: string, params: Object, options?: RunOptions): Promise; - - export function beforeSave(className: string, handler: ClassHookFunction): void; - export function afterSave(className: string, handler: ClassHookFunction): void; - export function beforeUpdate(className: string, handler: ClassHookFunction): void; - export function afterUpdate(className: string, handler: ClassHookFunction): void; - export function beforeDelete(className: string, handler: ClassHookFunction): void; - export function afterDelete(className: string, handler: ClassHookFunction): void; - - export function onVerified(handler: UserHookFunction): void; - export function onLogin(handler: UserHookFunction): void; - - export function onIMMessageReceived(handler: CloudFunction): void; - export function onIMReceiversOffline(handler: CloudFunction): void; - export function onIMMessageSent(handler: CloudFunction): void; - export function onIMConversationStart(handler: CloudFunction): void; - export function onIMConversationStarted(handler: CloudFunction): void; - export function onIMConversationAdd(handler: CloudFunction): void; - export function onIMConversationRemove(handler: CloudFunction): void; - export function onIMConversationUpdate(handler: CloudFunction): void; - - export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; - export function CookieSession(options?: CookieSessionOptions): RequestHandler; - export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; + type CloudFunction = (request: CloudFunctionRequest) => Promise; + type ClassHookFunction = (request: ClassHookRequest) => Promise; + type UserHookFunction = (request: UserHookRequest) => Promise; + + export class Error { + constructor(message: string, options?: {status?: number, code?: number}) } -} -export = AV; \ No newline at end of file + export function define(name: string, options: DefineOptions, handler: CloudFunction); + export function define(name: string, handler: CloudFunction); + + export function run(name: string, params: Object, options?: RunOptions): Promise; + export function rpc(name: string, params: Object, options?: RunOptions): Promise; + + export function beforeSave(className: string, handler: ClassHookFunction): void; + export function afterSave(className: string, handler: ClassHookFunction): void; + export function beforeUpdate(className: string, handler: ClassHookFunction): void; + export function afterUpdate(className: string, handler: ClassHookFunction): void; + export function beforeDelete(className: string, handler: ClassHookFunction): void; + export function afterDelete(className: string, handler: ClassHookFunction): void; + + export function onVerified(handler: UserHookFunction): void; + export function onLogin(handler: UserHookFunction): void; + + export function onIMMessageReceived(handler: CloudFunction): void; + export function onIMReceiversOffline(handler: CloudFunction): void; + export function onIMMessageSent(handler: CloudFunction): void; + export function onIMConversationStart(handler: CloudFunction): void; + export function onIMConversationStarted(handler: CloudFunction): void; + export function onIMConversationAdd(handler: CloudFunction): void; + export function onIMConversationRemove(handler: CloudFunction): void; + export function onIMConversationUpdate(handler: CloudFunction): void; + + export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; + export function CookieSession(options?: CookieSessionOptions): RequestHandler; + export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; +} From 31cef079a7d222bbce8880dae4cd395421ac9d70 Mon Sep 17 00:00:00 2001 From: jysperm Date: Sat, 24 Feb 2018 18:09:39 +0800 Subject: [PATCH 057/122] :sparkles: AV.express add `onError` option --- leanengine.d.ts | 4 ++-- lib/leanengine.js | 2 ++ test/constructor-test.js | 28 ++++++++++++++++++++++++++++ test/fixtures/app.js | 6 +++--- 4 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 test/constructor-test.js diff --git a/leanengine.d.ts b/leanengine.d.ts index c7d85e9..20fc74d 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -23,7 +23,6 @@ declare namespace Express { } } - interface InitializeOptions { appId: string, appKey: string, @@ -32,7 +31,8 @@ interface InitializeOptions { interface MiddlewareOptions { timeout?: string, - printFullStack?: boolean + printFullStack?: boolean, + onError?(err: Error) } export function init(options: InitializeOptions): void; diff --git a/lib/leanengine.js b/lib/leanengine.js index cab616b..aab3a09 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -131,6 +131,8 @@ function createCloudFunctionRouter(options) { error: err.message || err.responseText || err || 'unknown error' })); } + + options.onError && options.onError(err); }); }); diff --git a/test/constructor-test.js b/test/constructor-test.js new file mode 100644 index 0000000..245e816 --- /dev/null +++ b/test/constructor-test.js @@ -0,0 +1,28 @@ +const request = require('supertest'); +const should = require('should'); + +require('./fixtures/functions'); + +const {appId, appKey} = require('./fixtures/app-info'); + +describe('onError option', function() { + it('should be called with error', function(done) { + const app = require('./fixtures/app')({ + onError: (err) => { + err.message.should.be.equal('some message'); + err.status.should.be.equal(400); + done(); + } + }); + + request(app) + .post('/1.1/functions/clientErrorPromise') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .expect(400, (err) => { + if (err) { + done(err); + } + }); + }); +}); diff --git a/test/fixtures/app.js b/test/fixtures/app.js index e817ff9..cdc4db2 100644 --- a/test/fixtures/app.js +++ b/test/fixtures/app.js @@ -1,12 +1,12 @@ const AV = require('../..'); -module.exports = function() { +module.exports = function(options) { if (process.env.FRAMEWORK == 'koa') { const Koa = require('koa'); var app = new Koa(); - app.use(AV.koa()); + app.use(AV.koa(options)); return app.listen(); } else { - return AV.express(); + return AV.express(options); } } From 3b7c0363b661064b5528f7ef1622b627b130e8dd Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 26 Feb 2018 15:01:43 +0800 Subject: [PATCH 058/122] :pencil2: Fix typo verifType -> verifyType --- lib/leanengine.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/leanengine.js b/lib/leanengine.js index aab3a09..21af9d2 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -247,8 +247,8 @@ function callClassHook(req, className, hookName) { }); } -function callUserHook(req, hookName, verifType) { - const userHookFunction = Cloud.functions[utils.hookNameMapping[hookName] + verifType]; +function callUserHook(req, hookName, verifyType) { + const userHookFunction = Cloud.functions[utils.hookNameMapping[hookName] + verifyType]; checkHookKey(req); From 8ad83df70491767b6d114a9b4204f32aa1bb4fa7 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 26 Feb 2018 15:44:34 +0800 Subject: [PATCH 059/122] :sparkles: AV.express add `ignoreInvalidSessionToken` option --- leanengine.d.ts | 3 ++- lib/leanengine.js | 10 +++++++--- test/constructor-test.js | 17 +++++++++++++++-- test/fixtures/functions.js | 4 ++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index 20fc74d..0dc7eee 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -32,7 +32,8 @@ interface InitializeOptions { interface MiddlewareOptions { timeout?: string, printFullStack?: boolean, - onError?(err: Error) + onError?(err: Error), + ignoreInvalidSessionToken?: boolean } export function init(options: InitializeOptions): void; diff --git a/lib/leanengine.js b/lib/leanengine.js index 21af9d2..f4c19f5 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -93,7 +93,7 @@ function createCloudFunctionRouter(options) { const hookName = urlParams[2]; if (!hookName) { - return callCloudFunction(req, functionOrClass); + return callCloudFunction(req, functionOrClass, options); } else if (functionOrClass === 'onVerified') { return callUserHook(req, 'onVerified', hookName); } else if (functionOrClass === '_User' && hookName === 'onLogin') { @@ -148,7 +148,7 @@ function createCloudFunctionRouter(options) { return cloudFunctions; } -function callCloudFunction(req, funcName) { +function callCloudFunction(req, funcName, options) { const cloudFunction = Cloud.functions[funcName]; if (!cloudFunction) { @@ -167,7 +167,11 @@ function callCloudFunction(req, funcName) { return promiseTry( () => { if (cloudFunction.fetchUser !== false && req.AV.sessionToken && req.AV.sessionToken !== '') { - return AV.User.become(req.AV.sessionToken); + return AV.User.become(req.AV.sessionToken).catch( err => { + if (!options.ignoreInvalidSessionToken) { + throw err; + } + }); } }).then( user => { const request = utils.prepareRequestObject({req, user, params}); diff --git a/test/constructor-test.js b/test/constructor-test.js index 245e816..90225de 100644 --- a/test/constructor-test.js +++ b/test/constructor-test.js @@ -5,8 +5,8 @@ require('./fixtures/functions'); const {appId, appKey} = require('./fixtures/app-info'); -describe('onError option', function() { - it('should be called with error', function(done) { +describe('constructor', function() { + it('onError option', function(done) { const app = require('./fixtures/app')({ onError: (err) => { err.message.should.be.equal('some message'); @@ -25,4 +25,17 @@ describe('onError option', function() { } }); }); + + it('ignoreInvalidSessionToken option', function(done) { + const app = require('./fixtures/app')({ + ignoreInvalidSessionToken: true + }); + + request(app) + .post('/1.1/functions/whoami') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Session', '00000000000000000000') + .expect(200, done); + }); }); diff --git a/test/fixtures/functions.js b/test/fixtures/functions.js index 04b5e9d..baa59a1 100644 --- a/test/fixtures/functions.js +++ b/test/fixtures/functions.js @@ -123,6 +123,10 @@ AV.Cloud.define('testUser', function(request, response) { response.success('ok'); }); +AV.Cloud.define('whoami', function(request) { + return request.currentUser; +}); + AV.Cloud.define('dontFetchUser', {fetchUser: false}, function(req, res) { should.not.exist(res.user); should.not.exist(res.currentUser); From d8eca0e2ee7f2b9366d0470eb724587b5c1b8a5b Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 26 Feb 2018 15:45:39 +0800 Subject: [PATCH 060/122] :construction_worker: Run tsc to test typescript definition --- package.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 86d365e..d750cf2 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,10 @@ }, "devDependencies": { "blanket": "^1.2.3", + "es6-promise": "^4.2.4", "express": "^4.14.1", "mocha": "^3.2.0", + "npm-run-all": "^4.1.2", "should": "^11.2.0", "supertest": "^3.0.0" }, @@ -48,9 +50,10 @@ "email": "support@leancloud.rocks" }, "scripts": { - "test": "npm install leancloud-storage@3 && npm run test-express && npm run test-koa1 && npm run test-koa2", + "test": "npm install --no-save leancloud-storage@3 && npm-run-all test-tsd test-express test-koa1 test-koa2", "test-express": "mocha test test/express", - "test-koa1": "env FRAMEWORK=koa npm install koa@1 koa-bodyparser@2 && mocha test test/koa", - "test-koa2": "env FRAMEWORK=koa npm install koa@2 koa-bodyparser@4 && mocha test test/koa test/koa2" + "test-tsd": "tsc leanengine.d.ts", + "test-koa1": "env FRAMEWORK=koa npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && mocha test test/koa", + "test-koa2": "env FRAMEWORK=koa npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && mocha test test/koa test/koa2" } } From 5e8b2b88380e536012a36795a546ba5775befac0 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 26 Feb 2018 15:54:13 +0800 Subject: [PATCH 061/122] :bookmark: Prepare 3.1.0 --- CHANGELOG.md | 6 ++++++ README.md | 5 ++--- package.json | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0872036..5f411b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # 更新日志 +## v3.1.0 + +- `AV.Express()` 添加 `onError`(全局云函数错误处理)和 `ignoreInvalidSessionToken`(忽略不正确的 Session Token 而不是返回错误)选项。 +- 修复改进 TypeScript 定义文件 +- 修复发出请求的 User Agent + ## v3.0.2 - 修复 Promise 写法的 beforeHook 无法正确工作的问题。 diff --git a/README.md b/README.md index d2d468c..93b2c1b 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ ## 安装 ```bash -npm install leanengine --save -npm install leancloud-storage@3 --save +npm install --save leanengine leancloud-storage@3 --save ``` 建议使用 Node.js 6.0 以上的版本(可在 `package.json` 中设置 `engines.node` 为 `6.x`)。 @@ -20,7 +19,7 @@ npm install leancloud-storage@3 --save ## 项目示例 * 项目模板: -* Todo 列表示例: +* Node.js Demo 汇总: * 微信公众平台: * 微博 OAuth 授权验证: diff --git a/package.json b/package.json index d750cf2..36c2507 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.0.2", + "version": "3.1.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 8e58fb66bd9900c6e23f63a3ee821d1df473da8c Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Mar 2018 15:09:55 +0800 Subject: [PATCH 062/122] :bug: Fix https-redirect for koa --- lib/frameworks.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/frameworks.js b/lib/frameworks.js index b328357..0365f69 100644 --- a/lib/frameworks.js +++ b/lib/frameworks.js @@ -4,6 +4,8 @@ function express(middleware) { function koa(middleware) { return function*(next) { + this.req.secure = this.secure; // used by cookie-session + yield middleware.bind(null, this.req, this.res); if (this.req.currentUser) { @@ -33,6 +35,8 @@ function koa(middleware) { function koa2(middleware) { return function(ctx, next) { return new Promise( (resolve, reject) => { + ctx.req.secure = ctx.secure; // used by cookie-session + middleware(ctx.req, ctx.res, err => { if (ctx.req.currentUser) { ctx.currentUser = ctx.req.currentUser; From 945d2abf4bac5aa6ff9dff4964a8d1ccb45a0414 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Mar 2018 15:10:40 +0800 Subject: [PATCH 063/122] :green_heart: Fix tests --- test/express/https-redirect-test.js | 11 ++++++++++- test/function-test.js | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/express/https-redirect-test.js b/test/express/https-redirect-test.js index 7d14f39..9c54df2 100644 --- a/test/express/https-redirect-test.js +++ b/test/express/https-redirect-test.js @@ -28,10 +28,19 @@ describe('https-redirect', function() { }); }); - it('should not redirect', function(done) { + it('should not redirect (local)', function(done) { request(app) .get('/test') .expect(200) .expect("Hello World!", done); }); + + it('should not redirect (https)', function(done) { + request(app) + .get('/test') + .set('HOST', 'stg-abc.leanapp.cn') + .set('X-Forwarded-Proto', 'https') + .expect(200) + .expect("Hello World!", done); + }); }); diff --git a/test/function-test.js b/test/function-test.js index 976cc17..a23c4c7 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -147,7 +147,7 @@ describe('functions', function() { __type: 'File', objectId: '55543fc2e4b0846760bd92f3', name: 'ttt.jpg', - url: 'http://ac-4h2h4okw.clouddn.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg' + url: 'http://lc-4h2h4okw.cn-n1.lcfile.com/4qSbLMO866Tf4YtT9QEwJwysTlHGC9sMl7bpTwhQ.jpg' }); result.avObjects.forEach(function(object) { From a57693637ba0538a6cd2d70fe323c33d9ef6f3ca Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Mar 2018 15:11:43 +0800 Subject: [PATCH 064/122] :white_check_mark: Merge koa1 and koa2 tests --- package.json | 4 +- test/fixtures/app.js | 10 +- test/koa/cookie-session-koa-test.js | 100 -------------------- test/koa/cookie-session-test.js | 139 ++++++++++++++++++++++++++++ test/koa/https-redirect-koa-test.js | 40 -------- test/koa/https-redirect-test.js | 59 ++++++++++++ test/koa/koa-test.js | 38 ++++++++ test/koa2/koa2-test.js | 29 ------ 8 files changed, 246 insertions(+), 173 deletions(-) delete mode 100644 test/koa/cookie-session-koa-test.js create mode 100644 test/koa/cookie-session-test.js delete mode 100644 test/koa/https-redirect-koa-test.js create mode 100644 test/koa/https-redirect-test.js create mode 100644 test/koa/koa-test.js delete mode 100644 test/koa2/koa2-test.js diff --git a/package.json b/package.json index 36c2507..478bca5 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "test": "npm install --no-save leancloud-storage@3 && npm-run-all test-tsd test-express test-koa1 test-koa2", "test-express": "mocha test test/express", "test-tsd": "tsc leanengine.d.ts", - "test-koa1": "env FRAMEWORK=koa npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && mocha test test/koa", - "test-koa2": "env FRAMEWORK=koa npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && mocha test test/koa test/koa2" + "test-koa1": "npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test test/koa", + "test-koa2": "npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test test/koa" } } diff --git a/test/fixtures/app.js b/test/fixtures/app.js index cdc4db2..2718702 100644 --- a/test/fixtures/app.js +++ b/test/fixtures/app.js @@ -1,10 +1,16 @@ const AV = require('../..'); module.exports = function(options) { - if (process.env.FRAMEWORK == 'koa') { + if (process.env.FRAMEWORK === 'koa') { const Koa = require('koa'); var app = new Koa(); - app.use(AV.koa(options)); + + if (process.env.KOA_VER === '1') { + app.use(AV.koa(options)); + } else { + app.use(AV.koa2(options)); + } + return app.listen(); } else { return AV.express(options); diff --git a/test/koa/cookie-session-koa-test.js b/test/koa/cookie-session-koa-test.js deleted file mode 100644 index 7fe1495..0000000 --- a/test/koa/cookie-session-koa-test.js +++ /dev/null @@ -1,100 +0,0 @@ -var koa = require('koa'); -var bodyParser = require('koa-bodyparser'); -var request = require('supertest'); -var should = require('should'); - -const AV = require('../..'); -const appInfo = require('../fixtures/app-info'); - -var app = new koa(); - -app.use(AV.koa()); -app.use(bodyParser()); -app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true})); - -app.use(function *(next) { - try { - yield next; - } catch (err) { - this.status = err.status || 500; - this.body = err.message; - this.app.emit('error', err, this); - } -}); - -app.use(function *(next) { - var method = this.request.method; - var url = this.request.url; - - if (method === 'GET' && url === '/') { - this.status = 200; - this.body = '

Hello world

'; - } else if (method === 'POST' && url === '/login') { - return AV.User.logIn(this.request.body.username, this.request.body.password).then( user => { - this.response.saveCurrentUser(user); - this.response.redirect('/profile'); - }); - } else if (method === 'GET' && url === '/profile') { - this.status = 200; - this.body = this.request.currentUser; - } else if (method === 'POST' && url === '/logout') { - this.status = 200; - this.response.saveCurrentUser(null); - } else { - yield next; - } -}); - -var server = app.listen(); - -describe('webhosting-koa', function() { - it('index', function(done) { - request(server).get('/') - .expect(200, function(err, res) { - res.headers['content-type'].should.be.startWith('text/html'); - res.text.should.be.equal('

Hello world

'); - done(err); - }); - }); - - it('loign', function(done) { - request(server).post('/login') - .send({ - username: 'admin', - password: 'admin' - }) - .expect(302, function(err, res) { - res.headers.location.should.equal('/profile'); - res.headers['set-cookie'][0].indexOf('avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; path=/; expires=').should.equal(0); - res.headers['set-cookie'][1].indexOf('avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0; path=/; expires=').should.equal(0); - done(err); - }); - }); - - it('profile', function(done) { - request(server).get('/profile') - .set('Cookie', 'avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0') - .expect(200, function(err, res) { - should.exist(res.body.objectId); - res.body.username.should.be.equal('admin'); - done(err); - }); - }); - - it('profile without cookie', function(done) { - request(server).get('/profile') - .expect(204, function(err, res) { - res.body.should.be.empty(); - done(err); - }); - }); - - it('logout', function(done) { - request(server).post('/logout') - .set('Cookie', 'avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0') - .expect(200, function(err, res) { - res.headers['set-cookie'][0].indexOf('avos:sess=; path=/; expires=').should.equal(0); - done(err); - }); - }) -}); diff --git a/test/koa/cookie-session-test.js b/test/koa/cookie-session-test.js new file mode 100644 index 0000000..74b6635 --- /dev/null +++ b/test/koa/cookie-session-test.js @@ -0,0 +1,139 @@ +var Koa = require('koa'); +var bodyParser = require('koa-bodyparser'); +var request = require('supertest'); +var should = require('should'); + +const AV = require('../..'); +const appInfo = require('../fixtures/app-info'); + +var app = new Koa(); + +if (process.env.KOA_VER === '1') { + app.use(AV.koa()); + app.use(bodyParser()); + app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true})); + + app.use(function *(next) { + try { + yield next; + } catch (err) { + this.status = err.status || 500; + this.body = err.message; + this.app.emit('error', err, this); + } + }); + + app.use(function *(next) { + var method = this.request.method; + var url = this.request.url; + + if (method === 'GET' && url === '/') { + this.status = 200; + this.body = '

Hello world

'; + } else if (method === 'POST' && url === '/login') { + return AV.User.logIn(this.request.body.username, this.request.body.password).then( user => { + this.saveCurrentUser(user); + this.response.redirect('/profile'); + }); + } else if (method === 'GET' && url === '/profile') { + this.status = 200; + this.body = this.currentUser; + } else if (method === 'POST' && url === '/logout') { + this.status = 200; + this.saveCurrentUser(null); + } else { + yield next; + } + }); +} else { + app.use(AV.koa2()); + app.use(bodyParser()); + app.use(AV.Cloud.CookieSession({framework: 'koa2', secret: 'my secret', maxAge: 3600000, fetchUser: true})); + + app.use(async (ctx, next) => { + try { + await next(); + } catch (err) { + ctx.status = err.status || 500; + ctx.body = err.message; + ctx.app.emit('error', err, this); + } + }); + + app.use(async (ctx, next) => { + var method = ctx.request.method; + var url = ctx.request.url; + + if (method === 'GET' && url === '/') { + ctx.status = 200; + ctx.body = '

Hello world

'; + } else if (method === 'POST' && url === '/login') { + return AV.User.logIn(ctx.request.body.username, ctx.request.body.password).then( user => { + ctx.saveCurrentUser(user); + ctx.response.redirect('/profile'); + }); + } else if (method === 'GET' && url === '/profile') { + ctx.status = 200; + ctx.body = ctx.currentUser; + } else if (method === 'POST' && url === '/logout') { + ctx.status = 200; + ctx.saveCurrentUser(null); + } else { + return next(); + } + }); +} + +var server = app.listen(); + +describe('koa/cookie-session', function() { + it('index', function(done) { + request(server).get('/') + .expect(200, function(err, res) { + res.headers['content-type'].should.be.startWith('text/html'); + res.text.should.be.equal('

Hello world

'); + done(err); + }); + }); + + it('loign', function(done) { + request(server).post('/login') + .send({ + username: 'admin', + password: 'admin' + }) + .expect(302, function(err, res) { + res.headers.location.should.equal('/profile'); + res.headers['set-cookie'][0].indexOf('avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; path=/; expires=').should.equal(0); + res.headers['set-cookie'][1].indexOf('avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0; path=/; expires=').should.equal(0); + done(err); + }); + }); + + it('profile', function(done) { + request(server).get('/profile') + .set('Cookie', 'avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0') + .expect(200, function(err, res) { + should.exist(res.body.objectId); + res.body.username.should.be.equal('admin'); + done(err); + }); + }); + + it('profile without cookie', function(done) { + request(server).get('/profile') + .expect(204, function(err, res) { + res.body.should.be.empty(); + done(err); + }); + }); + + it('logout', function(done) { + request(server).post('/logout') + .set('Cookie', 'avos:sess=eyJfdWlkIjoiNTRmZDZhMDNlNGIwNmM0MWUwMGIxZjQwIiwiX3Nlc3Npb25Ub2tlbiI6IncyanJ0a2JlaHAzOG90cW1oYnF1N3liczkifQ==; avos:sess.sig=jMYF3Iwhmw903-K1K12MVdAFOh0') + .expect(200, function(err, res) { + res.headers['set-cookie'][0].indexOf('avos:sess=; path=/; expires=').should.equal(0); + done(err); + }); + }) +}); diff --git a/test/koa/https-redirect-koa-test.js b/test/koa/https-redirect-koa-test.js deleted file mode 100644 index ffbd28e..0000000 --- a/test/koa/https-redirect-koa-test.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -var koa = require('koa'); -var request = require('supertest'); -require('should'); - -var AV = require('../..'); -const appInfo = require('../fixtures/app-info'); - -var app = new koa(); - -app.proxy = true; -app.use(AV.Cloud.HttpsRedirect({framework: 'koa'})); - -app.use(function *(next) { - this.body = 'Hello World!'; -}); - -var server = app.listen(); - -describe('https-redirect-koa', function() { - it('should redirect', function(done) { - request(server) - .get('/test') - .set('host', 'stg-abc.leanapp.cn') - .expect(302) - .end(function(err, res) { - res.headers.location.should.equal('https://stg-abc.leanapp.cn/test'); - res.text.should.endWith('Redirecting to https://stg-abc.leanapp.cn/test'); - done(); - }); - }); - - it('should not redirect', function(done) { - request(server) - .get('/test') - .expect(200) - .expect("Hello World!", done); - }); -}); diff --git a/test/koa/https-redirect-test.js b/test/koa/https-redirect-test.js new file mode 100644 index 0000000..98f5a33 --- /dev/null +++ b/test/koa/https-redirect-test.js @@ -0,0 +1,59 @@ +'use strict'; + +var Koa = require('koa'); +var request = require('supertest'); +require('should'); + +var AV = require('../..'); +const appInfo = require('../fixtures/app-info'); + +var app = new Koa(); + +app.proxy = true; + +if (process.env.KOA_VER === '1') { + app.use(AV.Cloud.HttpsRedirect({framework: 'koa'})); + + app.use(function *(next) { + this.body = 'Hello World!'; + yield next; + }); +} else { + app.use(AV.Cloud.HttpsRedirect({framework: 'koa2'})); + + app.use(async ctx => { + ctx.body = 'Hello World!'; + }); +} + +var server = app.listen(); + +describe('koa/https-redirect', function() { + it('should redirect', function(done) { + request(server) + .get('/test') + .set('host', 'stg-abc.leanapp.cn') + .expect(302) + .end(function(err, res) { + res.headers.location.should.equal('https://stg-abc.leanapp.cn/test'); + res.text.should.endWith('Redirecting to https://stg-abc.leanapp.cn/test'); + done(); + }); + }); + + it('should not redirect (local)', function(done) { + request(server) + .get('/test') + .expect(200) + .expect("Hello World!", done); + }); + + it('should not redirect (https)', function(done) { + request(server) + .get('/test') + .set('HOST', 'stg-abc.leanapp.cn') + .set('X-Forwarded-Proto', 'https') + .expect(200) + .expect("Hello World!", done); + }); +}); diff --git a/test/koa/koa-test.js b/test/koa/koa-test.js new file mode 100644 index 0000000..284ffe8 --- /dev/null +++ b/test/koa/koa-test.js @@ -0,0 +1,38 @@ +const bodyParser = require('koa-bodyparser'); +const Koa = require('koa'); +const request = require('supertest'); +const should = require('should'); + +const AV = require('../..'); +const appInfo = require('../fixtures/app-info'); + +const app = new Koa(); + +if (process.env.KOA_VER === '1') { + app.use(AV.koa()); + app.use(bodyParser()); + app.use(AV.Cloud.HttpsRedirect({framework: 'koa'})); + app.use(AV.Cloud.CookieSession({framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true})); + app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa'})); +} else { + app.use(AV.koa2()); + app.use(bodyParser()); + app.use(AV.Cloud.HttpsRedirect({framework: 'koa2'})); + app.use(AV.Cloud.CookieSession({framework: 'koa2', secret: 'my secret', maxAge: 3600000, fetchUser: true})); + app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa2'})); +} + + +const server = app.listen(); + +describe('koa', function() { + it('health-check', done => { + request(server) + .get('/__engine/1/ping') + .expect(200, (err, res) => { + should.exist(res.body.runtime); + should.exist(res.body.version); + done(err); + }); + }); +}); diff --git a/test/koa2/koa2-test.js b/test/koa2/koa2-test.js deleted file mode 100644 index 91eb0cc..0000000 --- a/test/koa2/koa2-test.js +++ /dev/null @@ -1,29 +0,0 @@ -const bodyParser = require('koa-bodyparser'); -const Koa = require('koa'); -const request = require('supertest'); -const should = require('should'); - -const AV = require('../..'); -const appInfo = require('../fixtures/app-info'); - -const app = new Koa(); - -app.use(AV.koa2()); -app.use(bodyParser()); -app.use(AV.Cloud.HttpsRedirect({framework: 'koa2'})); -app.use(AV.Cloud.CookieSession({framework: 'koa2', secret: 'my secret', maxAge: 3600000, fetchUser: true})); -app.use(AV.Cloud.LeanCloudHeaders({framework: 'koa2'})); - -const server = app.listen(); - -describe('koa2', function() { - it('health-check', done => { - request(server) - .get('/__engine/1/ping') - .expect(200, (err, res) => { - should.exist(res.body.runtime); - should.exist(res.body.version); - done(err); - }); - }); -}); From 6413f6cf3826dda51ef5d9eea8e7e0c07a02190f Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 28 Mar 2018 15:18:54 +0800 Subject: [PATCH 065/122] :bookmark: Prepare 3.1.1 --- CHANGELOG.md | 4 ++++ README.md | 2 +- package.json | 9 +++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f411b2..85a7df2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## v3.1.1 + +- 修复 `AV.Cloud.HttpsRedirect` 在 koa 中会出现循环重定向的问题。 + ## v3.1.0 - `AV.Express()` 添加 `onError`(全局云函数错误处理)和 `ignoreInvalidSessionToken`(忽略不正确的 Session Token 而不是返回错误)选项。 diff --git a/README.md b/README.md index 93b2c1b..b9af822 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ npm install --save leanengine leancloud-storage@3 --save ``` -建议使用 Node.js 6.0 以上的版本(可在 `package.json` 中设置 `engines.node` 为 `6.x`)。 +建议使用 Node.js 8.0 以上的版本(可在 `package.json` 中设置 `engines.node` 为 `8.x`)。 ## 文档 diff --git a/package.json b/package.json index 478bca5..717e84b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.1.0", + "version": "3.1.1", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", @@ -29,10 +29,11 @@ "leancloud-storage": "^3.0.0" }, "keywords": [ - "LeanCloud", - "LeanEngine", + "leancloud", + "leanengine", "cloud", - "BaaS" + "express", + "koa" ], "config": { "blanket": { From 7897d083da14e8afc012da5d39f236b50f29b675 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 4 Jan 2018 11:38:10 +0800 Subject: [PATCH 066/122] :sparkles: Cloud.enqueue --- API.md | 22 +++++++++++++++++++++- leanengine.d.ts | 13 +++++++++++++ lib/cloud.js | 18 ++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/API.md b/API.md index 6e7e525..7f5d458 100644 --- a/API.md +++ b/API.md @@ -75,7 +75,7 @@ new AV.Cloud.Error(message: string, options?) 运行已定义的云函数,与 JavaScript SDK 中会发起 HTTP 请求不同,在云引擎中默认变成直接调用指定的函数。 ```javascript -AV.Cloud.run(name: string, data: object, options?: object): Promise +AV.Cloud.run(name: string, params: object, options?: object): Promise ``` `options` 的属性包括: @@ -91,6 +91,26 @@ AV.Cloud.run(name: string, data: object, options?: object): Promise 兼容 JavaScript SDK 的同名函数,是 `AV.Cloud.run` 的一个别名。 +### AV.Cloud.enqueue + +在队列中运行云函数。 + +```javascript +AV.Cloud.run(name: string, params: object, options?: object): Promise +``` + +`options` 的属性包括: + +* `attempts?: number`:最大重试次数,默认 `3`. +* `backoff?: number`:重试间隔(毫秒),默认 `60000`. +* `delay?: number`:延时执行(毫秒)。 +* `notify?: string`: 将执行结果通知到指定云函数。 +* `retryTimeout?: boolean`: 将超时视作失败来进行重试,默认 `true`. + +`TaskInfo` 的属性包括: + +- `uniqueId`:任务的唯一 Id,会包含在日志中。 + ### 定义 Class Hook * AV.Cloud.beforeSave diff --git a/leanengine.d.ts b/leanengine.d.ts index 0dc7eee..5c96ab9 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -65,6 +65,18 @@ export namespace Cloud { req?: Request } + interface EnqueueOptions { + attempts?: number, + backoff?: number, + delay?: number, + notify?: string, + retryTimeout?: boolean, + } + + interface TaskInfo { + uniqueId: string + } + interface MiddlewareOptions { framework?: string } @@ -107,6 +119,7 @@ export namespace Cloud { export function run(name: string, params: Object, options?: RunOptions): Promise; export function rpc(name: string, params: Object, options?: RunOptions): Promise; + export function enqueue(name: string, params: Object, options?: EnqueueOptions): Promise; export function beforeSave(className: string, handler: ClassHookFunction): void; export function afterSave(className: string, handler: ClassHookFunction): void; diff --git a/lib/cloud.js b/lib/cloud.js index 91e2f7c..dbe574f 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -90,6 +90,24 @@ Cloud.rpc = function(name, data, options) { } }; +Cloud.enqueue = function(name, params, options) { + options = options || {}; + + if (!options.prod && !AV.Cloud.__prod) { + options.prod = 0; + } + + return AV.request({ + method: 'POST', + path: '/engine/cloud-queue/enqueue', + data: _.extend({ + function: name, + params: params + }, options), + authOptions: {useMasterKey: true} + }); +} + Cloud.beforeSave = function(nameOrClass, func) { defineClassHook(className(nameOrClass), '__before_save_for_', func); }; From b6f88cc39cc4f44f454b42527623dfdce968e1f1 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 3 May 2018 17:45:00 +0800 Subject: [PATCH 067/122] :bulb: Add `updatedKeys` to tsd --- leanengine.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/leanengine.d.ts b/leanengine.d.ts index 5c96ab9..50b9be7 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -45,6 +45,8 @@ export function koa2(options?: MiddlewareOptions): Function; export class Object extends LCObject { disableBeforeHook(): void; disableAfterHook(): void; + + updatedKeys?: string[]; } export namespace Insight { From ef384fa0cbdfdaf48e286300b48f14bae7983d76 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 3 May 2018 17:56:15 +0800 Subject: [PATCH 068/122] :ok_hand: Wrap 211 `Could not find user` error --- lib/leanengine.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/leanengine.js b/lib/leanengine.js index f4c19f5..8ab30ec 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -168,7 +168,13 @@ function callCloudFunction(req, funcName, options) { return promiseTry( () => { if (cloudFunction.fetchUser !== false && req.AV.sessionToken && req.AV.sessionToken !== '') { return AV.User.become(req.AV.sessionToken).catch( err => { - if (!options.ignoreInvalidSessionToken) { + if (options.ignoreInvalidSessionToken) { + return; + } + + if (err.code === 211) { + throw new Cloud.Error(`Verify sessionToken failed, maybe login expired: ${err.message}`, {status: 401, code: 211}); + } else { throw err; } }); From 5e9df41f7ad05896dc66ef50810753c1bb46d3d5 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 14 May 2018 16:54:27 +0800 Subject: [PATCH 069/122] :memo: Update API document --- API.md | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/API.md b/API.md index 7f5d458..7187893 100644 --- a/API.md +++ b/API.md @@ -27,6 +27,11 @@ AV.koa(options?: object) AV.koa2(options?: object) ``` +`options` 的属性包括: + +- `onError?: function(err: Error)`:全局错误处理器,当云函数和 Hook 抛出异常时会调用该回调,可用于统一的错误报告。 +- `ignoreInvalidSessionToken?: boolean`:忽略客户端发来的错误的 sessionToken(`X-LC-Session` 头),而不是报错 `211 Could not find user`。 + ## AV.Object * `AV.Object#disableBeforeHook()` @@ -113,12 +118,12 @@ AV.Cloud.run(name: string, params: object, options?: object): Promise ### 定义 Class Hook -* AV.Cloud.beforeSave -* AV.Cloud.afterSave -* AV.Cloud.beforeUpdate -* AV.Cloud.afterUpdate -* AV.Cloud.beforeDelete -* AV.Cloud.afterDelete +* `AV.Cloud.beforeSave` +* `AV.Cloud.afterSave` +* `AV.Cloud.beforeUpdate` +* `AV.Cloud.afterUpdate` +* `AV.Cloud.beforeDelete` +* `AV.Cloud.afterDelete` 这些函数的签名:`function(className: string, func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数。在 before 类 Hook 中如果没有抛出异常则视作接受这次操作。如果抛出使用 `AV.Cloud.Error` 构造的异常表示客户端错误,拒绝本次操作;如果抛出其他类型的异常则视作服务器端错误,返回 500 响应并打印错误到标准输出,也会拒绝本次操作。 @@ -134,8 +139,8 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 ### 登录和认证 Hook -* AV.Cloud.onVerified -* AV.Cloud.onLogin +* `AV.Cloud.onVerified` +* `AV.Cloud.onLogin` 这两个函数的签名:`function(func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,如果没有抛出异常则视作接受这次操作。 @@ -148,14 +153,14 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 包括: -* `onIMMessageReceived` -* `onIMReceiversOffline` -* `onIMMessageSent` -* `onIMConversationStart` -* `onIMConversationStarted` -* `onIMConversationAdd` -* `onIMConversationRemove` -* `onIMConversationUpdate` +* `AV.Cloud.onIMMessageReceived` +* `AV.Cloud.onIMReceiversOffline` +* `AV.Cloud.onIMMessageSent` +* `AV.Cloud.onIMConversationStart` +* `AV.Cloud.onIMConversationStarted` +* `AV.Cloud.onIMConversationAdd` +* `AV.Cloud.onIMConversationRemove` +* `AV.Cloud.onIMConversationUpdate` LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调用者的确是 LeanCloud 或本地调试时的命令行工具。 From 2723234c3a5e9ea821a1f7b4ce336202b36b6f6d Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 18 May 2018 11:59:26 +0800 Subject: [PATCH 070/122] :bookmark: Prepare 3.2.0 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85a7df2..edc4c73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## v3.2.0 + +- 新增 `AV.Cloud.enqueue`,任务队列支持。 + ## v3.1.1 - 修复 `AV.Cloud.HttpsRedirect` 在 koa 中会出现循环重定向的问题。 diff --git a/package.json b/package.json index 717e84b..f83ebea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.1.1", + "version": "3.2.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From df868267d90d8434c2e07106e2eb2133614603b5 Mon Sep 17 00:00:00 2001 From: jysperm Date: Wed, 23 May 2018 11:53:31 +0800 Subject: [PATCH 071/122] :pencil2: Fix typo in `API.md` --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 7187893..fdca8e3 100644 --- a/API.md +++ b/API.md @@ -101,7 +101,7 @@ AV.Cloud.run(name: string, params: object, options?: object): Promise 在队列中运行云函数。 ```javascript -AV.Cloud.run(name: string, params: object, options?: object): Promise +AV.Cloud.enqueue(name: string, params: object, options?: object): Promise ``` `options` 的属性包括: From 452a6ac3acdc54d95ce90b315eaa8648ba5e3155 Mon Sep 17 00:00:00 2001 From: wchen Date: Fri, 17 Aug 2018 00:26:46 -0400 Subject: [PATCH 072/122] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20AV.Cloud.s?= =?UTF-8?q?tart()=20=E5=92=8C=20AV.Cloud.close()=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 26 ++++++++++++++++++++++++++ API.md | 16 ++++++++++++++++ leanengine.d.ts | 3 +++ lib/cloud.js | 34 ++++++++++++++++++++++++++++------ 4 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..2083853 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + "env": { + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "rules": { + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], + "no-console": 0, + } +}; diff --git a/API.md b/API.md index fdca8e3..5aafb11 100644 --- a/API.md +++ b/API.md @@ -166,6 +166,22 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 这些 Hook 函数签名是 `function(func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回 Promise 的函数,详见文档 [实时通信概览:云引擎 Hook](https://leancloud.cn/docs/realtime_v2.html#云引擎_Hook) +### 启动和停止 + +单独运行云函数时,可以使用 `AV.Cloud.start()` 启动应用。如果该方法调用时 AV 对象尚未初始化,则 LeanEngine 中间件会使用 `LEANCLOUD_APP_ID` 等环境变量进行初始化。 + +可以在应用收到 `SIGTERM` 信号时调用 `AV.Cloud.close()`,使应用优雅退出: + +``` +process.on('SIGTERM', () => { + console.log('Received SIGTERM. App will exit.'); + AV.Cloud.close(); +}); +``` + +更多关于信号量的说明见 [Node.js 文档](https://nodejs.org/api/process.html#process_signal_events)。 + + ## Middlewares 因为 Node SDK 同时支持多种路由框架,需要你在创建中间件时指定类型,默认为 express: diff --git a/leanengine.d.ts b/leanengine.d.ts index 50b9be7..b9ab817 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -145,4 +145,7 @@ export namespace Cloud { export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; export function CookieSession(options?: CookieSessionOptions): RequestHandler; export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; + + export function start(): void; + export function close(): void; } diff --git a/lib/cloud.js b/lib/cloud.js index dbe574f..3368cc2 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -106,7 +106,7 @@ Cloud.enqueue = function(name, params, options) { }, options), authOptions: {useMasterKey: true} }); -} +}; Cloud.beforeSave = function(nameOrClass, func) { defineClassHook(className(nameOrClass), '__before_save_for_', func); @@ -154,9 +154,9 @@ AV.Insight.on = function(action, func) { Cloud.Error = class CloudError extends Error { constructor(message, extra) { - super() + super(); - extra = extra || {} + extra = extra || {}; if (!extra.status) { extra.status = 400; @@ -165,11 +165,11 @@ Cloud.Error = class CloudError extends Error { _.extend(this, { name: 'CloudError', message: message - }, extra) + }, extra); - Error.captureStackTrace(this, this.constructor) + Error.captureStackTrace(this, this.constructor); } -} +}; Cloud.logInByIdAndSessionToken = function(uid, sessionToken, fetchUser, cb) { if (fetchUser) { @@ -208,3 +208,25 @@ function className(clazz) { throw new Error('Unknown class:' + clazz); } } + +const PORT = parseInt(process.env.LEANCLOUD_APP_PORT || 3000); +let server; + +Cloud.start = function() { + if (!AV.applicationId) { + AV.init({ + appId: process.env.LEANCLOUD_APP_ID, + appKey: process.env.LEANCLOUD_APP_KEY, + masterKey: process.env.LEANCLOUD_APP_MASTER_KEY, + }); + } + server = AV.express().listen(PORT, function() { + console.log('LeanEngine Cloud Functions app is running, port:', PORT); + }); +}; + +Cloud.close = function() { + if (server) { + server.close(); + } +}; From 9738fbe82507c886b9b491adc99d1b9674c613fc Mon Sep 17 00:00:00 2001 From: wchen Date: Mon, 20 Aug 2018 00:09:11 -0400 Subject: [PATCH 073/122] fix: change name AV.Cloud.close() -> AV.Cloud.stop() --- API.md | 4 ++-- leanengine.d.ts | 2 +- lib/cloud.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/API.md b/API.md index 5aafb11..cba2ec0 100644 --- a/API.md +++ b/API.md @@ -170,12 +170,12 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 单独运行云函数时,可以使用 `AV.Cloud.start()` 启动应用。如果该方法调用时 AV 对象尚未初始化,则 LeanEngine 中间件会使用 `LEANCLOUD_APP_ID` 等环境变量进行初始化。 -可以在应用收到 `SIGTERM` 信号时调用 `AV.Cloud.close()`,使应用优雅退出: +可以在应用收到 `SIGTERM` 信号时调用 `AV.Cloud.stop()`,使应用优雅退出: ``` process.on('SIGTERM', () => { console.log('Received SIGTERM. App will exit.'); - AV.Cloud.close(); + AV.Cloud.stop(); }); ``` diff --git a/leanengine.d.ts b/leanengine.d.ts index b9ab817..ed20fa4 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -147,5 +147,5 @@ export namespace Cloud { export function HttpsRedirect(options?: MiddlewareOptions): RequestHandler; export function start(): void; - export function close(): void; + export function stop(): void; } diff --git a/lib/cloud.js b/lib/cloud.js index 3368cc2..1aa3e06 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -225,7 +225,7 @@ Cloud.start = function() { }); }; -Cloud.close = function() { +Cloud.stop = function() { if (server) { server.close(); } From 92e7e6b70ee6e973fb0aaaf583148b255c731f97 Mon Sep 17 00:00:00 2001 From: wchen Date: Thu, 6 Sep 2018 23:49:40 -0400 Subject: [PATCH 074/122] =?UTF-8?q?doc:=20=E4=BF=AE=E6=94=B9=E5=85=B3?= =?UTF-8?q?=E4=BA=8E=20AV.Cloud.stop()=20=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/API.md b/API.md index cba2ec0..455800e 100644 --- a/API.md +++ b/API.md @@ -170,17 +170,7 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 单独运行云函数时,可以使用 `AV.Cloud.start()` 启动应用。如果该方法调用时 AV 对象尚未初始化,则 LeanEngine 中间件会使用 `LEANCLOUD_APP_ID` 等环境变量进行初始化。 -可以在应用收到 `SIGTERM` 信号时调用 `AV.Cloud.stop()`,使应用优雅退出: - -``` -process.on('SIGTERM', () => { - console.log('Received SIGTERM. App will exit.'); - AV.Cloud.stop(); -}); -``` - -更多关于信号量的说明见 [Node.js 文档](https://nodejs.org/api/process.html#process_signal_events)。 - +在需要的时候,可以调用 `AV.Cloud.stop()` 来停止新链接的创建,但是已有链接不会主动断开。 ## Middlewares From e537c0717b0aa308dac9467062bc7449cb901b87 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 14 Sep 2018 14:27:01 +0800 Subject: [PATCH 075/122] :bookmark: Prepare 3.3.0 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edc4c73..2a56daa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## 3.3.0 + +- 添加 `AV.Cloud.start` 和 `AV.Cloud.stop` + ## v3.2.0 - 新增 `AV.Cloud.enqueue`,任务队列支持。 diff --git a/package.json b/package.json index f83ebea..6f7fb8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.2.0", + "version": "3.3.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From a6206d43d914645afc8d6904769c88ab39042c87 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 14 Sep 2018 14:30:53 +0800 Subject: [PATCH 076/122] :see_no_evil: Ignore `.nyc_output` in published package --- .gitignore | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index fedf8ec..0f227ae 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ coverage.html package-lock.json node_modules/ +.nyc_output diff --git a/package.json b/package.json index 6f7fb8b..d74fde2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.3.0", + "version": "3.3.1", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From c84fbd30f376ab8e3238e899c98fa46d73f34481 Mon Sep 17 00:00:00 2001 From: wchen Date: Tue, 18 Sep 2018 11:49:17 -0400 Subject: [PATCH 077/122] =?UTF-8?q?fix:=20=E4=BA=91=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E8=BF=90=E8=A1=8C=E6=97=B6=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20`/`=20=E8=B7=AF=E7=94=B1=EF=BC=8C=E7=94=A8=E6=9D=A5?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E4=BA=91=E5=BC=95=E6=93=8E=E5=81=A5=E5=BA=B7?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/cloud.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/cloud.js b/lib/cloud.js index 1aa3e06..3b225f1 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -220,7 +220,11 @@ Cloud.start = function() { masterKey: process.env.LEANCLOUD_APP_MASTER_KEY, }); } - server = AV.express().listen(PORT, function() { + const app = AV.express(); + app.use('/', function(req, res) { + res.end('This is a LeanEngine application.'); + }); + server = app.listen(PORT, function() { console.log('LeanEngine Cloud Functions app is running, port:', PORT); }); }; From 1c8a4cbd1442884e3226e84520ff5e099fd50f98 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 20 Sep 2018 13:19:07 +0800 Subject: [PATCH 078/122] :bookmark: Prepare 3.3.2 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a56daa..89d7dcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## 3.3.2 + +- 修复 `AV.Cloud.start` + ## 3.3.0 - 添加 `AV.Cloud.start` 和 `AV.Cloud.stop` diff --git a/package.json b/package.json index d74fde2..1457ef6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.3.1", + "version": "3.3.2", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From c362a4c35a68a5889d93413be2b3da115a43a044 Mon Sep 17 00:00:00 2001 From: leeyeh Date: Wed, 10 Oct 2018 11:57:40 +0800 Subject: [PATCH 079/122] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=96=87=E4=BB=B6=E4=B8=AD=20run/rpc/queue?= =?UTF-8?q?=20params=20=E5=8F=82=E6=95=B0=E5=BF=85=E9=80=89=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- leanengine.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index ed20fa4..fb9efcf 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -119,9 +119,9 @@ export namespace Cloud { export function define(name: string, options: DefineOptions, handler: CloudFunction); export function define(name: string, handler: CloudFunction); - export function run(name: string, params: Object, options?: RunOptions): Promise; - export function rpc(name: string, params: Object, options?: RunOptions): Promise; - export function enqueue(name: string, params: Object, options?: EnqueueOptions): Promise; + export function run(name: string, params?: Object, options?: RunOptions): Promise; + export function rpc(name: string, params?: Object, options?: RunOptions): Promise; + export function enqueue(name: string, params?: Object, options?: EnqueueOptions): Promise; export function beforeSave(className: string, handler: ClassHookFunction): void; export function afterSave(className: string, handler: ClassHookFunction): void; From 739fc7e1a58f3aac59a32b8ad2e6617182f38edc Mon Sep 17 00:00:00 2001 From: leeyeh Date: Wed, 10 Oct 2018 12:10:13 +0800 Subject: [PATCH 080/122] :green_heart: install typescript before test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1457ef6..a3fa913 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "email": "support@leancloud.rocks" }, "scripts": { - "test": "npm install --no-save leancloud-storage@3 && npm-run-all test-tsd test-express test-koa1 test-koa2", + "test": "npm install --no-save leancloud-storage@3 typescript@2 && npm-run-all test-tsd test-express test-koa1 test-koa2", "test-express": "mocha test test/express", "test-tsd": "tsc leanengine.d.ts", "test-koa1": "npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test test/koa", From c91eb2581e79e037ffd45dc7548a3ccb97335ff4 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 28 Jan 2019 16:44:02 +0800 Subject: [PATCH 081/122] :bug: Fix leanengine.d.ts --- leanengine.d.ts | 5 ++--- package.json | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index fb9efcf..b1a1295 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -1,4 +1,3 @@ -import {Promise} from 'es6-promise'; import {Request, RequestHandler} from 'express'; import {User, Object as LCObject} from 'leancloud-storage'; export * from 'leancloud-storage'; @@ -42,7 +41,7 @@ export function express(options?: MiddlewareOptions): RequestHandler; export function koa(options?: MiddlewareOptions): Function; export function koa2(options?: MiddlewareOptions): Function; -export class Object extends LCObject { +export class HookObject extends LCObject { disableBeforeHook(): void; disableAfterHook(): void; @@ -100,7 +99,7 @@ export namespace Cloud { } interface ClassHookRequest { - object: Object, + object: HookObject, currentUser?: User } diff --git a/package.json b/package.json index a3fa913..110fd7d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ }, "devDependencies": { "blanket": "^1.2.3", - "es6-promise": "^4.2.4", "express": "^4.14.1", "mocha": "^3.2.0", "npm-run-all": "^4.1.2", From b639fe6d4c131a500008c3ec914be374f4f74221 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 28 Jan 2019 16:57:24 +0800 Subject: [PATCH 082/122] :label: Use more strict tsd check --- leanengine.d.ts | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index b1a1295..89c3b82 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -17,8 +17,8 @@ declare namespace Express { } export interface Response { - saveCurrentUser(user: User); - clearCurrentUser(); + saveCurrentUser(user: User): void; + clearCurrentUser(): void; } } @@ -31,7 +31,7 @@ interface InitializeOptions { interface MiddlewareOptions { timeout?: string, printFullStack?: boolean, - onError?(err: Error), + onError?(err: Error): void, ignoreInvalidSessionToken?: boolean } @@ -115,8 +115,8 @@ export namespace Cloud { constructor(message: string, options?: {status?: number, code?: number}) } - export function define(name: string, options: DefineOptions, handler: CloudFunction); - export function define(name: string, handler: CloudFunction); + export function define(name: string, options: DefineOptions, handler: CloudFunction): void; + export function define(name: string, handler: CloudFunction): void; export function run(name: string, params?: Object, options?: RunOptions): Promise; export function rpc(name: string, params?: Object, options?: RunOptions): Promise; diff --git a/package.json b/package.json index 110fd7d..a5fcc2f 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "scripts": { "test": "npm install --no-save leancloud-storage@3 typescript@2 && npm-run-all test-tsd test-express test-koa1 test-koa2", "test-express": "mocha test test/express", - "test-tsd": "tsc leanengine.d.ts", + "test-tsd": "tsc --strict leanengine.d.ts", "test-koa1": "npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test test/koa", "test-koa2": "npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test test/koa" } From f239d5ad68b8793641a3019683bf203c9d2914a7 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 28 Jan 2019 18:06:28 +0800 Subject: [PATCH 083/122] :label: Export HookObject as Object --- leanengine.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/leanengine.d.ts b/leanengine.d.ts index 89c3b82..73d6536 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -41,13 +41,15 @@ export function express(options?: MiddlewareOptions): RequestHandler; export function koa(options?: MiddlewareOptions): Function; export function koa2(options?: MiddlewareOptions): Function; -export class HookObject extends LCObject { +declare class HookObject extends LCObject { disableBeforeHook(): void; disableAfterHook(): void; updatedKeys?: string[]; } +export { HookObject as Object } + export namespace Insight { type InsightHandler = (result: Object) => Promise; From 108521711bcbfb7d8eecd3dc5d774a495720ed3c Mon Sep 17 00:00:00 2001 From: Siyuan Miao Date: Thu, 7 Mar 2019 11:15:42 +0800 Subject: [PATCH 084/122] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=20TypeScript?= =?UTF-8?q?=20=E5=AE=9A=E4=B9=89=E6=96=87=E4=BB=B6=E4=B8=AD=E7=9A=84=20AV.?= =?UTF-8?q?koa2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ leanengine.d.ts | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d7dcc..89cc6e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## 3.3.3 + +- 修复 TypeScript 定义文件中的 AV.koa2. + ## 3.3.2 - 修复 `AV.Cloud.start` diff --git a/leanengine.d.ts b/leanengine.d.ts index fb9efcf..8e892fa 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -40,7 +40,7 @@ export function init(options: InitializeOptions): void; export function express(options?: MiddlewareOptions): RequestHandler; export function koa(options?: MiddlewareOptions): Function; -export function koa2(options?: MiddlewareOptions): Function; +export function koa2(options?: MiddlewareOptions): any; export class Object extends LCObject { disableBeforeHook(): void; diff --git a/package.json b/package.json index a3fa913..9ede118 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.3.2", + "version": "3.3.3", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 914ee807caf60a8198b9f32288ef14e6ecbef649 Mon Sep 17 00:00:00 2001 From: Siyuan Miao Date: Thu, 7 Mar 2019 11:50:23 +0800 Subject: [PATCH 085/122] =?UTF-8?q?:construction=5Fworker:=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20node=2010?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c7bd2a..bb660c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ language: node_js node_js: - - 4 - - 6 + - 10 - node script: From 4679f8f559255c9c235df9d17040eee769f0c276 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 9 May 2019 14:16:58 +0800 Subject: [PATCH 086/122] :sparkles: Add `internal` option for Cloud.define --- API.md | 1 + leanengine.d.ts | 1 + lib/cloud.js | 4 ++++ lib/leanengine.js | 12 ++++++++++++ test/authorization-test.js | 15 +++++++++++++++ test/fixtures/functions.js | 4 ++++ 6 files changed, 37 insertions(+) diff --git a/API.md b/API.md index 455800e..bfe6bbe 100644 --- a/API.md +++ b/API.md @@ -53,6 +53,7 @@ AV.Cloud.define(name: string, options: object, func: function) `options` 的属性包括: * `fetchUser: boolean`:是否自动抓取客户端的用户信息,默认为 `true`,若设置为 `false` 则 `request` 上将不会有 user 属性。 +* `internal: boolean`:只允许在云引擎内(使用 `AV.Cloud.run` 且未开启 `remote` 选项)或 masterKey 调用(使用 `AV.Cloud.run` 时传入 `useMasterKey`),不允许客户端直接调用,默认 `false`。 `Request` 上的属性包括: diff --git a/leanengine.d.ts b/leanengine.d.ts index b85aecd..bd3c848 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -59,6 +59,7 @@ export namespace Insight { export namespace Cloud { interface DefineOptions { fetchUser?: boolean + internal?: boolean } interface RunOptions { diff --git a/lib/cloud.js b/lib/cloud.js index 3b225f1..63ac642 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -21,6 +21,10 @@ Cloud.define = function(name, options, func) { func.fetchUser = false; } + if (options && options.internal) { + func.internal = true; + } + if (Cloud.functions[name]) { throw new Error(`LeanEngine: ${name} already defined`); } else { diff --git a/lib/leanengine.js b/lib/leanengine.js index 8ab30ec..66885eb 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -155,6 +155,10 @@ function callCloudFunction(req, funcName, options) { throw new Cloud.Error(`No such cloud function '${funcName}'`, {status: 404, printToLog: true, printFullStack: false}); } + if (cloudFunction.internal) { + checkInternal(req); + } + if (_.contains(_.values(utils.realtimeHookMapping), funcName)) { checkHookKey(req); } @@ -342,6 +346,14 @@ function checkHookKey(req) { } } +function checkInternal(req) { + if (req.headers['x-lc-hook-key'] !== AV.hookKey && !req.AV.authMasterKey) { + throw new Cloud.Error(`Internal cloud function, request from ${utils.getRemoteAddress(req)}`, { + status: 401, code: 401, printToLog: true, printFullStack: false + }); + } +} + function decodeUser(requestUser) { if (requestUser) { const user = new AV.User(); diff --git a/test/authorization-test.js b/test/authorization-test.js index bc5ed7e..8b7f7f4 100644 --- a/test/authorization-test.js +++ b/test/authorization-test.js @@ -118,4 +118,19 @@ describe('authorization', function() { .expect({code: 401, error: 'Unauthorized.'}, done); }); + it('internal function', done => { + request(app) + .post('/1/functions/internalFunction') + .set('X-LC-Id', appId) + .set('X-LC-Key', appKey) + .expect(401, done); + }) + + it('internal function, master key', done => { + request(app) + .post('/1/functions/internalFunction') + .set('X-LC-Id', appId) + .set('X-LC-Key', `${masterKey},master`) + .expect(200, done); + }) }); diff --git a/test/fixtures/functions.js b/test/fixtures/functions.js index baa59a1..0266c5a 100644 --- a/test/fixtures/functions.js +++ b/test/fixtures/functions.js @@ -134,6 +134,10 @@ AV.Cloud.define('dontFetchUser', {fetchUser: false}, function(req, res) { res.success(); }); +AV.Cloud.define('internalFunction', {internal: true}, () => { + +}); + AV.Cloud.define('testRun', function(request, response) { if (request.params.shouldRemote && process.env.NODE_ENV != 'production') { return response.error('Should be run on remote'); From d18a4892693a08c33990f1e43cb7e73db913f591 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 28 May 2019 16:09:51 +0800 Subject: [PATCH 087/122] :sparkles: Add `Cloud.getTaskInfo` --- API.md | 37 ++++++++++++++++++++++++++++++------- leanengine.d.ts | 15 ++++++++++++++- lib/cloud.js | 19 ++++++++++++++++++- test/function-test.js | 10 ++++++++++ 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/API.md b/API.md index bfe6bbe..8ac36b8 100644 --- a/API.md +++ b/API.md @@ -102,20 +102,43 @@ AV.Cloud.run(name: string, params: object, options?: object): Promise 在队列中运行云函数。 ```javascript -AV.Cloud.enqueue(name: string, params: object, options?: object): Promise +AV.Cloud.enqueue(name: string, params: object, options?: object): Promise<{uniqueId: string}> ``` `options` 的属性包括: -* `attempts?: number`:最大重试次数,默认 `3`. -* `backoff?: number`:重试间隔(毫秒),默认 `60000`. -* `delay?: number`:延时执行(毫秒)。 -* `notify?: string`: 将执行结果通知到指定云函数。 -* `retryTimeout?: boolean`: 将超时视作失败来进行重试,默认 `true`. +- `attempts?: number`:最大重试次数,默认 `1` +- `backoff?: number`:重试间隔(毫秒),默认 `60000`(一分钟) +- `delay?: number`:延时执行(毫秒) +- `deliveryMode?: string`:超时时的行为,值是 `atLeastOnce`(至少一次,可能会重试多次)、`atMostOnce`(至多一次,不会重试),默认是 `atLeastOnce` +- `keepResult?: number` 在队列中保留结果的时间(毫秒),默认 `300000`(五分钟) +- `priority?: number`:优先级,默认是当前时间戳,设置为更小的值可以在队列拥堵时让特定任务更快地被执行 +- `timeout?: number`:超时时间(毫秒),默认 `15000`,目前最大也是 `15000`,后续会提供更长的时间 +- `uniqueId?: string`:任务的唯一 ID,会据此进行去重,最长 32 个字符,默认是随机的 UUID + +### AV.Cloud.getTaskInfo + +查询队列任务结果。 + +```javascript +AV.Cloud.getTaskInfo(uniqueId: string): Promise +``` `TaskInfo` 的属性包括: -- `uniqueId`:任务的唯一 Id,会包含在日志中。 +- `uniqueId: string`:任务的唯一 ID +- `status: string`:任务的状态,包括 `queued`(等待或正在执行)、`success`(执行成功)、`failed`(执行失败) + +执行完成的 `TaskInfo` 会有: + +- `finishedAt?: string` 执行完成(成功或失败)的时间 +- `statusCode?: number` 云函数响应的 HTTP 状态码 +- `result?: object` 来自云函数的响应 + +执行失败的 `TaskInfo` 会有: + +- `error?: string` 错误提示 +- `retryAt?: string` 下次重试的时间 ### 定义 Class Hook diff --git a/leanengine.d.ts b/leanengine.d.ts index bd3c848..01e6b28 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -77,8 +77,20 @@ export namespace Cloud { retryTimeout?: boolean, } + enum TaskStatus { + Queued = 'queued', + Success = 'success', + Failed = 'failed' + } + interface TaskInfo { uniqueId: string + status: TaskStatus + finishedAt?: Date + statusCode?: number + result?: any + error?: string + retryAt?: Date } interface MiddlewareOptions { @@ -123,7 +135,8 @@ export namespace Cloud { export function run(name: string, params?: Object, options?: RunOptions): Promise; export function rpc(name: string, params?: Object, options?: RunOptions): Promise; - export function enqueue(name: string, params?: Object, options?: EnqueueOptions): Promise; + export function enqueue(name: string, params?: Object, options?: EnqueueOptions): Promise<{uniqueId: string}>; + export function getTaskInfo(uniqueId: string): Promise; export function beforeSave(className: string, handler: ClassHookFunction): void; export function afterSave(className: string, handler: ClassHookFunction): void; diff --git a/lib/cloud.js b/lib/cloud.js index 63ac642..9297808 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -103,7 +103,7 @@ Cloud.enqueue = function(name, params, options) { return AV.request({ method: 'POST', - path: '/engine/cloud-queue/enqueue', + path: '/engine/cloud-queue/tasks', data: _.extend({ function: name, params: params @@ -112,6 +112,23 @@ Cloud.enqueue = function(name, params, options) { }); }; +Cloud.getTaskInfo = function(uniqueId) { + return AV.request({ + method: 'GET', + path: `/engine/cloud-queue/tasks/${uniqueId}` + }).then( body => { + if (body.finishedAt) { + body.finishedAt = new Date(body.finishedAt); + } + + if (body.retryAt) { + body.retryAt = new Date(body.retryAt); + } + + return body; + }); +}; + Cloud.beforeSave = function(nameOrClass, func) { defineClassHook(className(nameOrClass), '__before_save_for_', func); }; diff --git a/test/function-test.js b/test/function-test.js index a23c4c7..7636ee1 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -480,4 +480,14 @@ describe('functions', function() { .expect('access-control-allow-origin', 'http://foo.bar') .expect(200, done); }); + + it('enqueue & getTaskInfo', async function() { + const {uniqueId} = await AV.Cloud.enqueue('hello'); + + uniqueId.length.should.be.equal(36); + + const taskInfo = await AV.Cloud.getTaskInfo(uniqueId); + + taskInfo.status.should.be.a.String(); + }) }); From 624b1708a3fac16e5abe96a5c956c07f275597ce Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 31 May 2019 15:03:01 +0800 Subject: [PATCH 088/122] :ok_hand: Make params of `Cloud.enqueue` optional --- lib/cloud.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cloud.js b/lib/cloud.js index 9297808..f8ee175 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -106,7 +106,7 @@ Cloud.enqueue = function(name, params, options) { path: '/engine/cloud-queue/tasks', data: _.extend({ function: name, - params: params + params: params || {} }, options), authOptions: {useMasterKey: true} }); From b54bc51cf3d26740664f4419d3f04e24ca661046 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 31 May 2019 17:03:52 +0800 Subject: [PATCH 089/122] :bookmark: Prepare 3.4.0 --- CHANGELOG.md | 5 +++++ LICENSE | 2 +- package.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c078692..f27e0f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 更新日志 +## 3.4.0 + +- `Cloud.define` 添加一个 `internal` 选项。 +- 跟进云队列的新版本,添加 `Cloud.getTaskInfo`。 + ## 3.3.3 - 修复 TypeScript 定义文件中的若干问题。 diff --git a/LICENSE b/LICENSE index 6dd5e6b..f696692 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 LeanCloud +Copyright (c) 2019 LeanCloud Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package.json b/package.json index a1b37a1..b95ff8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.3.3", + "version": "3.4.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From da89f0759a81d318a317dddefea7f6438c826203 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Wed, 19 Jun 2019 15:05:11 +0800 Subject: [PATCH 090/122] =?UTF-8?q?docs(API):=20=E6=9B=B4=E6=96=B0=20Inval?= =?UTF-8?q?idSessionToken=20=E6=8A=A5=E9=94=99=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit according to leancloud/leanengine-node-sdk/commit/ef384fa0cbdfdaf48e286300b48f14bae7983d76 --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 8ac36b8..a03ed90 100644 --- a/API.md +++ b/API.md @@ -30,7 +30,7 @@ AV.koa2(options?: object) `options` 的属性包括: - `onError?: function(err: Error)`:全局错误处理器,当云函数和 Hook 抛出异常时会调用该回调,可用于统一的错误报告。 -- `ignoreInvalidSessionToken?: boolean`:忽略客户端发来的错误的 sessionToken(`X-LC-Session` 头),而不是报错 `211 Could not find user`。 +- `ignoreInvalidSessionToken?: boolean`:忽略客户端发来的错误的 sessionToken(`X-LC-Session` 头),而不是抛出 401 错误 `{"code": 211, "error": "Verify sessionToken failed, maybe login expired: ..."}`。 ## AV.Object From efc6a2a65b24d58eb57c7fb2068b3b6587b61110 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Wed, 19 Jun 2019 17:00:16 +0800 Subject: [PATCH 091/122] =?UTF-8?q?docs(api):=20`AV.Cloud.run`=20=E7=9A=84?= =?UTF-8?q?=20`req`=20=E4=B9=9F=E6=94=AF=E6=8C=81=20koa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index a03ed90..189142e 100644 --- a/API.md +++ b/API.md @@ -89,7 +89,7 @@ AV.Cloud.run(name: string, params: object, options?: object): Promise * `user?: AV.User`:以特定的用户运行云函数(建议在 `remote: false` 时使用)。 * `sessionToken?: string`:以特定的 sessionToken 调用云函数(建议在 `remote: true` 时使用)。 * `remote?: boolean`:通过网络请求来调用云函数,默认 `false`. -* `req?`: Express 的 Request 对象,以便被调用的云函数得到 remoteAddress 等属性。 +* `req?`: `http.ClientRequest` 或 Express 的 Request 对象,以便被调用的云函数得到 remoteAddress 等属性。 更多有关云函数的内容请参考文档 [云函数开发指南:云函数](https://leancloud.cn/docs/leanengine_cloudfunction_guide-node.html#云函数)。 From 966e35c1393cde75fdf82d9225c810e9952cddb5 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Wed, 19 Jun 2019 18:06:35 +0800 Subject: [PATCH 092/122] docs(API): onVerified & onLogin request.object --- API.md | 1 + 1 file changed, 1 insertion(+) diff --git a/API.md b/API.md index 189142e..61ae65e 100644 --- a/API.md +++ b/API.md @@ -172,6 +172,7 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `currentUser: AV.User`:被操作的用户。 * `user: AV.User`:同 `currentUser`. +* `object: AV.User`:同 `currentUser`,因为登录认证 hook 被操作的对象正好是发起操作的用户。 ### 实时通信 Hook 函数 From 74d167636d5f77b949cf131c2d9dc9651fd77812 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Wed, 10 Jul 2019 16:15:20 +0800 Subject: [PATCH 093/122] docs: typo --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 61ae65e..66c65d6 100644 --- a/API.md +++ b/API.md @@ -58,7 +58,7 @@ AV.Cloud.define(name: string, options: object, func: function) `Request` 上的属性包括: * `params: object`:客户端发送的参数,当使用 `rpc` 调用时,也可能是 `AV.Object`. -* `currentUser?: AV.User`:客户端所关联的用户(根据客户端发送的 `LC-Session` 头)。 +* `currentUser?: AV.User`:客户端所关联的用户(根据客户端发送的 `X-LC-Session` 头)。 * `user?: AV.User`:同 `currentUser`. * `meta: {remoteAddress}`:`meta.remoteAddress` 是客户端的 IP. * `sessionToken?: string`:客户端发来的 sessionToken(`X-LC-Session` 头)。 From 45adfdaa118dc3e000fbcbf3a19b643e38eb1fc9 Mon Sep 17 00:00:00 2001 From: jwfing Date: Tue, 5 Nov 2019 17:54:11 +0800 Subject: [PATCH 094/122] support android dedicated key --- lib/storage-extra.js | 4 ++++ middleware/leancloud-headers.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/storage-extra.js b/lib/storage-extra.js index e6ed6d8..5b624f3 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -7,6 +7,10 @@ if (process.env.LEANCLOUD_REGION) { AV._config.region = process.env.LEANCLOUD_REGION; } +if (process.env.LEANCLOUD_APP_ANDX_KEY) { + AV._config.androidxKey = process.env.LEANCLOUD_APP_ANDX_KEY; +} + if (process.env.LC_API_SERVER) { AV.setServerURLs(process.env.LC_API_SERVER); } diff --git a/middleware/leancloud-headers.js b/middleware/leancloud-headers.js index 22c9f3c..daf084d 100644 --- a/middleware/leancloud-headers.js +++ b/middleware/leancloud-headers.js @@ -87,7 +87,7 @@ module.exports = function(AV) { sign = _ref[0]; timestamp = _ref[1]; master = _ref[2]; - key = master === 'master' ? AV.masterKey : AV.applicationKey; + key = master === 'master' ? AV.masterKey : ( master === 'ax-sig-1' ? AV._config.androidxKey : AV.applicationKey); validSign = signByKey(timestamp, key); if (validSign === sign.toLowerCase()) { if (master === 'master') { From 3cd44c43dc4df9e405ee78a722ac6fd70e0c1491 Mon Sep 17 00:00:00 2001 From: jwfing Date: Wed, 6 Nov 2019 00:34:35 +0800 Subject: [PATCH 095/122] test for androidx key --- middleware/leancloud-headers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware/leancloud-headers.js b/middleware/leancloud-headers.js index daf084d..2e49e5d 100644 --- a/middleware/leancloud-headers.js +++ b/middleware/leancloud-headers.js @@ -87,7 +87,7 @@ module.exports = function(AV) { sign = _ref[0]; timestamp = _ref[1]; master = _ref[2]; - key = master === 'master' ? AV.masterKey : ( master === 'ax-sig-1' ? AV._config.androidxKey : AV.applicationKey); + key = master === 'master' ? AV.masterKey : (master === 'ax-sig-1' ? AV._config.androidxKey : AV.applicationKey); validSign = signByKey(timestamp, key); if (validSign === sign.toLowerCase()) { if (master === 'master') { From d72c60cd37d4e8ac566c4f17fa21dbbbae2b3fe5 Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 2 Dec 2019 14:55:52 +0800 Subject: [PATCH 096/122] :pencil: Add CONTRIBUTING.md --- CONTRIBUTING.md | 10 ++++++++++ README.md | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..001f5dc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,10 @@ +## 发布新版本 + +- 将所有要发布的 PR 合并到 master +- 再次运行测试(`npm test`) +- 修改 CHANGELOG、根据 [semver](https://semver.org/) 修改 `package.json` 中的版本号 +- 提交上述改动,`git commit -m '🔖Prepare 3.x.x'` +- `git tag 3.x.x` +- `npm publish`(需先加入 [@leancloud](https://www.npmjs.com/org/leancloud)) +- `git push --tags` +- 在 [GitHub 的 releases](https://github.com/leancloud/leanengine-node-sdk/releases) 创建 Release,并填入 CHANGELOG 中的内容 diff --git a/README.md b/README.md index b9af822..139019d 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,5 @@ npm install --save leanengine leancloud-storage@3 --save - `npm install leanengine@2 --save` 升级说明见 [v3.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v3.0.0) - `npm install leanengine@1 --save` 升级说明见 [v2.0.0](https://github.com/leancloud/leanengine-node-sdk/releases/tag/v2.0.0) - `npm install leanengine@0 --save` 升级说明见 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html) + +若有意参与开发请看 [CONTRIBUTING.md]()。 From 6196f4a8e164373d7e96b76151fce6c303817c3c Mon Sep 17 00:00:00 2001 From: jysperm Date: Mon, 2 Dec 2019 15:06:19 +0800 Subject: [PATCH 097/122] :bookmark: Prepare 3.5.0 --- CHANGELOG.md | 4 ++++ CONTRIBUTING.md | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f27e0f7..2339f42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # 更新日志 +## 3.5.0 + +- 添加对 Android Key 的支持。 + ## 3.4.0 - `Cloud.define` 添加一个 `internal` 选项。 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 001f5dc..391883d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ - 再次运行测试(`npm test`) - 修改 CHANGELOG、根据 [semver](https://semver.org/) 修改 `package.json` 中的版本号 - 提交上述改动,`git commit -m '🔖Prepare 3.x.x'` -- `git tag 3.x.x` +- `git tag v3.x.x` - `npm publish`(需先加入 [@leancloud](https://www.npmjs.com/org/leancloud)) - `git push --tags` - 在 [GitHub 的 releases](https://github.com/leancloud/leanengine-node-sdk/releases) 创建 Release,并填入 CHANGELOG 中的内容 diff --git a/package.json b/package.json index b95ff8a..604dc41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.4.0", + "version": "3.5.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 2411bda8a008b72cbf7e16e32cb7ef5d3d9a4377 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Mon, 9 Dec 2019 14:32:32 +0800 Subject: [PATCH 098/122] feat: add onIMClient{On,Off}line hooks --- API.md | 2 ++ leanengine.d.ts | 2 ++ lib/utils.js | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/API.md b/API.md index 66c65d6..4f42f1d 100644 --- a/API.md +++ b/API.md @@ -186,6 +186,8 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `AV.Cloud.onIMConversationAdd` * `AV.Cloud.onIMConversationRemove` * `AV.Cloud.onIMConversationUpdate` +* `AV.Cloud.onIMClientOnline` +* `AV.Cloud.onIMClientOffline` LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调用者的确是 LeanCloud 或本地调试时的命令行工具。 diff --git a/leanengine.d.ts b/leanengine.d.ts index 01e6b28..d55d030 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -156,6 +156,8 @@ export namespace Cloud { export function onIMConversationAdd(handler: CloudFunction): void; export function onIMConversationRemove(handler: CloudFunction): void; export function onIMConversationUpdate(handler: CloudFunction): void; + export function onIMClientOnline(handler: CloudFunction): void; + export function onIMClientOffline(handler: CloudFunction): void; export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; export function CookieSession(options?: CookieSessionOptions): RequestHandler; diff --git a/lib/utils.js b/lib/utils.js index d1e8e81..5bfb783 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -21,7 +21,9 @@ exports.realtimeHookMapping = { onIMConversationStarted: '_conversationStarted', onIMConversationAdd: '_conversationAdd', onIMConversationRemove: '_conversationRemove', - onIMConversationUpdate: '_conversationUpdate' + onIMConversationUpdate: '_conversationUpdate', + onIMClientOnline: '_clientOnline', + onIMClientOffline: '_clientOffline' }; exports.unauthResp = function(res) { From 75fe3cee54ad154e0f54dc01fe12262dc2bf9b00 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Mon, 9 Dec 2019 14:54:09 +0800 Subject: [PATCH 099/122] test: fix test dependencies related error message: ``` leanengine@3.5.0 test-tsd /home/travis/build/leancloud/leanengine-node-sdk tsc --strict leanengine.d.ts leanengine.d.ts:1:39 - error TS7016: Could not find a declaration file for module 'express'. '/home/travis/build/leancloud/leanengine-node-sdk/node_modules/express/index.js' implicitly has an 'any' type. ``` --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 604dc41..bb008dc 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "underscore": "^1.8.3" }, "devDependencies": { + "@types/express": "^4.17.2", "blanket": "^1.2.3", "express": "^4.14.1", "mocha": "^3.2.0", From 1c5495df7e8a68fe07d5f73d418ab6d30213a4c4 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Mon, 9 Dec 2019 16:13:44 +0800 Subject: [PATCH 100/122] build: fix ci test timeout --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index bb008dc..1e5d8d4 100644 --- a/package.json +++ b/package.json @@ -52,9 +52,9 @@ }, "scripts": { "test": "npm install --no-save leancloud-storage@3 typescript@2 && npm-run-all test-tsd test-express test-koa1 test-koa2", - "test-express": "mocha test test/express", + "test-express": "mocha test --timeout 8000 test/express", "test-tsd": "tsc --strict leanengine.d.ts", - "test-koa1": "npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test test/koa", - "test-koa2": "npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test test/koa" + "test-koa1": "npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test --timeout 8000 test/koa", + "test-koa2": "npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test --timeout 8000 test/koa" } } From dccce1b5a63e35db0dffa07f2978131effb7b539 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Tue, 17 Dec 2019 11:49:53 +0800 Subject: [PATCH 101/122] feat: onIMClientSign --- API.md | 1 + leanengine.d.ts | 1 + lib/utils.js | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/API.md b/API.md index 4f42f1d..68b0e44 100644 --- a/API.md +++ b/API.md @@ -188,6 +188,7 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `AV.Cloud.onIMConversationUpdate` * `AV.Cloud.onIMClientOnline` * `AV.Cloud.onIMClientOffline` +* `AV.Cloud.onIMClientSign` LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调用者的确是 LeanCloud 或本地调试时的命令行工具。 diff --git a/leanengine.d.ts b/leanengine.d.ts index d55d030..212b58e 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -158,6 +158,7 @@ export namespace Cloud { export function onIMConversationUpdate(handler: CloudFunction): void; export function onIMClientOnline(handler: CloudFunction): void; export function onIMClientOffline(handler: CloudFunction): void; + export function onIMClientSign(handler: CloudFunction): { result: true | false, error?: string } export function LeanCloudHeaders(options?: MiddlewareOptions): RequestHandler; export function CookieSession(options?: CookieSessionOptions): RequestHandler; diff --git a/lib/utils.js b/lib/utils.js index 5bfb783..a2cc7da 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -23,7 +23,8 @@ exports.realtimeHookMapping = { onIMConversationRemove: '_conversationRemove', onIMConversationUpdate: '_conversationUpdate', onIMClientOnline: '_clientOnline', - onIMClientOffline: '_clientOffline' + onIMClientOffline: '_clientOffline', + onIMClientSign: '_rtmClientSign' }; exports.unauthResp = function(res) { From 027188332edd829d62694003c9d82985b052e6c1 Mon Sep 17 00:00:00 2001 From: Lee Yeh Date: Tue, 17 Mar 2020 16:28:15 +0800 Subject: [PATCH 102/122] :alien: explicitly specify the hookKey --- API.md | 1 + leanengine.d.ts | 3 ++- lib/cloud.js | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/API.md b/API.md index 4f42f1d..5f83008 100644 --- a/API.md +++ b/API.md @@ -10,6 +10,7 @@ AV.init({ appId: process.env.LEANCLOUD_APP_ID, appKey: process.env.LEANCLOUD_APP_KEY, masterKey: process.env.LEANCLOUD_APP_MASTER_KEY + hookKey: process.env.LEANCLOUD_APP_HOOK_KEY }); app.use(AV.express()); diff --git a/leanengine.d.ts b/leanengine.d.ts index d55d030..6abf4e7 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -25,7 +25,8 @@ declare namespace Express { interface InitializeOptions { appId: string, appKey: string, - masterKey: string + masterKey?: string, + hookKey?: string, } interface MiddlewareOptions { diff --git a/lib/cloud.js b/lib/cloud.js index f8ee175..a5f9b7a 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -239,6 +239,7 @@ Cloud.start = function() { appId: process.env.LEANCLOUD_APP_ID, appKey: process.env.LEANCLOUD_APP_KEY, masterKey: process.env.LEANCLOUD_APP_MASTER_KEY, + hookKey: process.env.LEANCLOUD_APP_HOOK_KEY, }); } const app = AV.express(); From bcd3bce126ad26b8702c0a1c864c115f9e953eb2 Mon Sep 17 00:00:00 2001 From: Lee Yeh Date: Tue, 17 Mar 2020 16:49:53 +0800 Subject: [PATCH 103/122] :green_heart: upgrade and lock dev deps to fix tests --- .gitignore | 1 - package-lock.json | 2048 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 10 +- 3 files changed, 2054 insertions(+), 5 deletions(-) create mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore index 0f227ae..a21715c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ *~ *.swp coverage.html -package-lock.json node_modules/ .nyc_output diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9f72409 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2048 @@ +{ + "name": "leanengine", + "version": "3.5.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/runtime": { + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", + "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@leancloud/adapters-superagent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@leancloud/adapters-superagent/-/adapters-superagent-1.0.1.tgz", + "integrity": "sha512-zR9d1XNSxgNFd0n9qXPAR+Y6bCZhafr21VmJ5FdIYgtxNP+lQcByd4VjgBnRDGZ4MT2vIhOKWD4xhY+OJoT+XA==", + "dev": true, + "requires": { + "superagent": "^5.2.2" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==", + "dev": true + }, + "superagent": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.2.2.tgz", + "integrity": "sha512-pMWBUnIllK4ZTw7p/UaobiQPwAO5w/1NRRTDpV0FTVNmECztsxKspj3ZWEordVEaqpZtmOQJJna4yTLyC/q7PQ==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.1", + "methods": "^1.1.2", + "mime": "^2.4.4", + "qs": "^6.9.1", + "readable-stream": "^3.4.0", + "semver": "^6.3.0" + } + } + } + }, + "@leancloud/runtime-adapters-browser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@leancloud/runtime-adapters-browser/-/runtime-adapters-browser-1.0.1.tgz", + "integrity": "sha512-1lFaNGmntYUdFsGvzjMa4AL9JHdMi5g0SwwRSPKSDnTLa8g4/xDfO2T832CU3WssvCX9wE9uKuaSAGOrpP3cQA==", + "dev": true, + "requires": { + "@leancloud/adapters-superagent": "^1.0.1" + } + }, + "@leancloud/runtime-adapters-node": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@leancloud/runtime-adapters-node/-/runtime-adapters-node-1.0.1.tgz", + "integrity": "sha512-zscoAqVLFgun07P9mnKOu0w6pIO9gegxzwRYpz7Y9FjM+xZM8XfELEsfZe1u0mvxhD1rJlij3nzfuwoRlhhUTw==", + "dev": true, + "requires": { + "@leancloud/adapters-superagent": "^1.0.1", + "localstorage-memory": "^1.0.2", + "ws": "^5.2.2" + } + }, + "@leancloud/runtime-adapters-weapp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@leancloud/runtime-adapters-weapp/-/runtime-adapters-weapp-1.0.2.tgz", + "integrity": "sha512-zj6AfOBe7Ej05Kxj0TxH8r1add/r9xGIvuwl4n2KfvAq4IWT3cOn0X/4/Z/Uz2Dqg8g6o2ffytZYrnxBdHuZNg==", + "dev": true, + "requires": { + "event-target-shim": "^5.0.1", + "miniprogram-api-typings": "^2.10.2" + } + }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz", + "integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz", + "integrity": "sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", + "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", + "dev": true + }, + "@types/node": { + "version": "13.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.1.tgz", + "integrity": "sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", + "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "dev": true, + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "blanket": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/blanket/-/blanket-1.2.3.tgz", + "integrity": "sha1-FRtJh8O9hFUrtfA7kO9fflkx5HM=", + "dev": true, + "requires": { + "acorn": "^1.0.3", + "falafel": "~1.2.0", + "foreach": "^2.0.5", + "isarray": "0.0.1", + "object-keys": "^1.0.6", + "xtend": "~4.0.0" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "dev": true, + "requires": { + "long": "~3" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "connect-timeout": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.9.0.tgz", + "integrity": "sha1-vCcyaxIhA3FL6/oNlYurM/ZSLjo=", + "requires": { + "http-errors": "~1.6.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + } + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true + }, + "cookies": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.6.2.tgz", + "integrity": "sha1-asGwUolSCOj8TE9fhqntMbnLXM8=", + "requires": { + "depd": "~1.1.0", + "keygrip": "~1.0.1" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.3.tgz", + "integrity": "sha512-vLf5iali3jKqlJoo6SryDwe3nxCmiueNjbjLWDIpNbAcKnQXAsAdZk+pM17nSYp3AQMbTmAQVCQSeDLfA87SNA==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true + }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=", + "dev": true + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "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.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "falafel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", + "integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=", + "dev": true, + "requires": { + "acorn": "^1.0.3", + "foreach": "^2.0.5", + "isarray": "0.0.1", + "object-keys": "^1.0.6" + } + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "javascript-state-machine": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/javascript-state-machine/-/javascript-state-machine-2.4.0.tgz", + "integrity": "sha1-2L4x7DjySsGhgy8LZy/DzV95yW4=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "keygrip": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.3.tgz", + "integrity": "sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "leancloud-cors-headers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/leancloud-cors-headers/-/leancloud-cors-headers-0.1.0.tgz", + "integrity": "sha1-papLNyWnmlVd/GeybDUP4zyAzzw=" + }, + "leancloud-realtime": { + "version": "5.0.0-rc.1", + "resolved": "https://registry.npmjs.org/leancloud-realtime/-/leancloud-realtime-5.0.0-rc.1.tgz", + "integrity": "sha512-U00kLZfuCtXEfzvAeLhtwl7QcV/h0nFSosO/34b0IE31FxEFqHh8wCstthpHJBZhvn6lR3nSTstgKaoYD1EEEQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.4", + "@leancloud/runtime-adapters-browser": "^1.0.1", + "@leancloud/runtime-adapters-node": "^1.0.1", + "@leancloud/runtime-adapters-weapp": "^1.0.2", + "base64-arraybuffer": "^0.1.5", + "debug": "^3.1.0", + "eventemitter3": "^3.0.0", + "javascript-state-machine": "^2.3.5", + "lodash": "^4.17.10", + "promise-timeout": "^1.3.0", + "protobufjs": "^5.0.1", + "uuid": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "leancloud-realtime-plugin-live-query": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/leancloud-realtime-plugin-live-query/-/leancloud-realtime-plugin-live-query-1.2.0.tgz", + "integrity": "sha512-eJooIH8/FyUoozr3Eeby2DpDnmX39m1bfxfxlYPuojkio+i/DLwPD+aTHnRDH6QXJcT6tNTt85RcxVR/Txg98Q==", + "dev": true + }, + "leancloud-storage": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/leancloud-storage/-/leancloud-storage-3.15.0.tgz", + "integrity": "sha512-UbR6pLA0tVYPcY7AND0pey45iFsB2PkIo8Wz0DZ9BabKyqndA1ey2LKzYpFDGNh3ODrmT3fValVn9yY4bgf9Uw==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "es6-promise": "4.2.3", + "eventemitter3": "^2.0.3", + "leancloud-realtime": "^5.0.0-alpha.3", + "leancloud-realtime-plugin-live-query": "^1.2.0", + "localstorage-memory": "^1.0.1", + "md5": "^2.0.0", + "superagent": "^3.3.1", + "underscore": "^1.8.3", + "uuid": "^3.3.2" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "localstorage-memory": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/localstorage-memory/-/localstorage-memory-1.0.3.tgz", + "integrity": "sha512-t9P8WB6DcVttbw/W4PIE8HOqum8Qlvx5SjR6oInwR9Uia0EEmyUeBh7S+weKByW+l/f45Bj4L/dgZikGFDM6ng==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", + "dev": true + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "dev": true, + "requires": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "miniprogram-api-typings": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.10.2.tgz", + "integrity": "sha512-nb2vtGCVyNRJqR8C01RVg9H4qCuq5u2eCdEVjrSO1E9ZDonUApCePs3ZEtd0C8CbTuBmp5ZlGhX1Npnu5dxEfg==", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "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": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "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" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pidtree": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promise-timeout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", + "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", + "dev": true + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "dev": true, + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "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.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, + "should": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/should/-/should-11.2.1.tgz", + "integrity": "sha1-kPVRRVUtAc/CAGZuToGKHJZw7aI=", + "dev": true, + "requires": { + "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": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-1.0.1.tgz", + "integrity": "sha1-C26VFvJgGp+wuy3MNpr6HH4gCvc=", + "dev": true, + "requires": { + "should-type": "^1.0.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.padend": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", + "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "dev": true, + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "supertest": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", + "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, + "underscore": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", + "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "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" + } + } + } +} diff --git a/package.json b/package.json index 1e5d8d4..b7fa6c9 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,12 @@ "@types/express": "^4.17.2", "blanket": "^1.2.3", "express": "^4.14.1", + "leancloud-storage": "^3.15.0", "mocha": "^3.2.0", "npm-run-all": "^4.1.2", "should": "^11.2.0", - "supertest": "^3.0.0" + "supertest": "^3.0.0", + "typescript": "^3.8.3" }, "peerDependency": { "leancloud-storage": "^3.0.0" @@ -51,10 +53,10 @@ "email": "support@leancloud.rocks" }, "scripts": { - "test": "npm install --no-save leancloud-storage@3 typescript@2 && npm-run-all test-tsd test-express test-koa1 test-koa2", + "test": "npm-run-all test-tsd test-express test-koa1 test-koa2", "test-express": "mocha test --timeout 8000 test/express", "test-tsd": "tsc --strict leanengine.d.ts", - "test-koa1": "npm install --no-save leancloud-storage@3 koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test --timeout 8000 test/koa", - "test-koa2": "npm install --no-save leancloud-storage@3 koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test --timeout 8000 test/koa" + "test-koa1": "npm install --no-save koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test --timeout 8000 test/koa", + "test-koa2": "npm install --no-save koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test --timeout 8000 test/koa" } } From dbd98a36413e8827c04620ca662334854c7c6b43 Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Wed, 18 Mar 2020 13:51:14 +0800 Subject: [PATCH 104/122] feat: onIMConversationAdded/Removed see also leancloud/avoscloud-push#2461 --- API.md | 2 ++ leanengine.d.ts | 2 ++ lib/utils.js | 2 ++ 3 files changed, 6 insertions(+) diff --git a/API.md b/API.md index ea39f7a..b8cf965 100644 --- a/API.md +++ b/API.md @@ -185,7 +185,9 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `AV.Cloud.onIMConversationStart` * `AV.Cloud.onIMConversationStarted` * `AV.Cloud.onIMConversationAdd` +* `AV.Cloud.onIMConversationAdded` * `AV.Cloud.onIMConversationRemove` +* `AV.Cloud.onIMConversationRemoved` * `AV.Cloud.onIMConversationUpdate` * `AV.Cloud.onIMClientOnline` * `AV.Cloud.onIMClientOffline` diff --git a/leanengine.d.ts b/leanengine.d.ts index 60230e2..4b699d8 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -155,7 +155,9 @@ export namespace Cloud { export function onIMConversationStart(handler: CloudFunction): void; export function onIMConversationStarted(handler: CloudFunction): void; export function onIMConversationAdd(handler: CloudFunction): void; + export function onIMConversationAdded(handler: CloudFunction): void; export function onIMConversationRemove(handler: CloudFunction): void; + export function onIMConversationRemoved(handler: CloudFunction): void; export function onIMConversationUpdate(handler: CloudFunction): void; export function onIMClientOnline(handler: CloudFunction): void; export function onIMClientOffline(handler: CloudFunction): void; diff --git a/lib/utils.js b/lib/utils.js index a2cc7da..aae7c9c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -20,7 +20,9 @@ exports.realtimeHookMapping = { onIMConversationStart: '_conversationStart', onIMConversationStarted: '_conversationStarted', onIMConversationAdd: '_conversationAdd', + onIMConversationAdded: '_conversationAdded', onIMConversationRemove: '_conversationRemove', + onIMConversationRemoved: '_conversationRemoved', onIMConversationUpdate: '_conversationUpdate', onIMClientOnline: '_clientOnline', onIMClientOffline: '_clientOffline', From 883599d08ea2abebfc44e4ddfc18bcc092e0f405 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 19 Mar 2020 14:17:51 +0800 Subject: [PATCH 105/122] :children_crossing: Set app infos from environments automatically (for JS SDK 4) --- lib/storage-extra.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/storage-extra.js b/lib/storage-extra.js index 5b624f3..4405c47 100644 --- a/lib/storage-extra.js +++ b/lib/storage-extra.js @@ -19,6 +19,13 @@ if (process.env.LEANCLOUD_API_SERVER) { AV.setServerURLs(process.env.LEANCLOUD_API_SERVER); } +if (AV.version && !AV.version.match(/^[0123]\./)) { + AV._config.applicationId = process.env.LEANCLOUD_APP_ID; + AV._config.applicationKey = process.env.LEANCLOUD_APP_KEY; + AV._config.masterKey = process.env.LEANCLOUD_APP_MASTER_KEY; + AV._config.hookKey = process.env.LEANCLOUD_APP_HOOK_KEY; +} + AV._sharedConfig.userAgent = 'AVOS Cloud Code Node ' + require('../package').version; AV.Cloud.__prod = process.env.NODE_ENV === 'production' ? 1 : 0; AV.setProduction(AV.Cloud.__prod); From b9811c975428eb97339db44d8de1bb794d4e2a16 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 19 Mar 2020 14:45:16 +0800 Subject: [PATCH 106/122] :bookmark: Prepare 3.6.0 --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2339f42..731931d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # 更新日志 +## 3.6.0 + +添加对新的即时通讯 Hook 的支持: + +- `AV.Cloud.onIMConversationAdded` +- `AV.Cloud.onIMConversationRemoved` +- `AV.Cloud.onIMClientOnline` +- `AV.Cloud.onIMClientOffline` +- `AV.Cloud.onIMClientSign` + +兼容 JS SDK (leancloud-storage) 4.5.0 及以上版本的初始化机制。 + ## 3.5.0 - 添加对 Android Key 的支持。 diff --git a/package-lock.json b/package-lock.json index 9f72409..20ee68c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.5.0", + "version": "3.6.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b7fa6c9..d60e747 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.5.0", + "version": "3.6.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From a100dda1ca3e64439294c5bce078a6674a632758 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Apr 2020 15:13:29 +0800 Subject: [PATCH 107/122] :iphone: Get remoteAddress from Forwarded header --- lib/utils.js | 33 ++++++++++++++++++++++++++++++++- package-lock.json | 8 ++++++-- package.json | 2 ++ test/fixtures/functions.js | 4 ++++ test/function-test.js | 25 +++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index aae7c9c..5452816 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,6 +1,9 @@ 'use strict'; var crypto = require('crypto'); +var parseForwarded = require('forwarded-parse'); +var ipaddr = require('ipaddr.js'); +var _ = require('underscore'); exports.hookNameMapping = { beforeSave: '__before_save_for_', @@ -70,9 +73,37 @@ exports.prepareResponseObject = function(res, callback) { }; var getRemoteAddress = exports.getRemoteAddress = function(req) { - return req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress + var forwardedClient = exports.getForwardedClient(req) + + if (forwardedClient) { + return forwardedClient.for + } else { + return req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress + } }; exports.endsWith = function(str, suffix) { return str.indexOf(suffix, str.length - suffix.length) !== -1; }; + +exports.getForwardedClient = function getForwardedClient(req) { + if (req.headers['forwarded']) { + try { + const forwards = parseForwarded(req.headers['forwarded']).reverse() + + for (var i = 0; i < forwards.length; i++) { + if (!forwards[i].for) { + return + } + + var range = ipaddr.parse(forwards[i].for).range() + + if (!_.include(['loopback', 'private'], range) || i === forwards.length - 1) { + return _.extend(forwards[i], {range: range}) + } + } + } catch (err) { + console.error('LeanEngine: parse Forwarded header failed', req.headers['forwarded'], err.stack) + } + } +} diff --git a/package-lock.json b/package-lock.json index 20ee68c..7f3ce0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -757,6 +757,11 @@ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, + "forwarded-parse": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.0.tgz", + "integrity": "sha512-as9a7Xelt0CvdUy7/qxrY73dZq2vMx49F556fwjjFrUyzq5uHHfeLgD2cCq/6P4ZvusGZzjD6aL2NdgGdS5Cew==" + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -884,8 +889,7 @@ "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is-arrayish": { "version": "0.2.1", diff --git a/package.json b/package.json index d60e747..9081512 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "connect-timeout": "^1.8.0", "cookies": "^0.6.2", "debug": "^2.6.0", + "forwarded-parse": "^2.1.0", + "ipaddr.js": "^1.9.1", "leancloud-cors-headers": "^0.1.0", "on-headers": "^1.0.1", "underscore": "^1.8.3" diff --git a/test/fixtures/functions.js b/test/fixtures/functions.js index 0266c5a..2a6b52e 100644 --- a/test/fixtures/functions.js +++ b/test/fixtures/functions.js @@ -231,6 +231,10 @@ AV.Cloud.define('testTimeout', function(req, res) { }, req.params.delay); }); +AV.Cloud.define('remoteAddress', function(request) { + return request.meta.remoteAddress +}) + AV.Cloud.onIMMessageReceived(function(request, response) { response.success('ok'); }); diff --git a/test/function-test.js b/test/function-test.js index 7636ee1..037ff9c 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -452,6 +452,31 @@ describe('functions', function() { }); }); + it('remoteAddress', function(done) { + request(app) + .post('/1.1/functions/remoteAddress') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('Forwarded', 'for=1.2.3.4; proto=https, for=10.0.0.1') + .expect(200, (err, res) => { + res.body.result.should.equal('1.2.3.4') + done(err) + }); + }) + + it('remoteAddress invalid Forwarded header', function(done) { + request(app) + .post('/1.1/functions/remoteAddress') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('Forwarded', 'for=1.2.3.456; proto=https, for=10.0.0.1') + .set('X-Real-IP', '5.6.7.8') + .expect(200, (err, res) => { + res.body.result.should.equal('5.6.7.8') + done(err) + }); + }) + it('_metadatas', function(done) { request(app) .get('/1/functions/_ops/metadatas') From dd45525009f438ad079946aba1f002b122c43b02 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Apr 2020 15:14:00 +0800 Subject: [PATCH 108/122] :iphone: Get proto from Forwarded header --- middleware/https-redirect.js | 7 ++++- test/express/https-redirect-test.js | 45 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/middleware/https-redirect.js b/middleware/https-redirect.js index fdc73b7..b610b2c 100644 --- a/middleware/https-redirect.js +++ b/middleware/https-redirect.js @@ -1,11 +1,16 @@ 'use strict'; var endsWith = require('../lib/utils').endsWith; +var getForwardedClient = require('../lib/utils').getForwardedClient; +var _ = require('underscore'); module.exports = function(AV) { return function() { return function(req, res, next) { - if ((AV.Cloud.__prod || endsWith(req.headers.host, '.leanapp.cn')) && (!req.secure)) { + var forwardedClient = getForwardedClient(req) + + if (forwardedClient && forwardedClient.proto === 'http' && !_.include(['loopback', 'private'], forwardedClient.range) || + !forwardedClient && (AV.Cloud.__prod || endsWith(req.headers.host, '.leanapp.cn')) && (!req.secure)) { const url = `https://${req.headers.host}${req.originalUrl || req.url}`; res.statusCode = 302; diff --git a/test/express/https-redirect-test.js b/test/express/https-redirect-test.js index 9c54df2..bc9c355 100644 --- a/test/express/https-redirect-test.js +++ b/test/express/https-redirect-test.js @@ -16,6 +16,13 @@ app.get('/test', function (req, res) { }); describe('https-redirect', function() { + var prod = AV.Cloud.__prod + + afterEach(function() { + // rollback changes on AV.Cloud.__prod + AV.Cloud.__prod = prod + }) + it('should redirect', function(done) { request(app) .get('/test') @@ -43,4 +50,42 @@ describe('https-redirect', function() { .expect(200) .expect("Hello World!", done); }); + + it('should redirect (Forwarded, custom domain on staging)', function(done) { + AV.Cloud.__prod = 0 + + request(app) + .get('/test') + .set('Host', 'stg-custom.domain.com') + .set('Forwarded', 'for=1.2.3.4; proto=http, for=10.0.0.1') + .expect(302) + .end(function(err, res) { + res.headers.location.should.equal('https://stg-custom.domain.com/test'); + done(); + }) + }); + + it('should not redirect (Forwarded, intranet)', function(done) { + AV.Cloud.__prod = 0 + + request(app) + .get('/test') + .set('Host', 'stg-custom.domain.com') + .set('Forwarded', 'for=10.0.0.1; proto=http') + .set('X-Forwarded-Proto', 'http') + .expect(200) + .expect("Hello World!", done); + }); + + it('should not redirect (Forwarded overwrite X-Forwarded-Proto)', function(done) { + AV.Cloud.__prod = 0 + + request(app) + .get('/test') + .set('Host', 'stg-custom.domain.com') + .set('Forwarded', 'for=1.2.3.4; proto=https, for=10.0.0.1; proto=http') + .set('X-Forwarded-Proto', 'http') + .expect(200) + .expect("Hello World!", done); + }); }); From d8a221e7fd421e212ff7247def1a075e4e8f7bf2 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 24 Apr 2020 15:14:23 +0800 Subject: [PATCH 109/122] :bookmark: Prepare 3.7.0 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 731931d..86b9eba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 更新日志 +## 3.7.0 + +- `req.meta.remoteAddress` 优先从 `Forwarded` 头获取客户端 IP,在线上的 Hook 中可以获取到触发 Hook 的客户端 IP。 +- `AV.Cloud.HttpsRedirect` 优先从 `Forwarded` 头判断协议,非 `.leanapp.cn` 域名的预备环境将被正确地重定向。 + ## 3.6.0 添加对新的即时通讯 Hook 的支持: diff --git a/package.json b/package.json index 9081512..c993676 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.6.0", + "version": "3.7.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git", From 04b05751d9c22b2bbe0eb20d395323dffeda786a Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Sat, 9 May 2020 11:46:07 +0800 Subject: [PATCH 110/122] feat: onIMMessageUpdate --- API.md | 1 + leanengine.d.ts | 1 + lib/utils.js | 1 + 3 files changed, 3 insertions(+) diff --git a/API.md b/API.md index b8cf965..083bc42 100644 --- a/API.md +++ b/API.md @@ -182,6 +182,7 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `AV.Cloud.onIMMessageReceived` * `AV.Cloud.onIMReceiversOffline` * `AV.Cloud.onIMMessageSent` +* `AV.Cloud.onIMMessageUpdate` * `AV.Cloud.onIMConversationStart` * `AV.Cloud.onIMConversationStarted` * `AV.Cloud.onIMConversationAdd` diff --git a/leanengine.d.ts b/leanengine.d.ts index 4b699d8..124bd1e 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -152,6 +152,7 @@ export namespace Cloud { export function onIMMessageReceived(handler: CloudFunction): void; export function onIMReceiversOffline(handler: CloudFunction): void; export function onIMMessageSent(handler: CloudFunction): void; + export function onIMMessageUpdate(handler: CloudFunction): void; export function onIMConversationStart(handler: CloudFunction): void; export function onIMConversationStarted(handler: CloudFunction): void; export function onIMConversationAdd(handler: CloudFunction): void; diff --git a/lib/utils.js b/lib/utils.js index aae7c9c..6f3784c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -17,6 +17,7 @@ exports.realtimeHookMapping = { onIMMessageReceived: '_messageReceived', onIMReceiversOffline: '_receiversOffline', onIMMessageSent: '_messageSent', + onIMMessageUpdate: '_messageUpdate', onIMConversationStart: '_conversationStart', onIMConversationStarted: '_conversationStarted', onIMConversationAdd: '_conversationAdd', From 145ee312c96a387acb1ff6e048ca3ac35de3ccbb Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 18 Jun 2020 15:01:42 +0800 Subject: [PATCH 111/122] :arrow_up: Upgrade dependencies --- package-lock.json | 52 +++++++++++++++++++++++++++-------------------- package.json | 6 +++--- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f3ce0a..0b24b7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.6.0", + "version": "3.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -120,36 +120,44 @@ } }, "@types/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz", - "integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", + "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", "dev": true, "requires": { "@types/body-parser": "*", "@types/express-serve-static-core": "*", + "@types/qs": "*", "@types/serve-static": "*" } }, "@types/express-serve-static-core": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz", - "integrity": "sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==", + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", + "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", "dev": true, "requires": { "@types/node": "*", + "@types/qs": "*", "@types/range-parser": "*" } }, "@types/mime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", - "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", + "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==", "dev": true }, "@types/node": { - "version": "13.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.1.tgz", - "integrity": "sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==", + "version": "14.0.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", + "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", + "dev": true + }, + "@types/qs": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", "dev": true }, "@types/range-parser": { @@ -159,9 +167,9 @@ "dev": true }, "@types/serve-static": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", - "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", + "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", "dev": true, "requires": { "@types/express-serve-static-core": "*", @@ -1933,15 +1941,15 @@ } }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", + "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", "dev": true }, "underscore": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", - "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==" + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" }, "unpipe": { "version": "1.0.0", diff --git a/package.json b/package.json index c993676..af62515 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,10 @@ "ipaddr.js": "^1.9.1", "leancloud-cors-headers": "^0.1.0", "on-headers": "^1.0.1", - "underscore": "^1.8.3" + "underscore": "^1.10.2" }, "devDependencies": { - "@types/express": "^4.17.2", + "@types/express": "^4.17.6", "blanket": "^1.2.3", "express": "^4.14.1", "leancloud-storage": "^3.15.0", @@ -27,7 +27,7 @@ "npm-run-all": "^4.1.2", "should": "^11.2.0", "supertest": "^3.0.0", - "typescript": "^3.8.3" + "typescript": "^3.9.5" }, "peerDependency": { "leancloud-storage": "^3.0.0" From f0167fa510a2f3602d40f7dace1dad89571b3b12 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 18 Jun 2020 15:08:20 +0800 Subject: [PATCH 112/122] :pencil: Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b9eba..252912c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - `req.meta.remoteAddress` 优先从 `Forwarded` 头获取客户端 IP,在线上的 Hook 中可以获取到触发 Hook 的客户端 IP。 - `AV.Cloud.HttpsRedirect` 优先从 `Forwarded` 头判断协议,非 `.leanapp.cn` 域名的预备环境将被正确地重定向。 +- 添加新的实时通讯 Hook `AV.Cloud.onIMMessageUpdate`。 ## 3.6.0 From 4c9eb69dac3a77c7595291e095e0a5bc913ed19e Mon Sep 17 00:00:00 2001 From: Jang Rush Date: Mon, 29 Jun 2020 12:56:03 +0800 Subject: [PATCH 113/122] fix(ts): refine CookieSessionOptions typing close #152 --- leanengine.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/leanengine.d.ts b/leanengine.d.ts index 124bd1e..5bc072b 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -100,7 +100,9 @@ export namespace Cloud { interface CookieSessionOptions extends MiddlewareOptions { secret: string + maxAge: number fetchUser?: boolean + name?: string } interface CloudFunctionRequestMeta { From e53fe4b6eb96e1b682c1548bc6475d5c67638648 Mon Sep 17 00:00:00 2001 From: Lee Yeh Date: Thu, 14 Jan 2021 13:13:52 +0800 Subject: [PATCH 114/122] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Support=20leanclou?= =?UTF-8?q?d-storage^4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af62515..2c822e1 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "typescript": "^3.9.5" }, "peerDependency": { - "leancloud-storage": "^3.0.0" + "leancloud-storage": "^3.0.0 || ^4.0.0" }, "keywords": [ "leancloud", From 23668ce36aa385e6b41397421f5f8e3aae070794 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 20 Jul 2021 14:50:38 +0800 Subject: [PATCH 115/122] :white_check_mark: Add test for leancloud-storage@4 --- package.json | 7 ++++--- test/fixtures/app-info.js | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 2c822e1..d60617d 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@types/express": "^4.17.6", "blanket": "^1.2.3", "express": "^4.14.1", - "leancloud-storage": "^3.15.0", + "leancloud-storage": "^4.11.1", "mocha": "^3.2.0", "npm-run-all": "^4.1.2", "should": "^11.2.0", @@ -55,8 +55,9 @@ "email": "support@leancloud.rocks" }, "scripts": { - "test": "npm-run-all test-tsd test-express test-koa1 test-koa2", - "test-express": "mocha test --timeout 8000 test/express", + "test": "npm-run-all test-tsd test-storage3-express test-storage4-express test-koa1 test-koa2", + "test-storage3-express": "npm install --no-save leancloud-storage@3 && mocha test --timeout 8000 test/express", + "test-storage4-express": "npm install --no-save leancloud-storage@4 && mocha test --timeout 8000 test/express", "test-tsd": "tsc --strict leanengine.d.ts", "test-koa1": "npm install --no-save koa@1 koa-bodyparser@2 && env FRAMEWORK=koa KOA_VER=1 mocha test --timeout 8000 test/koa", "test-koa2": "npm install --no-save koa@2 koa-bodyparser@4 && env FRAMEWORK=koa KOA_VER=2 mocha test --timeout 8000 test/koa" diff --git a/test/fixtures/app-info.js b/test/fixtures/app-info.js index 7bbe604..3dd32e6 100644 --- a/test/fixtures/app-info.js +++ b/test/fixtures/app-info.js @@ -5,7 +5,8 @@ const appInfo = { appKey: '3xjj1qw91cr3ygjq9lt0g8c3qpet38rrxtwmmp0yffyoy2t4', masterKey: '3v7z633lzfec9qzx8sjql6zimvdpmtwypcchr2gelu5mrzb0', hookKey: 'qlkcRqv9v5J5A11Byr3mzori', - sessionTokenAdmin: 'w2jrtkbehp38otqmhbqu7ybs9' + sessionTokenAdmin: 'w2jrtkbehp38otqmhbqu7ybs9', + serverURL: 'https://4h2h4okw.lc-cn-n1-shared.com' }; AV.init(appInfo); From 39c62eea988b933c9392271f9a3bde9629d5bb8e Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 20 Jul 2021 14:53:56 +0800 Subject: [PATCH 116/122] :arrow_up: Re-generate package-lock --- package-lock.json | 3658 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 3310 insertions(+), 348 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b24b7c..cf90dc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,109 +1,2867 @@ { "name": "leanengine", "version": "3.7.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "leanengine", + "version": "3.7.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.16.0", + "connect": "^3.5.0", + "connect-timeout": "^1.8.0", + "cookies": "^0.6.2", + "debug": "^2.6.0", + "forwarded-parse": "^2.1.0", + "ipaddr.js": "^1.9.1", + "leancloud-cors-headers": "^0.1.0", + "on-headers": "^1.0.1", + "underscore": "^1.10.2" + }, + "devDependencies": { + "@types/express": "^4.17.6", + "blanket": "^1.2.3", + "express": "^4.14.1", + "leancloud-storage": "^4.11.1", + "mocha": "^3.2.0", + "npm-run-all": "^4.1.2", + "should": "^11.2.0", + "supertest": "^3.0.0", + "typescript": "^3.9.5" + }, + "engines": { + "node": ">=4.4.7" + } + }, + "node_modules/@babel/runtime": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "node_modules/@leancloud/adapter-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@leancloud/adapter-types/-/adapter-types-5.0.0.tgz", + "integrity": "sha512-psnPaa4ONaA6X9y9xsjLmJXH+2spySH/YQUz59S0cZUTWVbZaUFwLQyHkv8OzZFixKqs+eV3xnWl7nUxCCCIeg==", + "dev": true + }, + "node_modules/@leancloud/adapter-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@leancloud/adapter-utils/-/adapter-utils-1.2.2.tgz", + "integrity": "sha512-B/bZM6WGN+sxMdZJeTWLAN/Gin00LX0E/M0MoygZhtrgCfCZSz47wgziOq5Fvl6yPifyvYBGaobydhyr7vxjxg==", + "dev": true + }, + "node_modules/@leancloud/adapters-superagent": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@leancloud/adapters-superagent/-/adapters-superagent-1.4.2.tgz", + "integrity": "sha512-UpawevTXaIIFEpvtW6rm6PKH28i3OCIjgdJUmcFWbI8lezHz6bBznKB9g0aCRX8/c2h6SJThzjgqNlPny8I32g==", + "dev": true, + "dependencies": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapter-utils": "^1.2.2", + "@types/superagent": "^4.1.7", + "superagent": "^5.2.2" + } + }, + "node_modules/@leancloud/platform-adapters-browser": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-browser/-/platform-adapters-browser-1.5.2.tgz", + "integrity": "sha512-O7FRG4KvH20tiIP+dUbb7FE7kgkwEZifu7XmSRdPB5yO/+wR61BKykVQggQUdqJE6T9HZVSrqqbWWNqcMdJK6g==", + "dev": true, + "dependencies": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapters-superagent": "^1.4.2" + } + }, + "node_modules/@leancloud/platform-adapters-node": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-node/-/platform-adapters-node-1.5.2.tgz", + "integrity": "sha512-FhvL6u0CXG33M5UCla2Rfja6Rrv8Sj1mrRWCZvI6m5sW4A7RyWFICW8akBL++uHUNP8WDc7szfrBz8TJHQWDcg==", + "dev": true, + "dependencies": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapters-superagent": "^1.4.2", + "@types/ws": "^7.2.2", + "localstorage-memory": "^1.0.2", + "ws": "^5.2.2" + } + }, + "node_modules/@leancloud/platform-adapters-weapp": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-weapp/-/platform-adapters-weapp-1.6.1.tgz", + "integrity": "sha512-/Pxj0Zk9829OTQdt1KdfglqVBiOteber8gUzw5Kgjws1+hlPJ7x8x5VZcdPM3lnTh6UsP4f6CkOtS/QOeLu6JA==", + "dev": true, + "dependencies": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapter-utils": "^1.2.2", + "event-target-shim": "^5.0.1", + "miniprogram-api-typings": "^2.10.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.3.tgz", + "integrity": "sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/superagent": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.12.tgz", + "integrity": "sha512-1GQvD6sySQPD6p9EopDFI3f5OogdICl1sU/2ij3Esobz/RtL9fWZZDPmsuv7eiy5ya+XNiPAxUcI3HIUTJa+3A==", + "dev": true, + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "dev": true, + "dependencies": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/blanket": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/blanket/-/blanket-1.2.3.tgz", + "integrity": "sha1-FRtJh8O9hFUrtfA7kO9fflkx5HM=", + "dev": true, + "dependencies": { + "acorn": "^1.0.3", + "falafel": "~1.2.0", + "foreach": "^2.0.5", + "isarray": "0.0.1", + "object-keys": "^1.0.6", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=0.10.7" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "node_modules/bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "dev": true, + "dependencies": { + "long": "~3" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-timeout": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.9.0.tgz", + "integrity": "sha1-vCcyaxIhA3FL6/oNlYurM/ZSLjo=", + "dependencies": { + "http-errors": "~1.6.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect-timeout/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-timeout/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true + }, + "node_modules/cookies": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.6.2.tgz", + "integrity": "sha1-asGwUolSCOj8TE9fhqntMbnLXM8=", + "dependencies": { + "depd": "~1.1.0", + "keygrip": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=", + "dev": true + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "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.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/falafel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", + "integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=", + "dev": true, + "dependencies": { + "acorn": "^1.0.3", + "foreach": "^2.0.5", + "isarray": "0.0.1", + "object-keys": "^1.0.6" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", + "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==", + "dev": true + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.1.tgz", + "integrity": "sha512-8Jh3uv3iaaTTvH3vM4qyRjKfe5dvR/THhiPY5zhsfFa/UviqnEd3hqNyxEtRCwL3+L2vv8JsanGZ5XHQcncyUA==" + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "node_modules/growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", + "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/javascript-state-machine": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/javascript-state-machine/-/javascript-state-machine-2.4.0.tgz", + "integrity": "sha1-2L4x7DjySsGhgy8LZy/DzV95yW4=", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "deprecated": "Please use the native JSON object instead of JSON 3", + "dev": true + }, + "node_modules/keygrip": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.3.tgz", + "integrity": "sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leancloud-cors-headers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/leancloud-cors-headers/-/leancloud-cors-headers-0.1.0.tgz", + "integrity": "sha1-papLNyWnmlVd/GeybDUP4zyAzzw=" + }, + "node_modules/leancloud-realtime": { + "version": "5.0.0-rc.6", + "resolved": "https://registry.npmjs.org/leancloud-realtime/-/leancloud-realtime-5.0.0-rc.6.tgz", + "integrity": "sha512-WJExh9oY+KoGgUyBZ348AuPG34pvxnNgJD3W054ERJos0DjJsxwpeG+flcBMXuSYGxt5huQ+Pxko3zefJFiLQQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.10.2", + "@leancloud/adapter-types": "^3.0.0", + "@leancloud/platform-adapters-browser": "^1.1.0", + "@leancloud/platform-adapters-node": "^1.1.0", + "@leancloud/platform-adapters-weapp": "^1.2.0", + "base64-arraybuffer": "^0.1.5", + "debug": "^3.1.0", + "eventemitter3": "^3.0.0", + "javascript-state-machine": "^2.3.5", + "lodash": "^4.17.10", + "promise-timeout": "^1.3.0", + "protobufjs": "^5.0.1", + "uuid": "^3.0.0" + } + }, + "node_modules/leancloud-realtime-plugin-live-query": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/leancloud-realtime-plugin-live-query/-/leancloud-realtime-plugin-live-query-1.2.0.tgz", + "integrity": "sha512-eJooIH8/FyUoozr3Eeby2DpDnmX39m1bfxfxlYPuojkio+i/DLwPD+aTHnRDH6QXJcT6tNTt85RcxVR/Txg98Q==", + "dev": true, + "peerDependencies": { + "leancloud-realtime": "^3.5.0 || ^4.0.0-beta.2 || ^5.0.0-alpha.2" + } + }, + "node_modules/leancloud-realtime/node_modules/@leancloud/adapter-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@leancloud/adapter-types/-/adapter-types-3.0.0.tgz", + "integrity": "sha512-/1l2PWJ6pXizHphBorMN7B0d2YjmxZJf1s+bitvLALt7wBid5qbGpHqGGKE/yRdNlCKwl9FbXG1x5wUFZfQwHQ==", + "dev": true + }, + "node_modules/leancloud-realtime/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/leancloud-realtime/node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "dev": true + }, + "node_modules/leancloud-realtime/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/leancloud-storage": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/leancloud-storage/-/leancloud-storage-4.11.1.tgz", + "integrity": "sha512-cNlgCjyZtdGWWUFnnDvvcoiBKjFY13iQT8PfrX0uzRqvm3XmKwkMOJnTE4AuL7fbjL1HsN4oEO2hlV9QOnAmxw==", + "dev": true, + "dependencies": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/platform-adapters-browser": "^1.5.2", + "@leancloud/platform-adapters-node": "^1.5.2", + "@leancloud/platform-adapters-weapp": "^1.6.1", + "babel-runtime": "^6.26.0", + "debug": "^3.1.0", + "eventemitter3": "^2.0.3", + "leancloud-realtime": "^5.0.0-rc.4", + "leancloud-realtime-plugin-live-query": "^1.2.0", + "md5": "^2.0.0", + "promise-timeout": "^1.3.0", + "underscore": "^1.8.3", + "uuid": "^3.3.2" + } + }, + "node_modules/leancloud-storage/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/leancloud-storage/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/localstorage-memory": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/localstorage-memory/-/localstorage-memory-1.0.3.tgz", + "integrity": "sha512-t9P8WB6DcVttbw/W4PIE8HOqum8Qlvx5SjR6oInwR9Uia0EEmyUeBh7S+weKByW+l/f45Bj4L/dgZikGFDM6ng==", + "dev": true + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "dependencies": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "node_modules/lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "node_modules/lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "node_modules/lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "node_modules/lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "dependencies": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "node_modules/long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dev": true, + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dependencies": { + "mime-db": "1.48.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "node_modules/miniprogram-api-typings": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz", + "integrity": "sha512-ibvbqeslVFur0IAvTxLMvsbtvVcMo6gwvOnj0YZHV7aeDLu091VQRrETT2QuiG9P6aZWRcxeNGJChRKVPCp9VQ==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "dependencies": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 0.10.x", + "npm": ">= 1.4.x" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=", + "dev": true + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-timeout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", + "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", + "dev": true + }, + "node_modules/protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "dev": true, + "dependencies": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + }, + "bin": { + "pbjs": "bin/pbjs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "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.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, + "node_modules/should": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/should/-/should-11.2.1.tgz", + "integrity": "sha1-kPVRRVUtAc/CAGZuToGKHJZw7aI=", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/should-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-1.0.1.tgz", + "integrity": "sha1-C26VFvJgGp+wuy3MNpr6HH4gCvc=", + "dev": true, + "dependencies": { + "should-type": "^1.0.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", + "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/superagent": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", + "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 7.0.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/superagent/node_modules/qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/superagent/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/supertest": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", + "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/supertest/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/supertest/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/supertest/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/supertest/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/supertest/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/supertest/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/supertest/node_modules/superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "dev": true, + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true, + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ws": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "dependencies": { + "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" + } + } + }, "dependencies": { "@babel/runtime": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", - "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + } } }, + "@leancloud/adapter-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@leancloud/adapter-types/-/adapter-types-5.0.0.tgz", + "integrity": "sha512-psnPaa4ONaA6X9y9xsjLmJXH+2spySH/YQUz59S0cZUTWVbZaUFwLQyHkv8OzZFixKqs+eV3xnWl7nUxCCCIeg==", + "dev": true + }, + "@leancloud/adapter-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@leancloud/adapter-utils/-/adapter-utils-1.2.2.tgz", + "integrity": "sha512-B/bZM6WGN+sxMdZJeTWLAN/Gin00LX0E/M0MoygZhtrgCfCZSz47wgziOq5Fvl6yPifyvYBGaobydhyr7vxjxg==", + "dev": true + }, "@leancloud/adapters-superagent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@leancloud/adapters-superagent/-/adapters-superagent-1.0.1.tgz", - "integrity": "sha512-zR9d1XNSxgNFd0n9qXPAR+Y6bCZhafr21VmJ5FdIYgtxNP+lQcByd4VjgBnRDGZ4MT2vIhOKWD4xhY+OJoT+XA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@leancloud/adapters-superagent/-/adapters-superagent-1.4.2.tgz", + "integrity": "sha512-UpawevTXaIIFEpvtW6rm6PKH28i3OCIjgdJUmcFWbI8lezHz6bBznKB9g0aCRX8/c2h6SJThzjgqNlPny8I32g==", "dev": true, "requires": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapter-utils": "^1.2.2", + "@types/superagent": "^4.1.7", "superagent": "^5.2.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "qs": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", - "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==", - "dev": true - }, - "superagent": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.2.2.tgz", - "integrity": "sha512-pMWBUnIllK4ZTw7p/UaobiQPwAO5w/1NRRTDpV0FTVNmECztsxKspj3ZWEordVEaqpZtmOQJJna4yTLyC/q7PQ==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.1", - "methods": "^1.1.2", - "mime": "^2.4.4", - "qs": "^6.9.1", - "readable-stream": "^3.4.0", - "semver": "^6.3.0" - } - } } }, - "@leancloud/runtime-adapters-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@leancloud/runtime-adapters-browser/-/runtime-adapters-browser-1.0.1.tgz", - "integrity": "sha512-1lFaNGmntYUdFsGvzjMa4AL9JHdMi5g0SwwRSPKSDnTLa8g4/xDfO2T832CU3WssvCX9wE9uKuaSAGOrpP3cQA==", + "@leancloud/platform-adapters-browser": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-browser/-/platform-adapters-browser-1.5.2.tgz", + "integrity": "sha512-O7FRG4KvH20tiIP+dUbb7FE7kgkwEZifu7XmSRdPB5yO/+wR61BKykVQggQUdqJE6T9HZVSrqqbWWNqcMdJK6g==", "dev": true, "requires": { - "@leancloud/adapters-superagent": "^1.0.1" + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapters-superagent": "^1.4.2" } }, - "@leancloud/runtime-adapters-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@leancloud/runtime-adapters-node/-/runtime-adapters-node-1.0.1.tgz", - "integrity": "sha512-zscoAqVLFgun07P9mnKOu0w6pIO9gegxzwRYpz7Y9FjM+xZM8XfELEsfZe1u0mvxhD1rJlij3nzfuwoRlhhUTw==", + "@leancloud/platform-adapters-node": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-node/-/platform-adapters-node-1.5.2.tgz", + "integrity": "sha512-FhvL6u0CXG33M5UCla2Rfja6Rrv8Sj1mrRWCZvI6m5sW4A7RyWFICW8akBL++uHUNP8WDc7szfrBz8TJHQWDcg==", "dev": true, "requires": { - "@leancloud/adapters-superagent": "^1.0.1", + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapters-superagent": "^1.4.2", + "@types/ws": "^7.2.2", "localstorage-memory": "^1.0.2", "ws": "^5.2.2" } }, - "@leancloud/runtime-adapters-weapp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@leancloud/runtime-adapters-weapp/-/runtime-adapters-weapp-1.0.2.tgz", - "integrity": "sha512-zj6AfOBe7Ej05Kxj0TxH8r1add/r9xGIvuwl4n2KfvAq4IWT3cOn0X/4/Z/Uz2Dqg8g6o2ffytZYrnxBdHuZNg==", + "@leancloud/platform-adapters-weapp": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-weapp/-/platform-adapters-weapp-1.6.1.tgz", + "integrity": "sha512-/Pxj0Zk9829OTQdt1KdfglqVBiOteber8gUzw5Kgjws1+hlPJ7x8x5VZcdPM3lnTh6UsP4f6CkOtS/QOeLu6JA==", "dev": true, "requires": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/adapter-utils": "^1.2.2", "event-target-shim": "^5.0.1", "miniprogram-api-typings": "^2.10.2" } }, "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", "dev": true, "requires": { "@types/connect": "*", @@ -111,30 +2869,36 @@ } }, "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, "requires": { "@types/node": "*" } }, + "@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, "@types/express": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", - "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "dev": true, "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "*", + "@types/express-serve-static-core": "^4.17.18", "@types/qs": "*", "@types/serve-static": "*" } }, "@types/express-serve-static-core": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", - "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", "dev": true, "requires": { "@types/node": "*", @@ -143,37 +2907,56 @@ } }, "@types/mime": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", - "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, "@types/node": { - "version": "14.0.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", - "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.3.tgz", + "integrity": "sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==", "dev": true }, "@types/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", "dev": true }, "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, "@types/serve-static": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", - "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/superagent": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.12.tgz", + "integrity": "sha512-1GQvD6sySQPD6p9EopDFI3f5OogdICl1sU/2ij3Esobz/RtL9fWZZDPmsuv7eiy5ya+XNiPAxUcI3HIUTJa+3A==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", "dev": true, "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" + "@types/node": "*" } }, "accepts": { @@ -235,10 +3018,20 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "base64-arraybuffer": { @@ -308,6 +3101,16 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -497,6 +3300,12 @@ "keygrip": "~1.0.1" } }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -514,14 +3323,6 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, "crypt": { @@ -596,22 +3397,27 @@ } }, "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, "es-to-primitive": { @@ -625,12 +3431,6 @@ "is-symbol": "^1.0.2" } }, - "es6-promise": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.3.tgz", - "integrity": "sha512-vLf5iali3jKqlJoo6SryDwe3nxCmiueNjbjLWDIpNbAcKnQXAsAdZk+pM17nSYp3AQMbTmAQVCQSeDLfA87SNA==", - "dev": true - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -717,9 +3517,9 @@ } }, "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", + "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==", "dev": true }, "finalhandler": { @@ -743,9 +3543,9 @@ "dev": true }, "form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -760,15 +3560,15 @@ "dev": true }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true }, "forwarded-parse": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.0.tgz", - "integrity": "sha512-as9a7Xelt0CvdUy7/qxrY73dZq2vMx49F556fwjjFrUyzq5uHHfeLgD2cCq/6P4ZvusGZzjD6aL2NdgGdS5Cew==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.1.tgz", + "integrity": "sha512-8Jh3uv3iaaTTvH3vM4qyRjKfe5dvR/THhiPY5zhsfFa/UviqnEd3hqNyxEtRCwL3+L2vv8JsanGZ5XHQcncyUA==" }, "fresh": { "version": "0.5.2", @@ -788,24 +3588,35 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.0.2", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "graceful-readlink": { @@ -829,6 +3640,12 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", @@ -836,9 +3653,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, "he": { @@ -848,9 +3665,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "http-errors": { @@ -905,6 +3722,21 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -912,15 +3744,24 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, + "is-core-module": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", + "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", "dev": true }, "is-fullwidth-code-point": { @@ -932,22 +3773,41 @@ "number-is-nan": "^1.0.0" } }, - "is-regex": { + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number-object": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", "dev": true, "requires": { - "has": "^1.0.3" + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" } }, + "is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true + }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "isarray": { @@ -1000,15 +3860,16 @@ "integrity": "sha1-papLNyWnmlVd/GeybDUP4zyAzzw=" }, "leancloud-realtime": { - "version": "5.0.0-rc.1", - "resolved": "https://registry.npmjs.org/leancloud-realtime/-/leancloud-realtime-5.0.0-rc.1.tgz", - "integrity": "sha512-U00kLZfuCtXEfzvAeLhtwl7QcV/h0nFSosO/34b0IE31FxEFqHh8wCstthpHJBZhvn6lR3nSTstgKaoYD1EEEQ==", + "version": "5.0.0-rc.6", + "resolved": "https://registry.npmjs.org/leancloud-realtime/-/leancloud-realtime-5.0.0-rc.6.tgz", + "integrity": "sha512-WJExh9oY+KoGgUyBZ348AuPG34pvxnNgJD3W054ERJos0DjJsxwpeG+flcBMXuSYGxt5huQ+Pxko3zefJFiLQQ==", "dev": true, "requires": { - "@babel/runtime": "^7.7.4", - "@leancloud/runtime-adapters-browser": "^1.0.1", - "@leancloud/runtime-adapters-node": "^1.0.1", - "@leancloud/runtime-adapters-weapp": "^1.0.2", + "@babel/runtime": "^7.10.2", + "@leancloud/adapter-types": "^3.0.0", + "@leancloud/platform-adapters-browser": "^1.1.0", + "@leancloud/platform-adapters-node": "^1.1.0", + "@leancloud/platform-adapters-weapp": "^1.2.0", "base64-arraybuffer": "^0.1.5", "debug": "^3.1.0", "eventemitter3": "^3.0.0", @@ -1019,10 +3880,16 @@ "uuid": "^3.0.0" }, "dependencies": { + "@leancloud/adapter-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@leancloud/adapter-types/-/adapter-types-3.0.0.tgz", + "integrity": "sha512-/1l2PWJ6pXizHphBorMN7B0d2YjmxZJf1s+bitvLALt7wBid5qbGpHqGGKE/yRdNlCKwl9FbXG1x5wUFZfQwHQ==", + "dev": true + }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1035,9 +3902,9 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -1046,39 +3913,43 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/leancloud-realtime-plugin-live-query/-/leancloud-realtime-plugin-live-query-1.2.0.tgz", "integrity": "sha512-eJooIH8/FyUoozr3Eeby2DpDnmX39m1bfxfxlYPuojkio+i/DLwPD+aTHnRDH6QXJcT6tNTt85RcxVR/Txg98Q==", - "dev": true + "dev": true, + "requires": {} }, "leancloud-storage": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/leancloud-storage/-/leancloud-storage-3.15.0.tgz", - "integrity": "sha512-UbR6pLA0tVYPcY7AND0pey45iFsB2PkIo8Wz0DZ9BabKyqndA1ey2LKzYpFDGNh3ODrmT3fValVn9yY4bgf9Uw==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/leancloud-storage/-/leancloud-storage-4.11.1.tgz", + "integrity": "sha512-cNlgCjyZtdGWWUFnnDvvcoiBKjFY13iQT8PfrX0uzRqvm3XmKwkMOJnTE4AuL7fbjL1HsN4oEO2hlV9QOnAmxw==", "dev": true, "requires": { + "@leancloud/adapter-types": "^5.0.0", + "@leancloud/platform-adapters-browser": "^1.5.2", + "@leancloud/platform-adapters-node": "^1.5.2", + "@leancloud/platform-adapters-weapp": "^1.6.1", + "babel-runtime": "^6.26.0", "debug": "^3.1.0", - "es6-promise": "4.2.3", "eventemitter3": "^2.0.3", - "leancloud-realtime": "^5.0.0-alpha.3", + "leancloud-realtime": "^5.0.0-rc.4", "leancloud-realtime-plugin-live-query": "^1.2.0", - "localstorage-memory": "^1.0.1", "md5": "^2.0.0", - "superagent": "^3.3.1", + "promise-timeout": "^1.3.0", "underscore": "^1.8.3", "uuid": "^3.3.2" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } @@ -1102,9 +3973,9 @@ "dev": true }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash._baseassign": { @@ -1181,15 +4052,24 @@ "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "dev": true, "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" } }, "media-typer": { @@ -1222,16 +4102,16 @@ "dev": true }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "requires": { - "mime-db": "1.43.0" + "mime-db": "1.48.0" } }, "minimatch": { @@ -1250,9 +4130,9 @@ "dev": true }, "miniprogram-api-typings": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.10.2.tgz", - "integrity": "sha512-nb2vtGCVyNRJqR8C01RVg9H4qCuq5u2eCdEVjrSO1E9ZDonUApCePs3ZEtd0C8CbTuBmp5ZlGhX1Npnu5dxEfg==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz", + "integrity": "sha512-ibvbqeslVFur0IAvTxLMvsbtvVcMo6gwvOnj0YZHV7aeDLu091VQRrETT2QuiG9P6aZWRcxeNGJChRKVPCp9VQ==", "dev": true }, "mkdirp": { @@ -1292,20 +4172,6 @@ "requires": { "ms": "2.0.0" } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "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" - } } } }, @@ -1336,14 +4202,6 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, "npm-run-all": { @@ -1370,9 +4228,9 @@ "dev": true }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", "dev": true }, "object-keys": { @@ -1382,15 +4240,15 @@ "dev": true }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "on-finished": { @@ -1458,9 +4316,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-to-regexp": { @@ -1479,9 +4337,9 @@ } }, "pidtree": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", - "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true }, "pify": { @@ -1515,12 +4373,12 @@ } }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, @@ -1569,17 +4427,18 @@ } }, "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -1595,9 +4454,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "send": { @@ -1721,10 +4580,21 @@ "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", "dev": true }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -1732,15 +4602,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -1748,9 +4618,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", "dev": true }, "statuses": { @@ -1758,6 +4628,23 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -1770,50 +4657,34 @@ } }, "string.prototype.padend": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", - "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", + "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.18.0-next.2" } }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "strip-ansi": { @@ -1832,27 +4703,79 @@ "dev": true }, "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", + "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", "dev": true, "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "supertest": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", + "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^3.8.3" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1876,9 +4799,9 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "readable-stream": { @@ -1904,19 +4827,27 @@ "requires": { "safe-buffer": "~5.1.0" } + }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "dev": true, + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + } } } }, - "supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - } - }, "supports-color": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", @@ -1941,15 +4872,27 @@ } }, "typescript": { - "version": "3.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", - "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", "dev": true }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" }, "unpipe": { "version": "1.0.0", @@ -1998,6 +4941,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", @@ -2021,9 +4977,9 @@ "dev": true }, "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", "dev": true, "requires": { "async-limiter": "~1.0.0" @@ -2036,9 +4992,15 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "yargs": { From bf3f4e39670678b4fe259702d071c91a77d76a9f Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 8 Jul 2021 16:48:05 +0800 Subject: [PATCH 117/122] :construction: Support beforeAuthDataMatch and beforeAuthDataCommit --- lib/cloud.js | 8 ++++++++ lib/leanengine.js | 3 +++ lib/utils.js | 4 +++- test/function-test.js | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index a5f9b7a..655bb66 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -161,6 +161,14 @@ Cloud.onLogin = function(func) { Cloud.define('__on_login__User', func); }; +Cloud.beforeAuthDataMatch = function(func) { + Cloud.define('__user_before_authdata_match__User', func); +}; + +Cloud.beforeAuthDataCommit = function(func) { + Cloud.define('__user_before_authdata_commit__User', func); +}; + _.each(utils.realtimeHookMapping, (metadataName, hookName) => { Cloud[hookName] = Cloud.define.bind(null, metadataName); }); diff --git a/lib/leanengine.js b/lib/leanengine.js index 66885eb..500c1c0 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -98,6 +98,9 @@ function createCloudFunctionRouter(options) { return callUserHook(req, 'onVerified', hookName); } else if (functionOrClass === '_User' && hookName === 'onLogin') { return callUserHook(req, 'onLogin', '_User'); + } else if (functionOrClass === '_User' && _.contains(['userBeforeAuthDataMatch', 'userBeforeAuthDataCommit'], hookName)) { + req.rpcCall = true; + return callCloudFunction(req, utils.hookNameMapping[hookName], options); } else if ((functionOrClass === 'BigQuery' || functionOrClass === 'Insight') && hookName === 'onComplete') { return onCompleteBigQueryJob(req); } else { diff --git a/lib/utils.js b/lib/utils.js index 42ff6ae..e58bbbb 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -13,7 +13,9 @@ exports.hookNameMapping = { beforeDelete: '__before_delete_for_', afterDelete: '__after_delete_for_', onVerified: '__on_verified_', - onLogin: '__on_login_' + onLogin: '__on_login_', + userBeforeAuthDataMatch: '__user_before_authdata_match__User', + userBeforeAuthDataCommit: '__user_before_authdata_commit__User' }; exports.realtimeHookMapping = { diff --git a/test/function-test.js b/test/function-test.js index 037ff9c..7fb71a8 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -506,7 +506,7 @@ describe('functions', function() { .expect(200, done); }); - it('enqueue & getTaskInfo', async function() { + it.only('enqueue & getTaskInfo', async function() { const {uniqueId} = await AV.Cloud.enqueue('hello'); uniqueId.length.should.be.equal(36); From 12f14f2cb22687ba9cac85cd72ac36283148e844 Mon Sep 17 00:00:00 2001 From: jysperm Date: Thu, 8 Jul 2021 18:01:04 +0800 Subject: [PATCH 118/122] :white_check_mark: Add tests --- test/fixtures/hooks.js | 20 ++++++++++++++++++++ test/function-test.js | 2 +- test/hook-test.js | 43 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/test/fixtures/hooks.js b/test/fixtures/hooks.js index 5d08800..5563004 100644 --- a/test/fixtures/hooks.js +++ b/test/fixtures/hooks.js @@ -124,3 +124,23 @@ AV.Insight.on('end', function(result) { "message": "当 status 为 ERROR 时的错误消息" }, result); }); + +AV.Cloud.beforeAuthDataMatch( request => { + let authData = request.params.authData; + + if (authData.weixin.code === '12345') { + authData.weixin.accessToken = '45678'; + } else { + throw new Error('invalid code'); + } + + return authData; +}); + +AV.Cloud.beforeAuthDataCommit( request => { + let authData = request.params.authData; + let user = request.params.user; + + assert.equal(authData.weixin.code, '12345') + assert.equal(user.username, 'admin') +}); diff --git a/test/function-test.js b/test/function-test.js index 7fb71a8..037ff9c 100644 --- a/test/function-test.js +++ b/test/function-test.js @@ -506,7 +506,7 @@ describe('functions', function() { .expect(200, done); }); - it.only('enqueue & getTaskInfo', async function() { + it('enqueue & getTaskInfo', async function() { const {uniqueId} = await AV.Cloud.enqueue('hello'); uniqueId.length.should.be.equal(36); diff --git a/test/hook-test.js b/test/hook-test.js index 6b5b629..8249128 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -503,4 +503,47 @@ describe('hook', function() { }) .expect(200, done); }); + + it('beforeAuthDataMatch', function(done) { + request(app) + .post('/1.1/functions/_User/userBeforeAuthDataMatch') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) + .send({ + authData: { + weixin: { + code: '12345' + } + } + }) + .expect(200, function(err, res) { + res.body.result.weixin.accessToken.should.equal('45678'); + done(); + }); + }); + + it('beforeAuthDataCommit', function(done) { + request(app) + .post('/1.1/functions/_User/userBeforeAuthDataCommit') + .set('X-AVOSCloud-Application-Id', appId) + .set('X-AVOSCloud-Application-Key', appKey) + .set('X-LC-Hook-Key', hookKey) + .send({ + "user": { + "username": "admin", + "importFromParse": true, + "emailVerified": false, + "objectId": "52aebbdee4b0c8b6fa455aa7", + "createdAt": "2013-12-16T16:37:50.059Z", + "updatedAt": "2013-12-16T16:37:50.059Z" + }, + authData: { + weixin: { + code: '12345' + } + } + }) + .expect(200, done); + }); }); From 46d43f84170520eb3b45b081820bfa2034a9ff9f Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 9 Jul 2021 17:29:00 +0800 Subject: [PATCH 119/122] :recycle: Rewrite to onAuthDataTransform --- lib/cloud.js | 8 ++------ lib/leanengine.js | 19 ++++++++++++------- lib/utils.js | 3 +-- test/fixtures/hooks.js | 12 ++---------- test/hook-test.js | 28 ++-------------------------- 5 files changed, 19 insertions(+), 51 deletions(-) diff --git a/lib/cloud.js b/lib/cloud.js index 655bb66..06117a0 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -161,12 +161,8 @@ Cloud.onLogin = function(func) { Cloud.define('__on_login__User', func); }; -Cloud.beforeAuthDataMatch = function(func) { - Cloud.define('__user_before_authdata_match__User', func); -}; - -Cloud.beforeAuthDataCommit = function(func) { - Cloud.define('__user_before_authdata_commit__User', func); +Cloud.onAuthDataTransform = function(func) { + Cloud.define('__on_authdata_transform__User', func); }; _.each(utils.realtimeHookMapping, (metadataName, hookName) => { diff --git a/lib/leanengine.js b/lib/leanengine.js index 500c1c0..74362be 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -96,11 +96,8 @@ function createCloudFunctionRouter(options) { return callCloudFunction(req, functionOrClass, options); } else if (functionOrClass === 'onVerified') { return callUserHook(req, 'onVerified', hookName); - } else if (functionOrClass === '_User' && hookName === 'onLogin') { - return callUserHook(req, 'onLogin', '_User'); - } else if (functionOrClass === '_User' && _.contains(['userBeforeAuthDataMatch', 'userBeforeAuthDataCommit'], hookName)) { - req.rpcCall = true; - return callCloudFunction(req, utils.hookNameMapping[hookName], options); + } else if (functionOrClass === '_User' && _.contains(['onLogin', 'onAuthDataTransform'], hookName)) { + return callUserHook(req, hookName, '_User'); } else if ((functionOrClass === 'BigQuery' || functionOrClass === 'Insight') && hookName === 'onComplete') { return onCompleteBigQueryJob(req); } else { @@ -281,6 +278,10 @@ function callUserHook(req, hookName, verifyType) { object: user }); + if (req.body.authData) { + request.authData = req.body.authData; + } + return new Promise( (resolve, reject) => { if (hookName === 'onLogin' && userHookFunction.length === 2) { userHookFunction(request, utils.prepareResponseObject(req.res, err => { @@ -291,8 +292,12 @@ function callUserHook(req, hookName, verifyType) { } })); } else { - promiseTry(userHookFunction.bind(null, request)).then( () => { - resolve({result: 'ok'}); + promiseTry(userHookFunction.bind(null, request)).then( result => { + if (hookName === 'onAuthDataTransform') { + resolve({result}); + } else { + resolve({result: 'ok'}); + } }).catch(reject); } }); diff --git a/lib/utils.js b/lib/utils.js index e58bbbb..478291f 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -14,8 +14,7 @@ exports.hookNameMapping = { afterDelete: '__after_delete_for_', onVerified: '__on_verified_', onLogin: '__on_login_', - userBeforeAuthDataMatch: '__user_before_authdata_match__User', - userBeforeAuthDataCommit: '__user_before_authdata_commit__User' + onAuthDataTransform: '__on_authdata_transform_' }; exports.realtimeHookMapping = { diff --git a/test/fixtures/hooks.js b/test/fixtures/hooks.js index 5563004..1f356f6 100644 --- a/test/fixtures/hooks.js +++ b/test/fixtures/hooks.js @@ -125,8 +125,8 @@ AV.Insight.on('end', function(result) { }, result); }); -AV.Cloud.beforeAuthDataMatch( request => { - let authData = request.params.authData; +AV.Cloud.onAuthDataTransform( request => { + let authData = request.authData; if (authData.weixin.code === '12345') { authData.weixin.accessToken = '45678'; @@ -136,11 +136,3 @@ AV.Cloud.beforeAuthDataMatch( request => { return authData; }); - -AV.Cloud.beforeAuthDataCommit( request => { - let authData = request.params.authData; - let user = request.params.user; - - assert.equal(authData.weixin.code, '12345') - assert.equal(user.username, 'admin') -}); diff --git a/test/hook-test.js b/test/hook-test.js index 8249128..c2f6755 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -504,9 +504,9 @@ describe('hook', function() { .expect(200, done); }); - it('beforeAuthDataMatch', function(done) { + it('onAuthDataTransform', function(done) { request(app) - .post('/1.1/functions/_User/userBeforeAuthDataMatch') + .post('/1.1/functions/_User/onAuthDataTransform') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) .set('X-LC-Hook-Key', hookKey) @@ -522,28 +522,4 @@ describe('hook', function() { done(); }); }); - - it('beforeAuthDataCommit', function(done) { - request(app) - .post('/1.1/functions/_User/userBeforeAuthDataCommit') - .set('X-AVOSCloud-Application-Id', appId) - .set('X-AVOSCloud-Application-Key', appKey) - .set('X-LC-Hook-Key', hookKey) - .send({ - "user": { - "username": "admin", - "importFromParse": true, - "emailVerified": false, - "objectId": "52aebbdee4b0c8b6fa455aa7", - "createdAt": "2013-12-16T16:37:50.059Z", - "updatedAt": "2013-12-16T16:37:50.059Z" - }, - authData: { - weixin: { - code: '12345' - } - } - }) - .expect(200, done); - }); }); From d1cfa9936335823216b80417aab3729abaf76604 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 9 Jul 2021 17:38:56 +0800 Subject: [PATCH 120/122] :memo: API and types for onAuthDataTransform --- API.md | 9 +++++++++ leanengine.d.ts | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/API.md b/API.md index 083bc42..b91c5fe 100644 --- a/API.md +++ b/API.md @@ -174,6 +174,15 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `currentUser: AV.User`:被操作的用户。 * `user: AV.User`:同 `currentUser`. * `object: AV.User`:同 `currentUser`,因为登录认证 hook 被操作的对象正好是发起操作的用户。 +* `authData: {[provider: string]: any}`,客户端发送的第三方登录信息(仅 `onAuthDataTransform`)。 + +#### `AV.Cloud.onAuthDataTransform` + +这个函数的签名:`function(func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回新的 authData 的异步函数,如果抛出异常会中断第三方登录。 + +`Request` 上的属性包括: + +* `authData: {[provider: string]: any}`,客户端发送的第三方登录信息。 ### 实时通信 Hook 函数 diff --git a/leanengine.d.ts b/leanengine.d.ts index 5bc072b..571a35a 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -125,9 +125,14 @@ export namespace Cloud { currentUser: User } + interface AuthDataTransformRequest { + authData: {[provider: string]: any} + } + type CloudFunction = (request: CloudFunctionRequest) => Promise; type ClassHookFunction = (request: ClassHookRequest) => Promise; type UserHookFunction = (request: UserHookRequest) => Promise; + type AuthDataTransformFunction = (request: AuthDataTransformRequest) => Promise<{[provider: string]: any}>; export class Error { constructor(message: string, options?: {status?: number, code?: number}) @@ -150,6 +155,7 @@ export namespace Cloud { export function onVerified(handler: UserHookFunction): void; export function onLogin(handler: UserHookFunction): void; + export function onAuthDataTransform(handler: AuthDataTransformFunction): void; export function onIMMessageReceived(handler: CloudFunction): void; export function onIMReceiversOffline(handler: CloudFunction): void; From f46b00c42ecc68f4a3c42368ca44b6ba99a52ed5 Mon Sep 17 00:00:00 2001 From: jysperm Date: Fri, 23 Jul 2021 15:38:54 +0800 Subject: [PATCH 121/122] :truck: Rename to onAuthData --- API.md | 4 +- leanengine.d.ts | 2 +- lib/cloud.js | 4 +- lib/leanengine.js | 4 +- lib/utils.js | 2 +- package-lock.json | 1392 ++++++++++++++++++---------------------- test/fixtures/hooks.js | 2 +- test/hook-test.js | 4 +- 8 files changed, 636 insertions(+), 778 deletions(-) diff --git a/API.md b/API.md index b91c5fe..fca491b 100644 --- a/API.md +++ b/API.md @@ -174,9 +174,9 @@ LeanEngine 中间件会为这些 Hook 函数检查「Hook 签名」,确保调 * `currentUser: AV.User`:被操作的用户。 * `user: AV.User`:同 `currentUser`. * `object: AV.User`:同 `currentUser`,因为登录认证 hook 被操作的对象正好是发起操作的用户。 -* `authData: {[provider: string]: any}`,客户端发送的第三方登录信息(仅 `onAuthDataTransform`)。 +* `authData: {[provider: string]: any}`,客户端发送的第三方登录信息(仅 `onAuthData`)。 -#### `AV.Cloud.onAuthDataTransform` +#### `AV.Cloud.onAuthData` 这个函数的签名:`function(func: function)`,其中 `func` 是接受一个 Request 对象作为参数,返回新的 authData 的异步函数,如果抛出异常会中断第三方登录。 diff --git a/leanengine.d.ts b/leanengine.d.ts index 571a35a..440e5f0 100644 --- a/leanengine.d.ts +++ b/leanengine.d.ts @@ -155,7 +155,7 @@ export namespace Cloud { export function onVerified(handler: UserHookFunction): void; export function onLogin(handler: UserHookFunction): void; - export function onAuthDataTransform(handler: AuthDataTransformFunction): void; + export function onAuthData(handler: AuthDataTransformFunction): void; export function onIMMessageReceived(handler: CloudFunction): void; export function onIMReceiversOffline(handler: CloudFunction): void; diff --git a/lib/cloud.js b/lib/cloud.js index 06117a0..6086226 100644 --- a/lib/cloud.js +++ b/lib/cloud.js @@ -161,8 +161,8 @@ Cloud.onLogin = function(func) { Cloud.define('__on_login__User', func); }; -Cloud.onAuthDataTransform = function(func) { - Cloud.define('__on_authdata_transform__User', func); +Cloud.onAuthData = function(func) { + Cloud.define('__on_authdata__User', func); }; _.each(utils.realtimeHookMapping, (metadataName, hookName) => { diff --git a/lib/leanengine.js b/lib/leanengine.js index 74362be..50facf3 100644 --- a/lib/leanengine.js +++ b/lib/leanengine.js @@ -96,7 +96,7 @@ function createCloudFunctionRouter(options) { return callCloudFunction(req, functionOrClass, options); } else if (functionOrClass === 'onVerified') { return callUserHook(req, 'onVerified', hookName); - } else if (functionOrClass === '_User' && _.contains(['onLogin', 'onAuthDataTransform'], hookName)) { + } else if (functionOrClass === '_User' && _.contains(['onLogin', 'onAuthData'], hookName)) { return callUserHook(req, hookName, '_User'); } else if ((functionOrClass === 'BigQuery' || functionOrClass === 'Insight') && hookName === 'onComplete') { return onCompleteBigQueryJob(req); @@ -293,7 +293,7 @@ function callUserHook(req, hookName, verifyType) { })); } else { promiseTry(userHookFunction.bind(null, request)).then( result => { - if (hookName === 'onAuthDataTransform') { + if (hookName === 'onAuthData') { resolve({result}); } else { resolve({result: 'ok'}); diff --git a/lib/utils.js b/lib/utils.js index 478291f..08eb168 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -14,7 +14,7 @@ exports.hookNameMapping = { afterDelete: '__after_delete_for_', onVerified: '__on_verified_', onLogin: '__on_login_', - onAuthDataTransform: '__on_authdata_transform_' + onAuthData: '__on_authdata_' }; exports.realtimeHookMapping = { diff --git a/package-lock.json b/package-lock.json index cf90dc2..ff2a117 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,9 +36,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", - "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", "dev": true, "dependencies": { "regenerator-runtime": "^0.13.4" @@ -48,9 +48,9 @@ } }, "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", "dev": true }, "node_modules/@leancloud/adapter-types": { @@ -77,6 +77,78 @@ "superagent": "^5.2.2" } }, + "node_modules/@leancloud/adapters-superagent/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@leancloud/adapters-superagent/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@leancloud/adapters-superagent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@leancloud/adapters-superagent/node_modules/qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@leancloud/adapters-superagent/node_modules/superagent": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", + "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 7.0.0" + } + }, "node_modules/@leancloud/platform-adapters-browser": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@leancloud/platform-adapters-browser/-/platform-adapters-browser-1.5.2.tgz", @@ -113,9 +185,9 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", "dev": true, "dependencies": { "@types/connect": "*", @@ -123,9 +195,9 @@ } }, "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", "dev": true, "dependencies": { "@types/node": "*" @@ -138,21 +210,21 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", + "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", "dev": true, "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", + "@types/express-serve-static-core": "*", "@types/qs": "*", "@types/serve-static": "*" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", - "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", + "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", "dev": true, "dependencies": { "@types/node": "*", @@ -161,37 +233,37 @@ } }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", + "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==", "dev": true }, "node_modules/@types/node": { - "version": "16.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.3.tgz", - "integrity": "sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==", + "version": "14.0.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", + "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", "dev": true }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", "dev": true }, "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", + "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", "dev": true, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "@types/express-serve-static-core": "*", + "@types/mime": "*" } }, "node_modules/@types/superagent": { @@ -298,9 +370,9 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "node_modules/base64-arraybuffer": { @@ -661,6 +733,15 @@ "node": ">=4.8" } }, + "node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", @@ -754,27 +835,22 @@ } }, "node_modules/es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" }, "engines": { "node": ">= 0.4" @@ -953,18 +1029,18 @@ } }, "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/forwarded-parse": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.1.tgz", - "integrity": "sha512-8Jh3uv3iaaTTvH3vM4qyRjKfe5dvR/THhiPY5zhsfFa/UviqnEd3hqNyxEtRCwL3+L2vv8JsanGZ5XHQcncyUA==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.0.tgz", + "integrity": "sha512-as9a7Xelt0CvdUy7/qxrY73dZq2vMx49F556fwjjFrUyzq5uHHfeLgD2cCq/6P4ZvusGZzjD6aL2NdgGdS5Cew==" }, "node_modules/fresh": { "version": "0.5.2", @@ -1002,26 +1078,29 @@ } }, "node_modules/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.2", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "node_modules/graceful-readlink": { @@ -1048,15 +1127,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", @@ -1067,9 +1137,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true, "engines": { "node": ">= 0.4" @@ -1088,9 +1158,9 @@ } }, "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, "node_modules/http-errors": { @@ -1157,30 +1227,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "node_modules/is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -1188,9 +1234,9 @@ "dev": true }, "node_modules/is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -1199,22 +1245,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true, "engines": { "node": ">= 0.4" @@ -1235,51 +1269,14 @@ "node": ">=0.10.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "has": "^1.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -1288,12 +1285,12 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1395,9 +1392,10 @@ "dev": true }, "node_modules/leancloud-realtime/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" @@ -1410,9 +1408,9 @@ "dev": true }, "node_modules/leancloud-realtime/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/leancloud-storage": { @@ -1437,18 +1435,19 @@ } }, "node_modules/leancloud-storage/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" } }, "node_modules/leancloud-storage/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/load-json-file": { @@ -1473,9 +1472,9 @@ "dev": true }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "node_modules/lodash._baseassign": { @@ -1568,14 +1567,14 @@ } }, "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", "dev": true, "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" } }, "node_modules/media-typer": { @@ -1623,19 +1622,19 @@ } }, "node_modules/mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "dependencies": { - "mime-db": "1.48.0" + "mime-db": "1.43.0" }, "engines": { "node": ">= 0.6" @@ -1660,9 +1659,9 @@ "dev": true }, "node_modules/miniprogram-api-typings": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz", - "integrity": "sha512-ibvbqeslVFur0IAvTxLMvsbtvVcMo6gwvOnj0YZHV7aeDLu091VQRrETT2QuiG9P6aZWRcxeNGJChRKVPCp9VQ==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.10.2.tgz", + "integrity": "sha512-nb2vtGCVyNRJqR8C01RVg9H4qCuq5u2eCdEVjrSO1E9ZDonUApCePs3ZEtd0C8CbTuBmp5ZlGhX1Npnu5dxEfg==", "dev": true }, "node_modules/mkdirp": { @@ -1715,6 +1714,23 @@ "ms": "2.0.0" } }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1747,6 +1763,15 @@ "validate-npm-package-license": "^3.0.1" } }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -1800,21 +1825,18 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, "node_modules/on-finished": { @@ -1903,9 +1925,9 @@ } }, "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "node_modules/path-to-regexp": { @@ -1927,9 +1949,9 @@ } }, "node_modules/pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", "dev": true, "bin": { "pidtree": "bin/pidtree.js" @@ -1978,12 +2000,12 @@ } }, "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "dev": true, "dependencies": { - "forwarded": "0.2.0", + "forwarded": "~0.1.2", "ipaddr.js": "1.9.1" }, "engines": { @@ -2056,12 +2078,11 @@ "dev": true }, "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "dependencies": { - "is-core-module": "^2.2.0", "path-parse": "^1.0.6" }, "funding": { @@ -2080,12 +2101,18 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { @@ -2234,9 +2261,9 @@ } }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -2244,15 +2271,15 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", @@ -2260,9 +2287,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "node_modules/statuses": { @@ -2317,14 +2344,13 @@ } }, "node_modules/string.prototype.padend": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", - "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", + "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" + "es-abstract": "^1.17.0-next.1" }, "engines": { "node": ">= 0.4" @@ -2333,27 +2359,33 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "node_modules/string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "node_modules/string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2381,115 +2413,37 @@ } }, "node_modules/superagent": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", - "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", "dev": true, "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" - }, - "engines": { - "node": ">= 7.0.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/superagent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/superagent/node_modules/qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/superagent/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" }, "engines": { - "node": ">=6.0.0" + "node": ">= 4.0" } }, - "node_modules/supertest/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/superagent/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" } }, - "node_modules/supertest/node_modules/form-data": { + "node_modules/superagent/node_modules/form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", @@ -2503,19 +2457,19 @@ "node": ">= 0.12" } }, - "node_modules/supertest/node_modules/isarray": { + "node_modules/superagent/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "node_modules/supertest/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/superagent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/supertest/node_modules/readable-stream": { + "node_modules/superagent/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", @@ -2530,7 +2484,7 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/supertest/node_modules/string_decoder": { + "node_modules/superagent/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", @@ -2539,25 +2493,17 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/supertest/node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "node_modules/supertest": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", + "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", "dev": true, "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" + "methods": "^1.1.2", + "superagent": "^3.8.3" }, "engines": { - "node": ">= 4.0" + "node": ">=6.0.0" } }, "node_modules/supports-color": { @@ -2593,9 +2539,9 @@ } }, "node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", + "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -2605,25 +2551,10 @@ "node": ">=4.2.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" }, "node_modules/unpipe": { "version": "1.0.0", @@ -2688,22 +2619,6 @@ "which": "bin/which" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", @@ -2736,9 +2651,9 @@ "dev": true }, "node_modules/ws": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", - "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, "dependencies": { "async-limiter": "~1.0.0" @@ -2754,9 +2669,9 @@ } }, "node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "node_modules/yallist": { @@ -2783,18 +2698,18 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", - "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" }, "dependencies": { "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", "dev": true } } @@ -2821,6 +2736,57 @@ "@leancloud/adapter-utils": "^1.2.2", "@types/superagent": "^4.1.7", "superagent": "^5.2.2" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "superagent": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", + "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + } + } } }, "@leancloud/platform-adapters-browser": { @@ -2859,9 +2825,9 @@ } }, "@types/body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", "dev": true, "requires": { "@types/connect": "*", @@ -2869,9 +2835,9 @@ } }, "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", "dev": true, "requires": { "@types/node": "*" @@ -2884,21 +2850,21 @@ "dev": true }, "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", + "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", "dev": true, "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", + "@types/express-serve-static-core": "*", "@types/qs": "*", "@types/serve-static": "*" } }, "@types/express-serve-static-core": { - "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", - "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", + "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", "dev": true, "requires": { "@types/node": "*", @@ -2907,37 +2873,37 @@ } }, "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", + "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==", "dev": true }, "@types/node": { - "version": "16.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.3.tgz", - "integrity": "sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==", + "version": "14.0.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", + "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", "dev": true }, "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", "dev": true }, "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", "dev": true }, "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", + "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", "dev": true, "requires": { - "@types/mime": "^1", - "@types/node": "*" + "@types/express-serve-static-core": "*", + "@types/mime": "*" } }, "@types/superagent": { @@ -3029,9 +2995,9 @@ } }, "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base64-arraybuffer": { @@ -3323,6 +3289,14 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "crypt": { @@ -3397,27 +3371,22 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" } }, "es-to-primitive": { @@ -3560,15 +3529,15 @@ "dev": true }, "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, "forwarded-parse": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.1.tgz", - "integrity": "sha512-8Jh3uv3iaaTTvH3vM4qyRjKfe5dvR/THhiPY5zhsfFa/UviqnEd3hqNyxEtRCwL3+L2vv8JsanGZ5XHQcncyUA==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.0.tgz", + "integrity": "sha512-as9a7Xelt0CvdUy7/qxrY73dZq2vMx49F556fwjjFrUyzq5uHHfeLgD2cCq/6P4ZvusGZzjD6aL2NdgGdS5Cew==" }, "fresh": { "version": "0.5.2", @@ -3600,23 +3569,23 @@ } }, "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.2", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "graceful-readlink": { @@ -3640,12 +3609,6 @@ "function-bind": "^1.1.1" } }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", @@ -3653,9 +3616,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, "he": { @@ -3665,9 +3628,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, "http-errors": { @@ -3722,21 +3685,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true - }, - "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3744,24 +3692,15 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", "dev": true }, - "is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, "is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, "is-fullwidth-code-point": { @@ -3773,41 +3712,22 @@ "number-is-nan": "^1.0.0" } }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", - "dev": true - }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has": "^1.0.3" } }, - "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", - "dev": true - }, "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.1" } }, "isarray": { @@ -3887,9 +3807,9 @@ "dev": true }, "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -3902,9 +3822,9 @@ "dev": true }, "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -3938,18 +3858,18 @@ }, "dependencies": { "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" } }, "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -3973,9 +3893,9 @@ "dev": true }, "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "lodash._baseassign": { @@ -4062,14 +3982,14 @@ } }, "md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", "dev": true, "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" } }, "media-typer": { @@ -4102,16 +4022,16 @@ "dev": true }, "mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" }, "mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "requires": { - "mime-db": "1.48.0" + "mime-db": "1.43.0" } }, "minimatch": { @@ -4130,9 +4050,9 @@ "dev": true }, "miniprogram-api-typings": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz", - "integrity": "sha512-ibvbqeslVFur0IAvTxLMvsbtvVcMo6gwvOnj0YZHV7aeDLu091VQRrETT2QuiG9P6aZWRcxeNGJChRKVPCp9VQ==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-2.10.2.tgz", + "integrity": "sha512-nb2vtGCVyNRJqR8C01RVg9H4qCuq5u2eCdEVjrSO1E9ZDonUApCePs3ZEtd0C8CbTuBmp5ZlGhX1Npnu5dxEfg==", "dev": true }, "mkdirp": { @@ -4172,6 +4092,20 @@ "requires": { "ms": "2.0.0" } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "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" + } } } }, @@ -4202,6 +4136,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "npm-run-all": { @@ -4240,15 +4182,15 @@ "dev": true }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, "on-finished": { @@ -4316,9 +4258,9 @@ "dev": true }, "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-to-regexp": { @@ -4337,9 +4279,9 @@ } }, "pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", "dev": true }, "pify": { @@ -4373,12 +4315,12 @@ } }, "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "dev": true, "requires": { - "forwarded": "0.2.0", + "forwarded": "~0.1.2", "ipaddr.js": "1.9.1" } }, @@ -4433,12 +4375,11 @@ "dev": true }, "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { - "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -4454,10 +4395,13 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } }, "send": { "version": "0.17.1", @@ -4592,9 +4536,9 @@ } }, "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -4602,15 +4546,15 @@ } }, "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -4618,9 +4562,9 @@ } }, "spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "statuses": { @@ -4657,34 +4601,33 @@ } }, "string.prototype.padend": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", - "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", + "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", "dev": true, "requires": { - "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" + "es-abstract": "^1.17.0-next.1" } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" } }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" } }, "strip-ansi": { @@ -4703,79 +4646,27 @@ "dev": true }, "superagent": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", - "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", "dev": true, "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" }, "dependencies": { "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -4799,9 +4690,9 @@ "dev": true }, "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "readable-stream": { @@ -4827,27 +4718,19 @@ "requires": { "safe-buffer": "~5.1.0" } - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - } } } }, + "supertest": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", + "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + } + }, "supports-color": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", @@ -4872,27 +4755,15 @@ } }, "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", + "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", "dev": true }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" }, "unpipe": { "version": "1.0.0", @@ -4941,19 +4812,6 @@ "isexe": "^2.0.0" } }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", @@ -4977,9 +4835,9 @@ "dev": true }, "ws": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", - "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, "requires": { "async-limiter": "~1.0.0" @@ -4992,9 +4850,9 @@ "dev": true }, "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yallist": { diff --git a/test/fixtures/hooks.js b/test/fixtures/hooks.js index 1f356f6..fc6ea4c 100644 --- a/test/fixtures/hooks.js +++ b/test/fixtures/hooks.js @@ -125,7 +125,7 @@ AV.Insight.on('end', function(result) { }, result); }); -AV.Cloud.onAuthDataTransform( request => { +AV.Cloud.onAuthData( request => { let authData = request.authData; if (authData.weixin.code === '12345') { diff --git a/test/hook-test.js b/test/hook-test.js index c2f6755..555afa5 100644 --- a/test/hook-test.js +++ b/test/hook-test.js @@ -504,9 +504,9 @@ describe('hook', function() { .expect(200, done); }); - it('onAuthDataTransform', function(done) { + it('onAuthData', function(done) { request(app) - .post('/1.1/functions/_User/onAuthDataTransform') + .post('/1.1/functions/_User/onAuthData') .set('X-AVOSCloud-Application-Id', appId) .set('X-AVOSCloud-Application-Key', appKey) .set('X-LC-Hook-Key', hookKey) From 1b0e7595ec8b38b6cdc0313cad61a63ccc3806f8 Mon Sep 17 00:00:00 2001 From: jysperm Date: Tue, 3 Aug 2021 11:41:51 +0800 Subject: [PATCH 122/122] :bookmark: Prepare 3.8.0 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 252912c..c239c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 更新日志 +## 3.8.0 + +- 添加对新的 Hook(`onAuthData`)的支持,这个 Hook 会在云存储处理第三方登录的 authData 时触发,开发者可以在这个 Hook 中进行对 authData 的校验。 +- 正式支持 JS SDK (leancloud-storage) 4.x,对于新的项目会自动安装 4.x 版本的 JS SDK(不影响既有项目)。 + ## 3.7.0 - `req.meta.remoteAddress` 优先从 `Forwarded` 头获取客户端 IP,在线上的 Hook 中可以获取到触发 Hook 的客户端 IP。 diff --git a/package.json b/package.json index d60617d..9281371 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leanengine", - "version": "3.7.0", + "version": "3.8.0", "description": "LeanCloud LeanEngine Node.js SDK.", "repository": { "type": "git",