@co0ontty/wand 1.55.3 → 1.56.0-beta.g2e46e59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +4 -4
- package/dist/server.js +31 -8
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
3
|
-
"builtAt": "2026-06-
|
|
4
|
-
"version": "1.
|
|
5
|
-
"channel": "
|
|
2
|
+
"commit": "2e46e594067e5aa7e18fa2f21abf903482e46db8",
|
|
3
|
+
"builtAt": "2026-06-12T12:37:42.451Z",
|
|
4
|
+
"version": "1.56.0-beta.g2e46e59",
|
|
5
|
+
"channel": "beta"
|
|
6
6
|
}
|
package/dist/server.js
CHANGED
|
@@ -137,14 +137,23 @@ async function fetchGitHubLatestApk(forceRefresh = false) {
|
|
|
137
137
|
return cachedGitHubApk ?? null;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
function parseApkChannel(value) {
|
|
141
|
+
return value === "beta" ? "beta" : "stable";
|
|
142
|
+
}
|
|
143
|
+
/** 版本号带 prerelease 后缀(如 -debug.06121811)即视为 beta 构建。 */
|
|
144
|
+
function isPrereleaseApkVersion(version) {
|
|
145
|
+
return !!version && version.includes("-");
|
|
146
|
+
}
|
|
147
|
+
async function resolveLatestApkVersion(configDir, config, channel) {
|
|
141
148
|
// local 与 github 两个来源都看,按安装序取真正更新的那个(持平偏向 local:同源下载更快)。
|
|
142
149
|
// 旧逻辑是「local 存在就一票否决」——本地目录留着旧包时,会把线上新版压住不提示。
|
|
143
|
-
const localApk = await resolveAndroidApkAsset(configDir, config);
|
|
150
|
+
const localApk = await resolveAndroidApkAsset(configDir, config, channel);
|
|
144
151
|
const local = localApk && localApk.version
|
|
145
152
|
? {
|
|
146
153
|
version: localApk.version,
|
|
147
|
-
|
|
154
|
+
// 下载链接始终带通道参数,保证「提示的版本」和「下载到的文件」出自同一套过滤:
|
|
155
|
+
// 裸 /android/download(网页下载页、二维码落地页)默认 beta = 目录里真正最新的包。
|
|
156
|
+
downloadUrl: `${localApk.downloadUrl}?channel=${channel}`,
|
|
148
157
|
fileName: localApk.fileName,
|
|
149
158
|
size: localApk.size,
|
|
150
159
|
source: "local",
|
|
@@ -494,7 +503,7 @@ function resolveAndroidApkDir(configDir, config) {
|
|
|
494
503
|
function extractAndroidApkVersion(fileName) {
|
|
495
504
|
return extractSemver(fileName.replace(/\.apk$/i, ""));
|
|
496
505
|
}
|
|
497
|
-
async function resolveAndroidApkAsset(configDir, config) {
|
|
506
|
+
async function resolveAndroidApkAsset(configDir, config, channel = "beta") {
|
|
498
507
|
if (config.android?.enabled !== true)
|
|
499
508
|
return null;
|
|
500
509
|
const apkDir = resolveAndroidApkDir(configDir, config);
|
|
@@ -524,7 +533,7 @@ async function resolveAndroidApkAsset(configDir, config) {
|
|
|
524
533
|
const apkFiles = entries.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".apk"));
|
|
525
534
|
if (apkFiles.length === 0)
|
|
526
535
|
return null;
|
|
527
|
-
const
|
|
536
|
+
const allCandidates = await Promise.all(apkFiles.map(async (entry) => {
|
|
528
537
|
const filePath = path.join(apkDir, entry.name);
|
|
529
538
|
const fileStat = await stat(filePath);
|
|
530
539
|
return {
|
|
@@ -533,6 +542,13 @@ async function resolveAndroidApkAsset(configDir, config) {
|
|
|
533
542
|
fileStat,
|
|
534
543
|
};
|
|
535
544
|
}));
|
|
545
|
+
// 通道过滤:stable 只看正式版文件(无 prerelease 后缀的版本号),beta 全量。
|
|
546
|
+
// 无版本号的文件两个通道都保留(排序时本来就垫底,仅在只有它时兜底可下载)。
|
|
547
|
+
const candidates = channel === "beta"
|
|
548
|
+
? allCandidates
|
|
549
|
+
: allCandidates.filter((c) => !isPrereleaseApkVersion(extractAndroidApkVersion(c.entry.name)));
|
|
550
|
+
if (candidates.length === 0)
|
|
551
|
+
return null;
|
|
536
552
|
// 按版本号选"最新", 而非修改时间 —— cp/rsync/解压/checkout 都可能让低版本号文件的
|
|
537
553
|
// mtime 更新, 用 mtime 会把旧版本号当成 latest 上报。版本相同或都无版本号时退回 mtime。
|
|
538
554
|
// 注意用安装序比较(同三段时 debug > release,镜像 versionCode),不是标准 semver:
|
|
@@ -1076,9 +1092,11 @@ export async function startServer(config, configPath) {
|
|
|
1076
1092
|
res.status(400).json({ error: "Missing currentVersion query parameter." });
|
|
1077
1093
|
return;
|
|
1078
1094
|
}
|
|
1079
|
-
|
|
1095
|
+
// 更新通道:beta 包含 -debug.* 构建,stable(默认,含不传参的老客户端)只推正式版。
|
|
1096
|
+
const channel = parseApkChannel(req.query.channel);
|
|
1097
|
+
const latest = await resolveLatestApkVersion(configDir, config, channel);
|
|
1080
1098
|
if (!latest) {
|
|
1081
|
-
res.json({ updateAvailable: false, currentVersion, latestVersion: null, downloadUrl: null, source: null });
|
|
1099
|
+
res.json({ updateAvailable: false, currentVersion, latestVersion: null, downloadUrl: null, source: null, channel });
|
|
1082
1100
|
return;
|
|
1083
1101
|
}
|
|
1084
1102
|
// 安装序比较(镜像 versionCode),不是标准 semver:只在系统安装器真能装上时才提示,
|
|
@@ -1092,6 +1110,7 @@ export async function startServer(config, configPath) {
|
|
|
1092
1110
|
fileName: updateAvailable ? latest.fileName : null,
|
|
1093
1111
|
size: updateAvailable ? latest.size : null,
|
|
1094
1112
|
source: latest.source,
|
|
1113
|
+
channel,
|
|
1095
1114
|
releaseNotes: updateAvailable ? (latest.releaseNotes ?? null) : null,
|
|
1096
1115
|
});
|
|
1097
1116
|
});
|
|
@@ -1100,7 +1119,11 @@ export async function startServer(config, configPath) {
|
|
|
1100
1119
|
res.status(404).json({ error: "Android APK 下载未启用。" });
|
|
1101
1120
|
return;
|
|
1102
1121
|
}
|
|
1103
|
-
|
|
1122
|
+
// 更新弹窗的下载链接由 /api/android-apk-update 按通道生成(始终带 ?channel=)。
|
|
1123
|
+
// 裸 /android/download(网页下载页、二维码落地页)不带参时默认 beta ——
|
|
1124
|
+
// 保持「下载页拿到的就是目录里真正最新的包」的旧行为。
|
|
1125
|
+
const channel = req.query.channel === "stable" ? "stable" : "beta";
|
|
1126
|
+
const androidApk = await resolveAndroidApkAsset(configDir, config, channel);
|
|
1104
1127
|
if (!androidApk) {
|
|
1105
1128
|
res.status(404).json({ error: "当前没有可下载的 APK 文件。" });
|
|
1106
1129
|
return;
|