feat/api-prox: add index and health pages

This commit is contained in:
Kentai Radiquum 2025-09-05 22:33:40 +05:00
parent 033b7fdea5
commit ec938960cb
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
4 changed files with 146 additions and 6 deletions

1
api-prox/src/config.json Normal file
View file

@ -0,0 +1 @@
{"appVersion": "0.0.1"}

View file

@ -1,9 +1,60 @@
import { Hono } from 'hono' import { Hono } from "hono";
import { asciiHTML, separatorHTML } from "./utils/info.js";
import config from "./config.json" with { type: "json" };
const app = new Hono() const app = new Hono();
app.get('/', (c) => { app.get("/", (c) => {
return c.text('Hello Hono!') return c.html(`
}) <!Doctype html>
<html lang="en" style="font-family: monospace; background-color: black; color: white;">
<head></head>
<body>
<style>
ul{list-style:none;padding-left:1rem;font-size:16px}
p{font-size:14px}
li::before{content:">";color:white;display:inline-block;width:1.25rem;margin-left:-1rem;margin-bottom:0.25rem;}
a,a:visited{color:white;}
a:hover{color:gray;}
</style>
<script>
window.onload = () => {deploy_url.textContent = window.location;}
</script>
${asciiHTML()}
${separatorHTML()}
<p>To get started, modify your apk to use <span id="deploy_url">unknown</span>[endpoint] or deploy the AniX web client</p>
${separatorHTML()}
<ul>
<li>Developer: <a href="https://wah.su/radiquum">Radiquum</a></li>
<li>Repository: <a href="https://github.com/Radiquum/AniX">https://github.com/Radiquum/AniX</a></li>
</ul>
</body>
</html>
`);
});
export default app app.get("/health", (c) => {
return c.html(`
<!Doctype html>
<html lang="en" style="font-family: monospace; background-color: black; color: white;">
<head></head>
<body>
<style>
p{font-size:14px;margin-bottom:-0.5rem;}
a,a:visited{color:white;}
a:hover{color:gray;}
</style>
${asciiHTML()}
${separatorHTML()}
<p id="status">Status: OK</p>
<p>Version: ${config.appVersion}</p>
</body>
</html>
`);
});
app.get("/health/json", (c) => {
return c.json({"status": "OK", "version": config.appVersion});
});
export default app;

View file

@ -0,0 +1,27 @@
// ___ _ __ ___ ____ ____ ____
// / | ____ (_) ______ ______/ /_ / | / __ \/ _/ / __ \_________ _ ____ __
// / /| | / __ \/ / |/_/ __ `/ ___/ __/ / /| | / /_/ // / / /_/ / ___/ __ \| |/_/ / / /
// / ___ |/ / / / /> </ /_/ / / / /_ / ___ |/ ____// / / ____/ / / /_/ /> </ /_/ /
// /_/ |_/_/ /_/_/_/|_|\__,_/_/ \__/ /_/ |_/_/ /___/ /_/ /_/ \____/_/|_|\__, /
// /____/
export function asciiHTML() {
const stringBuilder = [];
stringBuilder.push(`<pre>`);
stringBuilder.push(" ___ _ __ ___ ____ ____ ____ ")
stringBuilder.push(" / | ____ (_) ______ ______/ /_ / | / __ \\/ _/ / __ \\_________ _ ____ __")
stringBuilder.push(" / /| | / __ \\/ / |/_/ __ `/ ___/ __/ / /| | / /_/ // / / /_/ / ___/ __ \\| |/_/ / / /")
stringBuilder.push(" / ___ |/ / / / /&gt; &lt;/ /_/ / / / /_ / ___ |/ ____// / / ____/ / / /_/ /&gt; &lt;/ /_/ /")
stringBuilder.push("/_/ |_/_/ /_/_/_/|_|\\__,_/_/ \\__/ /_/ |_/_/ /___/ /_/ /_/ \\____/_/|_|\\__, /")
stringBuilder.push(" /____/")
stringBuilder.push(`</pre>`);
return stringBuilder.join("\n");
}
export function separatorHTML() {
const stringBuilder = [];
stringBuilder.push(`<pre>`);
stringBuilder.push("-".repeat(92))
stringBuilder.push(`</pre>`);
return stringBuilder.join("\n");
}

View file

@ -0,0 +1,61 @@
type Success<T> = {
data: T;
error: null;
};
type Failure<E> = {
data: null;
error: E;
};
type Result<T, E = Error> = Success<T> | Failure<E>;
export async function tryCatch<T, E = Error>(
promise: Promise<T>
): Promise<Result<T, E>> {
try {
const data = await promise;
return { data, error: null };
} catch (error) {
return { data: null, error: error as E };
}
}
function generateError(message: string, code: number) {
return {message: message, code: code}
}
export async function tryCatchAPI<T, E = Error>(
promise: Promise<any>
): Promise<Result<object | null, object | null>> {
const { data, error }: Awaited<Result<Response | null, Error | null>> = await tryCatch(promise);
if (!data || error) return { data: null, error: error };
if (
data.headers.get("content-length") &&
Number(data.headers.get("content-length")) == 0
) {
return {
data: null,
error: generateError("Not Found", 404),
};
}
try {
const body: Awaited<any> = await data.json();
if (body.code != 0) {
return {
data: null,
error: generateError("Anixart API Error", body.code),
};
}
return {
data: body,
error: null,
};
} catch {
return { data: null, error: generateError("failed to parse json", 500) }
}
return { data: null, error: generateError("tryCatch.ts: unreachable", 500) }
}