160 lines
5.2 KiB
JavaScript
160 lines
5.2 KiB
JavaScript
'use strict';
|
||
|
||
const platformAndroid = 'Android';
|
||
const platformIOS = 'iOS';
|
||
const platformHarmony = 'Harmony';
|
||
const packageApp = 'native_app';
|
||
const packageWgt = 'wgt';
|
||
const appVersionDbName = 'opendb-app-versions';
|
||
|
||
function errorResult(code, message) {
|
||
return { code, message };
|
||
}
|
||
|
||
function isNonEmptyString(value) {
|
||
return typeof value === 'string' && value.trim().length > 0;
|
||
}
|
||
|
||
function isValidVersion(value) {
|
||
return isNonEmptyString(value) && /^\d+(?:\.\d+)*$/.test(value.trim());
|
||
}
|
||
|
||
function parseHttpEvent(event) {
|
||
if (!event || typeof event !== 'object' || Array.isArray(event)) {
|
||
return { error: errorResult(-102, '请求参数必须是对象') };
|
||
}
|
||
if (!event.headers) return { data: event, isHttp: false };
|
||
|
||
const method = String(event.httpMethod || 'GET').toLowerCase();
|
||
let body;
|
||
try {
|
||
if (method === 'get') {
|
||
body = event.queryStringParameters || {};
|
||
if (typeof body === 'string') body = JSON.parse(body || '{}');
|
||
} else if (event.body && typeof event.body === 'object') {
|
||
body = event.body;
|
||
} else {
|
||
body = JSON.parse(event.body || '{}');
|
||
}
|
||
} catch (e) {
|
||
return { error: errorResult(-102, '请求参数格式错误') };
|
||
}
|
||
if (!body || typeof body !== 'object' || Array.isArray(body)) {
|
||
return { error: errorResult(-102, '请求参数必须是对象') };
|
||
}
|
||
|
||
return {
|
||
data: { ...event, ...body },
|
||
isHttp: true
|
||
};
|
||
}
|
||
|
||
function detectPlatform(event, context, isHttp) {
|
||
if (isHttp) {
|
||
const headers = typeof event.headers === 'string' ?
|
||
event.headers : JSON.stringify(event.headers || {});
|
||
if (/iPhone|iPad/i.test(headers)) return platformIOS;
|
||
if (/Android/i.test(headers)) return platformAndroid;
|
||
if (/HarmonyOS|Harmony/i.test(headers)) return platformHarmony;
|
||
}
|
||
|
||
const os = context && typeof context.OS === 'string' ? context.OS.toLowerCase() : '';
|
||
if (os === 'ios') return platformIOS;
|
||
if (os === 'harmonyos') return platformHarmony;
|
||
return platformAndroid;
|
||
}
|
||
|
||
module.exports = async (event, context) => {
|
||
const parsed = parseHttpEvent(event);
|
||
if (parsed.error) return parsed.error;
|
||
|
||
const request = parsed.data;
|
||
const appid = request.appid;
|
||
const appVersion = request.appVersion;
|
||
const wgtVersion = request.wgtVersion;
|
||
const isUniappX = request.is_uniapp_x === undefined ? false : request.is_uniapp_x;
|
||
if (!isNonEmptyString(appid) || !isValidVersion(appVersion) || !isValidVersion(wgtVersion)) {
|
||
return errorResult(-102, '请检查appid、appVersion、wgtVersion是否填写正确');
|
||
}
|
||
if (isUniappX !== true && isUniappX !== false) {
|
||
return errorResult(-102, 'is_uniapp_x必须是布尔值');
|
||
}
|
||
|
||
const platform = detectPlatform(request, context, parsed.isHttp);
|
||
try {
|
||
const collection = uniCloud.database().collection(appVersionDbName);
|
||
const record = await collection.where({
|
||
appid: appid.trim(),
|
||
platform,
|
||
stable_publish: true
|
||
}).orderBy('create_date', 'desc').get();
|
||
|
||
if (!record || !Array.isArray(record.data) || record.data.length === 0) {
|
||
return errorResult(-101, '暂无更新或检查appid是否填写正确');
|
||
}
|
||
|
||
const appVersionInDb = record.data.find(item => item && item.type === packageApp) || {};
|
||
const wgtVersionInDb = record.data.find(item => item && item.type === packageWgt) || {};
|
||
const hasAppPackage = isValidVersion(appVersionInDb.version);
|
||
const hasWgtPackage = isValidVersion(wgtVersionInDb.version);
|
||
|
||
let stablePublishDb = {};
|
||
if (isUniappX === true && platform === platformAndroid) {
|
||
if (hasAppPackage) stablePublishDb = appVersionInDb;
|
||
} else if (hasAppPackage && hasWgtPackage) {
|
||
stablePublishDb = compare(wgtVersionInDb.version, appVersionInDb.version) >= 0 ?
|
||
wgtVersionInDb : appVersionInDb;
|
||
} else if (hasAppPackage) {
|
||
stablePublishDb = appVersionInDb;
|
||
} else if (hasWgtPackage) {
|
||
stablePublishDb = wgtVersionInDb;
|
||
}
|
||
|
||
if (Object.keys(stablePublishDb).length > 0) {
|
||
const { version, min_uni_version: minUniVersion } = stablePublishDb;
|
||
const appUpdate = compare(version, appVersion) === 1;
|
||
const wgtUpdate = compare(version, wgtVersion) === 1;
|
||
|
||
if (appUpdate && wgtUpdate) {
|
||
if (isValidVersion(minUniVersion) && compare(minUniVersion, appVersion) < 1) {
|
||
return {
|
||
code: 101,
|
||
message: 'wgt更新',
|
||
...stablePublishDb
|
||
};
|
||
}
|
||
if (hasAppPackage && compare(appVersionInDb.version, appVersion) === 1) {
|
||
return {
|
||
code: 102,
|
||
message: '整包更新',
|
||
...appVersionInDb
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
return { code: 0, message: '当前版本已经是最新的,不需要更新' };
|
||
} catch (e) {
|
||
console.error('[checkVersion]', e);
|
||
return errorResult(-500, '检查版本失败');
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 对比版本号。v1 > v2 返回 1,v1 < v2 返回 -1,版本相同返回 0。
|
||
*/
|
||
function compare(v1 = '0', v2 = '0') {
|
||
const left = String(v1).split('.').map(Number);
|
||
const right = String(v2).split('.').map(Number);
|
||
const length = Math.max(left.length, right.length);
|
||
for (let i = 0; i < length; i++) {
|
||
const leftPart = Number.isFinite(left[i]) ? left[i] : 0;
|
||
const rightPart = Number.isFinite(right[i]) ? right[i] : 0;
|
||
if (leftPart > rightPart) return 1;
|
||
if (leftPart < rightPart) return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
module.exports.compare = compare;
|