Reorganize FE

This commit is contained in:
Jesse Wierzbinski 2024-04-13 19:26:29 -10:00
parent e27a80c40a
commit 354493133c
No known key found for this signature in database
10 changed files with 112 additions and 63 deletions

View file

@ -0,0 +1,29 @@
export const useConfig = async () => {
let host = useRequestHeader("X-Forwarded-Host");
if (!host && process.server) {
host = process.env.BUILD_HOST;
}
if (!host?.includes("http")) {
// On server, this will be some kind of localhost
host = `http://${host}`;
}
if (process.client) {
host = useRequestURL().origin.toString();
}
console.log(host);
if (!host) {
throw createError({
statusCode: 500,
statusMessage: "No X-Forwarded-Host header found",
});
}
return await fetch(new URL("/api/_fe/config", host)).then((res) =>
res.json(),
);
};

View file

@ -1,6 +1,7 @@
<template>
<div class="flex min-h-screen flex-col justify-center px-6 py-12 lg:px-8 relative">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)" />
</div>
@ -14,7 +15,7 @@ import { getHighlighterCore } from "shiki/core";
import getWasm from "shiki/wasm";
import { useRoute } from "vue-router";
const config = (await useFetch("/api/config")).data.value;
const config = await useConfig();
if (!config) {
throw new Error("Config not found");
@ -51,17 +52,17 @@ const code = highlighter.codeToHtml(JSON.stringify(data, null, 4), {
<style lang="postcss">
pre:has(code) {
word-wrap: normal;
background: transparent;
-webkit-hyphens: none;
hyphens: none;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
white-space: pre;
word-break: normal;
word-spacing: normal;
overflow-x: auto;
word-wrap: normal;
background: transparent;
-webkit-hyphens: none;
hyphens: none;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
white-space: pre;
word-break: normal;
word-spacing: normal;
overflow-x: auto;
@apply ring-1 ring-white/10 mt-4 bg-white/5 px-4 py-3 rounded;
}

View file

@ -1,6 +1,7 @@
<template>
<div class="flex min-h-screen flex-col justify-center px-6 py-12 lg:px-8 relative">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)" />
</div>
@ -14,7 +15,7 @@ import { getHighlighterCore } from "shiki/core";
import getWasm from "shiki/wasm";
import { useRoute } from "vue-router";
const config = (await useFetch("/api/config")).data.value;
const config = await useConfig();
if (!config) {
throw new Error("Config not found");
@ -62,17 +63,17 @@ const code = highlighter.codeToHtml(JSON.stringify(data, null, 4), {
<style lang="postcss">
pre:has(code) {
word-wrap: normal;
background: transparent;
-webkit-hyphens: none;
hyphens: none;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
white-space: pre;
word-break: normal;
word-spacing: normal;
overflow-x: auto;
word-wrap: normal;
background: transparent;
-webkit-hyphens: none;
hyphens: none;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
white-space: pre;
word-break: normal;
word-spacing: normal;
overflow-x: auto;
@apply ring-1 ring-white/10 mt-4 bg-white/5 px-4 py-3 rounded;
}

View file

@ -15,7 +15,8 @@
</div>
<div class="text-center">
<h1 class="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">Welcome to Lysand</h1>
<p class="mt-6 text-lg leading-8 text-gray-600">You can login to this server by pointing any Mastodon
<p class="mt-6 text-lg leading-8 text-gray-600">You can login to this server by pointing any
Mastodon
client at <strong class="font-bold">{{ config?.http.base_url }}</strong></p>
<div class="mt-10 flex items-center justify-center gap-6 md:flex-row flex-col">
<a href="https://github.com/lysand-org/lysand" target="_blank"
@ -29,7 +30,8 @@
<p class="mt-6 text-lg leading-8 text-gray-600">Here are some recommended clients:</p>
<ul class="w-full flex flex-col gap-3 mt-4">
<li v-for="client of recommendedClients" :key="client.name" class="w-full">
<a :href="client.link" class="rounded-sm ring-2 ring-black/10 px-4 py-2 w-full flex flex-row gap-3 items-center">
<a :href="client.link"
class="rounded-sm ring-2 ring-black/10 px-4 py-2 w-full flex flex-row gap-3 items-center">
<img :src="client.icon" :alt="client.name" class="h-10 w-10" />
<div class="flex flex-col justify-between items-start">
<h2 class="font-bold">{{ client.name }}</h2>
@ -39,11 +41,13 @@
</li>
</ul>
<p class="mt-6 text-lg leading-8 text-gray-600">
Many other clients exist, but <strong class="font-bold">they have not been tested for compatibility</strong>. Bug reports are nevertheless welcome.
Many other clients exist, but <strong class="font-bold">they have not been tested for
compatibility</strong>. Bug reports are nevertheless welcome.
</p>
<p class="mt-6 text-lg leading-8 text-gray-600">
Found a problem? Report it on <a href="https://github.com/lysand-org/lysand/issues/new/choose" class="underline text-purple-700">the issue tracker</a>.
Found a problem? Report it on <a href="https://github.com/lysand-org/lysand/issues/new/choose"
class="underline text-purple-700">the issue tracker</a>.
</p>
</div>
</div>
@ -60,8 +64,7 @@
import { recommendedClients } from "../constants";
// @ts-ignore
const version = __VERSION__;
const config = (await useFetch("/api/config")).data.value;
const config = await useConfig();
useServerSeoMeta({
title: "Welcome to Lysand!",

View file

@ -1,6 +1,7 @@
<template>
<div class="flex min-h-screen flex-col justify-center px-6 py-12 lg:px-8 relative">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)" />
</div>
@ -66,7 +67,8 @@
</div>
<div class="">
<input type="checkbox" :value="tosAccepted" @input="tosAccepted = Boolean(($event.target as any).value)"
<input type="checkbox" :value="tosAccepted"
@input="tosAccepted = Boolean(($event.target as any).value)"
class="rounded mr-1 align-middle mb-0.5" /> <span class="text-sm">I agree to the
terms and
conditions
@ -89,9 +91,11 @@
</form>
</div>
<div v-else>
<h1 class="text-2xl font-bold tracking-tight text-gray-900 sm:text-4xl text-center">Registrations are disabled
<h1 class="text-2xl font-bold tracking-tight text-gray-900 sm:text-4xl text-center">Registrations are
disabled
</h1>
<p class="mt-6 text-lg leading-8 text-gray-600 text-center">Ask this instance's admin to enable them in config!
<p class="mt-6 text-lg leading-8 text-gray-600 text-center">Ask this instance's admin to enable them in
config!
</p>
</div>
</div>
@ -101,7 +105,7 @@
import type { APIInstance } from "../../../../types/entities/instance";
import LoginInput from "../../components/LoginInput.vue";
const config = (await useFetch("/api/config")).data.value;
const config = await useConfig();
if (!config) {
throw new Error("Config not found");

View file

@ -1,21 +0,0 @@
import { loadConfig } from "c12";
import { type Config, defaultConfig } from "config-manager/config.type";
const promise = loadConfig<Config>({
configFile: "./config/config.toml",
defaultConfig: defaultConfig,
});
export default defineEventHandler(async () => {
const { config } = await promise;
return {
http: {
bind: config?.http.bind,
bind_port: config?.http.bind_port,
base_url: config?.http.base_url,
url: config?.http.bind.includes("http")
? `${config?.http.bind}:${config?.http.bind_port}`
: `http://${config?.http.bind}:${config?.http.bind_port}`,
},
};
});

View file

@ -1,3 +0,0 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

View file

@ -82,6 +82,7 @@ export const rawRoutes = {
"/api/v1/statuses/[id]/unpin": "./server/api/api/v1/statuses/[id]/unpin",
"/api/v1/statuses/[id]/unreblog":
"./server/api/api/v1/statuses/[id]/unreblog",
"/api/_fe/config": "./server/api/api/_fe/config/index",
"/media/[id]": "./server/api/media/[id]/index",
"/oauth/callback/[issuer]": "./server/api/oauth/callback/[issuer]/index",
"/objects/note/[uuid]": "./server/api/objects/note/[uuid]/index",

View file

@ -193,7 +193,12 @@ export const createServer = (
.replace(config.http.base_url, "http://localhost:5173")
.replace(base_url_with_http, "http://localhost:5173");
const proxy = await fetch(replacedUrl).catch(async (e) => {
const proxy = await fetch(replacedUrl, {
headers: {
// Include for SSR
"X-Forwarded-Host": `${config.http.bind}:${config.http.bind_port}`,
},
}).catch(async (e) => {
await logger.logError(
LogLevel.ERROR,
"Server.Proxy",

View file

@ -0,0 +1,29 @@
import { apiRoute, applyConfig } from "@api";
import { jsonResponse } from "@response";
export const meta = applyConfig({
allowedMethods: ["GET"],
ratelimits: {
max: 60,
duration: 120,
},
route: "/api/_fe/config",
auth: {
required: false,
},
});
export default apiRoute(async (req, matchedRoute, extraData) => {
const config = await extraData.configManager.getConfig();
return jsonResponse({
http: {
bind: config.http.bind,
bind_port: config.http.bind_port,
base_url: config.http.base_url,
url: config.http.bind.includes("http")
? `${config.http.bind}:${config.http.bind_port}`
: `http://${config.http.bind}:${config.http.bind_port}`,
},
});
});