From e4bfd07545c1ab245c25ff210ebde952e288568b Mon Sep 17 00:00:00 2001 From: Ahmed Elsakaan Date: Tue, 6 Feb 2024 22:51:55 +0000 Subject: [PATCH 1/2] feat(trpc): initial trpc implementation --- apps/web/next.config.js | 2 +- apps/web/package.json | 7 ++ apps/web/src/app/api/trpc/[trpc]/route.ts | 29 +++++ apps/web/src/app/page.tsx | 5 + apps/web/src/app/providers.tsx | 4 +- apps/web/src/env.js | 11 +- apps/web/src/lib/trpc/react.tsx | 44 +++++++ apps/web/src/lib/trpc/server.ts | 59 +++++++++ apps/web/src/lib/trpc/shared.ts | 11 ++ cspell.config.yaml | 3 + packages/trpc/.eslintrc.cjs | 7 ++ packages/trpc/package.json | 27 ++++ packages/trpc/src/index.ts | 14 +++ packages/trpc/src/routers/greeting.ts | 21 ++++ packages/trpc/src/trpc.ts | 45 +++++++ packages/trpc/tsconfig.json | 4 + pnpm-lock.yaml | 143 +++++++++++++++++++++- 17 files changed, 429 insertions(+), 7 deletions(-) create mode 100644 apps/web/src/app/api/trpc/[trpc]/route.ts create mode 100644 apps/web/src/lib/trpc/react.tsx create mode 100644 apps/web/src/lib/trpc/server.ts create mode 100644 apps/web/src/lib/trpc/shared.ts create mode 100644 packages/trpc/.eslintrc.cjs create mode 100644 packages/trpc/package.json create mode 100644 packages/trpc/src/index.ts create mode 100644 packages/trpc/src/routers/greeting.ts create mode 100644 packages/trpc/src/trpc.ts create mode 100644 packages/trpc/tsconfig.json diff --git a/apps/web/next.config.js b/apps/web/next.config.js index aeb1194c..d1c27a94 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -2,7 +2,7 @@ import './src/env.js'; /** @type {import('next').NextConfig} */ const nextConfig = { - transpilePackages: ['@orbitkit/db', '@orbitkit/auth'], + transpilePackages: ['@orbitkit/db', '@orbitkit/auth', '@orbitkit/trpc'], }; export default nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json index dd3dd2ab..2a6916d3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -16,14 +16,21 @@ "dependencies": { "@orbitkit/auth": "workspace:^", "@orbitkit/db": "workspace:^", + "@orbitkit/trpc": "workspace:^", "@orbitkit/ui": "workspace:^", "@t3-oss/env-nextjs": "^0.8.0", + "@tanstack/react-query": "4.36.1", "@total-typescript/ts-reset": "^0.5.1", + "@trpc/client": "^10.45.1", + "@trpc/react-query": "^10.45.1", + "@trpc/server": "^10.45.1", "geist": "^1.2.2", "next": "14.1.0", "next-themes": "^0.2.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "server-only": "^0.0.1", + "superjson": "^2.2.1", "zod": "^3.22.4" }, "devDependencies": { diff --git a/apps/web/src/app/api/trpc/[trpc]/route.ts b/apps/web/src/app/api/trpc/[trpc]/route.ts new file mode 100644 index 00000000..3d92a10b --- /dev/null +++ b/apps/web/src/app/api/trpc/[trpc]/route.ts @@ -0,0 +1,29 @@ +import { type NextRequest } from 'next/server'; + +import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; + +import { appRouter, createTRPCContext } from '@orbitkit/trpc'; + +import { env } from '@/env'; + +const createContext = async (req: NextRequest) => { + return createTRPCContext({ + headers: req.headers, + }); +}; + +const handler = (req: NextRequest) => + fetchRequestHandler({ + endpoint: '/api/trpc', + req, + router: appRouter, + createContext: () => createContext(req), + onError: ({ path, error }) => { + env.NODE_ENV === 'development' && + console.error( + `❌ tRPC failed on ${path ?? ''}: ${error.message}`, + ); + }, + }); + +export { handler as GET, handler as POST }; diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index 90a6fec7..ddd0588a 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -3,15 +3,20 @@ import { redirect } from 'next/navigation'; import { getSession } from '@orbitkit/auth'; import { Avatar, AvatarFallback, AvatarImage } from '@orbitkit/ui/avatar'; +import { trpc } from '@/lib/trpc/server'; + export default async function Home() { const { user } = await getSession(); if (!user) { return redirect('/login'); } + const hello = await trpc.greeting.hello.query({ name: 'John' }); + return (

Next.js app

+

{hello.greeting}

CN diff --git a/apps/web/src/app/providers.tsx b/apps/web/src/app/providers.tsx index 5205f2cc..0121da4d 100644 --- a/apps/web/src/app/providers.tsx +++ b/apps/web/src/app/providers.tsx @@ -3,10 +3,12 @@ import { type FC, type PropsWithChildren } from 'react'; import { ThemeProvider as NextThemesProvider } from 'next-themes'; +import { TRPCReactProvider } from '@/lib/trpc/react'; + export const Providers: FC = ({ children }) => { return ( - {children} + {children} ); }; diff --git a/apps/web/src/env.js b/apps/web/src/env.js index fe2c3566..6c9dbeb6 100644 --- a/apps/web/src/env.js +++ b/apps/web/src/env.js @@ -1,13 +1,20 @@ import { createEnv } from '@t3-oss/env-nextjs'; import { vercel } from '@t3-oss/env-nextjs/presets'; +import { z } from 'zod'; import { env as authEnv } from '@orbitkit/auth/env'; import { env as dbEnv } from '@orbitkit/db/env'; export const env = createEnv({ extends: [dbEnv, authEnv, vercel], - server: {}, + server: { + NODE_ENV: z.enum(['development', 'test', 'production']).optional(), + PORT: z.coerce.number().default(3000), + }, client: {}, - runtimeEnv: {}, + runtimeEnv: { + NODE_ENV: process.env.NODE_ENV, + PORT: process.env['PORT'], + }, emptyStringAsUndefined: true, }); diff --git a/apps/web/src/lib/trpc/react.tsx b/apps/web/src/lib/trpc/react.tsx new file mode 100644 index 00000000..f96b39e1 --- /dev/null +++ b/apps/web/src/lib/trpc/react.tsx @@ -0,0 +1,44 @@ +'use client'; + +import { useState } from 'react'; + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { loggerLink, unstable_httpBatchStreamLink } from '@trpc/client'; +import { createTRPCReact } from '@trpc/react-query'; +import superjson from 'superjson'; + +import { type AppRouter } from '@orbitkit/trpc'; + +import { env } from '@/env'; + +import { getUrl } from './shared'; + +export const trpc = createTRPCReact(); + +export function TRPCReactProvider(props: { children: React.ReactNode }) { + const [queryClient] = useState(() => new QueryClient()); + + const [trpcClient] = useState(() => + trpc.createClient({ + transformer: superjson, + links: [ + loggerLink({ + enabled: (op) => + env.NODE_ENV === 'development' || + (op.direction === 'down' && op.result instanceof Error), + }), + unstable_httpBatchStreamLink({ + url: getUrl(), + }), + ], + }), + ); + + return ( + + + {props.children} + + + ); +} diff --git a/apps/web/src/lib/trpc/server.ts b/apps/web/src/lib/trpc/server.ts new file mode 100644 index 00000000..fbfc8e2d --- /dev/null +++ b/apps/web/src/lib/trpc/server.ts @@ -0,0 +1,59 @@ +import 'server-only'; + +import { cache } from 'react'; +import { headers } from 'next/headers'; + +import type { AppRouter } from '@orbitkit/trpc'; + +import { + createTRPCProxyClient, + loggerLink, + TRPCClientError, +} from '@trpc/client'; +import { callProcedure } from '@trpc/server'; +import { observable } from '@trpc/server/observable'; +import { type TRPCErrorResponse } from '@trpc/server/rpc'; +import superjson from 'superjson'; + +import { appRouter, createTRPCContext } from '@orbitkit/trpc'; + +const createContext = cache(() => { + const heads = new Headers(headers()); + heads.set('x-trpc-source', 'rsc'); + + return createTRPCContext({ + headers: heads, + }); +}); + +export const trpc = createTRPCProxyClient({ + transformer: superjson, + links: [ + loggerLink({ + enabled: (op) => + process.env.NODE_ENV === 'development' || + (op.direction === 'down' && op.result instanceof Error), + }), + () => + ({ op }) => + observable((observer) => { + createContext() + .then((ctx) => { + return callProcedure({ + procedures: appRouter._def.procedures, + path: op.path, + rawInput: op.input, + ctx, + type: op.type, + }); + }) + .then((data) => { + observer.next({ result: { data } }); + observer.complete(); + }) + .catch((cause: TRPCErrorResponse) => { + observer.error(TRPCClientError.from(cause)); + }); + }), + ], +}); diff --git a/apps/web/src/lib/trpc/shared.ts b/apps/web/src/lib/trpc/shared.ts new file mode 100644 index 00000000..37f05269 --- /dev/null +++ b/apps/web/src/lib/trpc/shared.ts @@ -0,0 +1,11 @@ +import { env } from '@/env'; + +function getBaseUrl() { + if (typeof window !== 'undefined') return ''; + if (env.VERCEL_URL) return `https://${env.VERCEL_URL}`; + return `http://localhost:${env.PORT}`; +} + +export function getUrl() { + return getBaseUrl() + '/api/trpc'; +} diff --git a/cspell.config.yaml b/cspell.config.yaml index 958c37cb..1bf69904 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -25,7 +25,10 @@ words: - packagejson - shadcn - stylesheet + - superjson - tailwindcss + - tanstack + - trpc - tsbuildinfo - tsconfigs - tsup diff --git a/packages/trpc/.eslintrc.cjs b/packages/trpc/.eslintrc.cjs new file mode 100644 index 00000000..c7b13b75 --- /dev/null +++ b/packages/trpc/.eslintrc.cjs @@ -0,0 +1,7 @@ +/** @type {import('eslint').Linter.Config} */ +const config = { + root: true, + extends: ['orbitkit/base'], +}; + +module.exports = config; diff --git a/packages/trpc/package.json b/packages/trpc/package.json new file mode 100644 index 00000000..79a0feb9 --- /dev/null +++ b/packages/trpc/package.json @@ -0,0 +1,27 @@ +{ + "name": "@orbitkit/trpc", + "version": "0.1.0", + "private": true, + "description": "tRPC api for Orbitkit", + "license": "MIT", + "author": "Orbitkit", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "dependencies": { + "@orbitkit/auth": "workspace:^", + "@orbitkit/db": "workspace:^", + "@trpc/client": "^10.45.1", + "@trpc/next": "^10.45.1", + "@trpc/react-query": "^10.45.1", + "@trpc/server": "^10.45.1", + "superjson": "^2.2.1", + "zod": "^3.22.4" + }, + "devDependencies": { + "@orbitkit/tsconfig": "workspace:^", + "@types/node": "^20.11.16", + "eslint-config-orbitkit": "workspace:^" + } +} diff --git a/packages/trpc/src/index.ts b/packages/trpc/src/index.ts new file mode 100644 index 00000000..24a67638 --- /dev/null +++ b/packages/trpc/src/index.ts @@ -0,0 +1,14 @@ +import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server'; + +import { greetingRouter } from './routers/greeting'; +import { router } from './trpc'; + +export const appRouter = router({ + greeting: greetingRouter, +}); + +export type AppRouter = typeof appRouter; +export type RouterInputs = inferRouterInputs; +export type RouterOutputs = inferRouterOutputs; + +export { createTRPCContext } from './trpc'; diff --git a/packages/trpc/src/routers/greeting.ts b/packages/trpc/src/routers/greeting.ts new file mode 100644 index 00000000..e35bbbd4 --- /dev/null +++ b/packages/trpc/src/routers/greeting.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; + +import { protectedProcedure, publicProcedure, router } from '../trpc'; + +export const greetingRouter = router({ + hello: publicProcedure + .input(z.object({ name: z.string().optional() }).optional()) + .query(({ input }) => { + return { + greeting: `Hello, ${input?.name ?? 'World'}!`, + }; + }), + + protectedHello: protectedProcedure + .input(z.object({ name: z.string().optional() }).optional()) + .query(({ input, ctx }) => { + return { + greeting: `Hello, ${input?.name ?? 'World'}! Your user ID is ${ctx.session.user.id}`, + }; + }), +}); diff --git a/packages/trpc/src/trpc.ts b/packages/trpc/src/trpc.ts new file mode 100644 index 00000000..7a89ad0e --- /dev/null +++ b/packages/trpc/src/trpc.ts @@ -0,0 +1,45 @@ +import { initTRPC, TRPCError } from '@trpc/server'; +import superjson from 'superjson'; +import { ZodError } from 'zod'; + +import { getSession } from '@orbitkit/auth'; +import { db } from '@orbitkit/db'; + +export const createTRPCContext = async (opts: { headers: Headers }) => { + const session = await getSession(); + + return { + session, + db, + ...opts, + }; +}; + +const t = initTRPC.context().create({ + transformer: superjson, + errorFormatter({ shape, error }) { + return { + ...shape, + data: { + ...shape.data, + zodError: + error.cause instanceof ZodError ? error.cause.flatten() : null, + }, + }; + }, +}); + +export const router = t.router; +export const publicProcedure = t.procedure; + +export const protectedProcedure = t.procedure.use(({ ctx, next }) => { + if (!ctx.session.user) { + throw new TRPCError({ code: 'UNAUTHORIZED' }); + } + + return next({ + ctx: { + session: { ...ctx.session, user: ctx.session.user }, + }, + }); +}); diff --git a/packages/trpc/tsconfig.json b/packages/trpc/tsconfig.json new file mode 100644 index 00000000..8918efae --- /dev/null +++ b/packages/trpc/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": ["@orbitkit/tsconfig/base.json"], + "include": ["**/*.ts", ".eslintrc.cjs", "**/*.mjs"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58ca01d1..004fdbcf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,15 +159,30 @@ importers: '@orbitkit/db': specifier: workspace:^ version: link:../../packages/db + '@orbitkit/trpc': + specifier: workspace:^ + version: link:../../packages/trpc '@orbitkit/ui': specifier: workspace:^ version: link:../../packages/ui '@t3-oss/env-nextjs': specifier: ^0.8.0 version: 0.8.0(typescript@5.3.3)(zod@3.22.4) + '@tanstack/react-query': + specifier: 4.36.1 + version: 4.36.1(react-dom@18.2.0)(react@18.2.0) '@total-typescript/ts-reset': specifier: ^0.5.1 version: 0.5.1 + '@trpc/client': + specifier: ^10.45.1 + version: 10.45.1(@trpc/server@10.45.1) + '@trpc/react-query': + specifier: ^10.45.1 + version: 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0) + '@trpc/server': + specifier: ^10.45.1 + version: 10.45.1 geist: specifier: ^1.2.2 version: 1.2.2(next@14.1.0) @@ -183,6 +198,12 @@ importers: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + server-only: + specifier: ^0.0.1 + version: 0.0.1 + superjson: + specifier: ^2.2.1 + version: 2.2.1 zod: specifier: ^3.22.4 version: 3.22.4 @@ -384,6 +405,43 @@ importers: specifier: ^4.7.0 version: 4.7.0 + packages/trpc: + dependencies: + '@orbitkit/auth': + specifier: workspace:^ + version: link:../auth + '@orbitkit/db': + specifier: workspace:^ + version: link:../db + '@trpc/client': + specifier: ^10.45.1 + version: 10.45.1(@trpc/server@10.45.1) + '@trpc/next': + specifier: ^10.45.1 + version: 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/react-query@10.45.1)(@trpc/server@10.45.1)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0) + '@trpc/react-query': + specifier: ^10.45.1 + version: 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0) + '@trpc/server': + specifier: ^10.45.1 + version: 10.45.1 + superjson: + specifier: ^2.2.1 + version: 2.2.1 + zod: + specifier: ^3.22.4 + version: 3.22.4 + devDependencies: + '@orbitkit/tsconfig': + specifier: workspace:^ + version: link:../config/tsconfig + '@types/node': + specifier: ^20.11.16 + version: 20.11.16 + eslint-config-orbitkit: + specifier: workspace:^ + version: link:../config/eslint + packages/ui: dependencies: '@orbitkit/assets': @@ -6139,6 +6197,28 @@ packages: tailwindcss: 3.4.1 dev: false + /@tanstack/query-core@4.36.1: + resolution: {integrity: sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==} + dev: false + + /@tanstack/react-query@4.36.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@tanstack/query-core': 4.36.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + /@testing-library/dom@9.3.4: resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} engines: {node: '>=14'} @@ -6208,6 +6288,54 @@ packages: resolution: {integrity: sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==} dev: false + /@trpc/client@10.45.1(@trpc/server@10.45.1): + resolution: {integrity: sha512-nVbAk1xpIiI64WgzXGgfxPOGgHoYvffn1IsjV1D/Ri7DL4BKuo2qtZ7UQ+OuHkzH2M8j4ikSVBDpk545fOdvpw==} + peerDependencies: + '@trpc/server': 10.45.1 + dependencies: + '@trpc/server': 10.45.1 + dev: false + + /@trpc/next@10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/react-query@10.45.1)(@trpc/server@10.45.1)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-HSuQ0OcKUtt8mcQ4Mz4GQpy5PkNYJNvC9EEHkqTkEGa71BLEPKviyVWaE7biOlxjA0tM0aDOM21id+cRkEpfXA==} + peerDependencies: + '@tanstack/react-query': ^4.18.0 + '@trpc/client': 10.45.1 + '@trpc/react-query': 10.45.1 + '@trpc/server': 10.45.1 + next: '*' + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': 10.45.1(@trpc/server@10.45.1) + '@trpc/react-query': 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0) + '@trpc/server': 10.45.1 + next: 14.1.0(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@trpc/react-query@10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-48OOMpwVjQFUQJqlp9/tW1lqESZg9YEqB5iVci7mYaDzZPEs/YUcV85XKvYzgeW+7K9oShX/JMVce8muON/6uQ==} + peerDependencies: + '@tanstack/react-query': ^4.18.0 + '@trpc/client': 10.45.1 + '@trpc/server': 10.45.1 + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': 10.45.1(@trpc/server@10.45.1) + '@trpc/server': 10.45.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@trpc/server@10.45.1: + resolution: {integrity: sha512-KOzBEVaHW9IxEedUP9E50y0tYxAuvlzyjn80Bpemw4rcNbT4WtJnhkFPUY+qDJl7Crt3B/oY2qMgSxVWi9toLg==} + dev: false + /@tybys/wasm-util@0.8.1: resolution: {integrity: sha512-GSsTwyBl4pIzsxAY5wroZdyQKyhXk0d8PCRZtrSZ2WEB1cBdrp2EgGBwHOGCZtIIPun/DL3+AykCv+J6fyRH4Q==} requiresBuild: true @@ -8291,7 +8419,6 @@ packages: engines: {node: '>=12.13'} dependencies: is-what: 4.1.16 - dev: true /core-js-compat@3.35.1: resolution: {integrity: sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==} @@ -11352,7 +11479,6 @@ packages: /is-what@4.1.16: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} - dev: true /is-windows@0.2.0: resolution: {integrity: sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==} @@ -15325,6 +15451,10 @@ packages: /server-destroy@1.0.1: resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==} + /server-only@0.0.1: + resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + dev: false + /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true @@ -15915,7 +16045,6 @@ packages: engines: {node: '>=16'} dependencies: copy-anything: 3.0.5 - dev: true /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} @@ -16792,6 +16921,14 @@ packages: tslib: 2.6.2 dev: true + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} From 35ece14b3c27f6ce0f6a13b6d71fd1e54e859b72 Mon Sep 17 00:00:00 2001 From: Ahmed Elsakaan Date: Wed, 7 Feb 2024 23:32:27 +0000 Subject: [PATCH 2/2] feat: final touches --- apps/web/src/app/page.tsx | 4 +- apps/web/src/app/providers.tsx | 2 +- .../src/lib/trpc/{react.tsx => client.tsx} | 0 apps/web/src/lib/trpc/shared.ts | 7 ++ package.json | 2 +- packages/auth/package.json | 2 +- packages/db/package.json | 2 +- packages/trpc/package.json | 10 +- packages/trpc/src/index.ts | 4 - pnpm-lock.yaml | 97 +++++++------------ 10 files changed, 55 insertions(+), 75 deletions(-) rename apps/web/src/lib/trpc/{react.tsx => client.tsx} (100%) diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index ddd0588a..a0563e57 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -3,6 +3,7 @@ import { redirect } from 'next/navigation'; import { getSession } from '@orbitkit/auth'; import { Avatar, AvatarFallback, AvatarImage } from '@orbitkit/ui/avatar'; +import { ThemeSwitcher } from '@/components/ThemeSwitcher'; import { trpc } from '@/lib/trpc/server'; export default async function Home() { @@ -11,12 +12,13 @@ export default async function Home() { return redirect('/login'); } - const hello = await trpc.greeting.hello.query({ name: 'John' }); + const hello = await trpc.greeting.protectedHello.query(); return (

Next.js app

{hello.greeting}

+ CN diff --git a/apps/web/src/app/providers.tsx b/apps/web/src/app/providers.tsx index 0121da4d..8813979a 100644 --- a/apps/web/src/app/providers.tsx +++ b/apps/web/src/app/providers.tsx @@ -3,7 +3,7 @@ import { type FC, type PropsWithChildren } from 'react'; import { ThemeProvider as NextThemesProvider } from 'next-themes'; -import { TRPCReactProvider } from '@/lib/trpc/react'; +import { TRPCReactProvider } from '@/lib/trpc/client'; export const Providers: FC = ({ children }) => { return ( diff --git a/apps/web/src/lib/trpc/react.tsx b/apps/web/src/lib/trpc/client.tsx similarity index 100% rename from apps/web/src/lib/trpc/react.tsx rename to apps/web/src/lib/trpc/client.tsx diff --git a/apps/web/src/lib/trpc/shared.ts b/apps/web/src/lib/trpc/shared.ts index 37f05269..d1611aa6 100644 --- a/apps/web/src/lib/trpc/shared.ts +++ b/apps/web/src/lib/trpc/shared.ts @@ -1,3 +1,7 @@ +import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server'; + +import { type AppRouter } from '@orbitkit/trpc'; + import { env } from '@/env'; function getBaseUrl() { @@ -9,3 +13,6 @@ function getBaseUrl() { export function getUrl() { return getBaseUrl() + '/api/trpc'; } + +export type RouterInputs = inferRouterInputs; +export type RouterOutputs = inferRouterOutputs; diff --git a/package.json b/package.json index 280334e3..11000452 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "prettier-plugin-packagejson": "^2.4.10", "prettier-plugin-tailwindcss": "^0.5.11", "rimraf": "^5.0.5", - "turbo": "^1.12.2", + "turbo": "^1.12.3", "typescript": "^5.3.3" }, "packageManager": "pnpm@8.15.1", diff --git a/packages/auth/package.json b/packages/auth/package.json index 9c688092..ae6319d2 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -25,7 +25,7 @@ "arctic": "^1.1.4", "lucia": "^3.0.1", "next": "14.1.0", - "oslo": "^1.0.4", + "oslo": "^1.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "zod": "^3.22.4" diff --git a/packages/db/package.json b/packages/db/package.json index c1451c5b..4eb9375d 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -25,7 +25,7 @@ "typecheck": "tsc --noEmit --tsBuildInfoFile .tsbuildinfo" }, "dependencies": { - "@neondatabase/serverless": "^0.7.2", + "@neondatabase/serverless": "^0.8.1", "@t3-oss/env-core": "^0.8.0", "drizzle-orm": "^0.29.3", "pg": "^8.11.3", diff --git a/packages/trpc/package.json b/packages/trpc/package.json index 79a0feb9..40ebea03 100644 --- a/packages/trpc/package.json +++ b/packages/trpc/package.json @@ -9,12 +9,13 @@ "exports": { ".": "./src/index.ts" }, + "scripts": { + "lint": "eslint . --cache --max-warnings 0", + "typecheck": "tsc --noEmit --tsBuildInfoFile .tsbuildinfo" + }, "dependencies": { "@orbitkit/auth": "workspace:^", "@orbitkit/db": "workspace:^", - "@trpc/client": "^10.45.1", - "@trpc/next": "^10.45.1", - "@trpc/react-query": "^10.45.1", "@trpc/server": "^10.45.1", "superjson": "^2.2.1", "zod": "^3.22.4" @@ -23,5 +24,8 @@ "@orbitkit/tsconfig": "workspace:^", "@types/node": "^20.11.16", "eslint-config-orbitkit": "workspace:^" + }, + "volta": { + "extends": "../../package.json" } } diff --git a/packages/trpc/src/index.ts b/packages/trpc/src/index.ts index 24a67638..70e31464 100644 --- a/packages/trpc/src/index.ts +++ b/packages/trpc/src/index.ts @@ -1,5 +1,3 @@ -import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server'; - import { greetingRouter } from './routers/greeting'; import { router } from './trpc'; @@ -8,7 +6,5 @@ export const appRouter = router({ }); export type AppRouter = typeof appRouter; -export type RouterInputs = inferRouterInputs; -export type RouterOutputs = inferRouterOutputs; export { createTRPCContext } from './trpc'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 004fdbcf..40c4a409 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,8 +72,8 @@ importers: specifier: ^5.0.5 version: 5.0.5 turbo: - specifier: ^1.12.2 - version: 1.12.2 + specifier: ^1.12.3 + version: 1.12.3 typescript: specifier: ^5.3.3 version: 5.3.3 @@ -262,8 +262,8 @@ importers: specifier: 14.1.0 version: 14.1.0(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) oslo: - specifier: ^1.0.4 - version: 1.0.4 + specifier: ^1.1.0 + version: 1.1.0 react: specifier: ^18.2.0 version: 18.2.0 @@ -371,14 +371,14 @@ importers: packages/db: dependencies: '@neondatabase/serverless': - specifier: ^0.7.2 - version: 0.7.2 + specifier: ^0.8.1 + version: 0.8.1 '@t3-oss/env-core': specifier: ^0.8.0 version: 0.8.0(typescript@5.3.3)(zod@3.22.4) drizzle-orm: specifier: ^0.29.3 - version: 0.29.3(@neondatabase/serverless@0.7.2)(pg@8.11.3)(postgres@3.4.3) + version: 0.29.3(@neondatabase/serverless@0.8.1)(pg@8.11.3)(postgres@3.4.3) pg: specifier: ^8.11.3 version: 8.11.3 @@ -413,15 +413,6 @@ importers: '@orbitkit/db': specifier: workspace:^ version: link:../db - '@trpc/client': - specifier: ^10.45.1 - version: 10.45.1(@trpc/server@10.45.1) - '@trpc/next': - specifier: ^10.45.1 - version: 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/react-query@10.45.1)(@trpc/server@10.45.1)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0) - '@trpc/react-query': - specifier: ^10.45.1 - version: 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0) '@trpc/server': specifier: ^10.45.1 version: 10.45.1 @@ -3520,8 +3511,8 @@ packages: tar-fs: 2.1.1 dev: true - /@neondatabase/serverless@0.7.2: - resolution: {integrity: sha512-wU3WA2uTyNO7wjPs3Mg0G01jztAxUxzd9/mskMmtPwPTjf7JKWi9AW5/puOGXLxmZ9PVgRFeBVRVYq5nBPhsCg==} + /@neondatabase/serverless@0.8.1: + resolution: {integrity: sha512-nxZfTLbGqvDrw0W9WnQxzoPn4KC6SLjkvK4grdf6eWVMQSc24X+8udz9inZWOGu8f0O3wJAq586fCZ32r22lwg==} dependencies: '@types/pg': 8.6.6 dev: false @@ -6296,26 +6287,6 @@ packages: '@trpc/server': 10.45.1 dev: false - /@trpc/next@10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/react-query@10.45.1)(@trpc/server@10.45.1)(next@14.1.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-HSuQ0OcKUtt8mcQ4Mz4GQpy5PkNYJNvC9EEHkqTkEGa71BLEPKviyVWaE7biOlxjA0tM0aDOM21id+cRkEpfXA==} - peerDependencies: - '@tanstack/react-query': ^4.18.0 - '@trpc/client': 10.45.1 - '@trpc/react-query': 10.45.1 - '@trpc/server': 10.45.1 - next: '*' - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0) - '@trpc/client': 10.45.1(@trpc/server@10.45.1) - '@trpc/react-query': 10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0) - '@trpc/server': 10.45.1 - next: 14.1.0(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@trpc/react-query@10.45.1(@tanstack/react-query@4.36.1)(@trpc/client@10.45.1)(@trpc/server@10.45.1)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-48OOMpwVjQFUQJqlp9/tW1lqESZg9YEqB5iVci7mYaDzZPEs/YUcV85XKvYzgeW+7K9oShX/JMVce8muON/6uQ==} peerDependencies: @@ -7518,7 +7489,7 @@ packages: dotenv: 16.4.1 front-matter: 4.0.2 nanoid: 4.0.2 - oslo: 1.0.4 + oslo: 1.1.0 dev: false /autoprefixer@10.4.17(postcss@8.4.34): @@ -9051,7 +9022,7 @@ packages: - supports-color dev: true - /drizzle-orm@0.29.3(@neondatabase/serverless@0.7.2)(pg@8.11.3)(postgres@3.4.3): + /drizzle-orm@0.29.3(@neondatabase/serverless@0.8.1)(pg@8.11.3)(postgres@3.4.3): resolution: {integrity: sha512-uSE027csliGSGYD0pqtM+SAQATMREb3eSM/U8s6r+Y0RFwTKwftnwwSkqx3oS65UBgqDOM0gMTl5UGNpt6lW0A==} peerDependencies: '@aws-sdk/client-rds-data': '>=3' @@ -9122,7 +9093,7 @@ packages: sqlite3: optional: true dependencies: - '@neondatabase/serverless': 0.7.2 + '@neondatabase/serverless': 0.8.1 pg: 8.11.3 postgres: 3.4.3 dev: false @@ -13877,8 +13848,8 @@ packages: '@node-rs/bcrypt': 1.9.2 dev: false - /oslo@1.0.4: - resolution: {integrity: sha512-f8gRy1Kb3+uY0HjBRyz0XcC7PU/EGU0wmXgiwWxvKhvHjlO01i15mDfQV3ncyKRWmcqLBRhnyRnhcFIs+3E9SA==} + /oslo@1.1.0: + resolution: {integrity: sha512-uUvVt1boGt1aO0oMjzyzxIiDGAkfOdh6jPOzfJZBXsOsHuHfvTnrW7ealrBb27sgg5pHnTjmen6xPz4so+gQEQ==} dependencies: '@node-rs/argon2': 1.7.0 '@node-rs/bcrypt': 1.9.0 @@ -16445,64 +16416,64 @@ packages: engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} dev: false - /turbo-darwin-64@1.12.2: - resolution: {integrity: sha512-Aq/ePQ5KNx6XGwlZWTVTqpQYfysm1vkwkI6kAYgrX5DjMWn+tUXrSgNx4YNte0F+V4DQ7PtuWX+jRG0h0ZNg0A==} + /turbo-darwin-64@1.12.3: + resolution: {integrity: sha512-dDglIaux+A4jOnB9CDH69sujmrnuLJLrKw1t3J+if6ySlFuxSwC++gDq9TVuOZo2+S7lFkGh+x5ytn3wp+jE8Q==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /turbo-darwin-arm64@1.12.2: - resolution: {integrity: sha512-wTr+dqkwJo/eXE+4SPTSeNBKyyfQJhI6I9sKVlCSBmtaNEqoGNgdVzgMUdqrg9AIFzLIiKO+zhfskNaSWpVFow==} + /turbo-darwin-arm64@1.12.3: + resolution: {integrity: sha512-5TqqeujEyHMoVUWGzSzUl5ERSg7HDCdbU3gBs5ziWTpFRpeJ/+Y15kYyZJcMQcubRIH3Y1hL/yA5IhlGdgXOMA==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /turbo-linux-64@1.12.2: - resolution: {integrity: sha512-BggBKrLojGarDaa2zBo+kUR3fmjpd6bLA8Unm3Aa2oJw0UvEi3Brd+w9lNsPZHXXQYBUzNUY2gCdxf3RteWb0g==} + /turbo-linux-64@1.12.3: + resolution: {integrity: sha512-yUreU+/gq4vlBtcdyfjz7slwz4zM1RG8sSXvyHmAS+QXqSrGkegg4qLl2fRbv/c3EyA/XbfcZuD6tcrXkejr6g==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /turbo-linux-arm64@1.12.2: - resolution: {integrity: sha512-v/apSRvVuwYjq1D9MJFsHv2EpGd1S4VoSdZvVfW6FaM06L8CFZa92urNR1svdGYN28YVKwK9Ikc9qudC6t/d5A==} + /turbo-linux-arm64@1.12.3: + resolution: {integrity: sha512-XRwAsp2eRSqZmaMVNrmHoKqofeJMuD87zmefZLTRAObh38hIwKgyl2QRsJIbteob5RN77yFbv3lAJ36UIY5h7w==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /turbo-windows-64@1.12.2: - resolution: {integrity: sha512-3uDdwXcRGkgopYFdPDpxQiuQjfQ12Fxq0fhj+iGymav0eWA4W4wzYwSdlUp6rT22qOBIzaEsrIspRwx1DsMkNg==} + /turbo-windows-64@1.12.3: + resolution: {integrity: sha512-CPnRfnUCtmFeShOtUdMCthySjmyHaoTyh9JueiYFvtCNeO3WfDMj63dpOQstQWHdJFYmIrIGfhAclcds9ePQYA==} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true - /turbo-windows-arm64@1.12.2: - resolution: {integrity: sha512-zNIHnwtQfJSjFi7movwhPQh2rfrcKZ7Xv609EN1yX0gEp9GxooCUi2yNnBQ8wTqFjioA2M5hZtGJQ0RrKaEm/Q==} + /turbo-windows-arm64@1.12.3: + resolution: {integrity: sha512-cYA/wlzvp4vlCNHYJ2AjNS3FLXWwUC/5CJompBkTeKFFB6AviE/iLkbIhFikCVSNXZk/3AGanpMUXIkt3bdlwg==} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /turbo@1.12.2: - resolution: {integrity: sha512-BcoQjBZ+LJCMdjzWhzQflOinUjek28rWXj07aaaAQ8T3Ehs0JFSjIsXOm4qIbo52G4xk3gFVcUtJhh/QRADl7g==} + /turbo@1.12.3: + resolution: {integrity: sha512-a6q8I0TK9ohACYbkmxzG/JYPuDC4VCvfmXLTlf321qQ4BIAhoyaOj/O2g+zJ6L1vNYnZ82G4LrbMfgLLngbLsg==} hasBin: true optionalDependencies: - turbo-darwin-64: 1.12.2 - turbo-darwin-arm64: 1.12.2 - turbo-linux-64: 1.12.2 - turbo-linux-arm64: 1.12.2 - turbo-windows-64: 1.12.2 - turbo-windows-arm64: 1.12.2 + turbo-darwin-64: 1.12.3 + turbo-darwin-arm64: 1.12.3 + turbo-linux-64: 1.12.3 + turbo-linux-arm64: 1.12.3 + turbo-windows-64: 1.12.3 + turbo-windows-arm64: 1.12.3 dev: true /tween-functions@1.2.0: