Skip to content

Commit 8261808

Browse files
authored
feat: app router 2 and redesigned config APIs (#463)
* feat: support app router 2 and redesigned config APIs * fix(Insight): pick #464 * fix: skip refreshing if approuter disabled * docs: AV.init/AV.setServerURLs/AV.request * refactor(AppRouter): make disabled a property of AppRouter * fix(AppRouter): change default serverURLs * feat(AppRouter): use service urls for push and cloudfunction * fix: lowercase default server urls
1 parent 8d5d756 commit 8261808

File tree

18 files changed

+533
-444
lines changed

18 files changed

+533
-444
lines changed

src/app-router.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const {
2+
ajax,
3+
} = require('./utils');
4+
const Cache = require('./cache');
5+
6+
function AppRouter(AV) {
7+
this.AV = AV;
8+
this.lockedUntil = 0;
9+
Cache.getAsync('serverURLs').then(data => {
10+
if (!data) return this.lock(0);
11+
const {
12+
serverURLs,
13+
lockedUntil,
14+
} = data;
15+
this.AV._setServerURLs(serverURLs, false);
16+
this.lockedUntil = lockedUntil;
17+
}).catch(() => this.lock(0));
18+
}
19+
20+
AppRouter.prototype.disable = function disable() {
21+
this.disabled = true;
22+
};
23+
AppRouter.prototype.lock = function lock(ttl) {
24+
this.lockedUntil = Date.now() + ttl;
25+
};
26+
AppRouter.prototype.refresh = function refresh() {
27+
if (this.disabled) return;
28+
if (Date.now() < this.lockedUntil) return;
29+
this.lock(10);
30+
const url = 'https://app-router.leancloud.cn/2/route';
31+
return ajax({
32+
method: 'get',
33+
url,
34+
query: {
35+
appId: this.AV.applicationId,
36+
},
37+
}).then(servers => {
38+
if (this.disabled) return;
39+
let ttl = servers.ttl;
40+
if (!ttl) throw new Error('missing ttl');
41+
ttl = ttl * 1000;
42+
const protocal = 'https://';
43+
const serverURLs = {
44+
push: protocal + servers.push_server,
45+
stats: protocal + servers.stats_server,
46+
engine: protocal + servers.engine_server,
47+
api: protocal + servers.api_server,
48+
};
49+
this.AV._setServerURLs(serverURLs, false);
50+
this.lock(ttl);
51+
return Cache.setAsync('serverURLs', {
52+
serverURLs,
53+
lockedUntil: this.lockedUntil,
54+
}, ttl);
55+
}).catch(error => {
56+
// bypass all errors
57+
console.warn(`refresh server URLs failed: ${error.message}`);
58+
this.lock(600);
59+
});
60+
};
61+
62+
module.exports = AppRouter;

src/av.js

Lines changed: 8 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,25 @@
11
const _ = require('underscore');
22
const userAgent = require('./ua');
33
const {
4-
isNullOrUndefined,
4+
inherits,
5+
parseDate,
56
} = require('./utils');
67

78
const AV = global.AV || {};
89

910
// All internal configuration items
10-
AV._config = AV._config || {};
11-
const AVConfig = AV._config;
12-
13-
_.extend(AVConfig, {
14-
15-
// 服务器节点地区,默认中国大陆
16-
region: 'cn',
17-
18-
// 服务器的 URL,默认初始化时被设置为大陆节点地址
19-
APIServerURL: AVConfig.APIServerURL || '',
20-
21-
// 禁用 currentUser,通常用于多用户环境
22-
disableCurrentUser: false,
23-
24-
// Internal config can modifie the UserAgent
11+
AV._config = {
2512
userAgent,
26-
27-
// set production environment or test environment
28-
// 1: production environment, 0: test environment, null: default environment
29-
applicationProduction: null,
30-
});
13+
serverURLs: {},
14+
useMasterKey: false,
15+
production: null,
16+
};
3117

3218
/**
3319
* Contains all AV API classes and functions.
3420
* @namespace AV
3521
*/
3622

37-
// Helpers
38-
// -------
39-
40-
// Shared empty constructor function to aid in prototype-chain creation.
41-
var EmptyConstructor = function() {};
42-
43-
// Helper function to correctly set up the prototype chain, for subclasses.
44-
// Similar to `goog.inherits`, but uses a hash of prototype properties and
45-
// class properties to be extended.
46-
var inherits = function(parent, protoProps, staticProps) {
47-
var child;
48-
49-
// The constructor function for the new subclass is either defined by you
50-
// (the "constructor" property in your `extend` definition), or defaulted
51-
// by us to simply call the parent's constructor.
52-
if (protoProps && protoProps.hasOwnProperty('constructor')) {
53-
child = protoProps.constructor;
54-
} else {
55-
/** @ignore */
56-
child = function(){ parent.apply(this, arguments); };
57-
}
58-
59-
// Inherit class (static) properties from parent.
60-
_.extend(child, parent);
61-
62-
// Set the prototype chain to inherit from `parent`, without calling
63-
// `parent`'s constructor function.
64-
EmptyConstructor.prototype = parent.prototype;
65-
child.prototype = new EmptyConstructor();
66-
67-
// Add prototype properties (instance properties) to the subclass,
68-
// if supplied.
69-
if (protoProps) {
70-
_.extend(child.prototype, protoProps);
71-
}
72-
73-
// Add static properties to the constructor function, if supplied.
74-
if (staticProps) {
75-
_.extend(child, staticProps);
76-
}
77-
78-
// Correctly set child's `prototype.constructor`.
79-
child.prototype.constructor = child;
80-
81-
// Set a convenience property in case the parent's prototype is
82-
// needed later.
83-
child.__super__ = parent.prototype;
84-
85-
return child;
86-
};
87-
88-
/**
89-
* Call this method to set production environment variable.
90-
* @function AV.setProduction
91-
* @param {Boolean} production True is production environment,and
92-
* it's true by default.
93-
*/
94-
AV.setProduction = (production) => {
95-
if (!isNullOrUndefined(production)) {
96-
AVConfig.applicationProduction = production ? 1 : 0;
97-
} else {
98-
// change to default value
99-
AVConfig.applicationProduction = null;
100-
}
101-
};
102-
10323
/**
10424
* Returns prefix for localStorage keys used by this instance of AV.
10525
* @param {String} path The relative suffix to append to it.
@@ -158,26 +78,7 @@ AV._getInstallationId = function() {
15878
});
15979
};
16080

161-
AV._parseDate = function(iso8601) {
162-
var regexp = new RegExp(
163-
"^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})" + "T" +
164-
"([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})" +
165-
"(.([0-9]+))?" + "Z$");
166-
var match = regexp.exec(iso8601);
167-
if (!match) {
168-
return null;
169-
}
170-
171-
var year = match[1] || 0;
172-
var month = (match[2] || 1) - 1;
173-
var day = match[3] || 0;
174-
var hour = match[4] || 0;
175-
var minute = match[5] || 0;
176-
var second = match[6] || 0;
177-
var milli = match[8] || 0;
178-
179-
return new Date(Date.UTC(year, month, day, hour, minute, second, milli));
180-
};
81+
AV._parseDate = parseDate;
18182

18283
// A self-propagating extend function.
18384
AV._extend = function(protoProps, classProps) {
@@ -186,15 +87,6 @@ AV._extend = function(protoProps, classProps) {
18687
return child;
18788
};
18889

189-
// Helper function to get a value from a Backbone object as a property
190-
// or as a function.
191-
AV._getValue = function(object, prop) {
192-
if (!(object && object[prop])) {
193-
return null;
194-
}
195-
return _.isFunction(object[prop]) ? object[prop]() : object[prop];
196-
};
197-
19890
/**
19991
* Converts a value in a AV Object into the appropriate representation.
20092
* This is the JS equivalent of Java's AV.maybeReferenceAndEncode(Object)

src/cache.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const getCacheData = (cacheData, key) => {
2020
};
2121

2222
exports.getAsync = (key) => {
23-
key = `${AV.applicationId}/${key}`;
23+
key = `AV/${AV.applicationId}/${key}`;
2424
return storage.getItemAsync(key)
2525
.then(cache => getCacheData(cache, key));
2626
};
@@ -31,7 +31,7 @@ exports.setAsync = (key, value, ttl) => {
3131
cache.expiredAt = Date.now() + ttl;
3232
}
3333
return storage.setItemAsync(
34-
`${AV.applicationId}/${key}`,
34+
`AV/${AV.applicationId}/${key}`,
3535
JSON.stringify(cache)
3636
);
3737
};

src/cloudfunction.js

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const _ = require('underscore');
2-
const AVRequest = require('./request').request;
2+
const { _request, request } = require('./request');
33

44
module.exports = function(AV) {
55
/**
@@ -21,11 +21,14 @@ module.exports = function(AV) {
2121
* @return {Promise} A promise that will be resolved with the result
2222
* of the function.
2323
*/
24-
run: function(name, data, options) {
25-
var request = AVRequest('functions', name, null, 'POST',
26-
AV._encode(data, null, true), options);
27-
28-
return request.then(function(resp) {
24+
run(name, data, options) {
25+
return request({
26+
service: 'engine',
27+
method: 'POST',
28+
path: `/functions/${name}`,
29+
data: AV._encode(data, null, true),
30+
authOptions: options,
31+
}).then((resp) => {
2932
return AV._decode(resp).result;
3033
});
3134
},
@@ -38,12 +41,18 @@ module.exports = function(AV) {
3841
* @param {AuthOptions} options
3942
* @return {Promise} A promise that will be resolved with the result of the function.
4043
*/
41-
rpc: function(name, data, options) {
44+
rpc(name, data, options) {
4245
if (_.isArray(data)) {
4346
return Promise.reject(new Error('Can\'t pass Array as the param of rpc function in JavaScript SDK.'));
4447
}
4548

46-
return AVRequest('call', name, null, 'POST', AV._encodeObjectOrArray(data), options).then(function(resp) {
49+
return request({
50+
service: 'engine',
51+
method: 'POST',
52+
path: `/call/${name}`,
53+
data: AV._encodeObjectOrArray(data),
54+
authOptions: options,
55+
}).then((resp) => {
4756
return AV._decode(resp).result;
4857
});
4958
},
@@ -54,10 +63,8 @@ module.exports = function(AV) {
5463
* of the function.
5564
* @since 0.5.9
5665
*/
57-
getServerDate: function() {
58-
var request = AVRequest("date", null, null, 'GET');
59-
60-
return request.then(function(resp) {
66+
getServerDate() {
67+
return _request("date", null, null, 'GET').then(function(resp) {
6168
return AV._decode(resp);
6269
});
6370
},
@@ -69,16 +76,15 @@ module.exports = function(AV) {
6976
* @return {Promise} A promise that will be resolved with the result
7077
* of the function.
7178
*/
72-
requestSmsCode: function(data){
79+
requestSmsCode(data) {
7380
if(_.isString(data)) {
7481
data = { mobilePhoneNumber: data };
7582
}
7683
if(!data.mobilePhoneNumber) {
7784
throw new Error('Missing mobilePhoneNumber.');
7885
}
79-
var request = AVRequest("requestSmsCode", null, null, 'POST',
86+
return _request("requestSmsCode", null, null, 'POST',
8087
data);
81-
return request;
8288
},
8389

8490
/**
@@ -88,17 +94,16 @@ module.exports = function(AV) {
8894
* @return {Promise} A promise that will be resolved with the result
8995
* of the function.
9096
*/
91-
verifySmsCode: function(code, phone){
97+
verifySmsCode(code, phone) {
9298
if(!code)
9399
throw new Error('Missing sms code.');
94100
var params = {};
95101
if(_.isString(phone)) {
96102
params['mobilePhoneNumber'] = phone;
97103
}
98104

99-
var request = AVRequest("verifySmsCode", code, null, 'POST',
105+
return _request("verifySmsCode", code, null, 'POST',
100106
params);
101-
return request;
102107
}
103108
});
104109
};

src/file.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const cos = require('./uploader/cos');
33
const qiniu = require('./uploader/qiniu');
44
const s3 = require('./uploader/s3');
55
const AVError = require('./error');
6-
const AVRequest = require('./request').request;
6+
const AVRequest = require('./request')._request;
77
const Promise = require('./promise');
88
const { tap } = require('./utils');
99
const debug = require('debug')('leancloud:file');

0 commit comments

Comments
 (0)