Skip to content

Commit c3a3bd0

Browse files
authored
Merge pull request #17 from LovesWorking/add-storage-and-env-data
Add support for env and local storage
2 parents 493bfc3 + d9a45d8 commit c3a3bd0

15 files changed

+2400
-273
lines changed

README.md

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# React Query External Sync
22

3-
A powerful debugging tool for React Query state in any React-based application. Whether you're building for mobile, web, desktop, TV, or VR - this package has you covered. It works seamlessly across all platforms where React runs, with zero configuration to disable in production.
3+
A powerful debugging tool for React Query state and device storage in any React-based application. Whether you're building for mobile, web, desktop, TV, or VR - this package has you covered. It works seamlessly across all platforms where React runs, with zero configuration to disable in production.
44

55
Pairs perfectly with [React Native DevTools](https://github.com/LovesWorking/rn-better-dev-tools) for a complete development experience.
66

@@ -9,6 +9,7 @@ Pairs perfectly with [React Native DevTools](https://github.com/LovesWorking/rn-
99
## ✨ Features
1010

1111
- 🔄 Real-time React Query state synchronization
12+
- 💾 **Device storage monitoring with CRUD operations** - MMKV, AsyncStorage, and SecureStorage
1213
- 📱 Works with any React-based framework (React, React Native, Expo, Next.js, etc.)
1314
- 🖥️ Platform-agnostic: Web, iOS, Android, macOS, Windows, Linux, tvOS, VR - you name it!
1415
- 🔌 Socket.IO integration for reliable communication
@@ -37,8 +38,10 @@ Add the hook to your application where you set up your React Query context:
3738
```jsx
3839
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3940
import { useSyncQueriesExternal } from "react-query-external-sync";
40-
// Import Platform for React Native or use other platform detection for web/desktop
4141
import { Platform } from "react-native";
42+
import AsyncStorage from "@react-native-async-storage/async-storage";
43+
import * as SecureStore from "expo-secure-store";
44+
import { storage } from "./mmkv"; // Your MMKV instance
4245

4346
// Create your query client
4447
const queryClient = new QueryClient();
@@ -52,19 +55,30 @@ function App() {
5255
}
5356

5457
function AppContent() {
55-
// Set up the sync hook - automatically disabled in production!
58+
// Unified storage queries and external sync - all in one hook!
5659
useSyncQueriesExternal({
5760
queryClient,
58-
socketURL: "http://localhost:42831", // Default port for React Native DevTools
59-
deviceName: Platform?.OS || "web", // Platform detection
60-
platform: Platform?.OS || "web", // Use appropriate platform identifier
61-
deviceId: Platform?.OS || "web", // Use a PERSISTENT identifier (see note below)
61+
socketURL: "http://localhost:42831",
62+
deviceName: Platform.OS,
63+
platform: Platform.OS,
64+
deviceId: Platform.OS,
6265
extraDeviceInfo: {
63-
// Optional additional info about your device
6466
appVersion: "1.0.0",
65-
// Add any relevant platform info
6667
},
67-
enableLogs: false,
68+
enableLogs: true,
69+
envVariables: {
70+
NODE_ENV: process.env.NODE_ENV,
71+
},
72+
// Storage monitoring with CRUD operations
73+
mmkvStorage: storage, // MMKV storage for ['#storage', 'mmkv', 'key'] queries + monitoring
74+
asyncStorage: AsyncStorage, // AsyncStorage for ['#storage', 'async', 'key'] queries + monitoring
75+
secureStorage: SecureStore, // SecureStore for ['#storage', 'secure', 'key'] queries + monitoring
76+
secureStorageKeys: [
77+
"userToken",
78+
"refreshToken",
79+
"biometricKey",
80+
"deviceId",
81+
], // SecureStore keys to monitor
6882
});
6983

7084
// Your app content
@@ -107,15 +121,20 @@ For the best experience, use this package with the [React Native DevTools](https
107121

108122
The `useSyncQueriesExternal` hook accepts the following options:
109123

110-
| Option | Type | Required | Description |
111-
| ----------------- | ----------- | -------- | ----------------------------------------------------------------------- |
112-
| `queryClient` | QueryClient | Yes | Your React Query client instance |
113-
| `socketURL` | string | Yes | URL of the socket server (e.g., 'http://localhost:42831') |
114-
| `deviceName` | string | Yes | Human-readable name for your device |
115-
| `platform` | string | Yes | Platform identifier ('ios', 'android', 'web', 'macos', 'windows', etc.) |
116-
| `deviceId` | string | Yes | Unique identifier for your device |
117-
| `extraDeviceInfo` | object | No | Additional device metadata to display in DevTools |
118-
| `enableLogs` | boolean | No | Enable console logging for debugging (default: false) |
124+
| Option | Type | Required | Description |
125+
| ------------------- | ------------ | -------- | ----------------------------------------------------------------------- |
126+
| `queryClient` | QueryClient | Yes | Your React Query client instance |
127+
| `socketURL` | string | Yes | URL of the socket server (e.g., 'http://localhost:42831') |
128+
| `deviceName` | string | Yes | Human-readable name for your device |
129+
| `platform` | string | Yes | Platform identifier ('ios', 'android', 'web', 'macos', 'windows', etc.) |
130+
| `deviceId` | string | Yes | Unique identifier for your device |
131+
| `extraDeviceInfo` | object | No | Additional device metadata to display in DevTools |
132+
| `enableLogs` | boolean | No | Enable console logging for debugging (default: false) |
133+
| `envVariables` | object | No | Environment variables to sync with DevTools |
134+
| `mmkvStorage` | MmkvStorage | No | MMKV storage instance for real-time monitoring |
135+
| `asyncStorage` | AsyncStorage | No | AsyncStorage instance for polling-based monitoring |
136+
| `secureStorage` | SecureStore | No | SecureStore instance for secure data monitoring |
137+
| `secureStorageKeys` | string[] | No | Array of SecureStore keys to monitor (required if using secureStorage) |
119138

120139
## 🐛 Troubleshooting
121140

src/react-query-external-sync/User.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ export interface User {
33
deviceName: string;
44
deviceId?: string; // Optional for backward compatibility
55
platform?: string; // Device platform (iOS, Android, Web)
6+
extraDeviceInfo?: string; // json string of additional device information as key-value pairs
7+
envVariables?: Record<string, string>; // Environment variables from the mobile app
68
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Storage Query Keys
2+
export { storageQueryKeys } from './storageQueryKeys';
3+
4+
// Individual Storage Hooks
5+
export {
6+
type AsyncStorageQueryResult,
7+
useDynamicAsyncStorageQueries,
8+
type UseDynamicAsyncStorageQueriesOptions,
9+
} from './useDynamicAsyncStorageQueries';
10+
export {
11+
type MmkvQueryResult,
12+
type MmkvStorage,
13+
useDynamicMmkvQueries,
14+
type UseDynamicMmkvQueriesOptions,
15+
} from './useDynamicMmkvQueries';
16+
export {
17+
type SecureStorageQueryResult,
18+
useDynamicSecureStorageQueries,
19+
type UseDynamicSecureStorageQueriesOptions,
20+
} from './useDynamicSecureStorageQueries';
21+
22+
// Unified Storage Hook
23+
export { type StorageQueryResults, useStorageQueries, type UseStorageQueriesOptions } from './useStorageQueries';
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Centralized storage query keys for all storage hooks
3+
* This ensures consistency across MMKV, AsyncStorage, and SecureStorage hooks
4+
* and allows easy modification of the base storage key in one place
5+
*/
6+
export const storageQueryKeys = {
7+
/**
8+
* Base storage key - change this to update all storage-related queries
9+
*/
10+
base: () => ['#storage'] as const,
11+
12+
/**
13+
* MMKV storage query keys
14+
*/
15+
mmkv: {
16+
root: () => [...storageQueryKeys.base(), 'mmkv'] as const,
17+
key: (key: string) => [...storageQueryKeys.mmkv.root(), key] as const,
18+
all: () => [...storageQueryKeys.mmkv.root(), 'all'] as const,
19+
},
20+
21+
/**
22+
* AsyncStorage query keys
23+
*/
24+
async: {
25+
root: () => [...storageQueryKeys.base(), 'async'] as const,
26+
key: (key: string) => [...storageQueryKeys.async.root(), key] as const,
27+
all: () => [...storageQueryKeys.async.root(), 'all'] as const,
28+
},
29+
30+
/**
31+
* SecureStorage query keys
32+
*/
33+
secure: {
34+
root: () => [...storageQueryKeys.base(), 'secure'] as const,
35+
key: (key: string) => [...storageQueryKeys.secure.root(), key] as const,
36+
all: () => [...storageQueryKeys.secure.root(), 'all'] as const,
37+
},
38+
} as const;

0 commit comments

Comments
 (0)