GET /app-version читает манифест с диска (data/app-version.json, путь — env
APP_VERSION_FILE) → {android:{version_name,version_code,download_url,force_update,
sha256,notes}}. Релиз = заменить APK в /downloads + отредактировать json, без
пересборки. При сбое файла отдаёт version_code:0 (апдейт не навязываем).
Статика /downloads/ (DOWNLOADS_DIR) — раздаёт APK.
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
import { Controller, Get, Logger } from '@nestjs/common';
|
||
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||
import * as fs from 'fs';
|
||
import * as path from 'path';
|
||
|
||
interface PlatformVersion {
|
||
version_name: string;
|
||
version_code: number;
|
||
download_url: string;
|
||
force_update: boolean;
|
||
sha256?: string;
|
||
notes?: string;
|
||
}
|
||
|
||
/**
|
||
* Манифест последней версии приложения для авто-обновления (как в nkVPN).
|
||
* Читается с диска при каждом запросе, поэтому релиз = заменить APK в /downloads
|
||
* и отредактировать data/app-version.json — без пересборки бэкенда.
|
||
* Путь к файлу — env APP_VERSION_FILE, иначе data/app-version.json.
|
||
*/
|
||
@ApiTags('app-version')
|
||
@Controller('app-version')
|
||
export class AppVersionController {
|
||
private readonly logger = new Logger(AppVersionController.name);
|
||
private readonly file =
|
||
process.env.APP_VERSION_FILE ||
|
||
path.join(process.cwd(), 'data', 'app-version.json');
|
||
|
||
@Get()
|
||
@ApiOperation({ summary: 'Манифест последней версии приложения' })
|
||
getVersion(): { android: PlatformVersion } {
|
||
try {
|
||
const raw = fs.readFileSync(this.file, 'utf-8');
|
||
return JSON.parse(raw) as { android: PlatformVersion };
|
||
} catch (e) {
|
||
this.logger.warn(`app-version.json недоступен: ${(e as Error).message}`);
|
||
// Безопасный фолбэк: version_code 0 ⇒ установленное приложение (code ≥ 1)
|
||
// никогда не увидит «обновление», т.е. при сбое файла апдейт не навязываем.
|
||
return {
|
||
android: {
|
||
version_name: '0',
|
||
version_code: 0,
|
||
download_url: '',
|
||
force_update: false,
|
||
},
|
||
};
|
||
}
|
||
}
|
||
}
|