feat(api): Android self-update endpoints proxied from Gitea releases (M5)
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 43s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m12s
ci / api / api (push) Successful in 35s
ci / ts / ts (packages + web) (push) Successful in 1m20s

GET /api/v1/app/android/latest reads the latest Gitea release with the
server token (cached for 10 minutes); the download endpoint caches the
APK under /updates, verifies its SHA-256 and serves it with Range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-20 12:52:41 +03:00
1 parent 9fd616da57
commit 6a67c27f50
10 files changed
+940 -173

No files matched your search

@@ -882,6 +882,44 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/v1/app/android/latest": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Последняя версия Android-приложения (из релизов Gitea через сервер)
* @description Сервер сам опрашивает Gitea своим токеном и кэширует ответ на 10 минут, поэтому приложению
* не нужен доступ к Gitea. Нет настроек Gitea или релиза с APK — `404 app.update_unavailable`.
*/
get: operations["getAndroidLatest"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/app/android/download/{version}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** APK версии (кэшируется на сервере, поддерживает Range для докачки) */
get: operations["downloadAndroidApk"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
}
export type webhooks = Record<string, never>;
export interface components {
@@ -1446,6 +1484,19 @@ export interface components {
like_rate: number | null;
sessions: number;
};
AndroidRelease: {
/** @example 0.6.1 */
version: string;
version_code: number;
/** @description Что нового (Markdown из релиза) */
notes_md: string;
/** Format: int64 */
size: number;
sha256: string;
download_url: string;
/** @description Версии ниже обязаны обновиться */
min_supported: number;
};
Session: {
/** Format: uuid */
id: string;
@@ -2841,4 +2892,48 @@ export interface operations {
default: components["responses"]["Problem"];
};
};
getAndroidLatest: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Последний релиз */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AndroidRelease"];
};
};
default: components["responses"]["Problem"];
};
};
downloadAndroidApk: {
parameters: {
query?: never;
header?: never;
path: {
version: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description APK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/vnd.android.package-archive": string;
};
};
default: components["responses"]["Problem"];
};
};
}
+3
View File
@@ -71,5 +71,8 @@
},
"wave": {
"session_not_found": "The wave session has ended"
},
"app": {
"update_unavailable": "Update is unavailable"
}
}
+3
View File
@@ -71,5 +71,8 @@
},
"wave": {
"session_not_found": "Сессия волны завершена"
},
"app": {
"update_unavailable": "Обновление недоступно"
}
}