Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: apollo client dev tools #1516

Draft
wants to merge 55 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
e62f545
Initial reactotron-apollo-client
Sep 8, 2023
325cd83
fix(apollo-client): get build working
frankcalise Oct 15, 2023
0c984ca
chore: lint fixes
frankcalise Oct 15, 2023
a028397
feat(search): search obj values from display cmd
frankcalise Oct 17, 2023
9d80011
feat(app): apollo client ui and routes
frankcalise Oct 17, 2023
4a31bd4
feat(apollo-client): cache subscriptions
frankcalise Oct 17, 2023
1f278a4
Add apollo to the reactotron example app.
markrickert Feb 14, 2024
490f544
Readme update for reactotron-apollo-client
markrickert Feb 14, 2024
0f5281e
feat(reactotron-app): Each client now has an explicit list of plugins.
markrickert Feb 14, 2024
467392e
Fix some linting issues in reactotron-apollo-client
markrickert Feb 14, 2024
6308fcf
Reapply changes from #1439 to the reactotron-apollo-client
markrickert Feb 14, 2024
13664a1
Export the apollo-client properly.
markrickert Feb 14, 2024
76e5942
refactor: remove prev deleted files
frankcalise Mar 22, 2024
adea63d
chore: fix bad merge
frankcalise Mar 22, 2024
ed6688e
feat(example-app): apollo detail screen
frankcalise Mar 22, 2024
3c40be8
chore(apollo-client): add some debug
frankcalise Mar 22, 2024
ae12112
Adding name to redux plugin to fix build error
morganick Mar 22, 2024
86371c9
fix(example-app): observer apollo screens
frankcalise Mar 22, 2024
24506a6
feat(apollo-client): WIP server side comms
frankcalise Sep 25, 2024
a32cd02
feat(core-ui): add apollo client context
frankcalise Oct 17, 2024
81cc42c
feat(core-ui): allow for valueRenderer override in TreeView
frankcalise Oct 17, 2024
609d2e5
feat(apollo-client): render cache keys and body with search
frankcalise Oct 17, 2024
ff0f52d
chore(tree-view): remove console log
frankcalise Oct 18, 2024
53e4d41
fix(reactotron): move apollo provider
frankcalise Oct 18, 2024
7d0fcea
fix(core-ui): add cache key to apollo ctx
frankcalise Oct 18, 2024
53cded5
fix(core-ui): expose checkbox component
frankcalise Oct 18, 2024
61ee561
feat(apollo-client): search cache by key or data
frankcalise Oct 18, 2024
99954d9
feat(apollo-client): cache expand initially option
frankcalise Oct 18, 2024
928af8e
feat(cache): implement pinned keys
frankcalise Oct 18, 2024
bfbab46
chore(cache): clean up
frankcalise Oct 18, 2024
c163c69
fix(apollo-client): highlight selected pinned cache key
frankcalise Oct 18, 2024
b750011
fix(core-ui): add foregroundDarker
frankcalise Oct 18, 2024
fad56bc
feat(apollo-client): add cache forward/back history buttons
frankcalise Oct 18, 2024
3092bc8
feat(apollo-client): add launch external url for specific data
frankcalise Oct 19, 2024
19820d2
feat(apollo-client): view __ref data via tooltip
frankcalise Oct 19, 2024
5c1c148
feat(apollo-client): restore last viewed key after tab nav
frankcalise Oct 20, 2024
465cca4
feat(apollo-client): persist pinned keys across tab change
frankcalise Oct 20, 2024
6cd773a
refactor(apollo-client): move data to ctx
frankcalise Oct 20, 2024
5f0340c
fix(example-app): remove temp mutate button on ApolloScreen
frankcalise Oct 20, 2024
d2f7d8d
feat(apollo-client): wire up edit cache data with temp value
frankcalise Oct 20, 2024
1845ec0
feat(apollo-client): implement edit cache value from UI
frankcalise Oct 20, 2024
efad80a
fix(apollo-client): type specific inputs for edit cache values
frankcalise Oct 21, 2024
cf083c9
feat(apollo-client): lock root query and cache key editing
frankcalise Oct 22, 2024
7c7c587
fix(sidebar): only load apollo tab if plugin available
frankcalise Oct 22, 2024
bd33335
feat(apollo-client): add copy object
frankcalise Oct 29, 2024
3945d17
refactor(apollo-client): move polling apollo state out of cache tab
frankcalise Oct 29, 2024
0968774
style(cache): fix left/right panel scrolling
frankcalise Oct 29, 2024
8476583
chore: merge branch 'master' into frankcalise/reactotron-apollo-client
frankcalise Oct 30, 2024
ef093f6
fix(apollo-client): fix rollup config
frankcalise Oct 30, 2024
f62d7af
chore: lint fixes
frankcalise Oct 30, 2024
06416f4
chore: merge branch 'master' into frankcalise/reactotron-apollo-client
frankcalise Oct 30, 2024
484519a
test: fix plugin objects needing name
frankcalise Oct 30, 2024
4c1b345
test(filter-commands): remove search object value test
frankcalise Oct 30, 2024
2776ac8
chore: typecheck fixes
frankcalise Oct 30, 2024
86ff6cd
Merge branch 'master' into frankcalise/reactotron-apollo-client
frankcalise Nov 14, 2024
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
30 changes: 17 additions & 13 deletions apps/example-app/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ import { useFonts } from "expo-font"
import React from "react"
import { initialWindowMetrics, SafeAreaProvider } from "react-native-safe-area-context"
import * as Linking from "expo-linking"
import { useInitialRootStore } from "app/mobxStateTree"
import { useInitialRootStore } from "app/stores/mobxStateTree"
import { AppNavigator, useNavigationPersistence } from "app/navigators"
import { ErrorBoundary } from "app/screens/ErrorScreen/ErrorBoundary"
import * as storage from "app/utils/storage"
import { customFontsToLoad } from "app/theme"
import Config from "app/config"
import { GestureHandlerRootView } from "react-native-gesture-handler"
import { StatusBar, ViewStyle } from "react-native"
import { store } from "app/redux"
import { store } from "app/stores/redux"
import { Provider as ReduxProvider } from "react-redux"
import { ApolloProvider } from "@apollo/client"
import { client as apolloClient } from "app/stores/apollo"

export const NAVIGATION_PERSISTENCE_KEY = "NAVIGATION_STATE"

Expand Down Expand Up @@ -101,17 +103,19 @@ function App(props: AppProps) {
// otherwise, we're ready to render the app
return (
<ReduxProvider store={store}>
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
<ApolloProvider client={apolloClient}>
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<ErrorBoundary catchErrors={Config.catchErrors}>
<GestureHandlerRootView style={$container}>
<AppNavigator
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
/>
</GestureHandlerRootView>
</ErrorBoundary>
</SafeAreaProvider>
</ApolloProvider>
</ReduxProvider>
)
}
Expand Down
3 changes: 3 additions & 0 deletions apps/example-app/app/devtools/ReactotronConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { ArgType } from "reactotron-core-client"
import { mst } from "reactotron-mst"
import apisaucePlugin from "reactotron-apisauce"
import { reactotronRedux } from "reactotron-redux"
import apolloPlugin from "reactotron-apollo-client"

import { clear } from "app/utils/storage"
import { goBack, resetRoot, navigate } from "app/navigators/navigationUtilities"

import { Reactotron } from "./ReactotronClient"
import { client } from "../stores/apollo" // <--- update this location

let DevMenu = null
/**
Expand All @@ -41,6 +43,7 @@ const reactotron = Reactotron.configure({
filter: (event) => /postProcessSnapshot|@APPLY_SNAPSHOT/.test(event.name) === false,
})
)
.use(apolloPlugin({ apolloClient: client }))

if (Platform.OS !== "web") {
reactotron.setAsyncStorageHandler?.(AsyncStorage)
Expand Down
11 changes: 11 additions & 0 deletions apps/example-app/app/navigators/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ export type AppStackParamList = {
MobxStateTree: undefined
AsyncStorage: undefined
Redux: undefined
Apollo: undefined
ApolloDetail: {
item: {
__typename: string
id: number
number: number | null
title: string
}
}
}

/**
Expand Down Expand Up @@ -103,6 +112,8 @@ const AppStack = function AppStack() {
options={{ title: "Async Storage" }}
/>
<Stack.Screen name="Redux" component={Screens.ReduxScreen} />
<Stack.Screen name="Apollo" component={Screens.ApolloScreen} />
<Stack.Screen name="ApolloDetail" component={Screens.ApolloDetailScreen} />
</Stack.Group>
</Stack.Navigator>
)
Expand Down
99 changes: 99 additions & 0 deletions apps/example-app/app/screens/ApolloDetailScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from "react"
import { FlatList, TextStyle, View, ViewStyle } from "react-native"
import { ListItem, Text } from "app/components"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"
import { gql, useQuery } from "@apollo/client"
import { observer } from "mobx-react-lite"

const SECTIONS_QUERY = gql`
query Sections($id: Int!) {
chapter(id: $id) {
sections {
number
title
}
}
}
`

interface Section {
number: number
title: string
}

interface SectionItemProps {
chapter: {
__typename: string
id: number
number: number | null
title: string
}
section: Section
onPress?: () => void
}

const SectionItem: React.FC<SectionItemProps> = ({ chapter, section, onPress }) => (
<ListItem
text={`${chapter.number}.${section.number}: ${section.title}`}
onPress={onPress}
containerStyle={{ paddingHorizontal: spacing.sm }}
/>
)

interface ApolloDetailScreenProps extends AppStackScreenProps<"ApolloDetail"> {}

export const ApolloDetailScreen: React.FC<ApolloDetailScreenProps> = observer(
function ApolloScreen({ route }) {
const id = route.params.item.id

const { data, loading } = useQuery(SECTIONS_QUERY, {
variables: { id },
})

const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom"])

return (
<FlatList
style={$container}
contentContainerStyle={$bottomContainerInsets}
data={loading ? [] : data.chapter.sections}
renderItem={({ item }) => <SectionItem section={item} chapter={route.params.item} />}
ListHeaderComponent={() => {
return (
<View>
<Text
text="Reactotron can intercept and inspect Apollo client queries"
style={$subheading}
preset="subheading"
/>
<Text text="Like this example from the GraphQL example app:" style={$subheading} />
<View style={$bottomBorder} />
</View>
)
}}
keyExtractor={(section) => section.number.toString()}
/>
)
}
)

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
}

const $text: TextStyle = {
color: colors.text,
}
const $subheading: TextStyle = {
...$text,
margin: spacing.sm,
}

const $bottomBorder: ViewStyle = {
borderBottomWidth: 1,
borderBottomColor: colors.text,
marginHorizontal: spacing.sm,
}
99 changes: 99 additions & 0 deletions apps/example-app/app/screens/ApolloScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from "react"
import { FlatList, TextStyle, View, ViewStyle } from "react-native"
import { ListItem, Text } from "app/components"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"
import { gql, useQuery } from "@apollo/client"
import { useNavigation } from "@react-navigation/native"
import { observer } from "mobx-react-lite"

const CHAPTERS_QUERY = gql`
query Chapters {
chapters {
id
number
title
}
}
`

const ChapterItem = ({
chapter,
onPress,
}: {
chapter: { id: number; number: number; title: string }
onPress?: () => void
}) => {
const { number, title } = chapter
let header, subheader

if (number) {
header = `Chapter ${number}`
subheader = ` - ${title}`
} else {
header = title
subheader = ""
}

return (
<ListItem
text={`${header}${subheader}`}
onPress={onPress}
containerStyle={{ paddingHorizontal: spacing.sm }}
/>
)
}

interface ApolloScreenProps extends AppStackScreenProps<"Apollo"> {}

export const ApolloScreen: React.FC<ApolloScreenProps> = observer(function ApolloScreen() {
const { data, loading } = useQuery(CHAPTERS_QUERY)
const navigation = useNavigation()

const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom"])

return (
<FlatList
style={$container}
contentContainerStyle={$bottomContainerInsets}
data={loading ? [] : data.chapters}
renderItem={({ item }) => (
<ChapterItem chapter={item} onPress={() => navigation.navigate("ApolloDetail", { item })} />
)}
ListHeaderComponent={() => {
return (
<View>
<Text
text="Reactotron can intercept and inspect Apollo client queries"
style={$subheading}
preset="subheading"
/>
<Text text="Like this example from the GraphQL example app:" style={$subheading} />
<View style={$bottomBorder} />
</View>
)
}}
keyExtractor={(chapter) => chapter.id.toString()}
/>
)
})

const $container: ViewStyle = {
flex: 1,
backgroundColor: colors.background,
}

const $text: TextStyle = {
color: colors.text,
}
const $subheading: TextStyle = {
...$text,
margin: spacing.sm,
}

const $bottomBorder: ViewStyle = {
borderBottomWidth: 1,
borderBottomColor: colors.text,
marginHorizontal: spacing.sm,
}
4 changes: 2 additions & 2 deletions apps/example-app/app/screens/ErrorGeneratorScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useDispatch } from "react-redux"
import { Button, Text } from "app/components"
import type { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import type { AppDispatch } from "app/redux"
import { throwAnError, throwErrorAsync } from "app/redux/errorSlice"
import type { AppDispatch } from "app/stores/redux"
import { throwAnError, throwErrorAsync } from "app/stores/redux/errorSlice"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"

interface ErrorGeneratorScreenProps extends AppStackScreenProps<"ErrorGenerator"> {}
Expand Down
2 changes: 1 addition & 1 deletion apps/example-app/app/screens/MobxStateTreeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ScrollView, TextStyle, View, ViewStyle } from "react-native"
import { Button, Text } from "app/components"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import { useStores } from "app/mobxStateTree"
import { useStores } from "app/stores/mobxStateTree"
import { Repo } from "app/components/Repo"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"

Expand Down
6 changes: 3 additions & 3 deletions apps/example-app/app/screens/ReduxScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { Button, Text } from "app/components"
import { Repo } from "app/components/Repo"
import { AppStackScreenProps } from "app/navigators"
import { colors, spacing } from "app/theme"
import type { AppDispatch, RootState } from "app/redux"
import { fetchAsync, reset as repoReset } from "app/redux/repoSlice"
import { changeSize, changeSpeed, reset as logoReset } from "app/redux/logoSlice"
import type { AppDispatch, RootState } from "app/stores/redux"
import { fetchAsync, reset as repoReset } from "app/stores/redux/repoSlice"
import { changeSize, changeSpeed, reset as logoReset } from "app/stores/redux/logoSlice"
import { useSafeAreaInsetsStyle } from "app/utils/useSafeAreaInsetsStyle"

interface ReduxScreenProps extends AppStackScreenProps<"Redux"> {}
Expand Down
6 changes: 6 additions & 0 deletions apps/example-app/app/screens/WelcomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ export const WelcomeScreen: React.FC<WelcomeScreenProps> = function WelcomeScree
navigation.navigate("Redux")
}}
/>
<ListItem
text="Apollo Client"
onPress={() => {
navigation.navigate("Apollo")
}}
/>
</View>
</ScrollView>
</SafeAreaView>
Expand Down
2 changes: 2 additions & 0 deletions apps/example-app/app/screens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export * from "./MobxStateTreeScreen"
export * from "./ReduxScreen"
export * from "./ErrorGeneratorScreen"
export * from "./AsyncStorageScreen"
export * from "./ApolloScreen"
export * from "./ApolloDetailScreen"

export * from "./ErrorScreen/ErrorBoundary"
// export other screens here
10 changes: 10 additions & 0 deletions apps/example-app/app/stores/apollo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ApolloClient, InMemoryCache } from "@apollo/client"

const cache = new InMemoryCache()

export const client = new ApolloClient({
uri: "https://api.graphql.guide/graphql",
cache,
defaultOptions: { watchQuery: { fetchPolicy: "cache-and-network" } },
connectToDevTools: true,
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
import { applySnapshot, IDisposer, onSnapshot } from "mobx-state-tree"
import { RootStore, RootStoreSnapshot } from "../RootStore"
import * as storage from "../../utils/storage"
import * as storage from "app/utils/storage"

/**
* The key we'll be saving our state as within async storage.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { configureStore } from "@reduxjs/toolkit"
import type { GetDefaultEnhancers } from "@reduxjs/toolkit/dist/getDefaultEnhancers"
import logoReducer from "../redux/logoSlice"
import repoReducer from "../redux/repoSlice"
import errorReducer from "../redux/errorSlice"
import logoReducer from "./logoSlice"
import repoReducer from "./repoSlice"
import errorReducer from "./errorSlice"

const createEnhancers = (getDefaultEnhancers: GetDefaultEnhancers<any>) => {
if (__DEV__) {
const reactotron = require("../devtools/ReactotronConfig").default
const reactotron = require("../../devtools/ReactotronConfig").default
return getDefaultEnhancers().concat(reactotron.createEnhancer())
} else {
return getDefaultEnhancers()
Expand Down
Loading