From 7f6795416cc40139fa42dd73e1d60275634e1078 Mon Sep 17 00:00:00 2001
From: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
Date: Mon, 29 Nov 2021 22:36:09 +0100
Subject: [PATCH 1/3] chore: migrate example app to TypeScript
When upgrading Flow (from upgrading react-native), a bunch of errors
come from the test app. Taking this opportunity to migrate to TypeScript
to avoid future issues.
Next up would be to convert the rest of the Flow files.
---
example/App.js | 167 -----------
example/App.tsx | 151 ++++++++++
example/examples/{Basic.js => Basic.tsx} | 35 ++-
.../{GetSetClear.js => GetSetClear.tsx} | 11 +-
example/examples/MergeItem.js | 268 ------------------
example/examples/MergeItem.tsx | 223 +++++++++++++++
example/{index.js => index.ts} | 3 -
package.json | 9 +-
scripts/android_e2e.sh | 2 +-
scripts/ios_e2e.sh | 4 +-
tsconfig.json | 34 +++
yarn.lock | 36 +++
12 files changed, 481 insertions(+), 462 deletions(-)
delete mode 100644 example/App.js
create mode 100644 example/App.tsx
rename example/examples/{Basic.js => Basic.tsx} (87%)
rename example/examples/{GetSetClear.js => GetSetClear.tsx} (92%)
delete mode 100644 example/examples/MergeItem.js
create mode 100644 example/examples/MergeItem.tsx
rename example/{index.js => index.ts} (95%)
create mode 100644 tsconfig.json
diff --git a/example/App.js b/example/App.js
deleted file mode 100644
index b2fe194f..00000000
--- a/example/App.js
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- */
-
-import React, {Component} from 'react';
-import {
- StyleSheet,
- SafeAreaView,
- Text,
- TouchableOpacity,
- View,
- Keyboard,
- Button,
-} from 'react-native';
-
-import GetSetClear from './examples/GetSetClear';
-import MergeItem from './examples/MergeItem';
-import BasicExample from './examples/Basic';
-
-const TESTS = {
- GetSetClear: {
- title: 'Simple Get/Set value',
- testId: 'get-set-clear',
- description: 'Store and retrieve persisted data',
- render() {
- return ;
- },
- },
- MergeItem: {
- title: 'Merge item',
- testId: 'merge-item',
- description: 'Merge object with already stored data',
- render() {
- return ;
- },
- },
- Basic: {
- title: 'Basic',
- testId: 'basic',
- description: 'Basic functionality test',
- render() {
- return ;
- },
- },
-};
-
-type Props = {};
-type State = {restarting: boolean, currentTest: Object};
-
-export default class App extends Component {
- state = {
- restarting: false,
- currentTest: TESTS.GetSetClear,
- };
-
- _simulateRestart = () => {
- this.setState({restarting: true}, () => this.setState({restarting: false}));
- };
-
- _changeTest = (testName) => {
- this.setState({currentTest: TESTS[testName]});
- };
-
- render() {
- const {restarting, currentTest} = this.state;
- return (
-
- Keyboard.dismiss()}
- testID="closeKeyboard"
- />
-
-
- Simulate Restart
-
-
-
-
-
- {restarting ? null : (
-
- {currentTest.title}
-
- {currentTest.description}
-
-
- {currentTest.render()}
-
-
- )}
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: '#F5FCFF',
- padding: 8,
- },
- exampleContainer: {
- padding: 4,
- backgroundColor: '#FFF',
- borderColor: '#EEE',
- borderTopWidth: 1,
- borderBottomWidth: 1,
- flex: 1,
- },
- exampleTitle: {
- fontSize: 18,
- },
- exampleDescription: {
- color: '#333333',
- marginBottom: 16,
- },
- exampleInnerContainer: {
- borderColor: '#EEE',
- borderTopWidth: 1,
- paddingTop: 10,
- flex: 1,
- },
- restartButton: {
- padding: 6,
- borderRadius: 5,
- backgroundColor: '#F3F3F3',
- alignItems: 'center',
- justifyContent: 'center',
- alignSelf: 'flex-end',
- },
- closeKeyboardView: {
- width: 5,
- height: 5,
- },
- testPickerContainer: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- },
-});
diff --git a/example/App.tsx b/example/App.tsx
new file mode 100644
index 00000000..84a3c060
--- /dev/null
+++ b/example/App.tsx
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, { useCallback, useState } from 'react';
+import {
+ Button,
+ Keyboard,
+ SafeAreaView,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View
+} from 'react-native';
+import BasicExample from './examples/Basic';
+import GetSetClear from './examples/GetSetClear';
+import MergeItem from './examples/MergeItem';
+
+const TESTS = {
+ GetSetClear: {
+ title: 'Simple Get/Set value',
+ testId: 'get-set-clear',
+ description: 'Store and retrieve persisted data',
+ render() {
+ return ;
+ },
+ },
+ MergeItem: {
+ title: 'Merge item',
+ testId: 'merge-item',
+ description: 'Merge object with already stored data',
+ render() {
+ return ;
+ },
+ },
+ Basic: {
+ title: 'Basic',
+ testId: 'basic',
+ description: 'Basic functionality test',
+ render() {
+ return ;
+ },
+ },
+};
+
+export default function App(): JSX.Element {
+ const [iteration, setIteration] = useState(0);
+ const [currentTest, setCurrentTest] = useState(TESTS.GetSetClear);
+
+ const dismissKeyboard = useCallback(() => Keyboard.dismiss(), []);
+ const simulateRestart = useCallback(() => setIteration(iteration + 1), [iteration]);
+ const testBasic = useCallback(() => setCurrentTest(TESTS.Basic), []);
+ const testGetSetClear = useCallback(() => setCurrentTest(TESTS.GetSetClear), []);
+ const testMergeItem = useCallback(() => setCurrentTest(TESTS.MergeItem), []);
+
+ return (
+
+
+
+
+ Simulate Restart
+
+
+
+
+
+
+
+
+
+ {currentTest.title}
+
+ {currentTest.description}
+
+
+ {currentTest.render()}
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#F5FCFF',
+ padding: 8,
+ },
+ exampleContainer: {
+ padding: 4,
+ backgroundColor: '#FFF',
+ borderColor: '#EEE',
+ borderTopWidth: 1,
+ borderBottomWidth: 1,
+ flex: 1,
+ },
+ exampleTitle: {
+ fontSize: 18,
+ },
+ exampleDescription: {
+ color: '#333333',
+ marginBottom: 16,
+ },
+ exampleInnerContainer: {
+ borderColor: '#EEE',
+ borderTopWidth: 1,
+ paddingTop: 10,
+ flex: 1,
+ },
+ restartButton: {
+ padding: 6,
+ borderRadius: 5,
+ backgroundColor: '#F3F3F3',
+ alignItems: 'center',
+ justifyContent: 'center',
+ alignSelf: 'flex-end',
+ },
+ closeKeyboardView: {
+ width: 5,
+ height: 5,
+ },
+ testPickerContainer: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+});
diff --git a/example/examples/Basic.js b/example/examples/Basic.tsx
similarity index 87%
rename from example/examples/Basic.js
rename to example/examples/Basic.tsx
index 4dc2375e..93e119ca 100644
--- a/example/examples/Basic.js
+++ b/example/examples/Basic.tsx
@@ -1,7 +1,13 @@
-import React from 'react';
-import {View, Text, Button, StyleSheet, ScrollView, TextInput} from 'react-native';
+// @ts-ignore
import AsyncStorage from '@react-native-async-storage/async-storage';
+import React from 'react';
+import { Button, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';
+type DataType = {
+ deeper?: DataType;
+ nested?: DataType;
+ [key: string]: string | DataType | undefined;
+};
const mergeInitialValue = {
initial: 'keep',
@@ -16,11 +22,15 @@ const mergeInitialValue = {
},
};
+function hasMessage(e: unknown): e is { "message": string; } {
+ return Boolean(typeof e === 'object' && e && 'message' in e);
+}
+
function NextExample() {
const [keys, setKeys] = React.useState([]);
- const [error, setError] = React.useState(null);
- const [inputKey, setInputKey] = React.useState();
- const [inputValue, setInputValue] = React.useState();
+ const [error, setError] = React.useState('');
+ const [inputKey, setInputKey] = React.useState('');
+ const [inputValue, setInputValue] = React.useState('');
const [value, setValue] = React.useState();
const [mergedValue, setMergedValue] = React.useState();
const [overrideValue, setOverrideValue] = React.useState({
@@ -30,13 +40,17 @@ function NextExample() {
});
- function runWithCatch(block) {
+ function runWithCatch(block: () => Promise) {
return async () => {
try {
- setError(null);
+ setError('');
await block();
} catch (e) {
- setError('Caught: ' + e.message || e);
+ if (hasMessage(e)) {
+ setError('Caught error: ' + (e.message || e));
+ } else {
+ setError('Unknown error: ' + e);
+ }
}
};
}
@@ -90,9 +104,9 @@ function NextExample() {
const {override1, override2, override3} = overrideValue;
// leave out empty inputs
- const toMerge = {};
+ const toMerge: DataType = {};
if (override1) {
- toMerge.override1 = override1;
+ toMerge['override1'] = override1;
}
if (override2) {
toMerge.nested = {
@@ -186,7 +200,6 @@ function NextExample() {
;
}
-
const styles = StyleSheet.create({
example: {
paddingBottom: 24,
diff --git a/example/examples/GetSetClear.js b/example/examples/GetSetClear.tsx
similarity index 92%
rename from example/examples/GetSetClear.js
rename to example/examples/GetSetClear.tsx
index 6cc1853c..3b6ba6ed 100644
--- a/example/examples/GetSetClear.js
+++ b/example/examples/GetSetClear.tsx
@@ -3,22 +3,19 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
*/
-import React from 'react';
-import {StyleSheet, Text, View, Button} from 'react-native';
-
+// @ts-ignore
import AsyncStorage from '@react-native-async-storage/async-storage';
+import React from 'react';
+import { Button, StyleSheet, Text, View } from 'react-native';
export default function GetSet() {
const [storedNumber, setStoredNumber] = React.useState('');
const [needsRestart, setNeedsRestart] = React.useState(false);
React.useEffect(() => {
- AsyncStorage.getItem(STORAGE_KEY).then((value) => {
+ AsyncStorage.getItem(STORAGE_KEY).then((value: string) => {
if (value) {
setStoredNumber(value);
}
diff --git a/example/examples/MergeItem.js b/example/examples/MergeItem.js
deleted file mode 100644
index 03004799..00000000
--- a/example/examples/MergeItem.js
+++ /dev/null
@@ -1,268 +0,0 @@
-/**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- */
-
-import React, {Component} from 'react';
-import {
- Button,
- NativeModules,
- StyleSheet,
- Text,
- TextInput,
- View,
-} from 'react-native';
-
-import AsyncStorage from '@react-native-async-storage/async-storage';
-
-const KEY = '@@KEY';
-
-type Props = {};
-type State = {
- needRestart: boolean,
- name: string,
- age: string,
- traits: {
- trait1: string,
- trait2: string,
- },
-};
-
-const INPUTS = [
- {
- title: 'Name',
- stateFragment: 'name',
- testId: 'testInput-name',
- },
- {
- title: 'Age',
- stateFragment: 'age',
- inputType: 'number-pad',
- testId: 'testInput-age',
- },
- {
- title: 'Eyes color',
- stateFragment: 'trait1',
- testId: 'testInput-eyes',
- },
- {
- title: 'Shoe size',
- stateFragment: 'trait2',
- inputType: 'number-pad',
- testId: 'testInput-shoe',
- },
-];
-
-export default class Merge extends Component {
- state = {
- needRestart: false,
- name: '',
- age: '',
- traits: {
- trait1: '',
- trait2: '',
- },
- };
-
- mergeItem = async () => {
- const {
- name,
- age,
- traits: {trait1, trait2},
- } = this.state;
-
- const obj = {
- name,
- age,
- traits: {
- trait1,
- trait2,
- },
- };
-
- try {
- await AsyncStorage.mergeItem(KEY, JSON.stringify(obj));
- } catch (e) {
- console.warn(e);
- }
-
- this.setState({needRestart: true});
- };
-
- saveItem = async () => {
- const {
- name,
- age,
- traits: {trait1, trait2},
- } = this.state;
-
- const obj = {
- name,
- age,
- traits: {
- trait1,
- trait2,
- },
- };
-
- try {
- await AsyncStorage.setItem(KEY, JSON.stringify(obj));
- } catch (e) {
- console.warn(e);
- }
-
- this.setState({needRestart: true});
- };
-
- restoreItem = async () => {
- let storedItem = {};
-
- try {
- const saved = await AsyncStorage.getItem(KEY);
- storedItem = JSON.parse(saved || '{"traits": {}}');
- } catch (e) {
- console.warn(e);
- }
-
- const {traits} = storedItem || {};
-
- this.setState({
- name: storedItem.name || '',
- age: storedItem.age || '',
- traits: {
- trait1: traits.trait1 || '',
- trait2: traits.trait2 || '',
- },
- });
- };
-
- render() {
- const {needRestart, name, age, traits} = this.state;
- const {trait1, trait2} = traits;
- return (
-
-
- {`${name} is ${age}, has ${trait1} eyes and shoe size of ${trait2}.`}
-
-
- {INPUTS.map((input) => {
- const isTraitsPart = input.stateFragment.includes('trait');
-
- const value = isTraitsPart
- ? // $FlowFixMe
- traits[input.stateFragment]
- : // $FlowFixMe
- this.state[input.stateFragment];
-
- const onChangeHandler = (text) => {
- isTraitsPart
- ? this.setState(({traits: currentTraits}) => ({
- // $FlowFixMe
- traits: {
- // $FlowFixMe
- ...currentTraits,
- // $FlowFixMe
- [input.stateFragment]: text,
- },
- }))
- : this.setState((state) =>
- // $FlowFixMe
- ({
- // $FlowFixMe
- ...state,
- // $FlowFixMe
- [input.stateFragment]: text,
- }),
- );
- };
-
- return (
-
- {input.title}:
-
-
- );
- })}
-
-
-
-
-
-
-
-
-
- NativeModules.AsyncStorageTestSupport.test_setDelegate(() => {})
- }
- />
-
- NativeModules.AsyncStorageTestSupport.test_unsetDelegate(() => {})
- }
- />
-
-
- {needRestart ? Hit restart to see effect : null}
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- inputView: {
- borderColor: '#333',
- borderWidth: 0.5,
- borderStyle: 'solid',
- fontSize: 14,
- padding: 0,
- },
- bottomButtons: {
- justifyContent: 'space-around',
- marginTop: 20,
- flexDirection: 'row',
- },
- story: {
- fontSize: 18,
- color: '#222',
- },
-});
diff --git a/example/examples/MergeItem.tsx b/example/examples/MergeItem.tsx
new file mode 100644
index 00000000..f97170c6
--- /dev/null
+++ b/example/examples/MergeItem.tsx
@@ -0,0 +1,223 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// @ts-ignore
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import React, {useCallback, useState} from 'react';
+import {
+ Button,
+ NativeModules,
+ StyleSheet,
+ Text,
+ TextInput,
+ View,
+} from 'react-native';
+
+type Personalia = {
+ age: string,
+ name: string,
+ traits: {
+ trait1: string,
+ trait2: string,
+ },
+};
+
+const KEY = '@@KEY';
+
+const INPUTS = [
+ {
+ title: 'Name',
+ stateFragment: 'name',
+ inputType: undefined,
+ testId: 'testInput-name',
+ },
+ {
+ title: 'Age',
+ stateFragment: 'age',
+ inputType: 'number-pad',
+ testId: 'testInput-age',
+ },
+ {
+ title: 'Eyes color',
+ stateFragment: 'trait1',
+ inputType: undefined,
+ testId: 'testInput-eyes',
+ },
+ {
+ title: 'Shoe size',
+ stateFragment: 'trait2',
+ inputType: 'number-pad',
+ testId: 'testInput-shoe',
+ },
+] as const;
+
+export default function Merge(): JSX.Element {
+ const [needRestart, setNeedRestart] = useState(false);
+ const [name, setName] = useState('');
+ const [age, setAge] = useState('');
+ const [traits, setTraits] = useState({trait1: '', trait2: ''});
+
+ const mergeItem = useCallback(async () => {
+ const obj = {name, age, traits};
+ try {
+ await AsyncStorage.mergeItem(KEY, JSON.stringify(obj));
+ } catch (e) {
+ console.warn(e);
+ }
+
+ setNeedRestart(true);
+ }, [name, age, traits]);
+
+ const saveItem = useCallback(async () => {
+ const obj = {name, age, traits};
+ try {
+ await AsyncStorage.setItem(KEY, JSON.stringify(obj));
+ } catch (e) {
+ console.warn(e);
+ }
+
+ setNeedRestart(true);
+ }, [name, age, traits]);
+
+ const restoreItem = useCallback(async () => {
+ let storedItem: Partial = {};
+
+ try {
+ const saved = await AsyncStorage.getItem(KEY);
+ storedItem = JSON.parse(saved || '{"traits": {}}');
+ } catch (e) {
+ console.warn(e);
+ }
+
+ const {name, age, traits} = storedItem || {};
+
+ setName(name || '');
+ setAge(age || '');
+ setTraits(traits || {trait1: '', trait2: ''});
+ }, []);
+
+ const {trait1, trait2} = traits;
+
+ return (
+
+
+ {`${name} is ${age}, has ${trait1} eyes and shoe size of ${trait2}.`}
+
+
+ {INPUTS.map(({title, stateFragment, inputType, testId}) => {
+ const value = (() => {
+ switch (stateFragment) {
+ case 'age':
+ return age;
+ case 'name':
+ return name;
+
+ case 'trait1':
+ case 'trait2':
+ return traits[stateFragment];
+ }
+ })();
+
+ const onChangeHandler = (() => {
+ switch (stateFragment) {
+ case 'age':
+ return setAge;
+ case 'name':
+ return setName;
+
+ case 'trait1':
+ case 'trait2':
+ return (text: string) =>
+ setTraits({
+ ...traits,
+ [stateFragment]: text,
+ });
+ }
+ })();
+
+ return (
+
+ {title}:
+
+
+ );
+ })}
+
+
+
+
+
+
+
+
+
+ NativeModules['AsyncStorageTestSupport'].test_setDelegate(() => {})
+ }
+ />
+
+ NativeModules['AsyncStorageTestSupport'].test_unsetDelegate(
+ () => {},
+ )
+ }
+ />
+
+
+ {needRestart ? Hit restart to see effect : null}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ inputView: {
+ borderColor: '#333',
+ borderWidth: 0.5,
+ borderStyle: 'solid',
+ fontSize: 14,
+ padding: 0,
+ },
+ bottomButtons: {
+ justifyContent: 'space-around',
+ marginTop: 20,
+ flexDirection: 'row',
+ },
+ story: {
+ fontSize: 18,
+ color: '#222',
+ },
+});
diff --git a/example/index.js b/example/index.ts
similarity index 95%
rename from example/index.js
rename to example/index.ts
index d457c8a0..109c3b75 100644
--- a/example/index.js
+++ b/example/index.ts
@@ -3,9 +3,6 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
*/
import {AppRegistry, Platform} from 'react-native';
diff --git a/package.json b/package.json
index 7f67d773..acb3c6a8 100644
--- a/package.json
+++ b/package.json
@@ -52,8 +52,8 @@
"build:e2e:macos": "scripts/macos_e2e.sh 'build'",
"bundle:android": "scripts/android_e2e.sh 'bundle'",
"bundle:ios": "scripts/ios_e2e.sh 'bundle'",
- "bundle:macos": "react-native bundle --entry-file index.js --platform macos --bundle-output example/index.macos.jsbundle --use-react-native-macos",
- "test": "yarn test:lint && yarn test:flow",
+ "bundle:macos": "react-native bundle --entry-file index.ts --platform macos --bundle-output example/index.macos.jsbundle --use-react-native-macos",
+ "test": "yarn test:lint && yarn test:flow && tsc",
"test:flow": "flow check",
"test:lint": "eslint src/**/*.js example/**/*.js jest/*.js",
"test:e2e:android": "detox test -c android.emu.release --maxConcurrency 1",
@@ -76,6 +76,8 @@
"@react-native-community/eslint-config": "^3.0.0",
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/git": "9.0.0",
+ "@types/react": "^17.0.0",
+ "@types/react-native": "^0.64.0",
"detox": "17.10.6",
"eslint": "^7.0.0",
"expo": "^38.0.10",
@@ -94,7 +96,8 @@
"react-native-web": "~0.12.0",
"react-native-windows": "^0.63.41",
"react-test-renderer": "16.13.1",
- "semantic-release": "^17.4.6"
+ "semantic-release": "^17.4.6",
+ "typescript": "^4.5.0"
},
"jest": {
"preset": "react-native",
diff --git a/scripts/android_e2e.sh b/scripts/android_e2e.sh
index b63d9eb2..797abff2 100755
--- a/scripts/android_e2e.sh
+++ b/scripts/android_e2e.sh
@@ -13,7 +13,7 @@ bundle_js() {
extraArgs="$@"
echo
echo "[Detox e2e] Bundling JS"
- react-native bundle --entry-file index.js --platform android --bundle-output example/index.android.jsbundle $extraArgs
+ react-native bundle --entry-file index.ts --platform android --bundle-output example/index.android.jsbundle $extraArgs
}
wait_for_emulator_to_boot() {
diff --git a/scripts/ios_e2e.sh b/scripts/ios_e2e.sh
index d189a39f..59ca4d33 100755
--- a/scripts/ios_e2e.sh
+++ b/scripts/ios_e2e.sh
@@ -1,7 +1,7 @@
#!/bin/bash
RESOURCE_DIR="$PWD/example/ios/build/Build/Products/Release-iphonesimulator/ReactTestApp.app"
-ENTRY_FILE="example/index.js"
+ENTRY_FILE="example/index.ts"
BUNDLE_FILE="$RESOURCE_DIR/main.jsbundle"
EXTRA_PACKAGER_ARGS="--entry-file=$ENTRY_FILE"
SIMULATOR_NAME="iPhone 11"
@@ -53,7 +53,7 @@ bundle_js() {
extraArgs="$@"
echo
echo "[Detox e2e] Bundling JS"
- react-native bundle --entry-file index.js --platform ios --bundle-output example/index.ios.jsbundle $extraArgs
+ react-native bundle --entry-file index.ts --platform ios --bundle-output example/index.ios.jsbundle $extraArgs
}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..4f4c0021
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitOverride": true,
+ "noImplicitReturns": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "strict": true,
+
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+
+ "noEmit": true,
+
+ "allowJs": true,
+ "checkJs": true,
+
+ "allowSyntheticDefaultImports": true,
+
+ "forceConsistentCasingInFileNames": true,
+
+ "jsx": "react",
+
+ "target": "ESNext",
+
+ "skipLibCheck": true
+ },
+ "include": [
+ "example/*.ts",
+ "example/*.tsx",
+ "example/examples/**/*.tsx"
+ ]
+}
diff --git a/yarn.lock b/yarn.lock
index be7e33a2..2e9dab57 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2511,16 +2511,42 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3"
integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==
+"@types/prop-types@*":
+ version "15.7.4"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
+ integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
+
"@types/q@^1.5.1":
version "1.5.5"
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==
+"@types/react-native@^0.64.0":
+ version "0.64.19"
+ resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.64.19.tgz#2b888c082ad293fa0fa6ae34c5e9457cfb38e50a"
+ integrity sha512-bT62QhaPvOKFGmlfURIC98ILjUDoIFrc2Bn5EzL3qciZrT91vHwkxFOkuEyQJy+DWaHCa2z3IrtIEJywkGu/Bg==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@^17.0.0":
+ version "17.0.37"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.37.tgz#6884d0aa402605935c397ae689deed115caad959"
+ integrity sha512-2FS1oTqBGcH/s0E+CjrCCR9+JMpsu9b69RTFO+40ua43ZqP5MmQ4iUde/dMjWR909KxZwmOQIFq6AV6NjEG5xg==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
"@types/retry@^0.12.0":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
"@types/source-list-map@*":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
@@ -5004,6 +5030,11 @@ cssstyle@^2.3.0:
dependencies:
cssom "~0.3.6"
+csstype@^3.0.2:
+ version "3.0.10"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
+ integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==
+
cyclist@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@@ -13806,6 +13837,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+typescript@^4.5.0:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.2.tgz#8ac1fba9f52256fdb06fb89e4122fa6a346c2998"
+ integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==
+
ua-parser-js@^0.7.18:
version "0.7.28"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
From 1a1d7a8b83f4fa0d9569f69ab4325e386a252291 Mon Sep 17 00:00:00 2001
From: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
Date: Tue, 30 Nov 2021 22:36:04 +0100
Subject: [PATCH 2/3] specify BundleEntryFile for Windows
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 57fb6b3a..8f0a0767 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -64,5 +64,5 @@ jobs:
working-directory: example/windows
- name: Build
run: |
- MSBuild -t:Rebuild -p:Configuration=Release -p:Platform=x64 ReactTestApp.sln
+ MSBuild -t:Rebuild -p:Configuration=Release -p:Platform=x64 -p:BundleEntryFile=index.ts ReactTestApp.sln
working-directory: example/windows
From 232d6d0b9ea638d9122ca0f2786b7478affd137a Mon Sep 17 00:00:00 2001
From: Tommy Nguyen <4123478+tido64@users.noreply.github.com>
Date: Wed, 1 Dec 2021 10:59:51 +0100
Subject: [PATCH 3/3] use concurrently
---
ios/RNCAsyncStorage.m | 21 +++++++++-----------
package.json | 5 ++++-
tsconfig.json | 8 --------
yarn.lock | 45 ++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/ios/RNCAsyncStorage.m b/ios/RNCAsyncStorage.m
index b25cf861..75c87471 100644
--- a/ios/RNCAsyncStorage.m
+++ b/ios/RNCAsyncStorage.m
@@ -316,7 +316,6 @@ static void RCTStorageDirectoryMigrate(NSString *oldDirectoryPath,
}
}
-
/**
* Determine which of RCTOldStorageDirectory or RCTExpoStorageDirectory needs to migrated.
* If both exist, we remove the least recently modified and return the most recently modified.
@@ -329,17 +328,18 @@ static void RCTStorageDirectoryMigrate(NSString *oldDirectoryPath,
NSString *oldStoragePath = RCTCreateStorageDirectoryPath_deprecated(RCTOldStorageDirectory);
NSString *expoStoragePath = RCTCreateStorageDirectoryPath_deprecated(RCTExpoStorageDirectory);
NSFileManager *fileManager = [NSFileManager defaultManager];
- BOOL oldStorageDirectoryExists = [fileManager fileExistsAtPath:oldStoragePath isDirectory:&isDir] && isDir;
- BOOL expoStorageDirectoryExists = [fileManager fileExistsAtPath:expoStoragePath isDirectory:&isDir] && isDir;
-
+ BOOL oldStorageDirectoryExists =
+ [fileManager fileExistsAtPath:oldStoragePath isDirectory:&isDir] && isDir;
+ BOOL expoStorageDirectoryExists =
+ [fileManager fileExistsAtPath:expoStoragePath isDirectory:&isDir] && isDir;
// Check if both the old storage directory and Expo storage directory exist
if (oldStorageDirectoryExists && expoStorageDirectoryExists) {
- // If the old storage has been modified more recently than Expo storage, then clear Expo storage.
- // Otherwise, clear the old storage.
+ // If the old storage has been modified more recently than Expo storage, then clear Expo
+ // storage. Otherwise, clear the old storage.
if ([RCTManifestModificationDate(RCTCreateManifestFilePath(oldStoragePath))
- compare:RCTManifestModificationDate(
- RCTCreateManifestFilePath(expoStoragePath))] == NSOrderedDescending) {
+ compare:RCTManifestModificationDate(RCTCreateManifestFilePath(expoStoragePath))] ==
+ NSOrderedDescending) {
RCTStorageDirectoryCleanupOld(expoStoragePath);
return oldStoragePath;
} else {
@@ -355,7 +355,6 @@ static void RCTStorageDirectoryMigrate(NSString *oldDirectoryPath,
}
}
-
/**
* This check is added to make sure that anyone coming from pre-1.2.2 does not lose cached data.
* Check that data is migrated from the old location to the new location
@@ -433,9 +432,7 @@ - (instancetype)init
// Migrate our deprecated path "Documents/.../RNCAsyncLocalStorage_V1" or
// "Documents/.../RCTAsyncLocalStorage" to "Documents/.../RCTAsyncLocalStorage_V1"
RCTStorageDirectoryMigrationCheck(
- oldStoragePath,
- RCTCreateStorageDirectoryPath_deprecated(RCTStorageDirectory),
- YES);
+ oldStoragePath, RCTCreateStorageDirectoryPath_deprecated(RCTStorageDirectory), YES);
}
// Migrate what's in "Documents/.../RCTAsyncLocalStorage_V1" to
diff --git a/package.json b/package.json
index acb3c6a8..bfc168e0 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
},
"scripts": {
"ci": "yarn --pure-lockfile --non-interactive --cache-folder .cache/yarn",
+ "format": "concurrently yarn:format:*",
"format:c": "clang-format -i $(git ls-files '*.cpp' '*.h' '*.m' '*.mm')",
"format:js": "prettier --write $(git ls-files '*.js' '*.json' '*.yml')",
"prepare": "bob build",
@@ -53,9 +54,10 @@
"bundle:android": "scripts/android_e2e.sh 'bundle'",
"bundle:ios": "scripts/ios_e2e.sh 'bundle'",
"bundle:macos": "react-native bundle --entry-file index.ts --platform macos --bundle-output example/index.macos.jsbundle --use-react-native-macos",
- "test": "yarn test:lint && yarn test:flow && tsc",
+ "test": "concurrently -n flow,lint,ts yarn:test:flow yarn:test:lint yarn:test:ts",
"test:flow": "flow check",
"test:lint": "eslint src/**/*.js example/**/*.js jest/*.js",
+ "test:ts": "tsc",
"test:e2e:android": "detox test -c android.emu.release --maxConcurrency 1",
"test:e2e:ios": "detox test -c ios.sim.release --maxConcurrency 1",
"test:e2e:macos": "scripts/macos_e2e.sh 'test'"
@@ -78,6 +80,7 @@
"@semantic-release/git": "9.0.0",
"@types/react": "^17.0.0",
"@types/react-native": "^0.64.0",
+ "concurrently": "^6.4.0",
"detox": "17.10.6",
"eslint": "^7.0.0",
"expo": "^38.0.10",
diff --git a/tsconfig.json b/tsconfig.json
index 4f4c0021..477afb74 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,23 +7,15 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"strict": true,
-
"moduleResolution": "Node",
"resolveJsonModule": true,
-
"noEmit": true,
-
"allowJs": true,
"checkJs": true,
-
"allowSyntheticDefaultImports": true,
-
"forceConsistentCasingInFileNames": true,
-
"jsx": "react",
-
"target": "ESNext",
-
"skipLibCheck": true
},
"include": [
diff --git a/yarn.lock b/yarn.lock
index 2e9dab57..d42d5fbb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4565,6 +4565,20 @@ concat-stream@^1.5.0, concat-stream@^1.6.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
+concurrently@^6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.4.0.tgz#5387ee86be435a0eb51c292ade8a00acf479f170"
+ integrity sha512-HZ3D0RTQMH3oS4gvtYj1P+NBc6PzE2McEra6yEFcQKrUQ9HvtTGU4Dbne083F034p+LRb7kWU0tPRNvSGs1UCQ==
+ dependencies:
+ chalk "^4.1.0"
+ date-fns "^2.16.1"
+ lodash "^4.17.21"
+ rxjs "^6.6.3"
+ spawn-command "^0.0.2-1"
+ supports-color "^8.1.0"
+ tree-kill "^1.2.2"
+ yargs "^16.2.0"
+
connect@^3.6.5:
version "3.7.0"
resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
@@ -5056,6 +5070,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
+date-fns@^2.16.1:
+ version "2.27.0"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.27.0.tgz#e1ff3c3ddbbab8a2eaadbb6106be2929a5a2d92b"
+ integrity sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q==
+
dateformat@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
@@ -12465,6 +12484,13 @@ rx-lite@*, rx-lite@^4.0.8:
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=
+rxjs@^6.6.3:
+ version "6.6.7"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+ integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+ dependencies:
+ tslib "^1.9.0"
+
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -12954,6 +12980,11 @@ source-map@^0.7.3:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
+spawn-command@^0.0.2-1:
+ version "0.0.2-1"
+ resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
+ integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
+
spawn-error-forwarder@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz#1afd94738e999b0346d7b9fc373be55e07577029"
@@ -13358,6 +13389,13 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
+supports-color@^8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
@@ -13705,6 +13743,11 @@ traverse@~0.6.6:
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=
+tree-kill@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
+ integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
+
treeverse@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-1.0.4.tgz#a6b0ebf98a1bca6846ddc7ecbc900df08cb9cd5f"
@@ -13732,7 +13775,7 @@ ts-pnp@^1.1.6:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
-tslib@^1.8.1:
+tslib@^1.8.1, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==