const fs = require('fs') const os = require('os') const path = require('path') class Upate { constructor () { this._https = null this._crypto = null this._interval = this.DEFAULT_INTERVAL this._platform = process.env.UNI_PLATFORM this._fileData = {} this._compilerVersion = '' this._isAlpha = false this._uniId = '' this._appId = '' } get uniId () { return this._uniId } set uniId (value) { this._uniId = value } get appId () { return this._appId } set appId (value) { this._appId = value } get compilerVersion () { return this._compilerVersion } set compilerVersion (value) { this._compilerVersion = value } get isAlpha () { return this._isAlpha } set isAlpha (value) { this._isAlpha = value } get versionType () { return (this.isAlpha ? 'a' : 'r') } get https () { if (this._https == null) { this._https = require('https') } return this._https } get crypto () { if (this._crypto == null) { this._crypto = require('crypto') } return this._crypto } getBuildType () { return (process.env.NODE_ENV === 'production' ? 'build' : 'dev') } async check () { await this.readFile() const fileData = this._fileData const currentDate = Date.now() if (!fileData.lastCheck || (Math.abs(currentDate - fileData.lastCheck) > this._interval)) { this._fileData.lastCheck = currentDate this.checkUpdate() } else { if (fileData.newVersion && fileData.newVersion !== this.compilerVersion) { console.log() console.log(fileData.note) } } await this.update() } async readFile () { const filePath = await this.getFilePath() let fileData = {} if (fs.existsSync(filePath)) { fileData = require(filePath) } else { fileData.vid = this._buildUUID() } if (!fileData[this._platform]) { fileData[this._platform] = {} } this._fileData = fileData } async update () { const bt = this.getBuildType() const info = this._fileData[this._platform] const count = parseInt(info[bt] || 0) info[bt] = (count + 1) this.writeFile() } async writeFile (file) { try { const filePath = await this.getFilePath() const content = JSON.stringify(file || this._fileData) fs.writeFileSync(filePath, content, 'utf8') } catch (error) { } } checkUpdate () { const postData = JSON.stringify({ id: this.getPostData() }) var responseData = '' const req = this.https.request({ hostname: this.HOST, path: this.PATH, port: 443, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': postData.length } }, (res) => { res.setEncoding('utf8') res.on('data', (chunk) => { responseData += chunk }) res.on('end', () => { this.checkUpdateSuccess(JSON.parse(responseData)) }) }) req.write(postData) req.end() } getPostData () { var data = JSON.parse(JSON.stringify(this._fileData)) data.device = this._getMD5(this._getMac()) data.appid = this.uniId data.vtype = this.versionType data.vcode = this.compilerVersion delete data.lastCheck if (this.appId) { data[this._platform].appid = this.appId } if (data.appid) { delete data.vid } else { delete data.appid } return JSON.stringify(data) } checkUpdateSuccess (data) { if (data.code !== 0) { return } var fileData = { vid: this._fileData.vid, lastCheck: this._fileData.lastCheck } if (data.isUpdate === true) { fileData.newVersion = data.newVersion fileData.note = data.note } this.writeFile(fileData) } async getFilePath () { const rootDir = os.tmpdir() const fileName = this._getMD5(process.env.UNI_INPUT_DIR) return path.join(rootDir, `${this.UPDATE_FILE_NAME}_${fileName}.json`) } _getMac () { let mac const network = os.networkInterfaces() for (const key in network) { const array = network[key] for (let i = 0; i < array.length; i++) { const item = array[i] if (!item.family || (item.mac && item.mac === '00:00:00:00:00:00')) { continue } if (item.family === 'IPv4' || item.family === 'IPv6') { mac = item.mac break } } } return mac } _getMD5 (str) { return this.crypto.createHash('md5').update(str).digest('hex') } _buildUUID () { var result = '' for (let i = 0; i < 4; i++) { result += (65536 * (1 + Math.random()) | 0).toString(16).substring(1) } return 'UNI_' + result.toUpperCase() } } Object.assign(Upate.prototype, { HOST: 'uniapp.dcloud.net.cn', PATH: '/update/cli', UPDATE_FILE_NAME: 'uni_app_cli_update', DEFAULT_TIME: 2000, DEFAULT_INTERVAL: 1000 * 60 * 60 * 24 }) module.exports = async function checkUpdate () { const { isInHBuilderX, getManifestJson } = require('@dcloudio/uni-cli-shared') if (isInHBuilderX) { // 仅 cli 提供检测更新 return } const plp = require('@dcloudio/webpack-uni-pages-loader/package.json') const ppj = require(path.join(process.env.UNI_CLI_CONTEXT, 'package.json')) const manifest = getManifestJson() try { const update = new Upate() update.compilerVersion = plp['uni-app'].compilerVersion update.isAlpha = ppj.devDependencies['@dcloudio/vue-cli-plugin-uni'].includes('alpha') update.uniId = manifest.appid const appIdKey = process.env.UNI_PLATFORM.includes('quickapp') ? 'package' : 'appid' update.appId = manifest[process.env.UNI_PLATFORM] ? (manifest[process.env.UNI_PLATFORM][appIdKey] || '') : '' update.check() } catch (e) { } }