@buoy-gg/storage 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -614
- package/package.json +19 -8
package/README.md
CHANGED
|
@@ -1,651 +1,80 @@
|
|
|
1
|
-
# @buoy/storage
|
|
1
|
+
# @buoy-gg/storage
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@buoy-gg/storage) [](https://www.npmjs.com/package/@buoy-gg/storage)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Browse and edit every key-value pair your React Native app persists — AsyncStorage, MMKV, and SecureStore in one explorer with real-time updates.**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Part of [Buoy](https://github.com/Buoy-gg/buoy) — devtools that live inside your React Native app. Install it and it auto-appears in the floating menu from [`@buoy-gg/core`](https://www.npmjs.com/package/@buoy-gg/core).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- **MMKV Support**: Monitor and debug MMKV instances (including encrypted storage)
|
|
11
|
-
- **SecureStore Support**: Browse and delete Expo SecureStore values (registered keys — see below)
|
|
12
|
-
- **Multiple Storage Types**: Support for AsyncStorage, MMKV (multiple instances), and SecureStore
|
|
13
|
-
- **Live Event Monitoring**: Track all storage operations in real-time
|
|
14
|
-
- **Edit & Delete**: Modify or remove storage items directly
|
|
15
|
-
- **Add New Items**: Create new storage entries
|
|
16
|
-
- **Required Key Validation**: Define and validate required storage keys
|
|
17
|
-
- **Type Checking**: Validate storage value types
|
|
18
|
-
- **Value Validation**: Check if values match expected patterns
|
|
19
|
-
- **Search & Filter**: Search through keys and filter by status
|
|
20
|
-
- **Pin & Hide**: Pin keys you're watching to the top (persisted); hide noisy keys into the filter store with one tap
|
|
21
|
-
- **Inline Value Previews**: Short values and color-coded boolean badges visible without expanding cards
|
|
22
|
-
- **Copy Functionality**: Easily copy keys and values
|
|
23
|
-
- **Beautiful UI**: Modern, game-themed interface matching other React Buoy tools
|
|
9
|
+

|
|
24
10
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
This package is part of the React Buoy monorepo and is automatically available to other packages and the example app.
|
|
28
|
-
|
|
29
|
-
For external projects:
|
|
11
|
+
## Install
|
|
30
12
|
|
|
31
13
|
```bash
|
|
32
|
-
|
|
33
|
-
npm install @buoy/storage @react-native-async-storage/async-storage
|
|
34
|
-
|
|
35
|
-
# Optional: MMKV support (recommended for better performance)
|
|
36
|
-
npm install react-native-mmkv
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Or with pnpm/yarn:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
# Required
|
|
43
|
-
pnpm add @buoy/storage @react-native-async-storage/async-storage
|
|
44
|
-
|
|
45
|
-
# Optional: MMKV support
|
|
46
|
-
pnpm add react-native-mmkv
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Quick Start
|
|
50
|
-
|
|
51
|
-
### Simplest Setup - Just 1 Line!
|
|
52
|
-
|
|
53
|
-
**Import the preset and add it to your tools array. Done!**
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { storageToolPreset } from '@buoy/storage';
|
|
57
|
-
import { FloatingDevTools } from '@buoy/core';
|
|
58
|
-
|
|
59
|
-
const installedApps = [
|
|
60
|
-
storageToolPreset, // That's it! One line.
|
|
61
|
-
// ...your other tools
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
function App() {
|
|
65
|
-
return (
|
|
66
|
-
<FloatingDevTools
|
|
67
|
-
apps={installedApps}
|
|
68
|
-
environment="local"
|
|
69
|
-
userRole="admin"
|
|
70
|
-
/>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Done!** The preset automatically:
|
|
76
|
-
- ✅ Browses all AsyncStorage keys
|
|
77
|
-
- ✅ Monitors storage operations
|
|
78
|
-
- ✅ Provides edit/delete/add functionality
|
|
79
|
-
- ✅ No configuration required
|
|
80
|
-
|
|
81
|
-
### Custom Configuration
|
|
82
|
-
|
|
83
|
-
If you need to validate specific storage keys:
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
import { createStorageTool } from '@buoy/storage';
|
|
87
|
-
|
|
88
|
-
const requiredStorageKeys = [
|
|
89
|
-
{
|
|
90
|
-
key: "@app/session",
|
|
91
|
-
expectedType: "string",
|
|
92
|
-
description: "User session token",
|
|
93
|
-
storageType: "async",
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
key: "@app/settings:theme",
|
|
97
|
-
expectedValue: "dark",
|
|
98
|
-
description: "Preferred theme",
|
|
99
|
-
storageType: "async",
|
|
100
|
-
},
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
const myStorageTool = createStorageTool({
|
|
104
|
-
requiredStorageKeys,
|
|
105
|
-
colorPreset: "purple",
|
|
106
|
-
enableSharedModalDimensions: true,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
const installedApps = [
|
|
110
|
-
myStorageTool,
|
|
111
|
-
// ...other tools
|
|
112
|
-
];
|
|
14
|
+
npm install @buoy-gg/core @buoy-gg/storage
|
|
113
15
|
```
|
|
114
16
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
If you're not using FloatingDevTools or want more control:
|
|
17
|
+
## Quick start
|
|
118
18
|
|
|
119
|
-
|
|
120
|
-
import { StorageModalWithTabs } from '@buoy/storage';
|
|
19
|
+
AsyncStorage works out of the box. Render the floating menu once — the Storage Explorer is auto-discovered as soon as this package is installed:
|
|
121
20
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
key: "@app/session",
|
|
125
|
-
expectedType: "string",
|
|
126
|
-
description: "User session token",
|
|
127
|
-
storageType: "async",
|
|
128
|
-
},
|
|
129
|
-
];
|
|
130
|
-
|
|
131
|
-
function App() {
|
|
132
|
-
const [showStorage, setShowStorage] = useState(false);
|
|
21
|
+
```tsx
|
|
22
|
+
import { FloatingDevTools } from "@buoy-gg/core";
|
|
133
23
|
|
|
24
|
+
export default function App() {
|
|
134
25
|
return (
|
|
135
26
|
<>
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
</Button>
|
|
139
|
-
|
|
140
|
-
<StorageModalWithTabs
|
|
141
|
-
visible={showStorage}
|
|
142
|
-
onClose={() => setShowStorage(false)}
|
|
143
|
-
requiredStorageKeys={requiredStorageKeys}
|
|
144
|
-
/>
|
|
27
|
+
{/* your app */}
|
|
28
|
+
<FloatingDevTools />
|
|
145
29
|
</>
|
|
146
30
|
);
|
|
147
31
|
}
|
|
148
32
|
```
|
|
149
33
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
React Buoy Storage fully supports [react-native-mmkv](https://github.com/mrousavy/react-native-mmkv), a fast, efficient storage solution for React Native.
|
|
153
|
-
|
|
154
|
-
### Why MMKV?
|
|
155
|
-
|
|
156
|
-
- **10x faster** than AsyncStorage
|
|
157
|
-
- **Synchronous API** - no async/await needed
|
|
158
|
-
- **Encryption support** - built-in AES encryption
|
|
159
|
-
- **Multi-process support** - share data between extensions
|
|
160
|
-
- **Small bundle size** - ~30KB
|
|
161
|
-
|
|
162
|
-
### Setup Requirements
|
|
163
|
-
|
|
164
|
-
**⚠️ IMPORTANT:** Manual registration is **required** for MMKV v4. Auto-detection is not possible due to Metro bundler and ES6 module limitations.
|
|
165
|
-
|
|
166
|
-
You must call `registerMMKVInstance()` for each MMKV instance you want to monitor in the DevTools.
|
|
167
|
-
|
|
168
|
-
### Basic MMKV Setup
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
import { createMMKV } from 'react-native-mmkv';
|
|
172
|
-
import { registerMMKVInstance } from '@buoy/storage';
|
|
173
|
-
|
|
174
|
-
// 1. Create your MMKV instance
|
|
175
|
-
export const storage = createMMKV({
|
|
176
|
-
id: 'mmkv.default'
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// 2. Register it with DevTools (required!)
|
|
180
|
-
registerMMKVInstance('mmkv.default', storage);
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
**That's it!** Your MMKV instance is now visible in the Storage DevTools.
|
|
184
|
-
|
|
185
|
-
### Encrypted MMKV Setup
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
import { createMMKV } from 'react-native-mmkv';
|
|
189
|
-
import { registerMMKVInstance } from '@buoy/storage';
|
|
190
|
-
|
|
191
|
-
// Create encrypted instance
|
|
192
|
-
export const secureStorage = createMMKV({
|
|
193
|
-
id: 'secure-storage',
|
|
194
|
-
encryptionKey: 'my-encryption-key'
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
// Register with encrypted flag
|
|
198
|
-
registerMMKVInstance('secure-storage', secureStorage, {
|
|
199
|
-
encrypted: true
|
|
200
|
-
});
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Multiple MMKV Instances
|
|
204
|
-
|
|
205
|
-
You can create and monitor multiple MMKV instances for different purposes:
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
import { createMMKV } from 'react-native-mmkv';
|
|
209
|
-
import { registerMMKVInstance } from '@buoy/storage';
|
|
210
|
-
|
|
211
|
-
// User preferences
|
|
212
|
-
export const userPrefs = createMMKV({ id: 'user-prefs' });
|
|
213
|
-
registerMMKVInstance('user-prefs', userPrefs);
|
|
214
|
-
|
|
215
|
-
// API cache
|
|
216
|
-
export const apiCache = createMMKV({ id: 'api-cache' });
|
|
217
|
-
registerMMKVInstance('api-cache', apiCache);
|
|
218
|
-
|
|
219
|
-
// Secure auth storage
|
|
220
|
-
export const authStorage = createMMKV({
|
|
221
|
-
id: 'auth',
|
|
222
|
-
encryptionKey: process.env.ENCRYPTION_KEY
|
|
223
|
-
});
|
|
224
|
-
registerMMKVInstance('auth', authStorage, { encrypted: true });
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### MMKV with FloatingDevTools
|
|
228
|
-
|
|
229
|
-
Once registered, MMKV instances automatically appear in the Storage Browser:
|
|
230
|
-
|
|
231
|
-
```typescript
|
|
232
|
-
import { FloatingDevTools } from '@buoy/core';
|
|
233
|
-
import { storageToolPreset } from '@buoy/storage';
|
|
234
|
-
import './mmkv-setup'; // Import your MMKV setup file
|
|
235
|
-
|
|
236
|
-
function App() {
|
|
237
|
-
return (
|
|
238
|
-
<FloatingDevTools
|
|
239
|
-
apps={[storageToolPreset]}
|
|
240
|
-
environment="local"
|
|
241
|
-
userRole="admin"
|
|
242
|
-
/>
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
The Storage Browser will show:
|
|
248
|
-
- All your MMKV instances (default, user-prefs, api-cache, auth, etc.)
|
|
249
|
-
- All AsyncStorage keys
|
|
250
|
-
- Real-time updates when data changes
|
|
251
|
-
- Ability to edit, delete, and add keys
|
|
252
|
-
|
|
253
|
-
### MMKV Registration API
|
|
254
|
-
|
|
255
|
-
#### `registerMMKVInstance(id, instance, config?)`
|
|
256
|
-
|
|
257
|
-
Register an MMKV instance with DevTools for monitoring and debugging.
|
|
258
|
-
|
|
259
|
-
**Parameters:**
|
|
260
|
-
- `id` (string) - Unique identifier for this instance (should match the `id` used in `createMMKV`)
|
|
261
|
-
- `instance` (MMKV) - The MMKV instance returned from `createMMKV()`
|
|
262
|
-
- `config` (optional) - Configuration object
|
|
263
|
-
- `encrypted` (boolean) - Set to `true` if instance uses encryption
|
|
264
|
-
|
|
265
|
-
**Returns:** `void`
|
|
266
|
-
|
|
267
|
-
**Example:**
|
|
268
|
-
```typescript
|
|
269
|
-
import { createMMKV } from 'react-native-mmkv';
|
|
270
|
-
import { registerMMKVInstance } from '@buoy/storage';
|
|
271
|
-
|
|
272
|
-
const storage = createMMKV({ id: 'my-storage' });
|
|
273
|
-
registerMMKVInstance('my-storage', storage);
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
#### `unregisterMMKVInstance(id)`
|
|
277
|
-
|
|
278
|
-
Unregister an MMKV instance from DevTools monitoring. Typically not needed unless you're dynamically creating/destroying instances.
|
|
279
|
-
|
|
280
|
-
**Parameters:**
|
|
281
|
-
- `id` (string) - The instance ID to unregister
|
|
282
|
-
|
|
283
|
-
**Returns:** `void`
|
|
284
|
-
|
|
285
|
-
**Example:**
|
|
286
|
-
```typescript
|
|
287
|
-
import { unregisterMMKVInstance } from '@buoy/storage';
|
|
288
|
-
|
|
289
|
-
unregisterMMKVInstance('my-storage');
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Why Manual Registration?
|
|
293
|
-
|
|
294
|
-
Auto-detection is fundamentally impossible for MMKV v4 due to:
|
|
295
|
-
|
|
296
|
-
1. **ES6 Module Exports are Sealed** - Cannot monkey-patch `createMMKV` function
|
|
297
|
-
2. **Metro Bundler Limitations** - No access to `require.cache` or module interception
|
|
298
|
-
3. **Nitro Modules Architecture** - MMKV instances created in native C++ layer
|
|
299
|
-
|
|
300
|
-
Manual registration is a simple one-line call per instance and provides explicit control over what's monitored.
|
|
301
|
-
|
|
302
|
-
### MMKV Best Practices
|
|
303
|
-
|
|
304
|
-
**Recommended structure:**
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
// utils/storage.ts
|
|
308
|
-
import { createMMKV } from 'react-native-mmkv';
|
|
309
|
-
import { registerMMKVInstance } from '@buoy/storage';
|
|
310
|
-
|
|
311
|
-
export const storage = createMMKV({ id: 'mmkv.default' });
|
|
312
|
-
export const secureStorage = createMMKV({
|
|
313
|
-
id: 'secure',
|
|
314
|
-
encryptionKey: 'your-key'
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
if (__DEV__) {
|
|
318
|
-
registerMMKVInstance('mmkv.default', storage);
|
|
319
|
-
registerMMKVInstance('secure', secureStorage, { encrypted: true });
|
|
320
|
-
}
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
Then import in your app:
|
|
34
|
+
**MMKV** — register each instance once so the explorer can see it (required for MMKV v4; Metro can't auto-detect instances):
|
|
324
35
|
|
|
325
|
-
```
|
|
326
|
-
import {
|
|
36
|
+
```ts
|
|
37
|
+
import { createMMKV } from "react-native-mmkv";
|
|
38
|
+
import { registerMMKVInstance } from "@buoy-gg/storage";
|
|
327
39
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
secureStorage.set('auth.token', 'secret-token');
|
|
40
|
+
export const storage = createMMKV({ id: "mmkv.default" });
|
|
41
|
+
registerMMKVInstance("mmkv.default", storage);
|
|
331
42
|
```
|
|
332
43
|
|
|
333
|
-
|
|
44
|
+
**SecureStore** — the iOS Keychain / Android KeyStore has no key-listing API, so register the keys you want visible:
|
|
334
45
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
SecureStore has **no key-enumeration API** — there is no way to ask the Keychain "what's stored?". So, like MMKV instances, you register the keys you want visible. You pass the `expo-secure-store` module in, so this package has zero dependency on it (bare RN apps without Expo are unaffected).
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
import * as SecureStore from 'expo-secure-store';
|
|
343
|
-
import { registerSecureStoreKeys } from '@buoy/storage';
|
|
46
|
+
```ts
|
|
47
|
+
import * as SecureStore from "expo-secure-store";
|
|
48
|
+
import { registerSecureStoreKeys } from "@buoy-gg/storage";
|
|
344
49
|
|
|
345
50
|
registerSecureStoreKeys(SecureStore, [
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
// Keys written with options must register the SAME options,
|
|
351
|
-
// or the Keychain returns null on read
|
|
352
|
-
{ key: 'session.deviceKey', keychainService: 'com.myapp.auth' },
|
|
353
|
-
|
|
354
|
-
// Biometric-protected keys are listed but NEVER auto-read,
|
|
355
|
-
// so DevTools won't trigger surprise Face ID / fingerprint prompts
|
|
356
|
-
{ key: 'secure.pin', requireAuthentication: true },
|
|
51
|
+
"auth.accessToken",
|
|
52
|
+
{ key: "session", keychainService: "com.myapp.auth" },
|
|
53
|
+
// Biometric-protected keys are listed but never auto-read (no surprise Face ID prompts)
|
|
54
|
+
{ key: "pin", requireAuthentication: true },
|
|
357
55
|
]);
|
|
358
56
|
```
|
|
359
57
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
| Param | Type | Description |
|
|
363
|
-
|---|---|---|
|
|
364
|
-
| `module` | `SecureStoreLike` | The `expo-secure-store` module (`import * as SecureStore`) |
|
|
365
|
-
| `keys` | `(string \| { key, keychainService?, requireAuthentication?, description? })[]` | Keys to expose, with the options they were written with |
|
|
366
|
-
|
|
367
|
-
Registered keys that have no stored value show up as **Missing** — handy for spotting initialization bugs. Use `unregisterSecureStoreKey(key)` to remove one from the tool (the stored value is untouched).
|
|
368
|
-
|
|
369
|
-
### Platform notes
|
|
370
|
-
|
|
371
|
-
- iOS Keychain values **persist across app uninstalls** (same bundle ID); Android values don't.
|
|
372
|
-
- Values are read with the exact options each key was registered with — a `keychainService` mismatch reads as missing.
|
|
373
|
-
|
|
374
|
-
## API Reference
|
|
375
|
-
|
|
376
|
-
### Presets
|
|
377
|
-
|
|
378
|
-
#### `storageToolPreset`
|
|
379
|
-
|
|
380
|
-
Pre-configured AsyncStorage browser tool ready to use with FloatingDevTools.
|
|
381
|
-
|
|
382
|
-
**Example:**
|
|
383
|
-
```typescript
|
|
384
|
-
import { storageToolPreset } from '@buoy/storage';
|
|
385
|
-
|
|
386
|
-
const installedApps = [storageToolPreset];
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
#### `createStorageTool(options?)`
|
|
390
|
-
|
|
391
|
-
Create a custom AsyncStorage browser tool configuration.
|
|
392
|
-
|
|
393
|
-
**Options:**
|
|
394
|
-
```typescript
|
|
395
|
-
{
|
|
396
|
-
/** Tool name (default: "STORAGE") */
|
|
397
|
-
name?: string;
|
|
398
|
-
/** Tool description */
|
|
399
|
-
description?: string;
|
|
400
|
-
/** Icon color preset (default: "green") */
|
|
401
|
-
colorPreset?: "orange" | "cyan" | "purple" | "pink" | "yellow" | "green";
|
|
402
|
-
/** Custom tool ID (default: "storage") */
|
|
403
|
-
id?: string;
|
|
404
|
-
/** Array of required storage keys to validate */
|
|
405
|
-
requiredStorageKeys?: RequiredStorageKey[];
|
|
406
|
-
/** Enable shared modal dimensions */
|
|
407
|
-
enableSharedModalDimensions?: boolean;
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
**Example:**
|
|
412
|
-
```typescript
|
|
413
|
-
import { createStorageTool } from '@buoy/storage';
|
|
414
|
-
|
|
415
|
-
const requiredStorageKeys = [
|
|
416
|
-
{
|
|
417
|
-
key: "@app/session",
|
|
418
|
-
expectedType: "string",
|
|
419
|
-
description: "User session token",
|
|
420
|
-
storageType: "async",
|
|
421
|
-
},
|
|
422
|
-
];
|
|
423
|
-
|
|
424
|
-
const myStorageTool = createStorageTool({
|
|
425
|
-
name: "APP STORAGE",
|
|
426
|
-
requiredStorageKeys,
|
|
427
|
-
colorPreset: "cyan",
|
|
428
|
-
enableSharedModalDimensions: true,
|
|
429
|
-
});
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### Components
|
|
58
|
+
## What you get
|
|
433
59
|
|
|
434
|
-
|
|
60
|
+
- **Three backends, one explorer** — AsyncStorage, MMKV (multiple instances, including encrypted), and Expo SecureStore, with per-instance key counts and an instance switcher.
|
|
61
|
+
- **Edit in place** — modify, delete, and add keys directly; bulk-select to delete or export many at once.
|
|
62
|
+
- **Live events** — watch storage reads and writes stream in as your app runs.
|
|
63
|
+
- **Pin and hide** — pin the keys you're watching to the top (persists across sessions); one tap hides noisy keys non-destructively.
|
|
64
|
+
- **Inline previews** — short values show on the card (`number · 42`, `string · "en"`), booleans get color-coded true/false badges, and valid JSON is auto pretty-printed.
|
|
65
|
+
- **Biometric keys stay safe** — SecureStore keys behind Face ID / fingerprint are listed but never auto-read.
|
|
66
|
+
- **Required-key validation** — declare keys with expected types or values via `createStorageTool({ requiredStorageKeys })` and see what's missing or wrong.
|
|
435
67
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
**Props:**
|
|
439
|
-
```typescript
|
|
440
|
-
interface StorageModalWithTabsProps {
|
|
441
|
-
/** Whether the modal is visible */
|
|
442
|
-
visible: boolean;
|
|
443
|
-
/** Callback when modal is closed */
|
|
444
|
-
onClose: () => void;
|
|
445
|
-
/** Optional back button handler */
|
|
446
|
-
onBack?: () => void;
|
|
447
|
-
/** Whether to use shared modal dimensions */
|
|
448
|
-
enableSharedModalDimensions?: boolean;
|
|
449
|
-
/** Array of required storage keys to validate */
|
|
450
|
-
requiredStorageKeys?: RequiredStorageKey[];
|
|
451
|
-
}
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
**Example:**
|
|
455
|
-
```typescript
|
|
456
|
-
<StorageModalWithTabs
|
|
457
|
-
visible={isVisible}
|
|
458
|
-
onClose={handleClose}
|
|
459
|
-
requiredStorageKeys={requiredKeys}
|
|
460
|
-
enableSharedModalDimensions={true}
|
|
461
|
-
/>
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
### Types
|
|
465
|
-
|
|
466
|
-
#### `RequiredStorageKey`
|
|
467
|
-
|
|
468
|
-
```typescript
|
|
469
|
-
interface RequiredStorageKey {
|
|
470
|
-
/** Storage key to validate */
|
|
471
|
-
key: string;
|
|
472
|
-
/** Optional description of the key */
|
|
473
|
-
description?: string;
|
|
474
|
-
/** Expected value type */
|
|
475
|
-
expectedType?: "string" | "number" | "boolean" | "object" | "array";
|
|
476
|
-
/** Expected value */
|
|
477
|
-
expectedValue?: any;
|
|
478
|
-
/** Storage type: "async" for AsyncStorage, "mmkv" for MMKV, "secure" for Secure Storage */
|
|
479
|
-
storageType: "async" | "mmkv" | "secure";
|
|
480
|
-
/** Whether the key is required */
|
|
481
|
-
required?: boolean;
|
|
482
|
-
}
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
#### `AsyncStorageEvent`
|
|
486
|
-
|
|
487
|
-
```typescript
|
|
488
|
-
interface AsyncStorageEvent {
|
|
489
|
-
/** Unique event ID */
|
|
490
|
-
id: string;
|
|
491
|
-
/** Event type (set, get, remove, clear, etc.) */
|
|
492
|
-
type: "set" | "get" | "remove" | "clear" | "multiGet" | "multiSet" | "multiRemove";
|
|
493
|
-
/** Storage key(s) involved */
|
|
494
|
-
key?: string | string[];
|
|
495
|
-
/** Value (for set operations) */
|
|
496
|
-
value?: any;
|
|
497
|
-
/** Timestamp of the event */
|
|
498
|
-
timestamp: number;
|
|
499
|
-
/** Whether the operation succeeded */
|
|
500
|
-
success: boolean;
|
|
501
|
-
/** Error message if operation failed */
|
|
502
|
-
error?: string;
|
|
503
|
-
}
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
## Use Cases
|
|
507
|
-
|
|
508
|
-
### Session Management
|
|
509
|
-
|
|
510
|
-
Monitor and validate user session storage:
|
|
511
|
-
|
|
512
|
-
```typescript
|
|
513
|
-
import { createStorageTool } from '@buoy/storage';
|
|
514
|
-
|
|
515
|
-
const requiredStorageKeys = [
|
|
516
|
-
{
|
|
517
|
-
key: "@app/session:token",
|
|
518
|
-
expectedType: "string",
|
|
519
|
-
description: "JWT auth token",
|
|
520
|
-
storageType: "async",
|
|
521
|
-
required: true,
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
key: "@app/session:userId",
|
|
525
|
-
expectedType: "string",
|
|
526
|
-
description: "Current user ID",
|
|
527
|
-
storageType: "async",
|
|
528
|
-
required: true,
|
|
529
|
-
},
|
|
530
|
-
];
|
|
531
|
-
|
|
532
|
-
const storageTool = createStorageTool({ requiredStorageKeys });
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
### App Settings
|
|
536
|
-
|
|
537
|
-
Validate app configuration storage:
|
|
538
|
-
|
|
539
|
-
```typescript
|
|
540
|
-
const requiredStorageKeys = [
|
|
541
|
-
{
|
|
542
|
-
key: "@app/settings:theme",
|
|
543
|
-
expectedValue: "dark",
|
|
544
|
-
description: "UI theme preference",
|
|
545
|
-
storageType: "async",
|
|
546
|
-
},
|
|
547
|
-
{
|
|
548
|
-
key: "@app/settings:notifications",
|
|
549
|
-
expectedType: "boolean",
|
|
550
|
-
description: "Notifications enabled",
|
|
551
|
-
storageType: "async",
|
|
552
|
-
},
|
|
553
|
-
{
|
|
554
|
-
key: "@app/settings:language",
|
|
555
|
-
expectedType: "string",
|
|
556
|
-
description: "User language preference",
|
|
557
|
-
storageType: "async",
|
|
558
|
-
},
|
|
559
|
-
];
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
### Cache Management
|
|
563
|
-
|
|
564
|
-
Monitor cached data:
|
|
565
|
-
|
|
566
|
-
```typescript
|
|
567
|
-
const requiredStorageKeys = [
|
|
568
|
-
{
|
|
569
|
-
key: "@app/cache:userData",
|
|
570
|
-
expectedType: "object",
|
|
571
|
-
description: "Cached user profile data",
|
|
572
|
-
storageType: "async",
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
key: "@app/cache:timestamp",
|
|
576
|
-
expectedType: "number",
|
|
577
|
-
description: "Cache timestamp",
|
|
578
|
-
storageType: "async",
|
|
579
|
-
},
|
|
580
|
-
];
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
## Features in Detail
|
|
584
|
-
|
|
585
|
-
### Browser Tab
|
|
586
|
-
|
|
587
|
-
- **View All Keys**: See all AsyncStorage keys and their values
|
|
588
|
-
- **Search**: Search through keys by name
|
|
589
|
-
- **Filter**: Filter by validation status (all, missing, issues)
|
|
590
|
-
- **Edit**: Modify existing values directly
|
|
591
|
-
- **Delete**: Remove storage entries
|
|
592
|
-
- **Add**: Create new storage entries
|
|
593
|
-
- **Copy**: Copy keys and values to clipboard
|
|
594
|
-
- **Validation**: See which required keys are missing or invalid
|
|
595
|
-
|
|
596
|
-
### Events Tab
|
|
597
|
-
|
|
598
|
-
- **Live Monitoring**: Watch all storage operations in real-time
|
|
599
|
-
- **Event Types**: Track set, get, remove, clear, and multi-operations
|
|
600
|
-
- **Filtering**: Filter events by type or key
|
|
601
|
-
- **Search**: Search through event history
|
|
602
|
-
- **Timeline**: See chronological order of operations
|
|
603
|
-
- **Pause/Resume**: Control event capture
|
|
604
|
-
- **Clear**: Clear event history
|
|
605
|
-
|
|
606
|
-
### Validation
|
|
607
|
-
|
|
608
|
-
Required storage keys can be validated for:
|
|
609
|
-
- **Existence**: Check if the key exists
|
|
610
|
-
- **Type**: Validate the value type (string, number, boolean, object, array)
|
|
611
|
-
- **Value**: Check if the value matches an expected value
|
|
612
|
-
- **Custom Validation**: Implement custom validation logic
|
|
613
|
-
|
|
614
|
-
## Dependencies
|
|
615
|
-
|
|
616
|
-
- `@buoy/shared-ui` - Common UI components and utilities
|
|
617
|
-
- `@react-native-async-storage/async-storage` - AsyncStorage implementation (peer dependency; supports v2 and v3 — `^2.0.0 || ^3.1.0`. Avoid 3.0.x, which has an Android build issue fixed upstream in 3.1.0.)
|
|
618
|
-
- `react-native-mmkv` - MMKV storage implementation (optional peer dependency)
|
|
619
|
-
- React and React Native (peer dependencies)
|
|
620
|
-
|
|
621
|
-
## Development
|
|
622
|
-
|
|
623
|
-
### Building
|
|
624
|
-
|
|
625
|
-
```bash
|
|
626
|
-
pnpm build
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
### Type Checking
|
|
630
|
-
|
|
631
|
-
```bash
|
|
632
|
-
pnpm typecheck
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
### Clean Build
|
|
636
|
-
|
|
637
|
-
```bash
|
|
638
|
-
pnpm clean
|
|
639
|
-
```
|
|
68
|
+
## Desktop & AI
|
|
640
69
|
|
|
641
|
-
|
|
70
|
+
The same live session streams to [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) (free, macOS/Windows/Linux) and to Claude Code or Cursor via the [Buoy MCP server](https://buoy.gg/buoy/latest/docs/mcp).
|
|
642
71
|
|
|
643
|
-
|
|
72
|
+
## Free vs Pro
|
|
644
73
|
|
|
645
|
-
|
|
74
|
+
Every tool is free. [Pro](https://buoy.gg/pricing) unlocks production builds, the MCP server, and unlimited capture. Every weekend, Pro features unlock free for everyone.
|
|
646
75
|
|
|
647
|
-
|
|
76
|
+
---
|
|
648
77
|
|
|
649
|
-
|
|
78
|
+
📚 [Full docs](https://buoy.gg/buoy/latest/docs/tools/storage) · [All Buoy tools](https://github.com/Buoy-gg/buoy)
|
|
650
79
|
|
|
651
|
-
|
|
80
|
+
Proprietary software. © Buoy LLC. [Terms](https://buoy.gg/terms)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/storage",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "Browse & edit AsyncStorage, MMKV & SecureStore inside your React Native app, with change history. Part of Buoy devtools.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
7
7
|
"types": "lib/typescript/index.d.ts",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
],
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@buoy-gg/floating-tools-core": "
|
|
30
|
-
"@buoy-gg/shared-ui": "
|
|
29
|
+
"@buoy-gg/floating-tools-core": "7.0.0",
|
|
30
|
+
"@buoy-gg/shared-ui": "7.0.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@buoy-gg/license": "
|
|
33
|
+
"@buoy-gg/license": "7.0.0",
|
|
34
34
|
"@react-native-async-storage/async-storage": "^2.0.0 || ^3.1.0",
|
|
35
35
|
"react": "*",
|
|
36
36
|
"react-native": "*"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@types/react": "^19.1.0",
|
|
41
41
|
"@types/react-native": "^0.73.0",
|
|
42
42
|
"typescript": "~5.8.3",
|
|
43
|
-
"@buoy-gg/license": "
|
|
43
|
+
"@buoy-gg/license": "7.0.0"
|
|
44
44
|
},
|
|
45
45
|
"react-native-builder-bob": {
|
|
46
46
|
"source": "src",
|
|
@@ -63,17 +63,28 @@
|
|
|
63
63
|
},
|
|
64
64
|
"repository": {
|
|
65
65
|
"type": "git",
|
|
66
|
-
"url": "https://github.com/
|
|
66
|
+
"url": "https://github.com/Buoy-gg/buoy.git",
|
|
67
67
|
"directory": "packages/storage"
|
|
68
68
|
},
|
|
69
69
|
"bugs": {
|
|
70
70
|
"url": "https://github.com/LovesWorking/react-native-buoy/issues"
|
|
71
71
|
},
|
|
72
|
-
"homepage": "https://
|
|
72
|
+
"homepage": "https://buoy.gg/tools/storage",
|
|
73
73
|
"publishConfig": {
|
|
74
74
|
"access": "public",
|
|
75
75
|
"tag": "latest"
|
|
76
76
|
},
|
|
77
|
+
"keywords": [
|
|
78
|
+
"react-native",
|
|
79
|
+
"expo",
|
|
80
|
+
"devtools",
|
|
81
|
+
"debugging",
|
|
82
|
+
"react-native-devtools",
|
|
83
|
+
"flipper-alternative",
|
|
84
|
+
"async-storage",
|
|
85
|
+
"mmkv",
|
|
86
|
+
"storage-inspector"
|
|
87
|
+
],
|
|
77
88
|
"scripts": {
|
|
78
89
|
"build": "bob build",
|
|
79
90
|
"typecheck": "tsc --noEmit",
|