Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions __fixtures__/test-project/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,18 @@ api/src/lib/generateGraphiQLHeader.*
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Expo
.expo
web-build
expo-env.d.ts
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
.metro-health-check*
*.pem
*.tsbuildinfo
2 changes: 2 additions & 0 deletions __fixtures__/test-project/app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# EXPO_PUBLIC_RWJS_API_GRAPHQL_URL=http://localhost:8911/graphql
# EXPO_PUBLIC_API_URL=http://localhost:8911
33 changes: 33 additions & 0 deletions __fixtures__/test-project/app/ambient.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable no-var */

declare global {
/**
* FQDN or absolute path to the GraphQL serverless function, without the trailing slash.
* Example: `./redwood/functions/graphql` or `https://api.redwoodjs.com/graphql`
*/
var RWJS_API_GRAPHQL_URL: string

/**
* URL or absolute path to serverless functions, without the trailing slash.
* Example: `./redwood/functions/` or `https://api.redwoodjs.com/`
**/
var RWJS_API_URL: string

// Provided by Vite.config in the user's project
var RWJS_ENV: {
RWJS_API_GRAPHQL_URL: string
/** URL or absolute path to serverless functions */
RWJS_API_URL: string
}

namespace NodeJS {
interface Global {
/** URL or absolute path to the GraphQL serverless function */
RWJS_API_GRAPHQL_URL: string
/** URL or absolute path to serverless functions */
RWJS_API_URL: string
}
}
}

export {}
42 changes: 42 additions & 0 deletions __fixtures__/test-project/app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"expo": {
"name": "app",
"slug": "app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "app",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"edgeToEdgeEnabled": true
},
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
]
],
"experiments": {
"typedRoutes": true
}
}
}
65 changes: 65 additions & 0 deletions __fixtures__/test-project/app/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react'

import MaterialIcons from '@expo/vector-icons/MaterialIcons'
import { Link, Tabs } from 'expo-router'
import { Button, Platform, View } from 'react-native'

import { HapticTab } from '@/components/HapticTab'
import TabBarBackground from '@/components/ui/TabBarBackground'
import { Colors } from '@/constants/Colors'
import { useAuth } from '@/context/auth'
import { useColorScheme } from '@/hooks/useColorScheme'

export default function TabLayout() {
const colorScheme = useColorScheme()
const { isAuthenticated, logOut } = useAuth()

return (
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
tabBarButton: HapticTab,
tabBarBackground: TabBarBackground,
tabBarStyle: Platform.select({
ios: {
// Use a transparent background on iOS to show the blur effect
position: 'absolute',
},
default: {},
}),
headerRight: () => (
<View style={{ marginRight: 16 }}>
{isAuthenticated ? (
<Button onPress={logOut} title="Logout" color="red" />
) : (
<Link href="/modal">Login</Link>
)}
</View>
),
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Posts',
tabBarIcon: ({ color }) => (
<MaterialIcons name="article" size={28} color={color} />
),
}}
/>
<Tabs.Screen
name="admin"
options={{
title: 'Admin',
tabBarIcon: ({ color }) => (
<MaterialIcons
name="admin-panel-settings"
size={28}
color={color}
/>
),
}}
/>
</Tabs>
)
}
35 changes: 35 additions & 0 deletions __fixtures__/test-project/app/app/(tabs)/admin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react'

import { gql, useQuery } from '@apollo/client'

import { Post, PostProps } from '@/components/Post'
import ThemedScrollView from '@/components/ThemedScrollView'

export const FIND_POSTS_QUERY = gql`
query FindPosts {
posts {
id
title
body
author {
email
fullName
}
createdAt
}
}
`

export default function AdminScreen() {
const { data } = useQuery<{ posts: PostProps['post'][] }>(FIND_POSTS_QUERY)

const posts = data?.posts ?? []

return (
<ThemedScrollView>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ThemedScrollView>
)
}
42 changes: 42 additions & 0 deletions __fixtures__/test-project/app/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react'

import { gql, useQuery } from '@apollo/client'

import { BlogPost, BlogPostProps } from '@/components/BlogPost'
import ThemedScrollView from '@/components/ThemedScrollView'
import { ThemedView } from '@/components/ThemedView'

const QUERY = gql`
query BlogPostsQuery {
blogPosts: posts {
id
title
body
author {
email
fullName
}
createdAt
}
}
`

export default function HomeScreen() {
const { data } = useQuery(QUERY)

const blogPosts: BlogPostProps['blogPost'][] = data?.blogPosts ?? []

return (
<ThemedScrollView>
<ThemedView>
{blogPosts.map((blogPost, index) => (
<BlogPost
key={blogPost.id}
blogPost={blogPost}
isLast={index === blogPosts.length - 1}
/>
))}
</ThemedView>
</ThemedScrollView>
)
}
34 changes: 34 additions & 0 deletions __fixtures__/test-project/app/app/+not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react'

import { Link, Stack } from 'expo-router'
import { StyleSheet } from 'react-native'

import { ThemedText } from '@/components/ThemedText'
import { ThemedView } from '@/components/ThemedView'

export default function NotFoundScreen() {
return (
<>
<Stack.Screen options={{ title: 'Oops!' }} />
<ThemedView style={styles.container}>
<ThemedText type="title">This screen does not exist.</ThemedText>
<Link href="/" style={styles.link}>
<ThemedText type="link">Go to home screen!</ThemedText>
</Link>
</ThemedView>
</>
)
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 20,
},
link: {
marginTop: 15,
paddingVertical: 15,
},
})
50 changes: 50 additions & 0 deletions __fixtures__/test-project/app/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react'

import {
DarkTheme,
DefaultTheme,
ThemeProvider,
} from '@react-navigation/native'
import { useFonts } from 'expo-font'
import { Stack } from 'expo-router'
import { StatusBar } from 'expo-status-bar'

import { RedwoodApolloProvider } from '@cedarjs/web/apollo'

import { AuthProvider, useAuth } from '@/context/auth'
import { useColorScheme } from '@/hooks/useColorScheme'

import 'react-native-reanimated'

export default function RootLayout() {
const colorScheme = useColorScheme()
const [loaded] = useFonts({
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
})

if (!loaded) {
// Async font loading only occurs in development.
return null
}

return (
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<AuthProvider>
<RedwoodApolloProvider
useAuth={useAuth}
graphQLClientConfig={{ uri: process.env.EXPO_PUBLIC_API_URL! }}
>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
<Stack.Screen
name="modal"
options={{ presentation: 'modal', title: 'Login' }}
/>
</Stack>
<StatusBar style="auto" />
</RedwoodApolloProvider>
</AuthProvider>
</ThemeProvider>
)
}
Loading
Loading