Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
steeeee0223 committed Aug 15, 2024
1 parent f91f543 commit 9fc0a3d
Show file tree
Hide file tree
Showing 11 changed files with 344 additions and 1 deletion.
2 changes: 2 additions & 0 deletions apps/worxpace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dependencies": {
"@acme/i18n": "workspace:*",
"@acme/prisma": "workspace:*",
"@acme/trpc": "workspace:*",
"@acme/ui": "workspace:*",
"@acme/validators": "workspace:*",
"@blocknote/core": "^0.15.0",
Expand All @@ -30,6 +31,7 @@
"@liveblocks/react": "^1.12.0",
"@liveblocks/yjs": "^1.12.0",
"@t3-oss/env-nextjs": "^0.10.1",
"@trpc/server": "next",
"lucide-react": "^0.408.0",
"next": "^14.2.3",
"react": "18.3.1",
Expand Down
52 changes: 52 additions & 0 deletions apps/worxpace/src/app/api/trpc/[trpc]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { appRouter, createTRPCContext } from "@acme/trpc";
import * as trpcNext from '@trpc/server/adapters/next'

export const runtime = "edge";

/**
* Configure basic CORS headers
* You should extend this to match your needs
*/
const setCorsHeaders = (res: Response) => {
res.headers.set("Access-Control-Allow-Origin", "*");
res.headers.set("Access-Control-Request-Method", "*");
res.headers.set("Access-Control-Allow-Methods", "OPTIONS, GET, POST");
res.headers.set("Access-Control-Allow-Headers", "*");
};

export const OPTIONS = () => {
const response = new Response(null, {
status: 204,
});
setCorsHeaders(response);
return response;
};

const handler = trpcNext.createNextApiHandler( {
router: appRouter,
createContext: createTRPCContext,
onError({ error, path }) {
console.error(`>>> tRPC Error on '${path}'`, error);
},
})

// const handler = auth(async (req) => {
// const response = await fetchRequestHandler({
// endpoint: "/api/trpc",
// router: appRouter,
// req,
// createContext: () =>
// createTRPCContext({
// session: req.auth,
// headers: req.headers,
// }),
// onError({ error, path }) {
// console.error(`>>> tRPC Error on '${path}'`, error);
// },
// });

// setCorsHeaders(response);
// return response;
// });

export { handler as GET, handler as POST };
2 changes: 1 addition & 1 deletion apps/worxpace/src/hooks/use-documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
const fetcher = async ({ workspaceId }: DocumentsKey) => {
try {
return await fetchUrl<DetailedDocument[]>(
`/api/documents?workspaceId=${workspaceId}`,
`/api/trpc/documents?workspaceId=${workspaceId}`,
);
} catch (error) {
console.log(error);
Expand Down
41 changes: 41 additions & 0 deletions packages/trpc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@acme/trpc",
"version": "1.0.3",
"private": true,
"type": "module",
"exports": {
".": "./src/index.ts"
},
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
"format": "prettier --check . --ignore-path ../../.gitignore",
"lint": "eslint .",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@acme/prisma": "workspace:*",
"@acme/validators": "workspace:*",
"@clerk/nextjs": "^5.2.12",
"@t3-oss/env-nextjs": "^0.10.1",
"@trpc/client": "next",
"@trpc/server": "next",
"superjson": "2.2.1",
"zod": "^3.23.7"
},
"devDependencies": {
"@acme/eslint-config": "workspace:*",
"@acme/prettier-config": "workspace:*",
"@acme/tsconfig": "workspace:*",
"eslint": "^8.56.0",
"prettier": "^3.2.5",
"typescript": "^5.5.4"
},
"eslintConfig": {
"root": true,
"extends": [
"@acme/eslint-config/base"
]
},
"prettier": "@acme/prettier-config"
}
33 changes: 33 additions & 0 deletions packages/trpc/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server";

import type { AppRouter } from "./root";
import { appRouter } from "./root";
import { createCallerFactory, createTRPCContext } from "./trpc";

/**
* Create a server-side caller for the tRPC API
* @example
* const trpc = createCaller(createContext);
* const res = await trpc.post.all();
* ^? Post[]
*/
const createCaller = createCallerFactory(appRouter);

/**
* Inference helpers for input types
* @example
* type PostByIdInput = RouterInputs['post']['byId']
* ^? { id: number }
**/
type RouterInputs = inferRouterInputs<AppRouter>;

/**
* Inference helpers for output types
* @example
* type AllPostsOutput = RouterOutputs['post']['all']
* ^? Post[]
**/
type RouterOutputs = inferRouterOutputs<AppRouter>;

export { createTRPCContext, appRouter, createCaller };
export type { AppRouter, RouterInputs, RouterOutputs };
11 changes: 11 additions & 0 deletions packages/trpc/src/root.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { authRouter } from "./router/auth";
import { documentRouter } from "./router/document";
import { createTRPCRouter } from "./trpc";

export const appRouter = createTRPCRouter({
auth: authRouter,
document: documentRouter,
});

// export type definition of API
export type AppRouter = typeof appRouter;
16 changes: 16 additions & 0 deletions packages/trpc/src/router/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {currentUser} from "@clerk/nextjs/server"

import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";

export const authRouter = createTRPCRouter({
getAuth: publicProcedure.query(({ ctx }) => {
return ctx.auth;
}),
getUser: publicProcedure.query(() => {
return currentUser()
}),
getSecretMessage: protectedProcedure.query(() => {
// testing type validation of overridden next-auth Session in @acme/auth package
return "you can see this secret message!";
}),
});
24 changes: 24 additions & 0 deletions packages/trpc/src/router/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { z } from "zod";


import { createTRPCRouter, protectedProcedure } from "../trpc";

const include = { workspace: true, createdBy: true, updatedBy: true }

export const documentRouter = createTRPCRouter({
all: protectedProcedure
.input(z.object({ workspaceId: z.string(), isArchived: z.boolean().optional() }))
.query(({ ctx, input }) => {
return ctx.db.document.findMany({
where: input,
orderBy: { createdAt: "desc" },
include,
})
}),

byId: protectedProcedure
.input(z.string())
.query(({ ctx, input }) => {
return ctx.db.document.findUnique({ where: { id: input }, include });
}),
});
104 changes: 104 additions & 0 deletions packages/trpc/src/trpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* 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 { getAuth } from "@clerk/nextjs/server";
import {worxpace} from "@acme/prisma"
// import { NextApiRequest } from "@trpc/server/adapters/next";
import * as trpcNext from '@trpc/server/adapters/next'

/**
* 1. CONTEXT
*
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://trpc.io/docs/server/context
*/
export const createTRPCContext = async (opts: trpcNext.CreateNextContextOptions) => {

Check failure on line 30 in packages/trpc/src/trpc.ts

View workflow job for this annotation

GitHub Actions / lint

Async arrow function 'createTRPCContext' has no 'await' expression
const auth = getAuth(opts.req)
// const source = opts.headers.get("x-trpc-source") ?? "unknown";
// console.log(">>> tRPC Request from", source, "by", auth?.userId);

return {
auth,
db: worxpace,
};
};

/**
* 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 }) => ({
...shape,
data: {
...shape.data,
zodError: error.cause instanceof ZodError ? error.cause.flatten() : null,
},
}),
});

/**
* Create a server-side caller
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;

/**
* 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;

/**
* Protected (authenticated) procedure
*
* If you want a query or mutation to ONLY be accessible to logged in users, use this. It verifies
* the `AuthObject` is valid and guarantees `ctx.auth.userId` is not null.
*
* @see https://trpc.io/docs/procedures
*/
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
if (!ctx.auth.userId) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx: {
// infers the `auth` as non-nullable
auth: ctx.auth,
},
});
});
8 changes: 8 additions & 0 deletions packages/trpc/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "@acme/tsconfig/base.json",
"compilerOptions": {
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
},
"include": ["src"],
"exclude": ["node_modules"]
}
52 changes: 52 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 9fc0a3d

Please sign in to comment.