├── .eslintrc.js ├── .gitignore ├── .npmrc ├── .yarn └── install-state.gz ├── .yarnrc.yml ├── README.md ├── apps └── expo │ ├── .gitignore │ ├── app.json │ ├── app │ ├── api │ │ └── trpc │ │ │ └── [trpc]+api.ts │ └── index.tsx │ ├── assets │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon.png │ └── splash.png │ ├── babel.config.js │ ├── index.js │ ├── metro.config.js │ ├── package.json │ ├── tsconfig.json │ └── utils │ └── trpc.ts ├── package.json ├── packages ├── eslint-config │ ├── README.md │ ├── library.js │ ├── next.js │ ├── package.json │ └── react-internal.js ├── trpc-server │ ├── package.json │ ├── routers │ │ └── _app.ts │ └── trpc.ts └── typescript-config │ ├── base.json │ ├── expo.json │ ├── nextjs.json │ ├── package.json │ └── react-library.json ├── tsconfig.json ├── turbo.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This configuration only applies to the package manager root. 2 | /** @type {import("eslint").Linter.Config} */ 3 | module.exports = { 4 | ignorePatterns: ["apps/**", "packages/**"], 5 | extends: ["@repo/eslint-config/library.js"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | project: true, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # Local env files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Testing 16 | coverage 17 | 18 | # Turbo 19 | .turbo 20 | 21 | # Vercel 22 | .vercel 23 | 24 | # Build Outputs 25 | .next/ 26 | out/ 27 | build 28 | dist 29 | 30 | 31 | # Debug 32 | npm-debug.log* 33 | yarn-debug.log* 34 | yarn-error.log* 35 | 36 | # Misc 37 | .DS_Store 38 | *.pem 39 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intergalacticspacehighway/expo-trpc/5736872c4adc0915557515579e365f7d00658e97/.npmrc -------------------------------------------------------------------------------- /.yarn/install-state.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intergalacticspacehighway/expo-trpc/5736872c4adc0915557515579e365f7d00658e97/.yarn/install-state.gz -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Universal Expo tRPC 2 | 3 | - `apps/expo` - Universal frontend app with `@tanstack/react-query`, tRPC and expo-router. 4 | - `apps/expo/app/api/trpc/[trpc]+api.ts` - Expo API route with tRPC route handlers. 5 | - `packages/trpc-server` - tRPC routers and procedures. 6 | 7 | ### Installation 8 | 9 | Go to the root directory and run `yarn` to install dependencies. 10 | 11 | ### Run web app 12 | 13 | ```bash 14 | cd apps/expo 15 | yarn web 16 | ``` 17 | 18 | ### Run iOS app 19 | 20 | ```bash 21 | cd apps/expo 22 | yarn ios 23 | ``` 24 | 25 | ### Run android app 26 | 27 | ```bash 28 | cd apps/expo 29 | yarn android 30 | ``` 31 | -------------------------------------------------------------------------------- /apps/expo/.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # Expo 7 | .expo/ 8 | dist/ 9 | web-build/ 10 | 11 | # Native 12 | *.orig.* 13 | *.jks 14 | *.p8 15 | *.p12 16 | *.key 17 | *.mobileprovision 18 | 19 | # Metro 20 | .metro-health-check* 21 | 22 | # debug 23 | npm-debug.* 24 | yarn-debug.* 25 | yarn-error.* 26 | 27 | # macOS 28 | .DS_Store 29 | *.pem 30 | 31 | # local env files 32 | .env*.local 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | -------------------------------------------------------------------------------- /apps/expo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "drakula", 4 | "slug": "drakula", 5 | "version": "1.0.0", 6 | "scheme": "drakula", 7 | "orientation": "portrait", 8 | "icon": "./assets/icon.png", 9 | "userInterfaceStyle": "light", 10 | "splash": { 11 | "image": "./assets/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "assetBundlePatterns": ["**/*"], 16 | "ios": { 17 | "supportsTablet": true 18 | }, 19 | "android": { 20 | "adaptiveIcon": { 21 | "foregroundImage": "./assets/adaptive-icon.png", 22 | "backgroundColor": "#ffffff" 23 | } 24 | }, 25 | "web": { 26 | "favicon": "./assets/favicon.png", 27 | "bundler": "metro", 28 | "output": "server" 29 | }, 30 | "plugins": ["expo-router"] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/expo/app/api/trpc/[trpc]+api.ts: -------------------------------------------------------------------------------- 1 | import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; 2 | import { appRouter } from "@repo/trpc-server/routers/_app"; 3 | 4 | export async function GET(req: Request) { 5 | return fetchRequestHandler({ 6 | endpoint: "/api/trpc", 7 | req, 8 | router: appRouter, 9 | createContext: () => ({}), 10 | }); 11 | } 12 | 13 | export async function POST(req: Request) { 14 | return fetchRequestHandler({ 15 | endpoint: "/api/trpc", 16 | req, 17 | router: appRouter, 18 | createContext: () => ({}), 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /apps/expo/app/index.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 2 | import { httpBatchLink } from "@trpc/client"; 3 | import React, { useState } from "react"; 4 | import { trpc } from "../utils/trpc"; 5 | import { Button, Text } from "react-native"; 6 | 7 | function App() { 8 | const [queryClient] = useState(() => new QueryClient()); 9 | const [trpcClient] = useState(() => 10 | trpc.createClient({ 11 | links: [ 12 | httpBatchLink({ 13 | url: "http://localhost:8081/api/trpc", 14 | 15 | // You can pass any HTTP headers you wish here 16 | async headers() { 17 | return { 18 | // authorization: getAuthCookie(), 19 | }; 20 | }, 21 | }), 22 | ], 23 | }) 24 | ); 25 | 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | } 34 | 35 | const TestComp = () => { 36 | const userQuery = trpc.hello.useQuery({ 37 | text: "world", 38 | }); 39 | const echoMutate = trpc.echo.useMutation(); 40 | 41 | return ( 42 | <> 43 | {userQuery.data?.greeting} 44 |