Remote debugging and development tools client library for React Native applications
npm install @not-true/devtoolsRemote debugging and development tools client library for React Native applications.
- 🔧 Real-time Console Logging - Automatically capture and stream console output
- 🎮 Remote REPL - Execute JavaScript commands remotely on your device
- 📱 Screenshot Capture - Take screenshots of your app remotely
- 🔄 State Synchronization - Monitor Redux, Context, and AsyncStorage state
- ⚙️ Remote Configuration - Update feature flags and config dynamically
- 🔌 Automatic Reconnection - Robust connection handling with queue management
- 📊 Device Information - Collect and display device/app metadata
- 🚀 TypeScript Support - Fully typed for better developer experience
``bash`
npm install @not-true/devtoolsor
yarn add @not-true/devtools
The package includes socket.io-client 2.5.0 which is optimized for React Native compatibility:
`bash`
npm install @not-true/devtoolssocket.io-client 2.5.0 is included as a dependency
`typescript
import RemoteDevTools from '@not-true/devtools';
const devTools = new RemoteDevTools({
serverUrl: 'http://your-devtools-server:3000',
name: 'My React Native App',
version: '1.0.0',
}, {
onConnect: () => console.log('Connected to DevTools'),
onDisconnect: () => console.log('Disconnected from DevTools'),
});
// Connect to the server
await devTools.connect();
`
`typescript
import React, { useEffect } from 'react';
import { useRemoteDevTools, useReduxSync } from '@not-true/devtools';
import { store } from './store'; // Your Redux store
function App() {
const { devTools, isConnected, connect, connectionStatus } = useRemoteDevTools({
serverUrl: 'http://localhost:3000',
name: 'My App',
version: '1.0.0',
}, {
onConnect: () => console.log('DevTools connected!'),
onRemoteConfig: (config) => {
// Handle remote configuration updates
console.log('Received config:', config);
},
});
// Automatically sync Redux state
useReduxSync(devTools, store);
useEffect(() => {
connect();
}, [connect]);
return (
DevTools Status: {connectionStatus}
Configuration
$3
`typescript
interface RemoteDevToolsConfig {
serverUrl: string; // Required: WebSocket server URL
name: string; // Required: Client display name
version: string; // Required: Application version
// Optional settings
maxQueueSize?: number; // Default: 1000
maxReconnectAttempts?: number; // Default: 5
reconnectDelay?: number; // Default: 1000ms // Feature toggles
enableConsoleLogging?: boolean; // Default: true
enableStateSync?: boolean; // Default: true
enableScreenshots?: boolean; // Default: true
enableREPL?: boolean; // Default: true
enableRemoteConfig?: boolean; // Default: true
// Screenshot settings
screenshotQuality?: number; // 0-1, default: 0.8
screenshotFormat?: 'png' | 'jpg'; // Default: 'png'
// State sync settings
stateUpdateThrottle?: number; // ms, default: 500
// Custom info
deviceInfo?: object;
clientInfo?: object;
}
`Usage Examples
$3
`typescript
// These will be automatically captured if enableConsoleLogging is true
console.log('Hello from device!');
console.warn('Warning message');
console.error('Error occurred');// Or send logs manually
devTools.log('info', 'Custom log message', { data: 'example' });
`$3
`typescript
// Redux state sync (automatic with useReduxSync hook)
import { StateUtils } from '@not-true/devtools';const stateUpdate = StateUtils.createReduxStateUpdate(store.getState());
devTools.updateState(stateUpdate);
// Custom state sync
const customState = StateUtils.createCustomStateUpdate({
userPreferences: { theme: 'dark', language: 'en' },
featureFlags: { newUI: true }
}, 'app-state');
devTools.updateState(customState);
// AsyncStorage sync
const asyncStorageUpdate = StateUtils.createAsyncStorageUpdate('userToken', 'abc123');
devTools.updateState(asyncStorageUpdate);
`$3
The client library requires you to implement your own screenshot capture (e.g., using
react-native-view-shot or similar):`typescript
import { ScreenshotUtils } from '@not-true/devtools';
// You need to install and import your screenshot library
// import { captureScreen } from 'react-native-view-shot';// Handle remote screenshot requests
const devTools = new RemoteDevTools(config, {
onScreenshotRequest: async (options) => {
// Implement your own screenshot capture
const uri = await captureScreen({
format: options.format || 'png',
quality: options.quality || 0.8,
result: 'data-uri' // or 'base64'
});
// Convert to base64 if needed
const base64 = ScreenshotUtils.dataURIToBase64(uri);
// Create screenshot data with metadata
return ScreenshotUtils.createScreenshotWithMetadata(base64, {
width: 375, // actual screen width
height: 812, // actual screen height
format: options.format || 'png'
});
}
});
// Send screenshot manually
const sendScreenshot = async () => {
try {
const uri = await captureScreen({ format: 'png', quality: 0.8 });
const base64 = ScreenshotUtils.dataURIToBase64(uri);
const screenshot = ScreenshotUtils.createScreenshotWithMetadata(base64, {
width: 375,
height: 812,
format: 'png'
});
devTools.sendScreenshot(screenshot);
} catch (error) {
console.error('Screenshot failed:', error);
}
};
`$3
`typescript
const devTools = new RemoteDevTools(config, {
onREPLCommand: async (command) => {
// Handle remote JavaScript execution
try {
// Safely evaluate the command
if (command.command === 'getAppVersion()') {
return '1.0.0';
}
if (command.command === 'getCurrentUser()') {
return { id: 1, name: 'John Doe' };
}
// For security, limit what can be executed
throw new Error('Command not allowed');
} catch (error) {
throw error;
}
}
});
`$3
`typescript
const devTools = new RemoteDevTools(config, {
onRemoteConfig: (config) => {
// Apply configuration changes
if (config.config.enableDarkMode) {
// Enable dark mode
}
if (config.config.apiEndpoint) {
// Update API endpoint
}
// Update feature flags
updateFeatureFlags(config.config.featureFlags || {});
}
});
`$3
`typescript
import React, { useContext } from 'react';
import { useContextSync } from '@not-true/devtools';const ThemeContext = React.createContext({ theme: 'light' });
function MyComponent({ devTools }) {
const themeValue = useContext(ThemeContext);
// Automatically sync context value
useContextSync(devTools, themeValue, 'ThemeContext');
return
Component content;
}
`Advanced Usage
$3
`typescript
import { QueueManager } from '@not-true/devtools';const customQueue = new QueueManager(500); // Custom size limit
// Manually manage queue
customQueue.enqueue({
type: 'log',
data: { level: 'info', message: 'Custom message' },
timestamp: Date.now()
});
// Get queue stats
const stats = customQueue.getStats();
console.log(
Queue size: ${stats.size}/${stats.maxSize});
`$3
`typescript
import { DeviceInfoUtils } from '@not-true/devtools';const deviceInfo = DeviceInfoUtils.getDeviceInfo();
console.log('Platform:', deviceInfo.platform);
console.log('OS Version:', deviceInfo.osVersion);
console.log('Screen Size:', deviceInfo.screenSize);
const memoryInfo = DeviceInfoUtils.getMemoryInfo();
const networkInfo = DeviceInfoUtils.getNetworkInfo();
`$3
`typescript
const devTools = new RemoteDevTools(config, {
onError: (error) => {
console.error('DevTools error:', error);
// Handle or report error
},
onReconnectError: (error) => {
console.error('Failed to reconnect:', error);
// Show user notification or fallback
}
});
`API Reference
$3
#### Methods
-
connect(): Promise - Connect to the server
- disconnect(): void - Disconnect from the server
- log(level, ...args): void - Send log entry
- updateState(stateUpdate): void - Send state update
- sendScreenshot(data): void - Send screenshot data
- sendREPLResult(result): void - Send REPL execution result
- isConnectedToServer(): boolean - Check connection status
- getConfig(): RemoteDevToolsConfig - Get current configuration
- updateConfig(config): void - Update configuration
- destroy(): void - Cleanup and disconnect$3
-
useRemoteDevTools(config, handlers) - Main hook for RemoteDevTools integration
- useReduxSync(devTools, store, throttleMs?) - Automatic Redux state synchronization
- useREPLHandler(devTools, evaluator?) - REPL command handling
- useScreenshotHandler(devTools, capturer?) - Screenshot request handling
- useContextSync(devTools, contextValue, name, throttleMs?) - React Context synchronization$3
-
DeviceInfoUtils - Device and platform information
- QueueManager - Message queue management
- ScreenshotUtils - Screenshot capture utilities
- StateUtils - State management helpersDevelopment Server
This client library works with the Remote DevTools Platform server. To set up the server:
`bash
Clone the server repository
git clone https://github.com/your-org/remote-devtools-platform
cd remote-devtools-platformInstall dependencies
npm installStart development server
npm run devOr start production server
npm run build && npm start
`The dashboard will be available at
http://localhost:3000.Security Considerations
- REPL Execution: The remote REPL feature allows arbitrary code execution. Only use in development environments.
- Network Security: Use HTTPS/WSS in production environments.
- Data Sanitization: State data is automatically sanitized to prevent large payloads and circular references.
- Access Control: Implement proper authentication/authorization in your server setup.
Platform Support
- ✅ React Native (iOS/Android)
- ✅ Expo (managed/bare workflow)
- ⚠️ Web (limited screenshot support)
- ❌ React Native Windows/macOS (not tested)
Troubleshooting
$3
`typescript
// Check if server is accessible
const devTools = new RemoteDevTools(config, {
onConnect: () => console.log('✅ Connected'),
onDisconnect: () => console.log('❌ Disconnected'),
onReconnect: (attempt) => console.log(🔄 Reconnecting... (${attempt})),
onError: (error) => console.error('❗ Error:', error)
});
`$3
`typescript
// Increase throttling for state updates
const config = {
// ... other config
stateUpdateThrottle: 1000, // Update at most once per second
};// Reduce queue size
const config = {
// ... other config
maxQueueSize: 100,
};
``Contributions are welcome! Please see our contributing guidelines for more details.
MIT License - see LICENSE file for details.