feat: add fate vite integration

This commit is contained in:
Aarnav Tale
2026-05-16 20:37:57 -04:00
parent 04ff2138d2
commit ad7e58570f
8 changed files with 107 additions and 14 deletions
+71
View File
@@ -0,0 +1,71 @@
import {
createFateServer,
createLiveEventBus,
type SourceDefinition,
type SourceRegistry,
} from "@nkzw/fate/server";
import type { Context } from "hono";
import type { AppContext } from "./context";
import type { RuntimeApiClient } from "./headscale/api/endpoints";
import type { Principal } from "./web/auth";
export interface HonoFateEnv {
Variables: {
appContext: AppContext;
};
}
interface FateContext {
api: RuntimeApiClient;
app: AppContext;
principal: Principal;
request: Request;
}
type FateAdapterContext = Context<HonoFateEnv>;
export const live = createLiveEventBus();
export const roots = {};
const queries = {};
const lists = {};
const mutations = {};
const registry = new Map() as SourceRegistry<FateContext>;
export const fate = createFateServer<
FateContext,
typeof roots,
typeof queries,
typeof lists,
typeof mutations,
FateAdapterContext
>({
context: async ({ adapterContext, request }) => {
if (!adapterContext) {
throw new Error("Fate request is missing Hono context");
}
const app = adapterContext.get("appContext");
const principal = await app.auth.require(request);
const api = app.hsApi.getRuntimeClient(app.auth.getHeadscaleApiKey(principal));
return {
api,
app,
principal,
request,
};
},
live,
roots,
sources: {
registry,
getSource(target) {
return target as SourceDefinition;
},
},
});
export type { FateAdapterContext, FateContext };
+11 -3
View File
@@ -1,9 +1,11 @@
import { versions } from "node:process";
import { serveStatic } from "@hono/node-server/serve-static";
import { createHonoFateHandler } from "@nkzw/fate/server";
import { Hono, type Context } from "hono";
import type { AppContext } from "./context";
import { fate, type HonoFateEnv } from "./fate";
interface HonoAppOptions {
context: AppContext;
@@ -12,7 +14,13 @@ interface HonoAppOptions {
}
export function createHeadplaneHonoApp({ context, prefix, staticRoot }: HonoAppOptions) {
const app = new Hono();
const app = new Hono<HonoFateEnv>();
const fateHandler = createHonoFateHandler(fate);
app.use("*", async (c, next) => {
c.set("appContext", context);
await next();
});
const health = async (c: Context) => {
const api = context.hsApi.getRuntimeClient("fake-api-key");
@@ -86,8 +94,8 @@ export function createHeadplaneHonoApp({ context, prefix, staticRoot }: HonoAppO
}
});
app.all(`${prefix}/fate`, (c) => c.json({ error: "Fate server is not mounted yet" }, 501));
app.all(`${prefix}/fate/*`, (c) => c.json({ error: "Fate server is not mounted yet" }, 501));
app.all(`${prefix}/fate`, fateHandler);
app.all(`${prefix}/fate/*`, fateHandler);
if (staticRoot) {
const stripPrefix = (path: string) => path.slice(prefix.length) || "/";
+5 -8
View File
@@ -1,15 +1,12 @@
import { RouterProvider } from "@tanstack/react-router";
import { FateClient, createClient, createHTTPTransport } from "react-fate";
import { FateClient } from "react-fate";
import { createFateClient } from "react-fate/client";
import { router } from "./router";
const fate = createClient({
roots: {},
transport: createHTTPTransport({
fetch: (input, init) => fetch(input, { ...init, credentials: "include" }),
url: `${__PREFIX__}/fate`,
}),
types: [],
const fate = createFateClient({
fetch: (input, init) => fetch(input, { ...init, credentials: "include" }),
url: `${__PREFIX__}/fate`,
});
export function App() {