initial commit

This commit is contained in:
2026-02-24 11:30:24 +01:00
commit 47f9a25834
178 changed files with 18440 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import type { QueryClient } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { HeadContent, Outlet, Scripts, createRootRouteWithContext } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import type { orpc } from "@/utils/orpc";
import { Toaster } from "@/components/ui/sonner";
import Header from "../components/header";
import appCss from "../index.css?url";
export interface RouterAppContext {
orpc: typeof orpc;
queryClient: QueryClient;
}
export const Route = createRootRouteWithContext<RouterAppContext>()({
head: () => ({
meta: [
{
charSet: "utf-8",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
},
{
title: "My App",
},
],
links: [
{
rel: "stylesheet",
href: appCss,
},
],
}),
component: RootDocument,
});
function RootDocument() {
return (
<html lang="en" className="dark">
<head>
<HeadContent />
</head>
<body>
<div className="grid h-svh grid-rows-[auto_1fr]">
<Header />
<Outlet />
</div>
<Toaster richColors />
<TanStackRouterDevtools position="bottom-left" />
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
<Scripts />
</body>
</html>
);
}

View File

@@ -0,0 +1,15 @@
import { auth } from "@kk/auth";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/api/auth/$")({
server: {
handlers: {
GET: ({ request }) => {
return auth.handler(request);
},
POST: ({ request }) => {
return auth.handler(request);
},
},
},
});

View File

@@ -0,0 +1,58 @@
import { createContext } from "@kk/api/context";
import { appRouter } from "@kk/api/routers/index";
import { OpenAPIHandler } from "@orpc/openapi/fetch";
import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins";
import { onError } from "@orpc/server";
import { RPCHandler } from "@orpc/server/fetch";
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
import { createFileRoute } from "@tanstack/react-router";
const rpcHandler = new RPCHandler(appRouter, {
interceptors: [
onError((error) => {
console.error(error);
}),
],
});
const apiHandler = new OpenAPIHandler(appRouter, {
plugins: [
new OpenAPIReferencePlugin({
schemaConverters: [new ZodToJsonSchemaConverter()],
}),
],
interceptors: [
onError((error) => {
console.error(error);
}),
],
});
async function handle({ request }: { request: Request }) {
const rpcResult = await rpcHandler.handle(request, {
prefix: "/api/rpc",
context: await createContext({ req: request }),
});
if (rpcResult.response) return rpcResult.response;
const apiResult = await apiHandler.handle(request, {
prefix: "/api/rpc/api-reference",
context: await createContext({ req: request }),
});
if (apiResult.response) return apiResult.response;
return new Response("Not found", { status: 404 });
}
export const Route = createFileRoute("/api/rpc/$")({
server: {
handlers: {
HEAD: handle,
GET: handle,
POST: handle,
PUT: handle,
PATCH: handle,
DELETE: handle,
},
},
});

View File

@@ -0,0 +1,34 @@
import { useQuery } from "@tanstack/react-query";
import { createFileRoute, redirect } from "@tanstack/react-router";
import { getUser } from "@/functions/get-user";
import { orpc } from "@/utils/orpc";
export const Route = createFileRoute("/dashboard")({
component: RouteComponent,
beforeLoad: async () => {
const session = await getUser();
return { session };
},
loader: async ({ context }) => {
if (!context.session) {
throw redirect({
to: "/login",
});
}
},
});
function RouteComponent() {
const { session } = Route.useRouteContext();
const privateData = useQuery(orpc.privateData.queryOptions());
return (
<div>
<h1>Dashboard</h1>
<p>Welcome {session?.user.name}</p>
<p>API: {privateData.data?.message}</p>
</div>
);
}

View File

@@ -0,0 +1,51 @@
import { useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import { orpc } from "@/utils/orpc";
export const Route = createFileRoute("/")({
component: HomeComponent,
});
const TITLE_TEXT = `
██████╗ ███████╗████████╗████████╗███████╗██████╗
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝
██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗
██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║
╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗
╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
██║ ███████╗ ██║ ███████║██║ █████╔╝
██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗
██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
`;
function HomeComponent() {
const healthCheck = useQuery(orpc.healthCheck.queryOptions());
return (
<div className="container mx-auto max-w-3xl px-4 py-2">
<pre className="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
<div className="grid gap-6">
<section className="rounded-lg border p-4">
<h2 className="mb-2 font-medium">API Status</h2>
<div className="flex items-center gap-2">
<div
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
/>
<span className="text-muted-foreground text-sm">
{healthCheck.isLoading
? "Checking..."
: healthCheck.data
? "Connected"
: "Disconnected"}
</span>
</div>
</section>
</div>
</div>
);
}

View File

@@ -0,0 +1,19 @@
import { createFileRoute } from "@tanstack/react-router";
import { useState } from "react";
import SignInForm from "@/components/sign-in-form";
import SignUpForm from "@/components/sign-up-form";
export const Route = createFileRoute("/login")({
component: RouteComponent,
});
function RouteComponent() {
const [showSignIn, setShowSignIn] = useState(false);
return showSignIn ? (
<SignInForm onSwitchToSignUp={() => setShowSignIn(false)} />
) : (
<SignUpForm onSwitchToSignIn={() => setShowSignIn(true)} />
);
}