UNPKG

cloudbase-accesstoken-cache

Version:

cloudbase-accesstoken-cache , use cloudbase database to manager your accesstoken easily !

151 lines (148 loc) 4.78 kB
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 };