├── .gitignore ├── LICENSE ├── README.md ├── images └── output.gif ├── lerna-debug.log ├── lerna.json ├── package-lock.json ├── package.json └── packages ├── flipper-plugin-async-storage-advanced ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── src │ └── index.tsx ├── tsconfig.json └── yarn.lock └── rn-flipper-async-storage-advanced ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | example 2 | node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Lukasz Baldy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flipper Async Storage Advanced plugin 2 | 3 | ## Introduction 4 | 5 | This plugin is designed to work with Flipper (https://fbflipper.com/) and Async Storage (https://github.com/react-native-async-storage/async-storage) library. 6 | 7 | The plugin provides standard read/write/delete/update operations on the Async Storage keys in React Native applications. 8 | 9 | ![plugin_video](images/output.gif "Plugin Video") 10 | 11 | ## Installation 12 | 13 | Similarly to other Flipper plugins for React Native, this one comes in two packages. 14 | 15 | ### Client package 16 | 17 | The first package is a client package that has to be installed in your React Native app. 18 | 19 | #### Install the package 20 | 21 | If you haven't already installed `react-native-flipper` you need to do it now. 22 | 23 | Simply run: 24 | 25 | `npm i react-native-flipper --save` 26 | 27 | Once the react-native-flipper package is installed, you can go ahead and install the actual rn-flipper-async-storage-advanced package. 28 | 29 | `npm i rn-flipper-async-storage-advanced --save` 30 | 31 | Once the package is installed, simply import it 32 | 33 | `import FlipperAsyncStorage from 'rn-flipper-async-storage-advanced';` 34 | 35 | and include the component somewhere in you main component, example below adds it inside App.js 36 | 37 | ``` 38 | const App: () => Node = () => { 39 | const isDarkMode = useColorScheme() === 'dark'; 40 | 41 | const backgroundStyle = { 42 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, 43 | }; 44 | 45 | return ( 46 | 47 | <--- This line 48 | { 50 | AsyncStorage.setItem('sads', 'das'); 51 | }}> 52 | add 53 | 54 | 55 | ); 56 | }; 57 | ``` 58 | 59 | ### Flipper plugin 60 | 61 | The second package is a plugin package that has to be installed from inside Flipper. 62 | 63 | Open Flipper and find your plugin manager, simply search for 'flipper-plugin-async-storage-advanced' and install it. 64 | -------------------------------------------------------------------------------- /images/output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbaldy/flipper-plugin-async-storage-advanced/a147fcc1d6ad2c2e70e5124198f364755a9f5963/images/output.gif -------------------------------------------------------------------------------- /lerna-debug.log: -------------------------------------------------------------------------------- 1 | 0 silly argv { 2 | 0 silly argv _: [ 'create' ], 3 | 0 silly argv lernaVersion: '3.22.1', 4 | 0 silly argv '$0': 'lerna', 5 | 0 silly argv name: 'flipper-plugin-async-storage-advanced' 6 | 0 silly argv } 7 | 1 notice cli v3.22.1 8 | 2 verbose rootPath /Users/lbaldy/projects/async-storage-lerna 9 | 3 warn ENOREMOTE No git remote found, skipping repository property 10 | 4 error Error: canceled 11 | 4 error at Interface. (/Users/lbaldy/.nvm/versions/node/v14.17.0/lib/node_modules/lerna/node_modules/read/lib/read.js:66:13) 12 | 4 error at Interface.emit (events.js:376:20) 13 | 4 error at Interface._ttyWrite (readline.js:880:16) 14 | 4 error at ReadStream.onkeypress (readline.js:213:10) 15 | 4 error at ReadStream.emit (events.js:376:20) 16 | 4 error at emitKeys (internal/readline/utils.js:345:14) 17 | 4 error at emitKeys.next () 18 | 4 error at ReadStream.onData (readline.js:1149:36) 19 | 4 error at ReadStream.emit (events.js:376:20) 20 | 4 error at addChunk (internal/streams/readable.js:309:12) 21 | 4 error at readableAddChunk (internal/streams/readable.js:284:9) 22 | 4 error at ReadStream.Readable.push (internal/streams/readable.js:223:10) 23 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "1.0.8" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "devDependencies": { 5 | "lerna": "^3.22.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist/ 3 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Lukasz Baldy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/README.md: -------------------------------------------------------------------------------- 1 | # `flipper-plugin-async-storage-advanced` 2 | 3 | This is a Flipper plugin for debugging Async Storage in React Native apps. 4 | 5 | It allows to view the string values as well as json objects. 6 | 7 | Simply install it from your Flipper plugin search. 8 | 9 | It has to go together with the `rn-flipper-async-storage-advanced` package. For more details please refer to the main repo's [README](https://github.com/lbaldy/flipper-plugin-async-storage-advanced) 10 | 11 | or to the `rn-flipper-async-storage-advanced` [README](https://github.com/lbaldy/flipper-plugin-async-storage-advanced/blob/main/packages/rn-flipper-async-storage-advanced/README.md) 12 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@babel/preset-typescript', 4 | '@babel/preset-react', 5 | ['@babel/preset-env', {targets: {node: 'current'}}] 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://fbflipper.com/schemas/plugin-package/v2.json", 3 | "name": "flipper-plugin-async-storage-advanced", 4 | "id": "FlipperAsyncStorageAdvanced", 5 | "version": "1.0.8", 6 | "pluginType": "client", 7 | "main": "dist/bundle.js", 8 | "flipperBundlerEntry": "src/index.tsx", 9 | "license": "MIT", 10 | "keywords": [ 11 | "flipper-plugin", 12 | "async-storage", 13 | "flipper" 14 | ], 15 | "icon": "apps", 16 | "title": "Advanced Async Storage", 17 | "description": "CRUD Async Storage Flipper plugin", 18 | "scripts": { 19 | "lint": "flipper-pkg lint", 20 | "prepack": "flipper-pkg lint && flipper-pkg bundle", 21 | "build": "flipper-pkg bundle", 22 | "watch": "flipper-pkg bundle --watch", 23 | "test": "jest --no-watchman" 24 | }, 25 | "peerDependencies": { 26 | "antd": "latest", 27 | "flipper-plugin": "*" 28 | }, 29 | "devDependencies": { 30 | "@babel/preset-react": "latest", 31 | "@babel/preset-typescript": "latest", 32 | "@testing-library/react": "latest", 33 | "@types/jest": "latest", 34 | "@types/react": "latest", 35 | "@types/react-dom": "latest", 36 | "antd": "latest", 37 | "flipper-pkg": "*", 38 | "flipper-plugin": "*", 39 | "jest": "latest", 40 | "typescript": "latest" 41 | }, 42 | "dependencies": { 43 | "immutability-helper": "^3.1.1", 44 | "lodash": "^4.17.21" 45 | }, 46 | "gitHead": "49182e5df03e7f365d27e60e69db4a6a3f676895" 47 | } 48 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { PluginClient, usePlugin, createState, useValue, Layout, DetailSidebar, DataInspector, Panel } from 'flipper-plugin'; 3 | import { Button, Input, Form, Row, } from 'antd'; 4 | import Text from 'antd/lib/typography/Text'; 5 | import update from 'immutability-helper'; 6 | import { findIndex } from 'lodash' 7 | 8 | export function plugin(client: PluginClient) { 9 | const data = createState([], { persist: 'data' }); 10 | 11 | client.onMessage('newData', (newData) => { 12 | data.set(newData); 13 | }); 14 | 15 | client.addMenuEntry({ 16 | action: 'clear', 17 | handler: async () => { 18 | data.set({}); 19 | }, 20 | }); 21 | 22 | // const method 23 | const clear = () => client.send('clear', {}); 24 | 25 | const refresh = () => client.send('refresh', {}); 26 | 27 | const update = () => client.send('update', data); 28 | 29 | const setData = (newData) => data.set(newData); 30 | 31 | return { data, setData, clear, refresh, update }; 32 | } 33 | 34 | const buttonStyle = { 35 | margin: 5 36 | } 37 | 38 | export function Component() { 39 | const instance = usePlugin(plugin); 40 | const data = useValue(instance.data); 41 | 42 | const [newItemKey, setNewItemKey] = useState(''); 43 | const [newItemValue, setItemValue] = useState(''); 44 | 45 | const [keyFilter, setKeyFilter] = useState(); 46 | 47 | const [highlightedKey, setHighlightedKey] = useState(''); 48 | const [highlightedValue, setHighlightedValue] = useState(''); 49 | const [highlightedType, setHighlightedType] = useState(''); 50 | 51 | const setHighlight = (d: any) => { 52 | setHighlightedKey(d.id) 53 | 54 | const content = JSON.parse(d.content) 55 | setHighlightedValue(content) 56 | 57 | if (typeof content === 'object' || Array.isArray(content)) { 58 | setHighlightedType('json') 59 | } else { 60 | setHighlightedType('text') 61 | } 62 | } 63 | 64 | return ( 65 | <> 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Add a new item 76 |
77 | 78 | Async Storage Key 79 | { setNewItemKey(e.target.value) }} /> 80 | 81 | 82 | Async Storage Value 83 | { setItemValue(e.target.value) }} /> 84 | 85 | 86 | 99 | 100 | 101 |
102 |
103 | 104 | 105 |
106 | Local storage items 107 | { setKeyFilter(new RegExp(e.target.value, 'i')) }} /> 108 |
109 | {data 110 | .filter((d) => { 111 | if(!keyFilter) return d 112 | 113 | return keyFilter.test(d.id) 114 | }) 115 | .map((d) => { 116 | 117 | return ( 118 | 119 | 120 | setHighlight(d)}>Key: {d.id} 121 | 122 | 123 | { 127 | const indexToUpdate = findIndex(data, (item) => item.id === ev.target.name) 128 | const newData = update(data, { 129 | [indexToUpdate]: { 130 | content: { 131 | $set: ev.target.value 132 | } 133 | } 134 | }) 135 | 136 | instance.setData(newData) 137 | }} /> 138 | 139 | 140 | 151 | 152 | 153 | ) 154 | }) 155 | } 156 |
157 |
158 | { 159 | highlightedValue && 160 | 161 | { highlightedType === 'json' && ( 162 | 166 | )} 167 | { highlightedType === 'text' && ( 168 | 169 | {highlightedValue} 170 | 171 | )} 172 | 173 | 174 | } 175 | 176 | ); 177 | } 178 | -------------------------------------------------------------------------------- /packages/flipper-plugin-async-storage-advanced/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "module": "ES6", 5 | "jsx": "react", 6 | "sourceMap": true, 7 | "noEmit": true, 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "esModuleInterop": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "files": ["src/index.tsx"] 14 | } 15 | -------------------------------------------------------------------------------- /packages/rn-flipper-async-storage-advanced/README.md: -------------------------------------------------------------------------------- 1 | # `rn-flipper-async-storage-advanced` 2 | 3 | This is a client package for the flipper-plugin-async-storage-adavanced plugin. 4 | 5 | This package supports async-storage https://github.com/react-native-async-storage/async-storage. 6 | 7 | It has to be installed side by site with `react-native-flipper` package. 8 | 9 | For detailed installation instructions please refer to the main readme file. 10 | 11 | ## Installation 12 | 13 | Obviously async-storage itself is a dependency. 14 | 15 | Unless you already have it installed in your project, please install `react-native-flipper` 16 | 17 | `npm i react-native-flipper --save` 18 | 19 | Once installed you can go ahead and install the actual package. 20 | 21 | `npm i rn-flipper-async-storage-advanced --save` 22 | 23 | ## Usage 24 | 25 | To use this package in your project, first you need to import it: 26 | 27 | `import FlipperAsyncStorage from 'rn-flipper-async-storage-advanced';` 28 | 29 | and include the component somewhere in you main component, example below adds it inside App.js 30 | 31 | ``` 32 | const App: () => Node = () => { 33 | const isDarkMode = useColorScheme() === 'dark'; 34 | 35 | const backgroundStyle = { 36 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, 37 | }; 38 | 39 | return ( 40 | 41 | <--- This line 42 | { 44 | AsyncStorage.setItem('sads', 'das'); 45 | }}> 46 | add 47 | 48 | 49 | ); 50 | }; 51 | ``` 52 | 53 | That's it, now you should be able to see your async storage keys via the `flipper-plugin-async-storage-advanced` 54 | -------------------------------------------------------------------------------- /packages/rn-flipper-async-storage-advanced/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { addPlugin } from "react-native-flipper"; 3 | import AsyncStorage from "@react-native-async-storage/async-storage"; 4 | 5 | export default function FlipperAsyncStorage() { 6 | const getAsyncStorageContent = async () => { 7 | try { 8 | const keys = await AsyncStorage.getAllKeys(); 9 | 10 | const localStorageContent = await Promise.all( 11 | keys.map(async (key) => { 12 | const value = await AsyncStorage.getItem(key); 13 | return { id: key, content: value }; 14 | }) 15 | ); 16 | return localStorageContent; 17 | } catch (e) { 18 | console.error(e); 19 | } 20 | }; 21 | 22 | useEffect(() => { 23 | addPlugin({ 24 | getId() { 25 | return "FlipperAsyncStorageAdvanced"; 26 | }, 27 | onConnect(connection) { 28 | connection.receive("clear", async () => { 29 | await AsyncStorage.clear(); 30 | const asyncStorageContent = await getAsyncStorageContent(); 31 | connection.send("newData", asyncStorageContent); 32 | }); 33 | 34 | connection.receive("refresh", async () => { 35 | const asyncStorageContent = await getAsyncStorageContent(); 36 | connection.send("newData", asyncStorageContent); 37 | }); 38 | 39 | connection.receive("update", async (data) => { 40 | await AsyncStorage.clear(); 41 | data.value.forEach((dataItem) => { 42 | console.log(dataItem); 43 | AsyncStorage.setItem(dataItem.id, dataItem.content); 44 | }); 45 | }); 46 | 47 | const loadInitialData = async () => { 48 | const asyncStorageContent = await getAsyncStorageContent(); 49 | connection.send("newData", asyncStorageContent); 50 | }; 51 | loadInitialData(); 52 | }, 53 | onDisconnect() {}, 54 | }); 55 | }, []); 56 | 57 | return null; 58 | } 59 | -------------------------------------------------------------------------------- /packages/rn-flipper-async-storage-advanced/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rn-flipper-async-storage-advanced", 3 | "version": "1.0.5", 4 | "description": "React Native part of the flipper-plugin-async-storage-advanced", 5 | "keywords": [ 6 | "flipper-plugin", 7 | "flipper", 8 | "async-storage" 9 | ], 10 | "author": "lbaldy", 11 | "homepage": "https://github.com/lbaldy/flipper-plugin-async-storage-advanced.git", 12 | "license": "ISC", 13 | "main": "index.js", 14 | "directories": { 15 | "lib": "lib", 16 | "test": "__tests__" 17 | }, 18 | "files": [ 19 | "lib" 20 | ], 21 | "scripts": { 22 | "test": "echo \"Error: run tests from root\" && exit 1" 23 | }, 24 | "peerDependencies": { 25 | "@react-native-async-storage/async-storage": "^1.17.12", 26 | "react": "^18.2.0", 27 | "react-native-flipper": "*" 28 | } 29 | } 30 | --------------------------------------------------------------------------------