mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
Add backend framework selection between hono, elysiajs
This commit is contained in:
@@ -8,10 +8,8 @@
|
||||
"compile": "bun build --compile --minify --sourcemap --bytecode ./src/index.ts --outfile server"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hono/trpc-server": "^0.3.4",
|
||||
"@trpc/server": "^11.0.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"hono": "^4.7.5",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": "./",
|
||||
"outDir": "./dist",
|
||||
"types": ["node"],
|
||||
"types": ["node", "bun"],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "hono/jsx"
|
||||
},
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { Context as HonoContext } from "hono";
|
||||
import type { Context as ElysiaContext } from "elysia";
|
||||
import { auth } from "./auth";
|
||||
|
||||
export type CreateContextOptions = {
|
||||
hono: HonoContext;
|
||||
context: ElysiaContext;
|
||||
};
|
||||
|
||||
export async function createContext({ hono }: CreateContextOptions) {
|
||||
export async function createContext({ context }: CreateContextOptions) {
|
||||
const session = await auth.api.getSession({
|
||||
headers: hono.req.raw.headers,
|
||||
headers: context.request.headers,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -2,12 +2,12 @@ import type { Context as HonoContext } from "hono";
|
||||
import { auth } from "./auth";
|
||||
|
||||
export type CreateContextOptions = {
|
||||
hono: HonoContext;
|
||||
context: HonoContext;
|
||||
};
|
||||
|
||||
export async function createContext({ hono }: CreateContextOptions) {
|
||||
export async function createContext({ context }: CreateContextOptions) {
|
||||
const session = await auth.api.getSession({
|
||||
headers: hono.req.raw.headers,
|
||||
headers: context.req.raw.headers,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -1,7 +1,7 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||
import * as schema from "../db/schema/auth";
|
||||
import { db } from "../db";
|
||||
import * as schema from "../db/schema/auth";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: drizzleAdapter(db, {
|
||||
@@ -0,0 +1,38 @@
|
||||
import "dotenv/config";
|
||||
import { Elysia } from "elysia";
|
||||
import { cors } from "@elysiajs/cors";
|
||||
import { auth } from "./lib/auth";
|
||||
import { createContext } from "./lib/context";
|
||||
import { appRouter } from "./routers/index";
|
||||
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
||||
|
||||
const app = new Elysia()
|
||||
.use(
|
||||
cors({
|
||||
origin: process.env.CORS_ORIGIN || "",
|
||||
methods: ["GET", "POST", "OPTIONS"],
|
||||
allowedHeaders: ["Content-Type", "Authorization"],
|
||||
credentials: true,
|
||||
}),
|
||||
)
|
||||
.all("/api/auth/*", async (context) => {
|
||||
const { request } = context;
|
||||
if (["POST", "GET"].includes(request.method)) {
|
||||
return auth.handler(request);
|
||||
} else {
|
||||
context.error(405);
|
||||
}
|
||||
})
|
||||
.all("/trpc/*", async (context) => {
|
||||
const res = await fetchRequestHandler({
|
||||
endpoint: "/trpc",
|
||||
router: appRouter,
|
||||
req: context.request,
|
||||
createContext: () => createContext({ context }),
|
||||
});
|
||||
return res;
|
||||
})
|
||||
.get("/", () => "OK")
|
||||
.listen(3000, () => {
|
||||
console.log(`Server is running on http://localhost:3000`);
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import { trpcServer } from "@hono/trpc-server";
|
||||
import "dotenv/config";
|
||||
import { Hono } from "hono";
|
||||
@@ -27,8 +28,8 @@ app.use(
|
||||
"/trpc/*",
|
||||
trpcServer({
|
||||
router: appRouter,
|
||||
createContext: (_opts, hono) => {
|
||||
return createContext({ hono });
|
||||
createContext: (_opts, context) => {
|
||||
return createContext({ context });
|
||||
},
|
||||
}),
|
||||
);
|
||||
@@ -1,44 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { router, publicProcedure } from "../lib/trpc";
|
||||
import { todo } from "../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../db";
|
||||
|
||||
export const todoRouter = router({
|
||||
getAll: publicProcedure.query(async () => {
|
||||
return await db.select().from(todo).all();
|
||||
}),
|
||||
|
||||
create: publicProcedure
|
||||
.input(z.object({ text: z.string().min(1) }))
|
||||
.mutation(async ({ input }) => {
|
||||
return await db
|
||||
.insert(todo)
|
||||
.values({
|
||||
text: input.text,
|
||||
})
|
||||
.returning()
|
||||
.get();
|
||||
}),
|
||||
|
||||
toggle: publicProcedure
|
||||
.input(z.object({ id: z.number(), completed: z.boolean() }))
|
||||
.mutation(async ({ input }) => {
|
||||
return await db
|
||||
.update(todo)
|
||||
.set({ completed: input.completed })
|
||||
.where(eq(todo.id, input.id))
|
||||
.returning()
|
||||
.get();
|
||||
}),
|
||||
|
||||
delete: publicProcedure
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(async ({ input }) => {
|
||||
return await db
|
||||
.delete(todo)
|
||||
.where(eq(todo.id, input.id))
|
||||
.returning()
|
||||
.get();
|
||||
}),
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import type { Context as HonoContext } from "hono";
|
||||
import { auth } from "./auth";
|
||||
|
||||
export type CreateContextOptions = {
|
||||
hono: HonoContext;
|
||||
};
|
||||
|
||||
export async function createContext({ hono }: CreateContextOptions) {
|
||||
const session = await auth.api.getSession({
|
||||
headers: hono.req.raw.headers,
|
||||
});
|
||||
|
||||
return {
|
||||
session,
|
||||
};
|
||||
}
|
||||
|
||||
export type Context = Awaited<ReturnType<typeof createContext>>;
|
||||
@@ -1,24 +0,0 @@
|
||||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import type { Context } from "./context";
|
||||
|
||||
export const t = initTRPC.context<Context>().create();
|
||||
|
||||
export const router = t.router;
|
||||
|
||||
export const publicProcedure = t.procedure;
|
||||
|
||||
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
if (!ctx.session) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
cause: "No session",
|
||||
});
|
||||
}
|
||||
return next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
session: ctx.session,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import type { Context } from "./context";
|
||||
|
||||
export const t = initTRPC.context<Context>().create();
|
||||
|
||||
export const router = t.router;
|
||||
|
||||
export const publicProcedure = t.procedure;
|
||||
|
||||
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
if (!ctx.session) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
cause: "No session",
|
||||
});
|
||||
}
|
||||
return next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
session: ctx.session,
|
||||
},
|
||||
});
|
||||
});
|
||||
27
apps/cli/template/with-elysia/apps/server/src/index.ts
Normal file
27
apps/cli/template/with-elysia/apps/server/src/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import "dotenv/config";
|
||||
import { Elysia } from "elysia";
|
||||
import { cors } from "@elysiajs/cors";
|
||||
import { createContext } from "./lib/context";
|
||||
import { appRouter } from "./routers/index";
|
||||
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
||||
|
||||
const app = new Elysia()
|
||||
.use(
|
||||
cors({
|
||||
origin: process.env.CORS_ORIGIN || "",
|
||||
methods: ["GET", "POST", "OPTIONS"],
|
||||
}),
|
||||
)
|
||||
.all("/trpc/*", async (context) => {
|
||||
const res = await fetchRequestHandler({
|
||||
endpoint: "/trpc",
|
||||
router: appRouter,
|
||||
req: context.request,
|
||||
createContext: () => createContext({ context }),
|
||||
});
|
||||
return res;
|
||||
})
|
||||
.get("/", () => "OK")
|
||||
.listen(3000, () => {
|
||||
console.log(`Server is running on http://localhost:3000`);
|
||||
});
|
||||
13
apps/cli/template/with-elysia/apps/server/src/lib/context.ts
Normal file
13
apps/cli/template/with-elysia/apps/server/src/lib/context.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { Context as ElysiaContext } from "elysia";
|
||||
|
||||
export type CreateContextOptions = {
|
||||
context: ElysiaContext;
|
||||
};
|
||||
|
||||
export async function createContext({ context }: CreateContextOptions) {
|
||||
return {
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
|
||||
export type Context = Awaited<ReturnType<typeof createContext>>;
|
||||
@@ -22,8 +22,8 @@ app.use(
|
||||
"/trpc/*",
|
||||
trpcServer({
|
||||
router: appRouter,
|
||||
createContext: (_opts, hono) => {
|
||||
return createContext({ hono });
|
||||
createContext: (_opts, context) => {
|
||||
return createContext({ context });
|
||||
},
|
||||
}),
|
||||
);
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { Context as HonoContext } from "hono";
|
||||
|
||||
export type CreateContextOptions = {
|
||||
hono: HonoContext;
|
||||
context: HonoContext;
|
||||
};
|
||||
|
||||
export async function createContext({ hono }: CreateContextOptions) {
|
||||
export async function createContext({ context }: CreateContextOptions) {
|
||||
return {
|
||||
session: null,
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
import type { Context as HonoContext } from "hono";
|
||||
import { auth } from "./auth";
|
||||
|
||||
export type CreateContextOptions = {
|
||||
hono: HonoContext;
|
||||
};
|
||||
|
||||
export async function createContext({ hono }: CreateContextOptions) {
|
||||
const session = await auth.api.getSession({
|
||||
headers: hono.req.raw.headers,
|
||||
});
|
||||
|
||||
return {
|
||||
session,
|
||||
};
|
||||
}
|
||||
|
||||
export type Context = Awaited<ReturnType<typeof createContext>>;
|
||||
@@ -1,24 +0,0 @@
|
||||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import type { Context } from "./context";
|
||||
|
||||
export const t = initTRPC.context<Context>().create();
|
||||
|
||||
export const router = t.router;
|
||||
|
||||
export const publicProcedure = t.procedure;
|
||||
|
||||
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
if (!ctx.session) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
cause: "No session",
|
||||
});
|
||||
}
|
||||
return next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
session: ctx.session,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import type { Context } from "./context";
|
||||
|
||||
export const t = initTRPC.context<Context>().create();
|
||||
|
||||
export const router = t.router;
|
||||
|
||||
export const publicProcedure = t.procedure;
|
||||
|
||||
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
|
||||
if (!ctx.session) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
cause: "No session",
|
||||
});
|
||||
}
|
||||
return next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
session: ctx.session,
|
||||
},
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user