mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-28 01:10:54 +01:00
Initial commit
This commit is contained in:
11
packages/api/src/root.ts
Normal file
11
packages/api/src/root.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { authRouter } from "./router/auth";
|
||||
import { postRouter } from "./router/post";
|
||||
import { createTRPCRouter } from "./trpc";
|
||||
|
||||
export const appRouter = createTRPCRouter({
|
||||
auth: authRouter,
|
||||
post: postRouter,
|
||||
});
|
||||
|
||||
// export type definition of API
|
||||
export type AppRouter = typeof appRouter;
|
||||
11
packages/api/src/router/auth.ts
Normal file
11
packages/api/src/router/auth.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
||||
|
||||
export const authRouter = createTRPCRouter({
|
||||
getSession: publicProcedure.query(({ ctx }) => {
|
||||
return ctx.session;
|
||||
}),
|
||||
getSecretMessage: protectedProcedure.query(() => {
|
||||
// testing type validation of overridden next-auth Session in @acme/auth package
|
||||
return "you can see this secret message!";
|
||||
}),
|
||||
});
|
||||
40
packages/api/src/router/post.ts
Normal file
40
packages/api/src/router/post.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { desc, eq, schema } from "@acme/db";
|
||||
|
||||
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
|
||||
|
||||
export const postRouter = createTRPCRouter({
|
||||
all: publicProcedure.query(({ ctx }) => {
|
||||
// return ctx.db.select().from(schema.post).orderBy(desc(schema.post.id));
|
||||
return ctx.db.query.post.findMany({ orderBy: desc(schema.post.id) });
|
||||
}),
|
||||
|
||||
byId: publicProcedure
|
||||
.input(z.object({ id: z.number() }))
|
||||
.query(({ ctx, input }) => {
|
||||
// return ctx.db
|
||||
// .select()
|
||||
// .from(schema.post)
|
||||
// .where(eq(schema.post.id, input.id));
|
||||
|
||||
return ctx.db.query.post.findFirst({
|
||||
where: eq(schema.post.id, input.id),
|
||||
});
|
||||
}),
|
||||
|
||||
create: protectedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
title: z.string().min(1),
|
||||
content: z.string().min(1),
|
||||
}),
|
||||
)
|
||||
.mutation(({ ctx, input }) => {
|
||||
return ctx.db.insert(schema.post).values(input);
|
||||
}),
|
||||
|
||||
delete: protectedProcedure.input(z.number()).mutation(({ ctx, input }) => {
|
||||
return ctx.db.delete(schema.post).where(eq(schema.post.id, input));
|
||||
}),
|
||||
});
|
||||
132
packages/api/src/trpc.ts
Normal file
132
packages/api/src/trpc.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
|
||||
* 1. You want to modify request context (see Part 1)
|
||||
* 2. You want to create a new middleware or type of procedure (see Part 3)
|
||||
*
|
||||
* tl;dr - this is where all the tRPC server stuff is created and plugged in.
|
||||
* The pieces you will need to use are documented accordingly near the end
|
||||
*/
|
||||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import superjson from "superjson";
|
||||
import { ZodError } from "zod";
|
||||
|
||||
import { auth } from "@acme/auth";
|
||||
import type { Session } from "@acme/auth";
|
||||
import { db } from "@acme/db";
|
||||
|
||||
/**
|
||||
* 1. CONTEXT
|
||||
*
|
||||
* This section defines the "contexts" that are available in the backend API
|
||||
*
|
||||
* These allow you to access things like the database, the session, etc, when
|
||||
* processing a request
|
||||
*
|
||||
*/
|
||||
interface CreateContextOptions {
|
||||
session: Session | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper generates the "internals" for a tRPC context. If you need to use
|
||||
* it, you can export it from here
|
||||
*
|
||||
* Examples of things you may need it for:
|
||||
* - testing, so we dont have to mock Next.js' req/res
|
||||
* - trpc's `createSSGHelpers` where we don't have req/res
|
||||
* @see https://create.t3.gg/en/usage/trpc#-servertrpccontextts
|
||||
*/
|
||||
const createInnerTRPCContext = (opts: CreateContextOptions) => {
|
||||
return {
|
||||
session: opts.session,
|
||||
db,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the actual context you'll use in your router. It will be used to
|
||||
* process every request that goes through your tRPC endpoint
|
||||
* @link https://trpc.io/docs/context
|
||||
*/
|
||||
export const createTRPCContext = async (opts: {
|
||||
req?: Request;
|
||||
auth: Session | null;
|
||||
}) => {
|
||||
const session = opts.auth ?? (await auth());
|
||||
const source = opts.req?.headers.get("x-trpc-source") ?? "unknown";
|
||||
|
||||
console.log(">>> tRPC Request from", source, "by", session?.user);
|
||||
|
||||
return createInnerTRPCContext({
|
||||
session,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 2. INITIALIZATION
|
||||
*
|
||||
* This is where the trpc api is initialized, connecting the context and
|
||||
* transformer
|
||||
*/
|
||||
const t = initTRPC.context<typeof createTRPCContext>().create({
|
||||
transformer: superjson,
|
||||
errorFormatter({ shape, error }) {
|
||||
return {
|
||||
...shape,
|
||||
data: {
|
||||
...shape.data,
|
||||
zodError:
|
||||
error.cause instanceof ZodError ? error.cause.flatten() : null,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
|
||||
*
|
||||
* These are the pieces you use to build your tRPC API. You should import these
|
||||
* a lot in the /src/server/api/routers folder
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is how you create new routers and subrouters in your tRPC API
|
||||
* @see https://trpc.io/docs/router
|
||||
*/
|
||||
export const createTRPCRouter = t.router;
|
||||
|
||||
/**
|
||||
* Public (unauthed) procedure
|
||||
*
|
||||
* This is the base piece you use to build new queries and mutations on your
|
||||
* tRPC API. It does not guarantee that a user querying is authorized, but you
|
||||
* can still access user session data if they are logged in
|
||||
*/
|
||||
export const publicProcedure = t.procedure;
|
||||
|
||||
/**
|
||||
* Reusable middleware that enforces users are logged in before running the
|
||||
* procedure
|
||||
*/
|
||||
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
|
||||
if (!ctx.session?.user) {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
return next({
|
||||
ctx: {
|
||||
// infers the `session` as non-nullable
|
||||
session: { ...ctx.session, user: ctx.session.user },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Protected (authed) procedure
|
||||
*
|
||||
* If you want a query or mutation to ONLY be accessible to logged in users, use
|
||||
* this. It verifies the session is valid and guarantees ctx.session.user is not
|
||||
* null
|
||||
*
|
||||
* @see https://trpc.io/docs/procedures
|
||||
*/
|
||||
export const protectedProcedure = t.procedure.use(enforceUserIsAuthed);
|
||||
Reference in New Issue
Block a user