this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

start making app

+451 -907
-16
.env.example
··· 3 3 4 4 # This file will be committed to version control, so make sure not to have any secrets in it. 5 5 # If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets. 6 - 7 - # We use dotenv to load Prisma from Next.js' .env file 8 - # @see https://www.prisma.io/docs/reference/database-reference/connection-urls 9 - DATABASE_URL=file:./db.sqlite 10 - 11 - # @see https://next-auth.js.org/configuration/options#nextauth_url 12 - NEXTAUTH_URL=http://localhost:3000 13 - 14 - # You can generate the secret via 'openssl rand -base64 32' on Unix 15 - # @see https://next-auth.js.org/configuration/options#secret 16 - NEXTAUTH_SECRET=supersecret 17 - 18 - # Preconfigured Discord OAuth provider, works out-of-the-box 19 - # @see https://next-auth.js.org/providers/discord 20 - DISCORD_CLIENT_ID= 21 - DISCORD_CLIENT_SECRET=
+1 -1
.eslintrc.js
··· 1 1 /** @type {import("eslint").Linter.Config} */ 2 2 const config = { 3 3 root: true, 4 - extends: ["@acme/eslint-config"], // uses the config in `packages/config/eslint` 4 + extends: ["@graysky/eslint-config"], // uses the config in `packages/config/eslint` 5 5 parser: "@typescript-eslint/parser", 6 6 parserOptions: { 7 7 ecmaVersion: "latest",
-5
.github/workflows/ci.yml
··· 47 47 - name: Install deps (with cache) 48 48 run: pnpm install 49 49 50 - # Normally, this would be done as part of the turbo pipeline - however since the Expo app doesn't depend on `@acme/db` it doesn't care. 51 - # TODO: Free for all to find a better solution here. 52 - - name: Generate Prisma Client 53 - run: pnpm turbo db:generate 54 - 55 50 - name: Build, lint and type-check 56 51 run: pnpm turbo build lint type-check 57 52 env:
-4
.gitignore
··· 8 8 # testing 9 9 coverage 10 10 11 - # database 12 - **/prisma/db.sqlite 13 - **/prisma/db.sqlite-journal 14 - 15 11 # next.js 16 12 .next/ 17 13 out/
-8
.npmrc
··· 3 3 # @link https://docs.expo.dev/guides/monorepos/#common-issues 4 4 node-linker=hoisted 5 5 6 - # In order to cache Prisma correctly 7 - public-hoist-pattern[]=*prisma* 8 - 9 - # FIXME: @prisma/client is required by the @acme/auth, 10 - # but we don't want it installed there since it's already 11 - # installed in the @acme/db package 12 - strict-peer-dependencies=false 13 - 14 6 # Prevent pnpm from adding the "workspace:"" prefix to local 15 7 # packages as it casues issues with manypkg 16 8 # @link https://pnpm.io/npmrc#prefer-workspace-packages
+1 -2
.vscode/extensions.json
··· 2 2 "recommendations": [ 3 3 "esbenp.prettier-vscode", 4 4 "dbaeumer.vscode-eslint", 5 - "bradlc.vscode-tailwindcss", 6 - "Prisma.prisma" 5 + "bradlc.vscode-tailwindcss" 7 6 ] 8 7 }
+1
README.md
··· 5 5 ## Installation 6 6 7 7 There are two ways of initializing an app using `create-t3-turbo` starter. You can either use this repository as a template or use Turbo's CLI to init your project: 8 + 8 9 ```bash 9 10 npx create-turbo@latest -e https://github.com/t3-oss/create-t3-turbo 10 11 ```
+3 -3
apps/expo/app.config.ts
··· 10 10 userInterfaceStyle: "light", 11 11 splash: { 12 12 image: "./assets/icon.png", 13 - resizeMode: "contain", 14 - backgroundColor: "#1F104A", 13 + resizeMode: "cover", 14 + backgroundColor: "#888888", 15 15 }, 16 16 updates: { 17 17 fallbackToCacheTimeout: 0, ··· 24 24 android: { 25 25 adaptiveIcon: { 26 26 foregroundImage: "./assets/icon.png", 27 - backgroundColor: "#1F104A", 27 + backgroundColor: "#888888", 28 28 }, 29 29 }, 30 30 extra: {
apps/expo/assets/graysky.png

This is a binary file and will not be displayed.

apps/expo/assets/icon.png

This is a binary file and will not be displayed.

+1
apps/expo/index.tsx
··· 1 + import "react-native-polyfill-globals/auto"; 1 2 import { registerRootComponent } from "expo"; 2 3 import { ExpoRoot } from "expo-router"; 3 4
+15 -5
apps/expo/package.json
··· 1 1 { 2 - "name": "@acme/expo", 2 + "name": "@graysky/app", 3 3 "version": "0.1.0", 4 4 "main": "index.tsx", 5 5 "scripts": { ··· 12 12 "type-check": "tsc --noEmit" 13 13 }, 14 14 "dependencies": { 15 + "@atproto/api": "^0.2.7", 15 16 "@expo/metro-config": "^0.7.1", 16 17 "@shopify/flash-list": "1.4.2", 17 18 "@tanstack/react-query": "^4.28.0", 18 19 "@trpc/client": "^10.20.0", 19 20 "@trpc/react-query": "^10.20.0", 20 21 "@trpc/server": "^10.20.0", 22 + "base-64": "^1.0.0", 23 + "clsx": "^1.2.1", 21 24 "expo": "^48.0.10", 22 25 "expo-constants": "~14.2.1", 23 26 "expo-linking": "~4.0.1", ··· 28 31 "react": "18.2.0", 29 32 "react-dom": "18.2.0", 30 33 "react-native": "0.71.6", 34 + "react-native-fetch-api": "^3.0.0", 35 + "react-native-get-random-values": "^1.8.0", 36 + "react-native-polyfill-globals": "^3.1.0", 31 37 "react-native-safe-area-context": "4.5.0", 32 38 "react-native-screens": "~3.20.0", 33 - "superjson": "1.9.1" 39 + "react-native-url-polyfill": "^1.3.0", 40 + "superjson": "1.9.1", 41 + "tailwind-merge": "^1.12.0", 42 + "text-encoding": "^0.7.0", 43 + "web-streams-polyfill": "^3.2.1" 34 44 }, 35 45 "devDependencies": { 36 - "@acme/api": "*", 37 - "@acme/eslint-config": "*", 38 - "@acme/tailwind-config": "*", 39 46 "@babel/core": "^7.21.4", 40 47 "@babel/preset-env": "^7.21.4", 41 48 "@babel/runtime": "^7.21.0", 42 49 "@expo/config-plugins": "^6.0.1", 50 + "@graysky/api": "*", 51 + "@graysky/eslint-config": "*", 52 + "@graysky/tailwind-config": "*", 43 53 "@types/babel__core": "^7.20.0", 44 54 "@types/react": "^18.0.33", 45 55 "@types/webpack-env": "^1.18.0",
+7 -11
apps/expo/src/app/_layout.tsx
··· 1 - import React from "react"; 2 1 import { SafeAreaProvider } from "react-native-safe-area-context"; 3 2 import { Stack } from "expo-router"; 4 3 import { StatusBar } from "expo-status-bar"; 4 + import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 5 5 6 - import { TRPCProvider } from "../utils/api"; 6 + const queryClient = new QueryClient(); 7 7 8 - // This is the main layout of the app 9 - // It wraps your pages with the providers they need 10 - const RootLayout = () => { 8 + export default function RootLayout() { 11 9 return ( 12 - <TRPCProvider> 10 + <QueryClientProvider client={queryClient}> 13 11 <SafeAreaProvider> 14 12 {/* 15 13 The Stack component displays the current page. ··· 18 16 <Stack 19 17 screenOptions={{ 20 18 headerStyle: { 21 - backgroundColor: "#f472b6", 19 + backgroundColor: "#fff", 22 20 }, 23 21 }} 24 22 /> 25 23 <StatusBar /> 26 24 </SafeAreaProvider> 27 - </TRPCProvider> 25 + </QueryClientProvider> 28 26 ); 29 - }; 30 - 31 - export default RootLayout; 27 + }
+25 -127
apps/expo/src/app/index.tsx
··· 1 - import React from "react"; 2 - import { Button, Text, TextInput, TouchableOpacity, View } from "react-native"; 1 + import { 2 + ImageBackground, 3 + Text, 4 + View, 5 + type ImageSourcePropType, 6 + } from "react-native"; 3 7 import { SafeAreaView } from "react-native-safe-area-context"; 4 - import { Stack, useRouter } from "expo-router"; 5 - import { FlashList } from "@shopify/flash-list"; 8 + import { Link, Stack } from "expo-router"; 9 + import { StatusBar } from "expo-status-bar"; 6 10 7 - import { api, type RouterOutputs } from "../utils/api"; 11 + import { LinkButton } from "../components/button"; 8 12 9 - const PostCard: React.FC<{ 10 - post: RouterOutputs["post"]["all"][number]; 11 - onDelete: () => void; 12 - }> = ({ post, onDelete }) => { 13 - const router = useRouter(); 13 + // eslint-disable-next-line @typescript-eslint/no-var-requires 14 + const background = require("../../assets/graysky.png") as ImageSourcePropType; 14 15 16 + export default function LandingPage() { 15 17 return ( 16 - <View className="flex flex-row rounded-lg bg-white/10 p-4"> 17 - <View className="flex-grow"> 18 - <TouchableOpacity onPress={() => router.push(`/post/${post.id}`)}> 19 - <Text className="text-xl font-semibold text-pink-400"> 20 - {post.title} 18 + <View className="flex-1"> 19 + <StatusBar style="light" /> 20 + <Stack.Screen options={{ header: () => null }} /> 21 + <ImageBackground className="flex-1" source={background}> 22 + <SafeAreaView className="flex flex-1 items-stretch justify-between p-4"> 23 + <Text className="mx-auto mt-16 text-6xl font-bold text-white"> 24 + GRAYSKY 21 25 </Text> 22 - <Text className="mt-2 text-white">{post.content}</Text> 23 - </TouchableOpacity> 24 - </View> 25 - <TouchableOpacity onPress={onDelete}> 26 - <Text className="font-bold uppercase text-pink-400">Delete</Text> 27 - </TouchableOpacity> 28 - </View> 29 - ); 30 - }; 31 - 32 - const CreatePost: React.FC = () => { 33 - const utils = api.useContext(); 34 - 35 - const [title, setTitle] = React.useState(""); 36 - const [content, setContent] = React.useState(""); 37 - 38 - const { mutate, error } = api.post.create.useMutation({ 39 - async onSuccess() { 40 - setTitle(""); 41 - setContent(""); 42 - await utils.post.all.invalidate(); 43 - }, 44 - }); 45 - 46 - return ( 47 - <View className="mt-4"> 48 - <TextInput 49 - className="mb-2 rounded bg-white/10 p-2 text-white" 50 - placeholderTextColor="rgba(255, 255, 255, 0.5)" 51 - value={title} 52 - onChangeText={setTitle} 53 - placeholder="Title" 54 - /> 55 - {error?.data?.zodError?.fieldErrors.title && ( 56 - <Text className="mb-2 text-red-500"> 57 - {error.data.zodError.fieldErrors.title} 58 - </Text> 59 - )} 60 - <TextInput 61 - className="mb-2 rounded bg-white/10 p-2 text-white" 62 - placeholderTextColor="rgba(255, 255, 255, 0.5)" 63 - value={content} 64 - onChangeText={setContent} 65 - placeholder="Content" 66 - /> 67 - {error?.data?.zodError?.fieldErrors.content && ( 68 - <Text className="mb-2 text-red-500"> 69 - {error.data.zodError.fieldErrors.content} 70 - </Text> 71 - )} 72 - <TouchableOpacity 73 - className="rounded bg-pink-400 p-2" 74 - onPress={() => { 75 - mutate({ 76 - title, 77 - content, 78 - }); 79 - }} 80 - > 81 - <Text className="font-semibold text-white">Publish post</Text> 82 - </TouchableOpacity> 26 + <LinkButton href="/login" variant="white"> 27 + Log in 28 + </LinkButton> 29 + </SafeAreaView> 30 + </ImageBackground> 83 31 </View> 84 32 ); 85 - }; 86 - 87 - const Index = () => { 88 - const utils = api.useContext(); 89 - 90 - const postQuery = api.post.all.useQuery(); 91 - 92 - const deletePostMutation = api.post.delete.useMutation({ 93 - onSettled: () => utils.post.all.invalidate(), 94 - }); 95 - 96 - return ( 97 - <SafeAreaView className="bg-[#1F104A]"> 98 - {/* Changes page title visible on the header */} 99 - <Stack.Screen options={{ title: "Home Page" }} /> 100 - <View className="h-full w-full p-4"> 101 - <Text className="mx-auto pb-2 text-5xl font-bold text-white"> 102 - Create <Text className="text-pink-400">T3</Text> Turbo 103 - </Text> 104 - 105 - <Button 106 - onPress={() => void utils.post.all.invalidate()} 107 - title="Refresh posts" 108 - color={"#f472b6"} 109 - /> 110 - 111 - <View className="py-2"> 112 - <Text className="font-semibold italic text-white"> 113 - Press on a post 114 - </Text> 115 - </View> 116 - 117 - <FlashList 118 - data={postQuery.data} 119 - estimatedItemSize={20} 120 - ItemSeparatorComponent={() => <View className="h-2" />} 121 - renderItem={(p) => ( 122 - <PostCard 123 - post={p.item} 124 - onDelete={() => deletePostMutation.mutate(p.item.id)} 125 - /> 126 - )} 127 - /> 128 - 129 - <CreatePost /> 130 - </View> 131 - </SafeAreaView> 132 - ); 133 - }; 134 - 135 - export default Index; 33 + }
+70
apps/expo/src/app/login.tsx
··· 1 + import { useState } from "react"; 2 + import { Button, TextInput, View } from "react-native"; 3 + import { SafeAreaView } from "react-native-safe-area-context"; 4 + import { Stack } from "expo-router"; 5 + import { 6 + BskyAgent, 7 + type AtpSessionData, 8 + type AtpSessionEvent, 9 + } from "@atproto/api"; 10 + import { useMutation } from "@tanstack/react-query"; 11 + 12 + const agent = new BskyAgent({ 13 + service: "https://bsky.app", 14 + // persistSession(evt: AtpSessionEvent, sess?: AtpSessionData) { 15 + // // store the session-data for reuse 16 + // console.log({ 17 + // evt, 18 + // sess, 19 + // }); 20 + // }, 21 + }); 22 + 23 + export default function Login() { 24 + const [identifier, setIdentifier] = useState(""); 25 + const [password, setPassword] = useState(""); 26 + 27 + const login = useMutation({ 28 + mutationKey: ["login"], 29 + mutationFn: async () => { 30 + try { 31 + console.log({ identifier, password }); 32 + await agent.login({ identifier, password }); 33 + } catch (err) { 34 + console.error("caught error"); 35 + console.error((err as Error).stack); 36 + } 37 + }, 38 + }); 39 + 40 + return ( 41 + <SafeAreaView className="flex-1 px-4"> 42 + <Stack.Screen options={{ title: "Log in" }} /> 43 + <View className="flex gap-4"> 44 + <TextInput 45 + className="rounded bg-white p-2 text-base" 46 + placeholder="Username or email address" 47 + value={identifier} 48 + onChangeText={setIdentifier} 49 + autoCapitalize="none" 50 + /> 51 + <TextInput 52 + className="rounded bg-white p-2 text-base" 53 + placeholder="Password" 54 + value={password} 55 + onChangeText={setPassword} 56 + secureTextEntry 57 + /> 58 + {identifier && password && ( 59 + <View> 60 + <Button 61 + disabled={login.isLoading} 62 + onPress={() => login.mutate()} 63 + title="Log in" 64 + /> 65 + </View> 66 + )} 67 + </View> 68 + </SafeAreaView> 69 + ); 70 + }
-24
apps/expo/src/app/post/[id].tsx
··· 1 - import { SafeAreaView, Text, View } from "react-native"; 2 - import { SplashScreen, Stack, useSearchParams } from "expo-router"; 3 - 4 - import { api } from "../../utils/api"; 5 - 6 - const Post: React.FC = () => { 7 - const { id } = useSearchParams(); 8 - if (!id || typeof id !== "string") throw new Error("unreachable"); 9 - const { data } = api.post.byId.useQuery({ id }); 10 - 11 - if (!data) return <SplashScreen />; 12 - 13 - return ( 14 - <SafeAreaView className="bg-[#1F104A]"> 15 - <Stack.Screen options={{ title: data.title }} /> 16 - <View className="h-full w-full p-4"> 17 - <Text className="py-2 text-3xl font-bold text-white">{data.title}</Text> 18 - <Text className="py-4 text-white">{data.content}</Text> 19 - </View> 20 - </SafeAreaView> 21 - ); 22 - }; 23 - 24 - export default Post;
+60
apps/expo/src/components/button.tsx
··· 1 + import React from "react"; 2 + import { Text, TouchableOpacity } from "react-native"; 3 + import { useRouter } from "expo-router"; 4 + 5 + import { cx } from "../utils/cx"; 6 + 7 + interface ButtonProps extends React.PropsWithChildren { 8 + onPress: () => void; 9 + variant?: "white" | "black" | "outline"; 10 + className?: string; 11 + } 12 + 13 + export const Button = ({ 14 + onPress, 15 + variant = "black", 16 + className, 17 + children, 18 + }: ButtonProps) => { 19 + const isChildAString = typeof children === "string"; 20 + return ( 21 + <TouchableOpacity 22 + onPress={onPress} 23 + className={cx( 24 + "flex items-center justify-center rounded-sm px-4 py-2", 25 + { 26 + black: "bg-black", 27 + white: "bg-white", 28 + outline: "border border-black", 29 + }[variant], 30 + className, 31 + )} 32 + > 33 + {isChildAString ? ( 34 + <Text 35 + className={cx( 36 + "text-base", 37 + { 38 + black: "text-white", 39 + white: "text-black", 40 + outline: "text-black", 41 + }[variant], 42 + )} 43 + > 44 + {children} 45 + </Text> 46 + ) : ( 47 + children 48 + )} 49 + </TouchableOpacity> 50 + ); 51 + }; 52 + 53 + interface LinkProps extends Omit<ButtonProps, "onPress"> { 54 + href: string; 55 + } 56 + 57 + export const LinkButton = ({ href, ...props }: LinkProps) => { 58 + const router = useRouter(); 59 + return <Button onPress={() => router.push(href)} {...props} />; 60 + };
+2 -2
apps/expo/src/utils/api.tsx
··· 5 5 import { createTRPCReact } from "@trpc/react-query"; 6 6 import superjson from "superjson"; 7 7 8 - import { type AppRouter } from "@acme/api"; 8 + import { type AppRouter } from "@graysky/api"; 9 9 10 10 /** 11 11 * A set of typesafe hooks for consuming your API. 12 12 */ 13 13 export const api = createTRPCReact<AppRouter>(); 14 - export { type RouterInputs, type RouterOutputs } from "@acme/api"; 14 + export { type RouterInputs, type RouterOutputs } from "@graysky/api"; 15 15 16 16 /** 17 17 * Extend this function when going to production by
+4
apps/expo/src/utils/cx.ts
··· 1 + import clsx, { type ClassValue } from "clsx"; 2 + import { twMerge } from "tailwind-merge"; 3 + 4 + export const cx = (...values: ClassValue[]) => twMerge(clsx(...values));
+1 -1
apps/expo/tailwind.config.js
··· 2 2 3 3 // import { type Config } from "tailwindcss"; 4 4 5 - // import baseConfig from "@acme/tailwind-config"; 5 + // import baseConfig from "@graysky/tailwind-config"; 6 6 7 7 // export default { 8 8 // presets: [baseConfig],
+1 -1
apps/nextjs/next.config.mjs
··· 8 8 const config = { 9 9 reactStrictMode: true, 10 10 /** Enables hot reloading for local packages without a build step */ 11 - transpilePackages: ["@acme/api", "@acme/auth", "@acme/db"], 11 + transpilePackages: ["@graysky/api"], 12 12 /** We already do linting and typechecking as separate tasks in CI */ 13 13 eslint: { ignoreDuringBuilds: !!process.env.CI }, 14 14 typescript: { ignoreBuildErrors: !!process.env.CI },
+4 -7
apps/nextjs/package.json
··· 1 1 { 2 - "name": "@acme/nextjs", 2 + "name": "@graysky/nextjs", 3 3 "version": "0.1.0", 4 4 "private": true, 5 5 "scripts": { ··· 13 13 "with-env": "dotenv -e ../../.env --" 14 14 }, 15 15 "dependencies": { 16 - "@acme/api": "^0.1.0", 17 - "@acme/auth": "^0.1.0", 18 - "@acme/db": "^0.1.0", 19 - "@acme/tailwind-config": "^0.1.0", 16 + "@graysky/api": "^0.1.0", 17 + "@graysky/tailwind-config": "^0.1.0", 20 18 "@tanstack/react-query": "^4.28.0", 21 19 "@trpc/client": "^10.20.0", 22 20 "@trpc/next": "^10.20.0", 23 21 "@trpc/react-query": "^10.20.0", 24 22 "@trpc/server": "^10.20.0", 25 23 "next": "^13.3.0", 26 - "next-auth": "^4.22.0", 27 24 "react": "18.2.0", 28 25 "react-dom": "18.2.0", 29 26 "superjson": "1.9.1", 30 27 "zod": "^3.21.4" 31 28 }, 32 29 "devDependencies": { 33 - "@acme/eslint-config": "^0.1.0", 30 + "@graysky/eslint-config": "^0.1.0", 34 31 "@types/node": "^18.15.11", 35 32 "@types/react": "^18.0.33", 36 33 "@types/react-dom": "^18.0.11",
+1 -1
apps/nextjs/postcss.config.cjs
··· 1 1 // @ts-expect-error - No types for postcss 2 - module.exports = require("@acme/tailwind-config/postcss"); 2 + module.exports = require("@graysky/tailwind-config/postcss");
+2 -11
apps/nextjs/src/pages/_app.tsx
··· 1 1 import "../styles/globals.css"; 2 2 import type { AppType } from "next/app"; 3 - import type { Session } from "next-auth"; 4 - import { SessionProvider } from "next-auth/react"; 5 3 6 4 import { api } from "~/utils/api"; 7 5 8 - const MyApp: AppType<{ session: Session | null }> = ({ 9 - Component, 10 - pageProps: { session, ...pageProps }, 11 - }) => { 12 - return ( 13 - <SessionProvider session={session}> 14 - <Component {...pageProps} /> 15 - </SessionProvider> 16 - ); 6 + const MyApp: AppType = ({ Component, pageProps: { ...pageProps } }) => { 7 + return <Component {...pageProps} />; 17 8 }; 18 9 19 10 export default api.withTRPC(MyApp);
-5
apps/nextjs/src/pages/api/auth/[...nextauth].ts
··· 1 - import NextAuth from "next-auth"; 2 - 3 - import { authOptions } from "@acme/auth"; 4 - 5 - export default NextAuth(authOptions);
+1 -1
apps/nextjs/src/pages/api/trpc/[trpc].ts
··· 1 1 import { createNextApiHandler } from "@trpc/server/adapters/next"; 2 2 3 - import { appRouter, createTRPCContext } from "@acme/api"; 3 + import { appRouter, createTRPCContext } from "@graysky/api"; 4 4 5 5 // export API handler 6 6 export default createNextApiHandler({
+8 -148
apps/nextjs/src/pages/index.tsx
··· 1 1 import { useState } from "react"; 2 2 import type { NextPage } from "next"; 3 3 import Head from "next/head"; 4 - import { signIn, signOut } from "next-auth/react"; 5 - 6 - import { api, type RouterOutputs } from "~/utils/api"; 7 - 8 - const PostCard: React.FC<{ 9 - post: RouterOutputs["post"]["all"][number]; 10 - onPostDelete?: () => void; 11 - }> = ({ post, onPostDelete }) => { 12 - return ( 13 - <div className="flex flex-row rounded-lg bg-white/10 p-4 transition-all hover:scale-[101%]"> 14 - <div className="flex-grow"> 15 - <h2 className="text-2xl font-bold text-pink-400">{post.title}</h2> 16 - <p className="mt-2 text-sm">{post.content}</p> 17 - </div> 18 - <div> 19 - <span 20 - className="cursor-pointer text-sm font-bold uppercase text-pink-400" 21 - onClick={onPostDelete} 22 - > 23 - Delete 24 - </span> 25 - </div> 26 - </div> 27 - ); 28 - }; 29 - 30 - const CreatePostForm: React.FC = () => { 31 - const utils = api.useContext(); 32 - 33 - const [title, setTitle] = useState(""); 34 - const [content, setContent] = useState(""); 35 - 36 - const { mutate, error } = api.post.create.useMutation({ 37 - async onSuccess() { 38 - setTitle(""); 39 - setContent(""); 40 - await utils.post.all.invalidate(); 41 - }, 42 - }); 43 - 44 - return ( 45 - <div className="flex w-full max-w-2xl flex-col p-4"> 46 - <input 47 - className="mb-2 rounded bg-white/10 p-2 text-white" 48 - value={title} 49 - onChange={(e) => setTitle(e.target.value)} 50 - placeholder="Title" 51 - /> 52 - {error?.data?.zodError?.fieldErrors.title && ( 53 - <span className="mb-2 text-red-500"> 54 - {error.data.zodError.fieldErrors.title} 55 - </span> 56 - )} 57 - <input 58 - className="mb-2 rounded bg-white/10 p-2 text-white" 59 - value={content} 60 - onChange={(e) => setContent(e.target.value)} 61 - placeholder="Content" 62 - /> 63 - {error?.data?.zodError?.fieldErrors.content && ( 64 - <span className="mb-2 text-red-500"> 65 - {error.data.zodError.fieldErrors.content} 66 - </span> 67 - )} 68 - <button 69 - className="rounded bg-pink-400 p-2 font-bold" 70 - onClick={() => { 71 - mutate({ 72 - title, 73 - content, 74 - }); 75 - }} 76 - > 77 - Create 78 - </button> 79 - </div> 80 - ); 81 - }; 82 4 83 - const Home: NextPage = () => { 84 - const postQuery = api.post.all.useQuery(); 85 - 86 - const deletePostMutation = api.post.delete.useMutation({ 87 - onSettled: () => postQuery.refetch(), 88 - }); 5 + export const Home: NextPage = () => { 6 + const [count, setCount] = useState(0); 89 7 90 8 return ( 91 - <> 9 + <div> 92 10 <Head> 93 - <title>Create T3 App</title> 94 - <meta name="description" content="Generated by create-t3-app" /> 95 - <link rel="icon" href="/favicon.ico" /> 11 + <title>Home</title> 96 12 </Head> 97 - <main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> 98 - <div className="container mt-12 flex flex-col items-center justify-center gap-4 px-4 py-8"> 99 - <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]"> 100 - Create <span className="text-pink-400">T3</span> Turbo 101 - </h1> 102 - <AuthShowcase /> 103 13 104 - <CreatePostForm /> 105 - 106 - {postQuery.data ? ( 107 - <div className="w-full max-w-2xl"> 108 - {postQuery.data?.length === 0 ? ( 109 - <span>There are no posts!</span> 110 - ) : ( 111 - <div className="flex h-[40vh] justify-center overflow-y-scroll px-4 text-2xl"> 112 - <div className="flex w-full flex-col gap-4"> 113 - {postQuery.data?.map((p) => { 114 - return ( 115 - <PostCard 116 - key={p.id} 117 - post={p} 118 - onPostDelete={() => deletePostMutation.mutate(p.id)} 119 - /> 120 - ); 121 - })} 122 - </div> 123 - </div> 124 - )} 125 - </div> 126 - ) : ( 127 - <p>Loading...</p> 128 - )} 129 - </div> 14 + <main> 15 + <h1>Home</h1> 16 + <p>Count: {count}</p> 17 + <button onClick={() => setCount((c) => c + 1)} /> 130 18 </main> 131 - </> 132 - ); 133 - }; 134 - 135 - export default Home; 136 - 137 - const AuthShowcase: React.FC = () => { 138 - const { data: session } = api.auth.getSession.useQuery(); 139 - 140 - const { data: secretMessage } = api.auth.getSecretMessage.useQuery( 141 - undefined, // no input 142 - { enabled: !!session?.user }, 143 - ); 144 - 145 - return ( 146 - <div className="flex flex-col items-center justify-center gap-4"> 147 - {session?.user && ( 148 - <p className="text-center text-2xl text-white"> 149 - {session && <span>Logged in as {session?.user?.name}</span>} 150 - {secretMessage && <span> - {secretMessage}</span>} 151 - </p> 152 - )} 153 - <button 154 - className="rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20" 155 - onClick={session ? () => void signOut() : () => void signIn()} 156 - > 157 - {session ? "Sign out" : "Sign in"} 158 - </button> 159 19 </div> 160 20 ); 161 21 };
+2 -2
apps/nextjs/src/utils/api.ts
··· 2 2 import { createTRPCNext } from "@trpc/next"; 3 3 import superjson from "superjson"; 4 4 5 - import type { AppRouter } from "@acme/api"; 5 + import type { AppRouter } from "@graysky/api"; 6 6 7 7 const getBaseUrl = () => { 8 8 if (typeof window !== "undefined") return ""; // browser should use relative url ··· 30 30 ssr: false, 31 31 }); 32 32 33 - export { type RouterInputs, type RouterOutputs } from "@acme/api"; 33 + export { type RouterInputs, type RouterOutputs } from "@graysky/api";
+1 -1
apps/nextjs/tailwind.config.ts
··· 1 1 import type { Config } from "tailwindcss"; 2 2 3 - import baseConfig from "@acme/tailwind-config"; 3 + import baseConfig from "@graysky/tailwind-config"; 4 4 5 5 export default { 6 6 content: ["./src/**/*.tsx"],
+3 -2
package.json
··· 11 11 "clean:workspaces": "turbo clean", 12 12 "db:generate": "turbo db:generate", 13 13 "db:push": "turbo db:push db:generate", 14 - "dev": "turbo dev --parallel", 14 + "dev:both": "turbo dev --parallel", 15 + "dev": "turbo dev --filter @graysky/app", 15 16 "format": "prettier --write \"**/*.{js,cjs,mjs,ts,tsx,md,json}\" --ignore-path .gitignore", 16 17 "lint": "turbo lint && manypkg check", 17 18 "lint:fix": "turbo lint:fix && manypkg fix", 18 19 "type-check": "turbo type-check" 19 20 }, 20 21 "dependencies": { 21 - "@acme/eslint-config": "^0.1.0", 22 + "@graysky/eslint-config": "^0.1.0", 22 23 "@ianvs/prettier-plugin-sort-imports": "^3.7.2", 23 24 "@manypkg/cli": "^0.20.0", 24 25 "@types/prettier": "^2.7.2",
+2 -4
packages/api/package.json
··· 1 1 { 2 - "name": "@acme/api", 2 + "name": "@graysky/api", 3 3 "version": "0.1.0", 4 4 "main": "./index.ts", 5 5 "types": "./index.ts", ··· 11 11 "type-check": "tsc --noEmit" 12 12 }, 13 13 "dependencies": { 14 - "@acme/auth": "^0.1.0", 15 - "@acme/db": "^0.1.0", 16 14 "@trpc/client": "^10.20.0", 17 15 "@trpc/server": "^10.20.0", 18 16 "superjson": "1.9.1", 19 17 "zod": "^3.21.4" 20 18 }, 21 19 "devDependencies": { 22 - "@acme/eslint-config": "^0.1.0", 20 + "@graysky/eslint-config": "^0.1.0", 23 21 "eslint": "^8.38.0", 24 22 "typescript": "^5.0.4" 25 23 }
+2 -4
packages/api/src/root.ts
··· 1 - import { authRouter } from "./router/auth"; 2 - import { postRouter } from "./router/post"; 1 + import { uselessRouter } from "./router/useless"; 3 2 import { createTRPCRouter } from "./trpc"; 4 3 5 4 export const appRouter = createTRPCRouter({ 6 - post: postRouter, 7 - auth: authRouter, 5 + useless: uselessRouter, 8 6 }); 9 7 10 8 // export type definition of API
-11
packages/api/src/router/auth.ts
··· 1 - import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; 2 - 3 - export const authRouter = createTRPCRouter({ 4 - getSession: publicProcedure.query(({ ctx }) => { 5 - return ctx.session; 6 - }), 7 - getSecretMessage: protectedProcedure.query(() => { 8 - // testing type validation of overridden next-auth Session in @acme/auth package 9 - return "you can see this secret message!"; 10 - }), 11 - });
-27
packages/api/src/router/post.ts
··· 1 - import { z } from "zod"; 2 - 3 - import { createTRPCRouter, publicProcedure } from "../trpc"; 4 - 5 - export const postRouter = createTRPCRouter({ 6 - all: publicProcedure.query(({ ctx }) => { 7 - return ctx.prisma.post.findMany({ orderBy: { id: "desc" } }); 8 - }), 9 - byId: publicProcedure 10 - .input(z.object({ id: z.string() })) 11 - .query(({ ctx, input }) => { 12 - return ctx.prisma.post.findFirst({ where: { id: input.id } }); 13 - }), 14 - create: publicProcedure 15 - .input( 16 - z.object({ 17 - title: z.string().min(1), 18 - content: z.string().min(1), 19 - }), 20 - ) 21 - .mutation(({ ctx, input }) => { 22 - return ctx.prisma.post.create({ data: input }); 23 - }), 24 - delete: publicProcedure.input(z.string()).mutation(({ ctx, input }) => { 25 - return ctx.prisma.post.delete({ where: { id: input } }); 26 - }), 27 - });
+5
packages/api/src/router/useless.ts
··· 1 + import { createTRPCRouter, publicProcedure } from "../trpc"; 2 + 3 + export const uselessRouter = createTRPCRouter({ 4 + ping: publicProcedure.query(() => "pong"), 5 + });
+4 -42
packages/api/src/trpc.ts
··· 6 6 * tl;dr - this is where all the tRPC server stuff is created and plugged in. 7 7 * The pieces you will need to use are documented accordingly near the end 8 8 */ 9 - import { TRPCError, initTRPC } from "@trpc/server"; 9 + import { initTRPC } from "@trpc/server"; 10 10 import { type CreateNextContextOptions } from "@trpc/server/adapters/next"; 11 11 import superjson from "superjson"; 12 12 import { ZodError } from "zod"; 13 - 14 - import { getServerSession, type Session } from "@acme/auth"; 15 - import { prisma } from "@acme/db"; 16 13 17 14 /** 18 15 * 1. CONTEXT ··· 23 20 * processing a request 24 21 * 25 22 */ 26 - type CreateContextOptions = { 27 - session: Session | null; 28 - }; 23 + type CreateContextOptions = Record<string, never>; 29 24 30 25 /** 31 26 * This helper generates the "internals" for a tRPC context. If you need to use ··· 37 32 * @see https://create.t3.gg/en/usage/trpc#-servertrpccontextts 38 33 */ 39 34 const createInnerTRPCContext = (opts: CreateContextOptions) => { 40 - return { 41 - session: opts.session, 42 - prisma, 43 - }; 35 + return {}; 44 36 }; 45 37 46 38 /** ··· 52 44 const { req, res } = opts; 53 45 54 46 // Get the session from the server using the unstable_getServerSession wrapper function 55 - const session = await getServerSession({ req, res }); 56 47 57 - return createInnerTRPCContext({ 58 - session, 59 - }); 48 + return createInnerTRPCContext({}); 60 49 }; 61 50 62 51 /** ··· 100 89 * can still access user session data if they are logged in 101 90 */ 102 91 export const publicProcedure = t.procedure; 103 - 104 - /** 105 - * Reusable middleware that enforces users are logged in before running the 106 - * procedure 107 - */ 108 - const enforceUserIsAuthed = t.middleware(({ ctx, next }) => { 109 - if (!ctx.session?.user) { 110 - throw new TRPCError({ code: "UNAUTHORIZED" }); 111 - } 112 - return next({ 113 - ctx: { 114 - // infers the `session` as non-nullable 115 - session: { ...ctx.session, user: ctx.session.user }, 116 - }, 117 - }); 118 - }); 119 - 120 - /** 121 - * Protected (authed) procedure 122 - * 123 - * If you want a query or mutation to ONLY be accessible to logged in users, use 124 - * this. It verifies the session is valid and guarantees ctx.session.user is not 125 - * null 126 - * 127 - * @see https://trpc.io/docs/procedures 128 - */ 129 - export const protectedProcedure = t.procedure.use(enforceUserIsAuthed);
-3
packages/auth/index.ts
··· 1 - export { authOptions } from "./src/auth-options"; 2 - export { getServerSession } from "./src/get-session"; 3 - export type { Session } from "next-auth";
-26
packages/auth/package.json
··· 1 - { 2 - "name": "@acme/auth", 3 - "version": "0.1.0", 4 - "main": "./index.ts", 5 - "types": "./index.ts", 6 - "license": "MIT", 7 - "scripts": { 8 - "clean": "rm -rf .turbo node_modules", 9 - "lint": "eslint .", 10 - "lint:fix": "pnpm lint --fix", 11 - "type-check": "tsc --noEmit" 12 - }, 13 - "dependencies": { 14 - "@acme/db": "^0.1.0", 15 - "@next-auth/prisma-adapter": "^1.0.5", 16 - "next": "^13.3.0", 17 - "next-auth": "^4.22.0", 18 - "react": "18.2.0", 19 - "react-dom": "18.2.0" 20 - }, 21 - "devDependencies": { 22 - "@acme/eslint-config": "^0.1.0", 23 - "eslint": "^8.38.0", 24 - "typescript": "^5.0.4" 25 - } 26 - }
-59
packages/auth/src/auth-options.ts
··· 1 - import { PrismaAdapter } from "@next-auth/prisma-adapter"; 2 - import { type DefaultSession, type NextAuthOptions } from "next-auth"; 3 - import DiscordProvider from "next-auth/providers/discord"; 4 - 5 - import { prisma } from "@acme/db"; 6 - 7 - /** 8 - * Module augmentation for `next-auth` types 9 - * Allows us to add custom properties to the `session` object 10 - * and keep type safety 11 - * @see https://next-auth.js.org/getting-started/typescript#module-augmentation 12 - **/ 13 - declare module "next-auth" { 14 - interface Session extends DefaultSession { 15 - user: { 16 - id: string; 17 - // ...other properties 18 - // role: UserRole; 19 - } & DefaultSession["user"]; 20 - } 21 - 22 - // interface User { 23 - // // ...other properties 24 - // // role: UserRole; 25 - // } 26 - } 27 - 28 - /** 29 - * Options for NextAuth.js used to configure 30 - * adapters, providers, callbacks, etc. 31 - * @see https://next-auth.js.org/configuration/options 32 - **/ 33 - export const authOptions: NextAuthOptions = { 34 - callbacks: { 35 - session({ session, user }) { 36 - if (session.user) { 37 - session.user.id = user.id; 38 - // session.user.role = user.role; <-- put other properties on the session here 39 - } 40 - return session; 41 - }, 42 - }, 43 - adapter: PrismaAdapter(prisma), 44 - providers: [ 45 - DiscordProvider({ 46 - clientId: process.env.DISCORD_CLIENT_ID as string, 47 - clientSecret: process.env.DISCORD_CLIENT_SECRET as string, 48 - }), 49 - /** 50 - * ...add more providers here 51 - * 52 - * Most other providers require a bit more work than the Discord provider. 53 - * For example, the GitHub provider requires you to add the 54 - * `refresh_token_expires_in` field to the Account model. Refer to the 55 - * NextAuth.js docs for the provider you want to use. Example: 56 - * @see https://next-auth.js.org/providers/github 57 - **/ 58 - ], 59 - };
-18
packages/auth/src/get-session.ts
··· 1 - import type { 2 - GetServerSidePropsContext, 3 - NextApiRequest, 4 - NextApiResponse, 5 - } from "next"; 6 - import { getServerSession as $getServerSession } from "next-auth"; 7 - 8 - import { authOptions } from "./auth-options"; 9 - 10 - type GetServerSessionContext = 11 - | { 12 - req: GetServerSidePropsContext["req"]; 13 - res: GetServerSidePropsContext["res"]; 14 - } 15 - | { req: NextApiRequest; res: NextApiResponse }; 16 - export const getServerSession = (ctx: GetServerSessionContext) => { 17 - return $getServerSession(ctx.req, ctx.res, authOptions); 18 - };
-4
packages/auth/tsconfig.json
··· 1 - { 2 - "extends": "../../tsconfig.json", 3 - "include": ["src", "index.ts"] 4 - }
+1 -1
packages/config/eslint/package.json
··· 1 1 { 2 - "name": "@acme/eslint-config", 2 + "name": "@graysky/eslint-config", 3 3 "version": "0.1.0", 4 4 "main": "index.js", 5 5 "license": "MIT",
+1 -1
packages/config/tailwind/package.json
··· 1 1 { 2 - "name": "@acme/tailwind-config", 2 + "name": "@graysky/tailwind-config", 3 3 "version": "0.1.0", 4 4 "main": "index.ts", 5 5 "license": "MIT",
-16
packages/db/index.ts
··· 1 - import { PrismaClient } from "@prisma/client"; 2 - 3 - export * from "@prisma/client"; 4 - 5 - const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }; 6 - 7 - export const prisma = 8 - globalForPrisma.prisma || 9 - new PrismaClient({ 10 - log: 11 - process.env.NODE_ENV === "development" 12 - ? ["query", "error", "warn"] 13 - : ["error"], 14 - }); 15 - 16 - if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
-22
packages/db/package.json
··· 1 - { 2 - "name": "@acme/db", 3 - "version": "0.1.0", 4 - "main": "./index.ts", 5 - "types": "./index.ts", 6 - "license": "MIT", 7 - "scripts": { 8 - "clean": "rm -rf .turbo node_modules", 9 - "db:generate": "pnpm with-env prisma generate", 10 - "db:push": "pnpm with-env prisma db push --skip-generate", 11 - "dev": "pnpm with-env prisma studio --port 5556", 12 - "with-env": "dotenv -e ../../.env --" 13 - }, 14 - "dependencies": { 15 - "@prisma/client": "^4.12.0" 16 - }, 17 - "devDependencies": { 18 - "dotenv-cli": "^7.1.0", 19 - "prisma": "^4.12.0", 20 - "typescript": "^5.0.4" 21 - } 22 - }
-65
packages/db/prisma/schema.prisma
··· 1 - // This is your Prisma schema file, 2 - // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 - 4 - generator client { 5 - provider = "prisma-client-js" 6 - } 7 - 8 - datasource db { 9 - provider = "postgresql" 10 - url = env("DATABASE_URL") 11 - } 12 - 13 - model Post { 14 - id String @id @default(cuid()) 15 - title String 16 - content String 17 - } 18 - 19 - // NextAuth.js Models 20 - // NOTE: When using postgresql, mysql or sqlserver, 21 - // uncomment the @db.Text annotations below 22 - // @see https://next-auth.js.org/schemas/models 23 - model Account { 24 - id String @id @default(cuid()) 25 - userId String 26 - type String 27 - provider String 28 - providerAccountId String 29 - refresh_token String? // @db.Text 30 - access_token String? // @db.Text 31 - expires_at Int? 32 - token_type String? 33 - scope String? 34 - id_token String? // @db.Text 35 - session_state String? 36 - user User @relation(fields: [userId], references: [id], onDelete: Cascade) 37 - 38 - @@unique([provider, providerAccountId]) 39 - } 40 - 41 - model Session { 42 - id String @id @default(cuid()) 43 - sessionToken String @unique 44 - userId String 45 - expires DateTime 46 - user User @relation(fields: [userId], references: [id], onDelete: Cascade) 47 - } 48 - 49 - model User { 50 - id String @id @default(cuid()) 51 - name String? 52 - email String? @unique 53 - emailVerified DateTime? 54 - image String? 55 - accounts Account[] 56 - sessions Session[] 57 - } 58 - 59 - model VerificationToken { 60 - identifier String 61 - token String @unique 62 - expires DateTime 63 - 64 - @@unique([identifier, token]) 65 - }
-4
packages/db/tsconfig.json
··· 1 - { 2 - "extends": "../../tsconfig.json", 3 - "include": ["index.ts"] 4 - }
+219 -194
pnpm-lock.yaml
··· 4 4 5 5 .: 6 6 dependencies: 7 - '@acme/eslint-config': 7 + '@graysky/eslint-config': 8 8 specifier: ^0.1.0 9 9 version: link:packages/config/eslint 10 10 '@ianvs/prettier-plugin-sort-imports': ··· 34 34 35 35 apps/expo: 36 36 dependencies: 37 + '@atproto/api': 38 + specifier: ^0.2.7 39 + version: 0.2.7 37 40 '@expo/metro-config': 38 41 specifier: ^0.7.1 39 42 version: 0.7.1 ··· 52 55 '@trpc/server': 53 56 specifier: ^10.20.0 54 57 version: 10.20.0 58 + base-64: 59 + specifier: ^1.0.0 60 + version: 1.0.0 61 + clsx: 62 + specifier: ^1.2.1 63 + version: 1.2.1 55 64 expo: 56 65 specifier: ^48.0.10 57 66 version: 48.0.10(@babel/core@7.21.4) ··· 82 91 react-native: 83 92 specifier: 0.71.6 84 93 version: 0.71.6(@babel/core@7.21.4)(@babel/preset-env@7.21.4)(react@18.2.0) 94 + react-native-fetch-api: 95 + specifier: ^3.0.0 96 + version: 3.0.0 97 + react-native-get-random-values: 98 + specifier: ^1.8.0 99 + version: 1.8.0(react-native@0.71.6) 100 + react-native-polyfill-globals: 101 + specifier: ^3.1.0 102 + version: 3.1.0(base-64@1.0.0)(react-native-fetch-api@3.0.0)(react-native-get-random-values@1.8.0)(react-native-url-polyfill@1.3.0)(text-encoding@0.7.0)(web-streams-polyfill@3.2.1) 85 103 react-native-safe-area-context: 86 104 specifier: 4.5.0 87 105 version: 4.5.0(react-native@0.71.6)(react@18.2.0) 88 106 react-native-screens: 89 107 specifier: ~3.20.0 90 108 version: 3.20.0(react-native@0.71.6)(react@18.2.0) 109 + react-native-url-polyfill: 110 + specifier: ^1.3.0 111 + version: 1.3.0(react-native@0.71.6) 91 112 superjson: 92 113 specifier: 1.9.1 93 114 version: 1.9.1 115 + tailwind-merge: 116 + specifier: ^1.12.0 117 + version: 1.12.0 118 + text-encoding: 119 + specifier: ^0.7.0 120 + version: 0.7.0 121 + web-streams-polyfill: 122 + specifier: ^3.2.1 123 + version: 3.2.1 94 124 devDependencies: 95 - '@acme/api': 96 - specifier: '*' 97 - version: link:../../packages/api 98 - '@acme/eslint-config': 99 - specifier: '*' 100 - version: link:../../packages/config/eslint 101 - '@acme/tailwind-config': 102 - specifier: '*' 103 - version: link:../../packages/config/tailwind 104 125 '@babel/core': 105 126 specifier: ^7.21.4 106 127 version: 7.21.4 ··· 113 134 '@expo/config-plugins': 114 135 specifier: ^6.0.1 115 136 version: 6.0.1 137 + '@graysky/api': 138 + specifier: '*' 139 + version: link:../../packages/api 140 + '@graysky/eslint-config': 141 + specifier: '*' 142 + version: link:../../packages/config/eslint 143 + '@graysky/tailwind-config': 144 + specifier: '*' 145 + version: link:../../packages/config/tailwind 116 146 '@types/babel__core': 117 147 specifier: ^7.20.0 118 148 version: 7.20.0 ··· 137 167 138 168 apps/nextjs: 139 169 dependencies: 140 - '@acme/api': 170 + '@graysky/api': 141 171 specifier: ^0.1.0 142 172 version: link:../../packages/api 143 - '@acme/auth': 144 - specifier: ^0.1.0 145 - version: link:../../packages/auth 146 - '@acme/db': 147 - specifier: ^0.1.0 148 - version: link:../../packages/db 149 - '@acme/tailwind-config': 173 + '@graysky/tailwind-config': 150 174 specifier: ^0.1.0 151 175 version: link:../../packages/config/tailwind 152 176 '@tanstack/react-query': ··· 167 191 next: 168 192 specifier: ^13.3.0 169 193 version: 13.3.0(@babel/core@7.21.4)(react-dom@18.2.0)(react@18.2.0) 170 - next-auth: 171 - specifier: ^4.22.0 172 - version: 4.22.0(next@13.3.0)(react-dom@18.2.0)(react@18.2.0) 173 194 react: 174 195 specifier: 18.2.0 175 196 version: 18.2.0 ··· 183 204 specifier: ^3.21.4 184 205 version: 3.21.4 185 206 devDependencies: 186 - '@acme/eslint-config': 207 + '@graysky/eslint-config': 187 208 specifier: ^0.1.0 188 209 version: link:../../packages/config/eslint 189 210 '@types/node': ··· 216 237 217 238 packages/api: 218 239 dependencies: 219 - '@acme/auth': 220 - specifier: ^0.1.0 221 - version: link:../auth 222 - '@acme/db': 223 - specifier: ^0.1.0 224 - version: link:../db 225 240 '@trpc/client': 226 241 specifier: ^10.20.0 227 242 version: 10.20.0(@trpc/server@10.20.0) ··· 235 250 specifier: ^3.21.4 236 251 version: 3.21.4 237 252 devDependencies: 238 - '@acme/eslint-config': 239 - specifier: ^0.1.0 240 - version: link:../config/eslint 241 - eslint: 242 - specifier: ^8.38.0 243 - version: 8.38.0 244 - typescript: 245 - specifier: ^5.0.4 246 - version: 5.0.4 247 - 248 - packages/auth: 249 - dependencies: 250 - '@acme/db': 251 - specifier: ^0.1.0 252 - version: link:../db 253 - '@next-auth/prisma-adapter': 254 - specifier: ^1.0.5 255 - version: 1.0.5(@prisma/client@4.12.0)(next-auth@4.22.0) 256 - next: 257 - specifier: ^13.3.0 258 - version: 13.3.0(@babel/core@7.21.4)(react-dom@18.2.0)(react@18.2.0) 259 - next-auth: 260 - specifier: ^4.22.0 261 - version: 4.22.0(next@13.3.0)(react-dom@18.2.0)(react@18.2.0) 262 - react: 263 - specifier: 18.2.0 264 - version: 18.2.0 265 - react-dom: 266 - specifier: 18.2.0 267 - version: 18.2.0(react@18.2.0) 268 - devDependencies: 269 - '@acme/eslint-config': 253 + '@graysky/eslint-config': 270 254 specifier: ^0.1.0 271 255 version: link:../config/eslint 272 256 eslint: ··· 319 303 specifier: ^3.3.1 320 304 version: 3.3.1(postcss@8.4.21) 321 305 322 - packages/db: 323 - dependencies: 324 - '@prisma/client': 325 - specifier: ^4.12.0 326 - version: 4.12.0(prisma@4.12.0) 327 - devDependencies: 328 - dotenv-cli: 329 - specifier: ^7.1.0 330 - version: 7.1.0 331 - prisma: 332 - specifier: ^4.12.0 333 - version: 4.12.0 334 - typescript: 335 - specifier: ^5.0.4 336 - version: 5.0.4 337 - 338 306 packages: 339 307 340 308 /@ampproject/remapping@2.2.0: ··· 343 311 dependencies: 344 312 '@jridgewell/gen-mapping': 0.1.1 345 313 '@jridgewell/trace-mapping': 0.3.17 314 + 315 + /@atproto/api@0.2.7: 316 + resolution: {integrity: sha512-Sz+lLD5apC2f0FSClkElIrt4w+aLgzqJ/wqtFO7xuQH8+hGfxdfGuVIK5GEDQ7epeDlWvVhVSouP6ZdGSKKtSA==} 317 + dependencies: 318 + '@atproto/common-web': 0.1.0 319 + '@atproto/uri': 0.0.2 320 + '@atproto/xrpc': 0.1.0 321 + tlds: 1.238.0 322 + typed-emitter: 2.1.0 323 + dev: false 324 + 325 + /@atproto/common-web@0.1.0: 326 + resolution: {integrity: sha512-qD6xF60hvH+cP++fk/mt+0S9cxs94KsK+rNWypNlgnlp7r9By4ltXwtDSR/DNTA8mwDeularUno4VbTd2IWIzA==} 327 + dependencies: 328 + multiformats: 9.9.0 329 + uint8arrays: 3.0.0 330 + zod: 3.21.4 331 + dev: false 332 + 333 + /@atproto/identifier@0.1.0: 334 + resolution: {integrity: sha512-3LV7+4E6S0k8Rru7NBkyDF6Zf6NHVUXVS9d4l9fiXWMC49ghZMjq0vPmz80xjG1rRuFdJFbpRf4ApFciGxLIyQ==} 335 + dependencies: 336 + '@atproto/common-web': 0.1.0 337 + dev: false 338 + 339 + /@atproto/lexicon@0.1.0: 340 + resolution: {integrity: sha512-Iy+gV9w42xLhrZrmcbZh7VFoHjXuzWvecGHIfz44owNjjv7aE/d2P5BbOX/XicSkmQ8Qkpg0BqwYDD1XBVS+DQ==} 341 + dependencies: 342 + '@atproto/common-web': 0.1.0 343 + '@atproto/identifier': 0.1.0 344 + '@atproto/nsid': 0.0.1 345 + '@atproto/uri': 0.0.2 346 + iso-datestring-validator: 2.2.2 347 + multiformats: 9.9.0 348 + zod: 3.21.4 349 + dev: false 350 + 351 + /@atproto/nsid@0.0.1: 352 + resolution: {integrity: sha512-t5M6/CzWBVYoBbIvfKDpqPj/+ZmyoK9ydZSStcTXosJ27XXwOPhz0VDUGKK2SM9G5Y7TPes8S5KTAU0UdVYFCw==} 353 + dev: false 354 + 355 + /@atproto/uri@0.0.2: 356 + resolution: {integrity: sha512-/6otLZF7BLpT9suSdHuXLbL12nINcWPsLmcOI+dctqovWUjH+XIRVNXDQgBYSrPVetxMiknuEwWelmnA33AEXg==} 357 + dependencies: 358 + '@atproto/identifier': 0.1.0 359 + '@atproto/nsid': 0.0.1 360 + dev: false 361 + 362 + /@atproto/xrpc@0.1.0: 363 + resolution: {integrity: sha512-LhBeZkQwPezjEtricGYnG62udFglOqlnmMSS0KyWgEAPi4KMp4H2F4jNoXcf5NPtZ9S4N4hJaErHX4PJYv2lfA==} 364 + dependencies: 365 + '@atproto/lexicon': 0.1.0 366 + zod: 3.21.4 367 + dev: false 346 368 347 369 /@babel/code-frame@7.10.4: 348 370 resolution: {integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==} ··· 2293 2315 read-yaml-file: 1.1.0 2294 2316 dev: false 2295 2317 2296 - /@next-auth/prisma-adapter@1.0.5(@prisma/client@4.12.0)(next-auth@4.22.0): 2297 - resolution: {integrity: sha512-VqMS11IxPXrPGXw6Oul6jcyS/n8GLOWzRMrPr3EMdtD6eOalM6zz05j08PcNiis8QzkfuYnCv49OvufTuaEwYQ==} 2298 - peerDependencies: 2299 - '@prisma/client': '>=2.26.0 || >=3' 2300 - next-auth: ^4 2301 - dependencies: 2302 - '@prisma/client': 4.12.0(prisma@4.12.0) 2303 - next-auth: 4.22.0(next@13.3.0)(react-dom@18.2.0)(react@18.2.0) 2304 - dev: false 2305 - 2306 2318 /@next/env@13.3.0: 2307 2319 resolution: {integrity: sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==} 2308 2320 dev: false ··· 2428 2440 rimraf: 3.0.2 2429 2441 dev: false 2430 2442 2431 - /@panva/hkdf@1.0.2: 2432 - resolution: {integrity: sha512-MSAs9t3Go7GUkMhpKC44T58DJ5KGk2vBo+h1cqQeqlMfdGkxaVB78ZWpv9gYi/g2fa4sopag9gJsNvS8XGgWJA==} 2433 - dev: false 2434 - 2435 2443 /@pkgr/utils@2.3.1: 2436 2444 resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==} 2437 2445 engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} ··· 2444 2452 tslib: 2.5.0 2445 2453 dev: false 2446 2454 2447 - /@prisma/client@4.12.0(prisma@4.12.0): 2448 - resolution: {integrity: sha512-j9/ighfWwux97J2dS15nqhl60tYoH8V0IuSsgZDb6bCFcQD3fXbXmxjYC8GHhIgOk3lB7Pq+8CwElz2MiDpsSg==} 2449 - engines: {node: '>=14.17'} 2450 - requiresBuild: true 2451 - peerDependencies: 2452 - prisma: '*' 2453 - peerDependenciesMeta: 2454 - prisma: 2455 - optional: true 2456 - dependencies: 2457 - '@prisma/engines-version': 4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7 2458 - prisma: 4.12.0 2459 - dev: false 2460 - 2461 - /@prisma/engines-version@4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7: 2462 - resolution: {integrity: sha512-JIHNj5jlXb9mcaJwakM0vpgRYJIAurxTUqM0iX0tfEQA5XLZ9ONkIckkhuAKdAzocZ+80GYg7QSsfpjg7OxbOA==} 2463 - dev: false 2464 - 2465 - /@prisma/engines@4.12.0: 2466 - resolution: {integrity: sha512-0alKtnxhNB5hYU+ymESBlGI4b9XrGGSdv7Ud+8TE/fBNOEhIud0XQsAR+TrvUZgS4na5czubiMsODw0TUrgkIA==} 2467 - requiresBuild: true 2468 - 2469 2455 /@radix-ui/react-compose-refs@1.0.0(react@18.2.0): 2470 2456 resolution: {integrity: sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==} 2471 2457 peerDependencies: ··· 3635 3621 /balanced-match@1.0.2: 3636 3622 resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 3637 3623 3624 + /base-64@1.0.0: 3625 + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} 3626 + dev: false 3627 + 3638 3628 /base64-js@1.5.1: 3639 3629 resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 3640 3630 ··· 4045 4035 engines: {node: '>=0.8'} 4046 4036 dev: false 4047 4037 4038 + /clsx@1.2.1: 4039 + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} 4040 + engines: {node: '>=6'} 4041 + dev: false 4042 + 4048 4043 /collection-visit@1.0.0: 4049 4044 resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} 4050 4045 engines: {node: '>=0.10.0'} ··· 4188 4183 /convert-source-map@1.9.0: 4189 4184 resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} 4190 4185 4191 - /cookie@0.5.0: 4192 - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 4193 - engines: {node: '>= 0.6'} 4194 - dev: false 4195 - 4196 4186 /copy-anything@3.0.3: 4197 4187 resolution: {integrity: sha512-fpW2W/BqEzqPp29QS+MwwfisHCQZtiduTe/m8idFo0xbti9fIZ2WVhAsCv4ggFVH3AgCkVdpoOCtQC6gBrdhjw==} 4198 4188 engines: {node: '>=12.13'} ··· 5285 5275 - supports-color 5286 5276 dev: false 5287 5277 5278 + /fast-base64-decode@1.0.0: 5279 + resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} 5280 + dev: false 5281 + 5288 5282 /fast-deep-equal@3.1.3: 5289 5283 resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 5290 5284 ··· 6334 6328 /isexe@2.0.0: 6335 6329 resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 6336 6330 6331 + /iso-datestring-validator@2.2.2: 6332 + resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} 6333 + dev: false 6334 + 6337 6335 /isobject@2.1.0: 6338 6336 resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} 6339 6337 engines: {node: '>=0.10.0'} ··· 6475 6473 resolution: {integrity: sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==} 6476 6474 dev: false 6477 6475 6478 - /jose@4.13.1: 6479 - resolution: {integrity: sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==} 6480 - dev: false 6481 - 6482 6476 /js-sdsl@4.4.0: 6483 6477 resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==} 6484 6478 ··· 7590 7584 resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 7591 7585 dev: false 7592 7586 7587 + /multiformats@9.9.0: 7588 + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} 7589 + dev: false 7590 + 7593 7591 /mv@2.1.1: 7594 7592 resolution: {integrity: sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==} 7595 7593 engines: {node: '>=0.8.0'} ··· 7682 7680 resolution: {integrity: sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==} 7683 7681 dev: false 7684 7682 7685 - /next-auth@4.22.0(next@13.3.0)(react-dom@18.2.0)(react@18.2.0): 7686 - resolution: {integrity: sha512-08+kjnDoE7aQ52O996x6cwA3ffc2CbHIkrCgLYhbE+aDIJBKI0oA9UbIEIe19/+ODYJgpAHHOtJx4izmsgaVag==} 7687 - peerDependencies: 7688 - next: ^12.2.5 || ^13 7689 - nodemailer: ^6.6.5 7690 - react: ^17.0.2 || ^18 7691 - react-dom: ^17.0.2 || ^18 7692 - peerDependenciesMeta: 7693 - nodemailer: 7694 - optional: true 7695 - dependencies: 7696 - '@babel/runtime': 7.21.0 7697 - '@panva/hkdf': 1.0.2 7698 - cookie: 0.5.0 7699 - jose: 4.13.1 7700 - next: 13.3.0(@babel/core@7.21.4)(react-dom@18.2.0)(react@18.2.0) 7701 - oauth: 0.9.15 7702 - openid-client: 5.4.0 7703 - preact: 10.11.3 7704 - preact-render-to-string: 5.2.6(preact@10.11.3) 7705 - react: 18.2.0 7706 - react-dom: 18.2.0(react@18.2.0) 7707 - uuid: 8.3.2 7708 - dev: false 7709 - 7710 7683 /next@13.3.0(@babel/core@7.21.4)(react-dom@18.2.0)(react@18.2.0): 7711 7684 resolution: {integrity: sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==} 7712 7685 engines: {node: '>=14.6.0'} ··· 7834 7807 resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} 7835 7808 dev: false 7836 7809 7837 - /oauth@0.9.15: 7838 - resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} 7839 - dev: false 7840 - 7841 7810 /ob1@0.73.9: 7842 7811 resolution: {integrity: sha512-kHOzCOFXmAM26fy7V/YuXNKne2TyRiXbFAvPBIbuedJCZZWQZHLdPzMeXJI4Egt6IcfDttRzN3jQ90wOwq1iNw==} 7843 7812 dev: false ··· 7860 7829 kind-of: 3.2.2 7861 7830 dev: false 7862 7831 7863 - /object-hash@2.2.0: 7864 - resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} 7865 - engines: {node: '>= 6'} 7866 - dev: false 7867 - 7868 7832 /object-hash@3.0.0: 7869 7833 resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 7870 7834 engines: {node: '>= 6'} ··· 7944 7908 es-abstract: 1.21.0 7945 7909 dev: false 7946 7910 7947 - /oidc-token-hash@5.0.1: 7948 - resolution: {integrity: sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ==} 7949 - engines: {node: ^10.13.0 || >=12.0.0} 7950 - dev: false 7951 - 7952 7911 /on-finished@2.3.0: 7953 7912 resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} 7954 7913 engines: {node: '>= 0.8'} ··· 8003 7962 is-wsl: 2.2.0 8004 7963 dev: false 8005 7964 8006 - /openid-client@5.4.0: 8007 - resolution: {integrity: sha512-hgJa2aQKcM2hn3eyVtN12tEA45ECjTJPXCgUh5YzTzy9qwapCvmDTVPWOcWVL0d34zeQoQ/hbG9lJhl3AYxJlQ==} 8008 - dependencies: 8009 - jose: 4.13.1 8010 - lru-cache: 6.0.0 8011 - object-hash: 2.2.0 8012 - oidc-token-hash: 5.0.1 8013 - dev: false 8014 - 8015 7965 /optionator@0.9.1: 8016 7966 resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} 8017 7967 engines: {node: '>= 0.8.0'} ··· 8070 8020 /p-cancelable@1.1.0: 8071 8021 resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} 8072 8022 engines: {node: '>=6'} 8023 + dev: false 8024 + 8025 + /p-defer@3.0.0: 8026 + resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} 8027 + engines: {node: '>=8'} 8073 8028 dev: false 8074 8029 8075 8030 /p-finally@1.0.0: ··· 8379 8334 picocolors: 1.0.0 8380 8335 source-map-js: 1.0.2 8381 8336 8382 - /preact-render-to-string@5.2.6(preact@10.11.3): 8383 - resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} 8384 - peerDependencies: 8385 - preact: '>=10' 8386 - dependencies: 8387 - preact: 10.11.3 8388 - pretty-format: 3.8.0 8389 - dev: false 8390 - 8391 - /preact@10.11.3: 8392 - resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} 8393 - dev: false 8394 - 8395 8337 /prelude-ls@1.2.1: 8396 8338 resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 8397 8339 engines: {node: '>= 0.8.0'} ··· 8487 8429 react-is: 18.2.0 8488 8430 dev: false 8489 8431 8490 - /pretty-format@3.8.0: 8491 - resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} 8492 - dev: false 8493 - 8494 - /prisma@4.12.0: 8495 - resolution: {integrity: sha512-xqVper4mbwl32BWzLpdznHAYvYDWQQWK2tBfXjdUD397XaveRyAP7SkBZ6kFlIg8kKayF4hvuaVtYwXd9BodAg==} 8496 - engines: {node: '>=14.17'} 8497 - hasBin: true 8498 - requiresBuild: true 8499 - dependencies: 8500 - '@prisma/engines': 4.12.0 8501 - 8502 8432 /process-nextick-args@2.0.1: 8503 8433 resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} 8504 8434 dev: false ··· 8700 8630 - supports-color 8701 8631 dev: false 8702 8632 8633 + /react-native-fetch-api@3.0.0: 8634 + resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==} 8635 + dependencies: 8636 + p-defer: 3.0.0 8637 + dev: false 8638 + 8703 8639 /react-native-gesture-handler@2.9.0(react-native@0.71.6)(react@18.2.0): 8704 8640 resolution: {integrity: sha512-a0BcH3Qb1tgVqUutc6d3VuWQkI1AM3+fJx8dkxzZs9t06qA27QgURYFoklpabuWpsUTzuKRpxleykp25E8m7tg==} 8705 8641 peerDependencies: ··· 8715 8651 react-native: 0.71.6(@babel/core@7.21.4)(@babel/preset-env@7.21.4)(react@18.2.0) 8716 8652 dev: false 8717 8653 8654 + /react-native-get-random-values@1.8.0(react-native@0.71.6): 8655 + resolution: {integrity: sha512-H/zghhun0T+UIJLmig3+ZuBCvF66rdbiWUfRSNS6kv5oDSpa1ZiVyvRWtuPesQpT8dXj+Bv7WJRQOUP+5TB1sA==} 8656 + peerDependencies: 8657 + react-native: '>=0.56' 8658 + dependencies: 8659 + fast-base64-decode: 1.0.0 8660 + react-native: 0.71.6(@babel/core@7.21.4)(@babel/preset-env@7.21.4)(react@18.2.0) 8661 + dev: false 8662 + 8718 8663 /react-native-gradle-plugin@0.71.17: 8719 8664 resolution: {integrity: sha512-OXXYgpISEqERwjSlaCiaQY6cTY5CH6j73gdkWpK0hedxtiWMWgH+i5TOi4hIGYitm9kQBeyDu+wim9fA8ROFJA==} 8720 8665 dev: false 8721 8666 8667 + /react-native-polyfill-globals@3.1.0(base-64@1.0.0)(react-native-fetch-api@3.0.0)(react-native-get-random-values@1.8.0)(react-native-url-polyfill@1.3.0)(text-encoding@0.7.0)(web-streams-polyfill@3.2.1): 8668 + resolution: {integrity: sha512-6ACmV1SjXvZP2LN6J2yK58yNACKddcvoiKLrSQdISx32IdYStfdmGXrbAfpd+TANrTlIaZ2SLoFXohNwhnqm/w==} 8669 + peerDependencies: 8670 + base-64: '*' 8671 + react-native-fetch-api: '*' 8672 + react-native-get-random-values: '*' 8673 + react-native-url-polyfill: '*' 8674 + text-encoding: '*' 8675 + web-streams-polyfill: '*' 8676 + dependencies: 8677 + base-64: 1.0.0 8678 + react-native-fetch-api: 3.0.0 8679 + react-native-get-random-values: 1.8.0(react-native@0.71.6) 8680 + react-native-url-polyfill: 1.3.0(react-native@0.71.6) 8681 + text-encoding: 0.7.0 8682 + web-streams-polyfill: 3.2.1 8683 + dev: false 8684 + 8722 8685 /react-native-safe-area-context@4.5.0(react-native@0.71.6)(react@18.2.0): 8723 8686 resolution: {integrity: sha512-0WORnk9SkREGUg2V7jHZbuN5x4vcxj/1B0QOcXJjdYWrzZHgLcUzYWWIUecUPJh747Mwjt/42RZDOaFn3L8kPQ==} 8724 8687 peerDependencies: ··· 8739 8702 react-freeze: 1.0.3(react@18.2.0) 8740 8703 react-native: 0.71.6(@babel/core@7.21.4)(@babel/preset-env@7.21.4)(react@18.2.0) 8741 8704 warn-once: 0.1.1 8705 + dev: false 8706 + 8707 + /react-native-url-polyfill@1.3.0(react-native@0.71.6): 8708 + resolution: {integrity: sha512-w9JfSkvpqqlix9UjDvJjm1EjSt652zVQ6iwCIj1cVVkwXf4jQhQgTNXY6EVTwuAmUjg6BC6k9RHCBynoLFo3IQ==} 8709 + peerDependencies: 8710 + react-native: '*' 8711 + dependencies: 8712 + react-native: 0.71.6(@babel/core@7.21.4)(@babel/preset-env@7.21.4)(react@18.2.0) 8713 + whatwg-url-without-unicode: 8.0.0-3 8742 8714 dev: false 8743 8715 8744 8716 /react-native@0.71.6(@babel/core@7.21.4)(@babel/preset-env@7.21.4)(react@18.2.0): ··· 9114 9086 dependencies: 9115 9087 queue-microtask: 1.2.3 9116 9088 9089 + /rxjs@7.8.0: 9090 + resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} 9091 + requiresBuild: true 9092 + dependencies: 9093 + tslib: 2.5.0 9094 + dev: false 9095 + optional: true 9096 + 9117 9097 /safe-buffer@5.1.2: 9118 9098 resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 9119 9099 dev: false ··· 9684 9664 tslib: 2.5.0 9685 9665 dev: false 9686 9666 9667 + /tailwind-merge@1.12.0: 9668 + resolution: {integrity: sha512-Y17eDp7FtN1+JJ4OY0Bqv9OA41O+MS8c1Iyr3T6JFLnOgLg3EvcyMKZAnQ8AGyvB5Nxm3t9Xb5Mhe139m8QT/g==} 9669 + dev: false 9670 + 9687 9671 /tailwindcss@3.3.1(postcss@8.4.21): 9688 9672 resolution: {integrity: sha512-Vkiouc41d4CEq0ujXl6oiGFQ7bA3WEhUZdTgXAhtKxSy49OmKs8rEfQmupsfF0IGW8fv2iQkp1EVUuapCFrZ9g==} 9689 9673 engines: {node: '>=12.13.0'} ··· 9799 9783 source-map-support: 0.5.21 9800 9784 dev: false 9801 9785 9786 + /text-encoding@0.7.0: 9787 + resolution: {integrity: sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==} 9788 + deprecated: no longer maintained 9789 + dev: false 9790 + 9802 9791 /text-table@0.2.0: 9803 9792 resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 9804 9793 ··· 9833 9822 dependencies: 9834 9823 globalyzer: 0.1.0 9835 9824 globrex: 0.1.2 9825 + dev: false 9826 + 9827 + /tlds@1.238.0: 9828 + resolution: {integrity: sha512-lFPF9pZFhLrPodaJ0wt9QIN0l8jOxqmUezGZnm7BfkDSVd9q667oVIJukLVzhF+4oW7uDlrLlfJrL5yu9RWwew==} 9829 + hasBin: true 9836 9830 dev: false 9837 9831 9838 9832 /tmp@0.0.33: ··· 10052 10046 call-bind: 1.0.2 10053 10047 for-each: 0.3.3 10054 10048 is-typed-array: 1.1.10 10049 + dev: false 10050 + 10051 + /typed-emitter@2.1.0: 10052 + resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==} 10053 + optionalDependencies: 10054 + rxjs: 7.8.0 10055 10055 dev: false 10056 10056 10057 10057 /typescript@5.0.4: ··· 10073 10073 source-map: 0.6.1 10074 10074 dev: false 10075 10075 10076 + /uint8arrays@3.0.0: 10077 + resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} 10078 + dependencies: 10079 + multiformats: 9.9.0 10080 + dev: false 10081 + 10076 10082 /unbox-primitive@1.0.2: 10077 10083 resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} 10078 10084 dependencies: ··· 10285 10291 defaults: 1.0.4 10286 10292 dev: false 10287 10293 10294 + /web-streams-polyfill@3.2.1: 10295 + resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} 10296 + engines: {node: '>= 8'} 10297 + dev: false 10298 + 10288 10299 /webidl-conversions@3.0.1: 10289 10300 resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 10301 + dev: false 10302 + 10303 + /webidl-conversions@5.0.0: 10304 + resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} 10305 + engines: {node: '>=8'} 10290 10306 dev: false 10291 10307 10292 10308 /whatwg-fetch@3.6.2: 10293 10309 resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} 10310 + dev: false 10311 + 10312 + /whatwg-url-without-unicode@8.0.0-3: 10313 + resolution: {integrity: sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==} 10314 + engines: {node: '>=10'} 10315 + dependencies: 10316 + buffer: 5.7.1 10317 + punycode: 2.3.0 10318 + webidl-conversions: 5.0.0 10294 10319 dev: false 10295 10320 10296 10321 /whatwg-url@5.0.0:
-1
pnpm-workspace.yaml
··· 2 2 - apps/expo 3 3 - apps/nextjs 4 4 - packages/api 5 - - packages/auth 6 5 - packages/db 7 6 - packages/config/*
+1 -1
prettier.config.cjs
··· 23 23 "^(expo(.*)$)|^(expo$)", 24 24 "<THIRD_PARTY_MODULES>", 25 25 "", 26 - "^@acme/(.*)$", 26 + "^@graysky/(.*)$", 27 27 "", 28 28 "^~/utils/(.*)$", 29 29 "^~/components/(.*)$",
+1 -1
renovate.json
··· 3 3 "extends": ["config:base"], 4 4 "packageRules": [ 5 5 { 6 - "matchPackagePatterns": ["^@acme/"], 6 + "matchPackagePatterns": ["^@graysky/"], 7 7 "enabled": false 8 8 } 9 9 ],
+1 -15
turbo.json
··· 2 2 "$schema": "https://turborepo.org/schema.json", 3 3 "globalDependencies": ["**/.env"], 4 4 "pipeline": { 5 - "db:generate": { 6 - "inputs": ["prisma/schema.prisma"], 7 - "cache": false 8 - }, 9 - "db:push": { 10 - "inputs": ["prisma/schema.prisma"], 11 - "cache": false 12 - }, 13 5 "dev": { 14 6 "persistent": true, 15 7 "cache": false 16 8 }, 17 9 "build": { 18 - "dependsOn": ["^build", "^db:generate"], 10 + "dependsOn": ["^build"], 19 11 "outputs": [".next/**", ".expo/**"] 20 12 }, 21 13 "lint": {}, ··· 27 19 "cache": false 28 20 }, 29 21 "type-check": { 30 - "dependsOn": ["^db:generate"], 31 22 "cache": false 32 23 } 33 24 }, 34 25 "globalEnv": [ 35 26 "CI", 36 - "DATABASE_URL", 37 - "DISCORD_CLIENT_ID", 38 - "DISCORD_CLIENT_SECRET", 39 27 "EXPO_ROUTER_APP_ROOT", 40 - "NEXTAUTH_SECRET", 41 - "NEXTAUTH_URL", 42 28 "NODE_ENV", 43 29 "SKIP_ENV_VALIDATION", 44 30 "VERCEL",