cloudbase-accesstoken-cache
Version:
cloudbase-accesstoken-cache , use cloudbase database to manager your accesstoken easily !
151 lines (148 loc) • 4.78 kB
JavaScript
import http from 'http';
import https from 'https';
import { URL } from 'url';
class SingleCacheManager {
constructor(config) {
var _a, _b;
this.appid = config.appid;
this.db = config.db;
this.secret = config.secret;
this.collectionName = (_a = config.collectionName) !== null && _a !== void 0 ? _a : 'accessToken';
this.tokenCol = this.db.collection(this.collectionName);
this.memoize = (_b = config.memoize) !== null && _b !== void 0 ? _b : true;
}
getAccessTokenByHttp() {
return new Promise((resolve, reject) => {
const url = new URL(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appid}&secret=${this.secret}`);
const protocol = url.protocol === 'https:' ? https : http;
protocol
.get(url, (res) => {
var _a;
const { statusCode } = res;
const contentType = (_a = res.headers['content-type']) !== null && _a !== void 0 ? _a : 'application/json';
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' + `Status Code: ${statusCode}`);
}
else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
res.resume();
return;
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => {
rawData += chunk;
});
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
}
catch (e) {
reject(e);
}
});
})
.on('error', (e) => {
reject(e);
});
});
}
/**
* 强制通过 http 请求获取 AccessToken (旧的会过期)
*/
forceGetAccessTokenByHttp() {
return this.getAccessTokenByHttp();
}
/**
* 创建此 Collection
*/
createCollection() {
return this.db.createCollection(this.collectionName);
}
// isExpired () {
// }
// async flush () {}
async createCacheItem(ts) {
const { appid } = this;
const data = await this.getAccessTokenByHttp();
const item = {
appid,
accessToken: data.access_token,
expiresIn: ts + data.expires_in * 1000
};
return item;
}
/**
* 远端策略
* @returns
*/
async remoteStrategy() {
const { tokenCol, memoize } = this;
const { data } = await tokenCol
.where({
appid: this.appid
})
.limit(1)
.get();
const ts = Date.now();
if (data.length) {
const hit = data[0];
if (ts < hit.expiresIn) {
return hit.accessToken;
}
else {
const item = await this.createCacheItem(ts);
await tokenCol.doc(hit._id).update(item);
if (memoize) {
this.cache = item;
}
return item.accessToken;
}
}
else {
const item = await this.createCacheItem(ts);
await tokenCol.add(item);
if (memoize) {
this.cache = item;
}
return item.accessToken;
}
}
/**
* 内存策略
* @returns
*/
async memoizeStrategy() {
const { cache } = this;
const ts = Date.now();
if (cache) {
if (ts < cache.expiresIn) {
return cache.accessToken;
}
else {
return await this.remoteStrategy();
}
}
else {
return await this.remoteStrategy();
}
}
/**
* 调用时,请确保 Collection 存在,如果不存在请调用 createCollection
*/
async getAccessToken() {
if (this.memoize) {
return await this.memoizeStrategy();
}
else {
return await this.remoteStrategy();
}
}
}
export { SingleCacheManager };