### Clone Repository and Install Dependencies (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md This snippet shows how to clone the project repository and install its dependencies using pnpm. It's the initial step for setting up the development environment. ```bash git clone https://github.com/LovesWorking/rn-better-dev-tools.git cd rn-better-dev-tools pnpm install ``` -------------------------------- ### Start Development Build (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md Commands to start the development server with hot reloading and to build the desktop application for testing. These are essential for iterative development and debugging. ```bash # Start in development mode with hot reload pnpm start # Build and copy to desktop for testing pnpm run make:desktop # Build only pnpm run make ``` -------------------------------- ### Configure Environment Variables (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md This command copies the example environment file and instructs the user to fill in Apple Developer credentials. This is crucial for building and signing the application on macOS. ```bash cp .env.example .env # Fill in your Apple Developer credentials in .env: # APPLE_ID=your.email@example.com # APPLE_PASSWORD=app-specific-password # APPLE_TEAM_ID=your-team-id ``` -------------------------------- ### Development Commands (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md A collection of useful development commands including a clean install, packaging without distributables, and running the linter. These commands help maintain a clean development environment and ensure code quality. ```bash # Clean install pnpm run nuke # Package without making distributables pnpm run package # Run linter pnpm run lint ``` -------------------------------- ### Install React Query External Sync and Socket.IO Client Source: https://github.com/buoy-gg/buoy-desktop/blob/main/README.md Installs necessary development dependencies for integrating React Query external sync and socket.IO client. Also installs expo-device for automatic device detection on React Native projects. ```bash # Using npm npm install --save-dev react-query-external-sync socket.io-client npm install expo-device # For automatic device detection # Using yarn yarn add -D react-query-external-sync socket.io-client yarn add expo-device # For automatic device detection # Using pnpm (recommended) pnpm add -D react-query-external-sync socket.io-client pnpm add expo-device # For automatic device detection ``` -------------------------------- ### Project Structure Overview Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md This section provides a high-level overview of the project's directory structure. It highlights key directories like `src/` for source code, `assets/` for static files, `.github/workflows/` for CI/CD, and `forge.config.ts` for Electron Forge configuration. ```plaintext . ├── src/ # Source code │ ├── main.ts # Main process │ ├── preload.ts # Preload scripts │ └── components/ # React components ├── assets/ # Static assets ├── .github/workflows/ # GitHub Actions └── forge.config.ts # Electron Forge config ``` -------------------------------- ### Install react-query-external-sync and socket.io-client Source: https://github.com/buoy-gg/buoy-desktop/blob/main/src/react-query-external-sync/README.md Installs the necessary packages for real-time React Query state synchronization using npm, yarn, or pnpm. These packages enable the communication between your application and the debugging tools. ```bash # Using npm npm install --save-dev react-query-external-sync socket.io-client # Using yarn yarn add -D react-query-external-sync socket.io-client # Using pnpm pnpm add -D react-query-external-sync socket.io-client ``` -------------------------------- ### Automate Release Process (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md This snippet demonstrates how to trigger the automated release script, which handles version bumping, building, tagging, and pushing to GitHub. It simplifies the release workflow. ```bash # Using npm script pnpm run auto-release # Or directly ./auto-release.sh ``` -------------------------------- ### Enable Debug Logs (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md Instructions to enable debug logs by adding a specific variable to the `.env` file. This is useful for diagnosing issues during development and building. ```bash DEBUG=electron-osx-sign* ``` -------------------------------- ### Local Build and Packaging Script Source: https://github.com/buoy-gg/buoy-desktop/blob/main/RELEASE.md Runs a script to build the application locally and create installation packages. The output is placed in a specific folder on the user's Desktop. ```bash pnpm run pack ``` -------------------------------- ### Connect React Query External Sync to Local Network IP with Expo Source: https://github.com/buoy-gg/buoy-desktop/blob/main/README.md This example shows how to configure the React Query External Sync hook for use with real devices on a local network using Expo. It dynamically retrieves the host machine's IP address and constructs the socket URL accordingly. It also includes setup for various storage types. ```jsx import Constants from "expo-constants"; import AsyncStorage from "@react-native-async-storage/async-storage"; import * as SecureStore from "expo-secure-store"; import { storage } from "./mmkv"; // Your MMKV instance // Get the host IP address dynamically const hostIP = Constants.expoGoConfig?.debuggerHost?.split(`:`)[0] || Constants.expoConfig?.hostUri?.split(`:`)[0]; function AppContent() { useSyncQueriesExternal({ queryClient, socketURL: `http://${hostIP}:42831`, // Use local network IP deviceName: Platform?.OS || "web", platform: Platform?.OS || "web", deviceId: Platform?.OS || "web", extraDeviceInfo: { appVersion: "1.0.0", }, enableLogs: false, envVariables: { NODE_ENV: process.env.NODE_ENV, }, // Storage monitoring mmkvStorage: storage, asyncStorage: AsyncStorage, secureStorage: SecureStore, secureStorageKeys: ["userToken", "refreshToken"], }); return ; } ``` -------------------------------- ### Fix Permissions and Clean Build Artifacts (Bash) Source: https://github.com/buoy-gg/buoy-desktop/blob/main/DEVELOPMENT.md These commands address common permission issues and clean up build artifacts. Running `sudo chown -R $(whoami) .` fixes directory ownership, and `rm -rf .vite out` removes temporary build files. ```bash # Fix directory permissions sudo chown -R $(whoami) . # Clean build artifacts rm -rf .vite out ``` -------------------------------- ### Handle Platform-Specific URL Transformations Source: https://context7.com/buoy-gg/buoy-desktop/llms.txt Provides a function to transform URLs based on the target platform, specifically adjusting 'localhost' to '10.0.2.2' for Android emulators. It includes examples for various platforms and demonstrates how to use the `isDevice` prop to conditionally apply these transformations. ```typescript import { getPlatformSpecificURL } from "react-query-external-sync"; type PlatformOS = | "ios" // iPhone, iPad, iPod | "android" // Android devices | "web" // Web browsers | "windows" // Windows desktop/UWP | "macos" // macOS desktop | "native" // Generic native | "tv" // Android TV | "tvos" // Apple TV | "visionos" // Apple Vision Pro | "maccatalyst"; // iOS on macOS const baseUrl = "http://localhost:42831"; // iOS - returns unchanged getPlatformSpecificURL(baseUrl, "ios"); // Result: "http://localhost:42831" // Android emulator - transforms localhost getPlatformSpecificURL(baseUrl, "android"); // Result: "http://10.0.2.2:42831" // Web - returns unchanged getPlatformSpecificURL(baseUrl, "web"); // Result: "http://localhost:42831" useSyncQueriesExternal({ socketURL: "http://localhost:42831", platform: "android", isDevice: ExpoDevice.isDevice, // ... other props }); ``` -------------------------------- ### Configure Real Device Network for DevTools (Expo) Source: https://context7.com/buoy-gg/buoy-desktop/llms.txt This example demonstrates how to configure the DevTools connection for real devices on a local network using Expo. It dynamically detects the host machine's IP address to establish the WebSocket connection, which is necessary when not running on a simulator. This ensures the DevTools can communicate with the app running on a physical device. ```jsx import Constants from "expo-constants"; import { Platform } from "react-native"; import * as ExpoDevice from "expo-device"; // Dynamically get host IP from Expo debugger configuration const hostIP = Constants.expoGoConfig?.debuggerHost?.split(":")[0] || Constants.expoConfig?.hostUri?.split(":")[0]; function AppContent() { useSyncQueriesExternal({ queryClient, // Use local network IP for real device connections socketURL: `http://${hostIP}:42831`, deviceName: `${Platform.OS}-device`, platform: Platform.OS, deviceId: Platform.OS, isDevice: ExpoDevice.isDevice, enableLogs: true, // Enable for debugging connection issues }); return ; } // Example output when connected: // [ios-device] Platform: ios, using URL: http://192.168.1.100:42831 // [ios-device] Socket connected successfully // [ios-device] Dashboard is requesting initial state // [ios-device] Sent initial state to dashboard (15 queries) ``` -------------------------------- ### Integrate useSyncQueriesExternal hook in React Query context Source: https://github.com/buoy-gg/buoy-desktop/blob/main/src/react-query-external-sync/README.md Demonstrates how to add the `useSyncQueriesExternal` hook within your React Query `QueryClientProvider`. This setup enables real-time synchronization of React Query state across different platforms, automatically disabling in production. ```jsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { useSyncQueriesExternal } from "react-query-external-sync"; // Import Platform for React Native or use other platform detection for web/desktop import { Platform } from "react-native"; // Create your query client const queryClient = new QueryClient(); function App() { return ( ); } function AppContent() { // Set up the sync hook - automatically disabled in production! useSyncQueriesExternal({ queryClient, socketURL: "http://localhost:42831", // Default port for React Native DevTools deviceName: Platform?.OS || "web", // Platform detection platform: Platform?.OS || "web", // Use appropriate platform identifier deviceId: Platform?.OS || "web", // Use a PERSISTENT identifier (see note below) extraDeviceInfo: { // Optional additional info about your device appVersion: "1.0.0", // Add any relevant platform info }, envVariables: { // Optional environment variables from your app NODE_ENV: process.env.NODE_ENV, API_URL: process.env.API_URL, // Add any relevant environment variables }, enableLogs: false, }); // Your app content return ; } ``` -------------------------------- ### Real Device Network Configuration Source: https://context7.com/buoy-gg/buoy-desktop/llms.txt When testing on real devices over a local network, you need to use the host machine's IP address instead of 'localhost'. This section provides an example of how to dynamically detect the host IP address for Expo applications. ```APIDOC ## Real Device Network Configuration ### Description Configures the `useSyncQueriesExternal` hook to connect to the DevTools dashboard from a real device on a local network by using the host machine's IP address. ### Method `useSyncQueriesExternal` (Hook) with dynamic `socketURL` configuration. ### Parameters #### Hook Options (relevant for this configuration) - **socketURL** (string) - Required - The URL of the Socket.IO server. This should be dynamically set to the host machine's IP address on the local network. - **enableLogs** (boolean) - Optional - Recommended to be set to `true` for debugging connection issues. ### Request Example ```jsx import Constants from "expo-constants"; import { Platform } from "react-native"; import * as ExpoDevice from "expo-device"; // Dynamically get host IP from Expo debugger configuration const hostIP = Constants.expoGoConfig?.debuggerHost?.split(":")[0] || Constants.expoConfig?.hostUri?.split(":")[0]; function AppContent() { useSyncQueriesExternal({ queryClient, // Use local network IP for real device connections socketURL: `http://${hostIP}:42831`, deviceName: `${Platform.OS}-device`, platform: Platform.OS, deviceId: Platform.OS, isDevice: ExpoDevice.isDevice, enableLogs: true, // Enable for debugging connection issues }); return ; } ``` ### Response Example (Console Output) ``` [ios-device] Platform: ios, using URL: http://192.168.1.100:42831 [ios-device] Socket connected successfully [ios-device] Dashboard is requesting initial state [ios-device] Sent initial state to dashboard (15 queries) ``` ``` -------------------------------- ### Detect Android Device Type for Buoy Desktop Source: https://github.com/buoy-gg/buoy-desktop/blob/main/README.md This snippet demonstrates how to correctly set the `isDevice` prop in the `useSyncQueriesExternal` hook for Buoy Desktop. It helps distinguish between real Android devices and emulators, which is crucial for proper WebSocket connections. The examples show recommended approaches using Expo Device, React Native's `__DEV__` flag, and `react-native-device-info`. ```jsx // Best approach using Expo Device (works with bare React Native too) import * as ExpoDevice from "expo-device"; useSyncQueriesExternal({ queryClient, socketURL: "http://localhost:42831", deviceName: Platform.OS, platform: Platform.OS, deviceId: Platform.OS, isDevice: ExpoDevice.isDevice, // Automatically detects real devices vs emulators // ... other props }); // Alternative: Simple approach using React Native's __DEV__ flag isDevice: !__DEV__, // true for production/real devices, false for development/simulators // Alternative: More sophisticated detection using react-native-device-info import DeviceInfo from 'react-native-device-info'; isDevice: !DeviceInfo.isEmulator(), // Automatically detects if running on emulator // Manual control for specific scenarios isDevice: Platform.OS === 'ios' ? !Platform.isPad : Platform.OS !== 'web', ``` -------------------------------- ### Define and Use Query Actions for Dashboard Control Source: https://context7.com/buoy-gg/buoy-desktop/llms.txt Defines TypeScript types for various query actions that can be sent from a dashboard to control query states on connected devices. It also includes the structure for query action messages and an example of simulating network status changes using the onlineManager. ```typescript type QueryActions = | "ACTION-REFETCH" // Refetch query without invalidating | "ACTION-INVALIDATE" // Invalidate and trigger refetch | "ACTION-RESET" // Reset query to initial state | "ACTION-REMOVE" // Remove query from cache | "ACTION-DATA-UPDATE" // Manually update query data | "ACTION-TRIGGER-ERROR" // Force error state for testing | "ACTION-RESTORE-ERROR" // Restore from error state | "ACTION-TRIGGER-LOADING" // Force loading state for testing | "ACTION-RESTORE-LOADING" // Restore from loading state | "ACTION-CLEAR-MUTATION-CACHE" // Clear all mutations | "ACTION-CLEAR-QUERY-CACHE"; // Clear all queries interface QueryActionMessage { queryHash: string; // Unique query identifier queryKey: QueryKey; // React Query key array data: unknown; // Data payload for updates action: QueryActions; // Action to perform deviceId: string; // Target device ID } interface OnlineManagerMessage { action: "ACTION-ONLINE-MANAGER-ONLINE" | "ACTION-ONLINE-MANAGER-OFFLINE"; targetDeviceId: string; // "All" or specific device ID } import { onlineManager } from "@tanstack/react-query"; // Simulate offline mode onlineManager.setOnline(false); // Return to online mode onlineManager.setOnline(true); ``` -------------------------------- ### Run Pack Script for Manual Release Source: https://github.com/buoy-gg/buoy-desktop/blob/main/GITHUB_RELEASE.md Executes the script to build and pack the application for a manual release. This is typically done after setting the GITHUB_TOKEN environment variable. ```bash pnpm run pack # or directly with ./build-and-pack.sh ``` -------------------------------- ### Integrate React Query DevTools with React Native Source: https://github.com/buoy-gg/buoy-desktop/blob/main/README.md Demonstrates how to integrate the `useSyncQueriesExternal` hook from `react-query-external-sync` into a React Native application. This hook enables real-time React Query state monitoring and device storage monitoring. It requires configuration for socket URL, device name, platform, device ID, and optionally includes environment variables and storage configurations for MMKV, AsyncStorage, and SecureStore. ```jsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { useSyncQueriesExternal } from "react-query-external-sync"; // Import Platform for React Native or use other platform detection for web/desktop import { Platform } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; import * as SecureStore from "expo-secure-store"; import * as ExpoDevice from "expo-device"; import { storage } from "./mmkv"; // Your MMKV instance // Create your query client const queryClient = new QueryClient(); function App() { return ( ); } function AppContent() { // Set up the sync hook - automatically disabled in production! useSyncQueriesExternal({ queryClient, socketURL: "http://localhost:42831", // Default port for React Native DevTools deviceName: Platform?.OS || "web", // Platform detection platform: Platform?.OS || "web", // Use appropriate platform identifier deviceId: Platform?.OS || "web", // Use a PERSISTENT identifier (see note below) isDevice: ExpoDevice.isDevice, // Automatically detects real devices vs emulators extraDeviceInfo: { // Optional additional info about your device appVersion: "1.0.0", // Add any relevant platform info }, enableLogs: false, envVariables: { NODE_ENV: process.env.NODE_ENV, // Add any private environment variables you want to monitor // Public environment variables are automatically loaded }, // Storage monitoring with CRUD operations mmkvStorage: storage, // MMKV storage for ['#storage', 'mmkv', 'key'] queries + monitoring asyncStorage: AsyncStorage, // AsyncStorage for ['#storage', 'async', 'key'] queries + monitoring secureStorage: SecureStore, // SecureStore for ['#storage', 'secure', 'key'] queries + monitoring secureStorageKeys: [ "userToken", "refreshToken", "biometricKey", "deviceId", ], // SecureStore keys to monitor }); // Your app content return ; } ``` -------------------------------- ### Interact with Storage using React Query Hooks Source: https://github.com/buoy-gg/buoy-desktop/blob/main/README.md This code demonstrates how to use React Query hooks (`useQuery`, `useMutation`) to interact with different storage types (MMKV, AsyncStorage) that are monitored by React Native DevTools. It shows reading data and updating storage, including invalidating queries to ensure data synchronization. ```jsx // In your app, use React Query to interact with storage import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; // Read from MMKV storage const { data: userData } = useQuery({ queryKey: ["#storage", "mmkv", "user"], // Data will be automatically synced with DevTools }); // Write to AsyncStorage const queryClient = useQueryClient(); const updateAsyncStorage = useMutation({ mutationFn: async ({ key, value }) => { await AsyncStorage.setItem(key, JSON.stringify(value)); // Invalidate to trigger sync queryClient.invalidateQueries(["#storage", "async", key]); }, }); ``` -------------------------------- ### Manual Git Tag Creation and Push Source: https://github.com/buoy-gg/buoy-desktop/blob/main/RELEASE.md Creates an annotated git tag for the new release version and pushes it to the remote repository. This action signals the release point and triggers CI/CD pipelines. ```bash git tag -a vx.y.z -m "Version x.y.z" git push origin vx.y.z ``` -------------------------------- ### Local Build Command for Testing Source: https://github.com/buoy-gg/buoy-desktop/blob/main/RELEASE.md Executes the 'make' command locally to perform a build. This is used for testing the build process integrity before creating a formal release. ```bash pnpm run make ``` -------------------------------- ### Run Automated Release Script Source: https://github.com/buoy-gg/buoy-desktop/blob/main/GITHUB_RELEASE.md Executes the automated script to manage the release process, including version bumping, committing, tagging, and publishing to GitHub. This script simplifies the release workflow by handling multiple steps interactively. ```bash pnpm run release # or directly with ./release-version.sh ``` -------------------------------- ### Connect React App to DevTools Dashboard (React Native) Source: https://context7.com/buoy-gg/buoy-desktop/llms.txt The `useSyncQueriesExternal` hook establishes a connection between a React application and the DevTools dashboard. It manages the socket connection, synchronizes React Query state, and handles actions from the dashboard. Dependencies include `@tanstack/react-query`, `react-native`, `react-native-async-storage`, `expo-secure-store`, `expo-device`, and MMKV storage. ```jsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { useSyncQueriesExternal } from "react-query-external-sync"; import { Platform } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; import * as SecureStore from "expo-secure-store"; import * as ExpoDevice from "expo-device"; import { storage } from "./mmkv"; const queryClient = new QueryClient(); function App() { return ( ); } function AppContent() { const { isConnected, connect, disconnect, socket } = useSyncQueriesExternal({ // Required: React Query client instance queryClient, // Required: Socket server URL (default DevTools port) socketURL: "http://localhost:42831", // Required: Human-readable device name deviceName: Platform?.OS || "web", // Required: Platform identifier platform: Platform?.OS || "web", // Required: Persistent unique device identifier deviceId: Platform?.OS || "web", // Optional: Real device detection (crucial for Android) isDevice: ExpoDevice.isDevice, // Optional: Additional device metadata extraDeviceInfo: { appVersion: "1.0.0", buildNumber: "42", }, // Optional: Enable debug logging enableLogs: false, // Optional: Environment variables to monitor envVariables: { NODE_ENV: process.env.NODE_ENV, API_URL: process.env.API_URL, }, // Optional: Storage instances for monitoring mmkvStorage: storage, asyncStorage: AsyncStorage, secureStorage: SecureStore, secureStorageKeys: ["userToken", "refreshToken", "deviceId"], }); return ; } ``` -------------------------------- ### Monitor Storage with React Query Hooks Source: https://context7.com/buoy-gg/buoy-desktop/llms.txt This set of hooks leverages React Query and specific DevTools conventions to provide real-time monitoring and CRUD operations for various storage types (MMKV, AsyncStorage, SecureStorage). Mutations automatically invalidate queries to sync changes with the DevTools. ```jsx import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import AsyncStorage from "@react-native-async-storage/async-storage"; // Read from MMKV storage via DevTools query key convention function useMMKVData(key: string) { return useQuery({ queryKey: ["#storage", "mmkv", key], // Data is automatically synced from device storage }); } // Read from AsyncStorage via DevTools query key convention function useAsyncStorageData(key: string) { return useQuery({ queryKey: ["#storage", "async", key], }); } // Read from SecureStorage via DevTools query key convention function useSecureStorageData(key: string) { return useQuery({ queryKey: ["#storage", "secure", key], }); } // Write to AsyncStorage with DevTools sync function useUpdateAsyncStorage() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ key, value }: { key: string; value: any }) => { await AsyncStorage.setItem(key, JSON.stringify(value)); return value; }, onSuccess: (_, { key }) => { // Invalidate to trigger sync with DevTools queryClient.invalidateQueries({ queryKey: ["#storage", "async", key] }); }, }); } // Example usage function UserSettings() { const { data: userData } = useMMKVData("user"); const { data: settings } = useAsyncStorageData("settings"); const { data: authToken } = useSecureStorageData("userToken"); const updateStorage = useUpdateAsyncStorage(); const handleSaveSettings = () => { updateStorage.mutate({ key: "settings", value: { theme: "dark", notifications: true }, }); }; return ( User: {JSON.stringify(userData)} Settings: {JSON.stringify(settings)} Auth: {authToken ? "Authenticated" : "Not logged in"}