all repos — stealth-developers @ 55e75f334ae0c5ba6067a5fd2c5ac161e526e2e7

api: serve frontend
vi did:web:vt3e.cat
Tue, 30 Jun 2026 19:33:54 +0100
commit

55e75f334ae0c5ba6067a5fd2c5ac161e526e2e7

parent

09320bf1c9710283bf986fc7672703b96918c031

M apps/api/package.jsonapps/api/package.json

@@ -14,6 +14,7 @@ "dependencies": {

"@elysia/cors": "^1.4.2", "@elysia/openapi": "^1.4.15", "@elysia/server-timing": "^1.4.1", + "@elysia/static": "^1.4.11", "@purrkit/ratelimit": "^1.0.1", "@purrkit/rest": "^1.1.2", "@purrkit/types": "^1.1.1",
M apps/api/src/app.tsapps/api/src/app.ts

@@ -1,6 +1,8 @@

import cors from "@elysia/cors"; import openapi from "@elysia/openapi"; import serverTiming from "@elysia/server-timing"; +import { staticPlugin } from "@elysia/static"; +import config from "@stealth-developers/config"; import { getUser } from "@stealth-developers/db"; import { Elysia, t } from "elysia";

@@ -11,10 +13,7 @@ import { ActorWithGuildSchema, ErrorSchema, UserSchema } from "./lib/schemas";

import * as routes from "./routes"; export const app = new Elysia() - .use(openapi()) - .use(cors()) - .use(authPlugin) - .use(serverTiming()) + .onError(({ error, set, request }) => { set.status = 500; console.error(request.url, error);

@@ -22,6 +21,17 @@

if (error instanceof Error) return { message: error.message ?? "Internal Server Error" }; return { message: "Unknown Error" }; }) + .use(openapi()) + .use(cors()) + .use( + staticPlugin({ + assets: config.api.publicDir, + indexHTML: true, + prefix: "/", + }), + ) + .use(authPlugin) + .use(serverTiming()) .use(routes.authRoutes) .group("/api", (app) => app
M apps/web/src/stores/api.tsapps/web/src/stores/api.ts

@@ -15,22 +15,31 @@ const actors = ref<Record<string, SanitisedActorWithGuild>>({});

const guild = ref<unknown | null>(null); async function getUser() { - const res = await client.api.me.get(); - if (res.status !== 200 || !res.data) return; - isAuthenticated.value = true; - isAuthenticating.value = false; - user.value = res.data.user; + try { + const res = await client.api.me.get(); + + if (res.status === 200 && res.data) { + isAuthenticated.value = true; + user.value = res.data.user; - const resActors = res.data.actors; - actors.value = resActors.reduce( - (acc, actor) => { - acc[actor.guild!.discordId!] = actor; - return acc; - }, - {} as Record<string, SanitisedActorWithGuild>, - ); + const resActors = res.data.actors; + actors.value = resActors.reduce( + (acc, actor) => { + if (actor.guild?.discordId) { + acc[actor.guild.discordId] = actor; + } + return acc; + }, + {} as Record<string, SanitisedActorWithGuild>, + ); - guild.value = res.data.actors[0]?.guild; + guild.value = res.data.actors[0]?.guild; + } + } catch (error) { + console.error(error); + } finally { + isAuthenticating.value = false; + } } async function waitForAuth() {
M bun.lockbun.lock

@@ -25,6 +25,7 @@ "dependencies": {

"@elysia/cors": "^1.4.2", "@elysia/openapi": "^1.4.15", "@elysia/server-timing": "^1.4.1", + "@elysia/static": "^1.4.11", "@purrkit/ratelimit": "^1.0.1", "@purrkit/rest": "^1.1.2", "@purrkit/types": "^1.1.1",

@@ -225,6 +226,8 @@

"@elysia/openapi": ["@elysia/openapi@1.4.15", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-MrVGCPo5hnRF4/yWGOyH5ddjt4DlSIbeC5rrkupQtHY8TEQe+XdJa2YM9aUOrtgtRcy4UNGyiVlLl/jllPkPQA=="], "@elysia/server-timing": ["@elysia/server-timing@1.4.1", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-+NDGhslxN0HZuyT8o4dt+hgib9bzsMuvxTE5bPrDhFFRl1duCNosseW3wE76pmwle8+m9+1aOeZ28mZAv51ggQ=="], + + "@elysia/static": ["@elysia/static@1.4.11", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-L3PN8V+cgz9Oz9kTow7ed3DHHCTHb9ZqZZDLxmKhrIKcFmWvjqzTm9TcMR2aLKjjls+QMSGuB7ZyaO+usIXovA=="], "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
M pkgs/config/src/schema.tspkgs/config/src/schema.ts

@@ -33,6 +33,7 @@ });

const apiSchema = z.object({ port: z.number().default(3000), + publicDir: z.string(), }); const s3Schema = z.object({