Merge pull request 'asyncStorage' (#5) from asyncStorage into master

Reviewed-on: #5
pull/6/head
Corentin RICHARD 2 years ago
commit 2f9223012c

@ -1,17 +1,53 @@
import { View } from 'react-native'; import { useDispatch } from "react-redux";
import { Image } from 'react-native'; import { Card } from "../models/Card";
import { setFavList } from "../redux/actions/action_setFavList";
import { ImageBackground, TouchableHighlight, View } from "react-native";
import React, { useEffect } from "react";
import {CardProps} from "../props/favprops"
import { FontAwesome } from '@expo/vector-icons';
import { StyleSheet} from 'react-native';
export default function Item(props: CardProps){ // a mettre dans components et definir une props pour passer le param
type ItemProps = { const {route} = props;
url : string //Image URL const item: Card = route.card;
} const bool: boolean = route.bool;
const dispatch = useDispatch()
export function ListItemComponent(props : ItemProps){ const HandleAddFav = (props : CardProps) => {
console.log("add new card")
dispatch(setFavList(props));
}
return( return(
<View>
<Image /* dispatch , */
source={{uri: props.url}} <View style={styles.item}>
style={{flex:1, minHeight:250, minWidth:180}}/> <ImageBackground source={{uri:item.img}} style={{flex:1, minHeight:250, minWidth:180}}>
<TouchableHighlight style={item.fav?styles.favoriteButtonFav:styles.favoriteButtonNonFav} onPress={() => HandleAddFav(props)} >
<FontAwesome name="heart-o" size={50} color="#fff" />
</TouchableHighlight>
</ImageBackground>
</View> </View>
) );
} }
const styles = StyleSheet.create({
item: {
},
favoriteButtonNonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
},
favoriteButtonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
},});

@ -1,14 +0,0 @@
// export class ApiDataManager{
// public async getCards() : Promise<String[]> {
// const CardPromise = await fetch('https://omgvamp-hearthstone-v1.p.rapidapi.com/cards')
// const CardListJson = await CardPromise.json();
// const CardList: String[] = Array.of(CardListJson);
// return CardList;
// }
// }

@ -1,13 +0,0 @@
import { Card } from "../models/Card"
export class StubLib {
public getCards(): Card[] {
const NOUNOURS_LIST : Card[] = [
]
return NOUNOURS_LIST
}
}

@ -5,9 +5,9 @@ import {Classe} from "./Classe";
export class Card { export class Card {
constructor(id: number,name :string, img : string, imgGold : string){//,set : CardSet,type : Type,clas : Classe,rarity : string,cost : number,attack : number, health : number, desc : string,flavor : string,artist : string,collectible : boolean,elite : boolean,race : string, cropImg :string) { constructor(id: string,name :string, img : string, imgGold : string,fav : boolean = true){//,set : CardSet,type : Type,clas : Classe,rarity : string,cost : number,attack : number, health : number, desc : string,flavor : string,artist : string,collectible : boolean,elite : boolean,race : string, cropImg :string ) {
this._id=id this.id=id
this._name=name this.name=name
//this._set=set //this._set=set
// this._type=type // this._type=type
// this._class=clas // this._class=clas
@ -19,27 +19,19 @@ export class Card {
// this._flavor = flavor // this._flavor = flavor
// this._artist = artist // this._artist = artist
// this._collectible = collectible // this._collectible = collectible
this._img = img this.img = img
this._imgGold = imgGold this.imgGold = imgGold
// this._cropImg = cropImg // this._cropImg = cropImg
this.fav = fav
} }
// ID // // ID //
private _id : number; public id;
get id(): number {
return this._id
}
// NAME // // NAME //
private _name : string; public name;
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
// private _set : CardSet; // private _set : CardSet;
@ -131,22 +123,8 @@ export class Card {
// this._collectible = value; // this._collectible = value;
// } // }
private _img : string public img;
public imgGold;
get img(): string {
return this._img;
}
set img(value: string) {
this._img = value ;
}
private _imgGold : string
get imgGold(): string {
return this._imgGold;
}
set imgGold(value: string) {
this._imgGold = value ;
}
// private _cropImg : string // private _cropImg : string
// get cropImg(): string { // get cropImg(): string {
@ -155,4 +133,6 @@ export class Card {
// set cropImg(value: string) { // set cropImg(value: string) {
// this._cropImg = value; // this._cropImg = value;
// } // }
public fav;
} }

@ -9,6 +9,7 @@
"web": "expo start --web" "web": "expo start --web"
}, },
"dependencies": { "dependencies": {
"@react-native-async-storage/async-storage": "1.17.11",
"@react-navigation/bottom-tabs": "^6.5.5", "@react-navigation/bottom-tabs": "^6.5.5",
"@react-navigation/native": "^6.1.4", "@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10", "@react-navigation/native-stack": "^6.9.10",

@ -0,0 +1,8 @@
import { Card } from "../models/Card";
export interface CardProps{
route : {
card: Card;
bool: boolean;
}
}

@ -25,7 +25,7 @@ import { Card } from "../../models/Card";
// constructor(cardId : String, name : String, manaCost : number, attack : number, health : number, desc : String){ // constructor(cardId : String, name : String, manaCost : number, attack : number, health : number, desc : String){
// this.cardId = cardId; // this.cardId = cardId;
// this.name = name; // this.name = name;
// this.manaCost = manaCost; // this.manaCost = manaCost;ADD_FAVORITE_DATA, FETCH_DATA,
// this.attack = attack; // this.attack = attack;
// this.health = health; // this.health = health;
// this.desc = desc; // this.desc = desc;
@ -50,7 +50,7 @@ export const getAllCards = () => {
// 'content-length':'9505', // 'content-length':'9505',
// 'content-type':'application/json; charset=utf-8', // 'content-type':'application/json; charset=utf-8',
// 'etag':'W/"74bb-QMT8DIj6saBS1wT4u5WWcEmZAdw"' // 'etag':'W/"74bb-QMT8DIj6saBS1wT4u5WWcEmZAdw"'
// } // }ADD_FAVORITE_DATA, FETCH_DATA,
//! Actualisation de l'API (16/03) : //! Actualisation de l'API (16/03) :
headers: { headers: {
@ -61,7 +61,7 @@ export const getAllCards = () => {
//'pageSize':'100' //'pageSize':'100'
}; };
//! Actualisation de l'API (16/03) : //! Actualisation de l'API (16/03) :
const CardsPromise = await fetch('https://us.api.blizzard.com/hearthstone/cards?locale=en_US&access_token=EU1AbKy9Q7sOUjQYC5AFF1O1JPuoAgCNxk', options); const CardsPromise = await fetch('https://us.api.blizzard.com/hearthstone/cards?locale=en_US&access_token=EUe6p4N9uLm8BbsHyYVZXIa4DDBP2hMR05', options);
//const CardsPromise = await fetch('https://us.api.blizzard.com/hearthstone/cards?locale=en_US&access_token=EURTWhjBC2SRb4Ez42BT1kx8R2NcJc07kL', options); //const CardsPromise = await fetch('https://us.api.blizzard.com/hearthstone/cards?locale=en_US&access_token=EURTWhjBC2SRb4Ez42BT1kx8R2NcJc07kL', options);
//console.log("FETCH") //console.log("FETCH")
//console.log(CardsPromise) //console.log(CardsPromise)

@ -1,8 +1,10 @@
import { Card } from '../../models/Card';
import { CardProps } from '../../props/favprops';
import {ADD_FAVORITE_DATA, FETCH_DATA} from '../constants'; import {ADD_FAVORITE_DATA, FETCH_DATA} from '../constants';
export const setFavList = (List: String[]) => { export const setFavList = (props : CardProps) => {
return { return {
type: ADD_FAVORITE_DATA, type: ADD_FAVORITE_DATA,
payload: List, payload: props,
}; };
} }

@ -0,0 +1,9 @@
import { Card } from '../../models/Card';
import {SET_FAVS} from '../constants';
export const setList = (list: []) => {
return {
type: SET_FAVS,
payload: list
};
}

@ -1,15 +0,0 @@
import {ADD_FAVORITE_DATA, FETCH_DATA} from '../constants';
export const setList = (List: String[]) => {
return {
type: FETCH_DATA,
payload: List,
};
}
// export const setFavList = (List: String[]) => {
// return {
// type: ADD_FAVORITE_DATA,
// payload: List,
// };
// }

@ -5,3 +5,6 @@ export const FETCH_DATA = "FETCH_DATA"
export const ADD_FAVORITE_DATA = "ADD_FAVORITE_DATA" export const ADD_FAVORITE_DATA = "ADD_FAVORITE_DATA"
export const DISPLAY_ALL_CARD = "DISPLAY_ALL_CARD" export const DISPLAY_ALL_CARD = "DISPLAY_ALL_CARD"
export const SET_FAVS = "SET_FAVS"

@ -1,10 +1,12 @@
import {FETCH_DATA, ADD_FAVORITE_DATA} from '../constants' import AsyncStorage from '@react-native-async-storage/async-storage'
import { Card } from '../../models/Card'
import { CardProps } from '../../props/favprops'
import {FETCH_DATA, ADD_FAVORITE_DATA, SET_FAVS} from '../constants'
import StorageHeart from '../../service/AsyncStorage'
const initialState = { const initialState = {
cards: [], cards: [],
favoriteCards: [], favoriteCards: []
// cards: ["C_ace", "C_K", "C_Q", "C_J"],
// favoriteCards: [ "C_ace", "C_K"],
} }
@ -12,11 +14,35 @@ const initialState = {
export default appReducer = (state = initialState, action) => { export default appReducer = (state = initialState, action) => {
switch (action.type) { switch (action.type) {
case ADD_FAVORITE_DATA: case ADD_FAVORITE_DATA:
const a : CardProps = action.payload
if(a.route.bool ==false){
if(state.favoriteCards == undefined){
const tab = [a.route.card]
StorageHeart.setItem("favoriteList",tab)
return {...state, favoriteCards : tab};
}
if( Array.from(state.favoriteCards).every((elem) => elem != a.route.card)){
//@ts-ignore //@ts-ignore
return {...state, favoriteCards: state.favoriteCards.push(action.payload)}; const tab = state.favoriteCards.concat([a.route.card])
console.log(state.favoriteCards)
StorageHeart.setItem("favoriteList",tab)
return {...state, favoriteCards : tab};
}
return {...state}
}
else{
const tab = state.favoriteCards.filter((item) => item!= a.route.card)
StorageHeart.setItem("favoriteList",tab)
return {...state, favoriteCards : tab };
}
case FETCH_DATA: case FETCH_DATA:
// @ts-ignore
return {...state, cards: action.payload}; return {...state, cards: action.payload};
case SET_FAVS:
//@ts-ignore
console.log("Set_favs : ",action.payload)
return {...state, favoriteCards: action.payload}
default: default:
return state; return state;
} }

@ -4,11 +4,53 @@ import { useNavigation } from '@react-navigation/native';
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer } from '@react-navigation/native';
import StackNavigation from '../navigation/StackNavigation' import StackNavigation from '../navigation/StackNavigation'
import { Colors } from 'react-native/Libraries/NewAppScreen'; import { Colors } from 'react-native/Libraries/NewAppScreen';
import { useDispatch } from 'react-redux';
import { useEffect } from 'react';
import { getAllCards } from "../redux/actions/actionSelection"
import StorageHeart from '../service/AsyncStorage';
import { setFavList } from '../redux/actions/action_setFavList';
import { setList } from '../redux/actions/action_setFavs';
import { Card } from '../models/Card';
//import { setList } from '../redux/actions/action_setList';
//import Button from 'react-bootstrap/Button';
// @ts-ignore //(ta gueule pour l'erreur sur navigation)
// @ts-ignore //
export default function HomeScreen({navigation}) { export default function HomeScreen({navigation}) {
const dispatch = useDispatch();
useEffect(() => {
console.log("USEEFFECT")
const loadFavCards = async () => {
//@ts-ignore
//await dispatch(getAllCards());
const list = await StorageHeart.getItem("favoriteList")
console.log("async favs : ",list)
//@ts-ignore
dispatch(setList(list))
};
loadFavCards();
}, [dispatch]);
useEffect(() => {
console.log("USEEFFECT")
const loadCards = async () => {
//@ts-ignore
await dispatch(getAllCards());
};
loadCards();
}, [dispatch]);
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.centered}> <View style={styles.centered}>

@ -1,91 +1,63 @@
import { StyleSheet, Text, View, Button, FlatList } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import React, { useState } from "react";
import {setFavList } from '../redux/actions/action_setFavList';
//redux import { StyleSheet, Text, View, Button, TouchableHighlight, TextInput, ImageBackground } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from "react";
import { FlatList } from 'react-native-gesture-handler';
import {useDispatch, useSelector} from 'react-redux'; import {useDispatch, useSelector} from 'react-redux';
import {useEffect} from 'react'; import { FontAwesome } from '@expo/vector-icons';
import { ThunkAction } from 'redux-thunk';
export const Cardslist = [
{
id: '1',
title: "premier élément",
},
{
id: '2',
title: "second élément",
},
{
id: '3',
title: "élément",
},
{
id: '4',
title: "barman douteux",
},
{
id: '10',
title: "dernier élément",
}
];
//? possiblement à supprimer
import { getAllCards } from "../redux/actions/actionSelection"
import { Card } from '../models/Card';
import { Image } from 'react-native';
import { ImageURISource } from 'react-native';
import Item from '../components/ListItemComponent';
//@ts-ignore //* Icons
const Item = ({title}) => ( // import { BiSearchAlt } from 'react-icons';
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
//TODO
// export const getFavList = () => {
// //In order to use await your callback must be asynchronous using async keyword.
// return async dispatch => {
// //Then perform your asynchronous operations.
// try {
// //Have it first fetch data from our starwars url.
// //const nounoursPromise = await fetch('https://iut-weather-api.azurewebsites.net/nounours');
// //Then use the json method to get json data from api/
// //const nounoursListJson = await nounoursPromise.json();
// //const nounoursList: Nounours[] = nounoursListJson.map(elt => new Nounours(elt["name"], elt["age"], elt["nbPoils"], elt["image"]));
// dispatch(setFavList(Array{id,title}));
// } catch (error) {
// console.log('Error---------', error);
// //You can dispatch to another action if you want to display an error message in the application
// //dispatch(fetchDataRejected(error))
// }
// }
// }
//* Components
//@ts-ignore
export default function ListScreen({navigation}){
//@ts-ignore
var nList : Card[] = useSelector(state => state.appReducer.favoriteCards);
console.log(" favs : ",nList)
export default function Main(){ const [searchValue, setSearchValue] = useState('');
const [count, setCount] = useState(0);
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text>Maman, J4AI UNE LISTE DE FAVORIS ! !</Text>
<StatusBar style="auto" /> <TextInput
<Text>{count}</Text> style={styles.textInput}
<Button onPress={()=> setCount(count+1)} title="+1"/> value={searchValue}
<Button onPress={()=> setCount(count+2)} title="+2"/> onChangeText={text => setSearchValue(text)}
<Button onPress={()=> setCount(count+10)} title="+10"/> placeholder="Rechercher une carte..."
/>
<FlatList data={Cardslist}
renderItem={({item}) => <Item title={item.title} />} <FlatList
keyExtractor={item => item.id}/> numColumns={2}
data={nList}
renderItem={({item}) =>
<TouchableHighlight onPress={() => navigation.navigate("ListFav")}>
<Item route={{
card: item,
bool: true
}} />
</TouchableHighlight>
}
keyExtractor={(item: Card) => item.id}
/>
</View> </View>
); );
} }
@ -94,17 +66,18 @@ export default function Main(){
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: '#fff', backgroundColor: '#ac9585',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'space-evenly',
}, },
item: { textInput: {
padding: 15,
margin: 5,
width:200,
backgroundColor: '#ffffff',
borderRadius : 15, borderRadius : 15,
backgroundColor: '#efefef', shadowColor: 'grey',
padding: 20, textAlign:'center'
margin : 10,
},
title: {
fontStyle: "italic",
} }
}); });

@ -1,17 +1,15 @@
import { StyleSheet, Text, View, Button, TouchableHighlight, TextInput } from 'react-native'; import { StyleSheet, Text, View, Button, TouchableHighlight, TextInput, ImageBackground, LogBox } from 'react-native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { FlatList } from 'react-native-gesture-handler'; import { FlatList } from 'react-native-gesture-handler';
import {useDispatch, useSelector} from 'react-redux'; import {useDispatch, useSelector} from 'react-redux';
import { FontAwesome } from '@expo/vector-icons';
import { ThunkAction } from 'redux-thunk'; import { ThunkAction } from 'redux-thunk';
//? possiblement à supprimer //? possiblement à supprimer
import { getAllCards } from "../redux/actions/actionSelection" import { getAllCards } from "../redux/actions/actionSelection"
import { StubLib } from '../data/stub';
import { Card } from '../models/Card'; import { Card } from '../models/Card';
import { Image } from 'react-native'; import { Image } from 'react-native';
import { ImageURISource } from 'react-native'; import { ImageURISource } from 'react-native';
@ -20,42 +18,31 @@ import { ImageURISource } from 'react-native';
// import { BiSearchAlt } from 'react-icons'; // import { BiSearchAlt } from 'react-icons';
//* Components //* Components
import {ListItemComponent} from '../components/ListItemComponent' import { setFavList } from '../redux/actions/action_setFavList';
import Item from '../components/ListItemComponent';
//@ts-ignore //@ts-ignore
export default function ListScreen({navigation}){ export default function ListScreen({navigation}){
const [count, setCount] = useState(0); const [count, setCount] = useState(0);
// // Initialize the binding content with the application initial state // // Initialize the binding content with the application initial state
//@ts-ignore //@ts-ignore
const nList = useSelector(state => state.appReducer.cards); var nList = useSelector(state => state.appReducer.cards);
// Create a const that will hold the react-redux events dispatcher // Create a const that will hold the react-redux events dispatcher
const dispatch = useDispatch(); const dispatch = useDispatch();
// Let's define a hook that will be used to update the rendered state after the return will be called // Let's define a hook that will be used to update the rendered state after the return will be called
// You cannot perform side-effects outside of a useEffect hook // You cannot perform side-effects outside of a useEffect hook
useEffect(() => { // useEffect(() => {
console.log("USEEFFECT") // console.log("USEEFFECT")
const loadCards = async () => { // const loadCards = async () => {
//@ts-ignore // //@ts-ignore
await dispatch(getAllCards()); // await dispatch(getAllCards());
}; // };
loadCards(); // loadCards();
}, [dispatch]); // }, [dispatch]);
//* Stub
// const {getCards} = new StubLib();
// const list: Card[] = getCards();
// const req = fetch('https://omgvamp-hearthstone-v1.p.rapidapi.com/cards')
//https://us.api.blizzard.com/hearthstone/cards/678?locale=en_US
//* Search : //* Search :
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
@ -78,7 +65,10 @@ export default function ListScreen({navigation}){
data={filteredList} data={filteredList}
renderItem={({item}) => renderItem={({item}) =>
<TouchableHighlight onPress={() => navigation.navigate("ListFav")}> <TouchableHighlight onPress={() => navigation.navigate("ListFav")}>
<ListItemComponent url={item.img}/> <Item route={{
card: item,
bool: false
}} ></Item>
</TouchableHighlight> </TouchableHighlight>
} }
keyExtractor={(item: Card) => item.id.toString()} keyExtractor={(item: Card) => item.id.toString()}
@ -99,25 +89,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-evenly', justifyContent: 'space-evenly',
}, },
border: {
flex: 1,
backgroundColor: '#ff0000',
maxHeight : 100,
borderWidth : 15,
borderRadius : 15,
borderColor : '#00ffaa',
alignItems: 'center',
justifyContent: 'center',
},
item: {
borderRadius : 15,
backgroundColor: '#efefef',
padding: 20,
margin : 10,
},
title: {
fontStyle: "italic",
},
textInput: { textInput: {
padding: 15, padding: 15,
margin: 5, margin: 5,
@ -128,3 +99,4 @@ const styles = StyleSheet.create({
textAlign:'center' textAlign:'center'
} }
}); });

@ -0,0 +1,28 @@
import { Card } from "../models/Card";
import AsyncStorage from "@react-native-async-storage/async-storage";
export default class StorageHeart {
static async getItem(key: string): Promise<any> {
try {
const value = await AsyncStorage.getItem(key);
console.log("load")
if (value !== null) {
return JSON.parse(value);
}
} catch (e) {
console.error(`AsyncStorage getItem error: ${e}`);
}
return null;
}
static async setItem(key: string, value: any): Promise<void> {
try {
await AsyncStorage.setItem(key, JSON.stringify(value));
console.log("save")
} catch (e) {
console.error(`AsyncStorage setItem error: ${e}`);
}
}
}

@ -1550,6 +1550,13 @@
mkdirp "^1.0.4" mkdirp "^1.0.4"
rimraf "^3.0.2" rimraf "^3.0.2"
"@react-native-async-storage/async-storage@1.17.11":
version "1.17.11"
resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz#7ec329c1b9f610e344602e806b04d7c928a2341d"
integrity sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw==
dependencies:
merge-options "^3.0.4"
"@react-native-community/cli-clean@^10.1.1": "@react-native-community/cli-clean@^10.1.1":
version "10.1.1" version "10.1.1"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-10.1.1.tgz#4c73ce93a63a24d70c0089d4025daac8184ff504" resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-10.1.1.tgz#4c73ce93a63a24d70c0089d4025daac8184ff504"
@ -4059,6 +4066,11 @@ is-path-inside@^3.0.2:
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
is-plain-obj@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-plain-object@^2.0.3, is-plain-object@^2.0.4: is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -4550,6 +4562,13 @@ memory-cache@~0.2.0:
resolved "https://registry.yarnpkg.com/memory-cache/-/memory-cache-0.2.0.tgz#7890b01d52c00c8ebc9d533e1f8eb17e3034871a" resolved "https://registry.yarnpkg.com/memory-cache/-/memory-cache-0.2.0.tgz#7890b01d52c00c8ebc9d533e1f8eb17e3034871a"
integrity sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA== integrity sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==
merge-options@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7"
integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==
dependencies:
is-plain-obj "^2.1.0"
merge-stream@^2.0.0: merge-stream@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"

Loading…
Cancel
Save