diff --git a/components/ListItemComponent.tsx b/components/ListItemComponent.tsx
index e9b4d7d..037b2cc 100644
--- a/components/ListItemComponent.tsx
+++ b/components/ListItemComponent.tsx
@@ -1,17 +1,53 @@
-import { View } from 'react-native';
-import { Image } from 'react-native';
+import { useDispatch } from "react-redux";
+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
+
+ const {route} = props;
+ const item: Card = route.card;
+ const bool: boolean = route.bool;
+ const dispatch = useDispatch()
-type ItemProps = {
- url : string //Image URL
-}
+ const HandleAddFav = (props : CardProps) => {
+ console.log("add new card")
+ dispatch(setFavList(props));
+ }
+ return(
-export function ListItemComponent(props : ItemProps){
- return (
-
-
-
- )
+ /* dispatch , */
+
+
+ HandleAddFav(props)} >
+
+
+
+
+
+ );
}
+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,
+ },});
\ No newline at end of file
diff --git a/data/ApiDataManager.tsx b/data/ApiDataManager.tsx
deleted file mode 100644
index a08be79..0000000
--- a/data/ApiDataManager.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-
-// export class ApiDataManager{
-
-
-// public async getCards() : Promise {
-
-
-// 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;
-// }
-// }
diff --git a/data/stub.ts b/data/stub.ts
deleted file mode 100644
index f700882..0000000
--- a/data/stub.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Card } from "../models/Card"
-
-export class StubLib {
-
- public getCards(): Card[] {
- const NOUNOURS_LIST : Card[] = [
-
-
- ]
- return NOUNOURS_LIST
- }
-}
-
diff --git a/models/Card.tsx b/models/Card.tsx
index d85f1f0..64ee37a 100644
--- a/models/Card.tsx
+++ b/models/Card.tsx
@@ -5,9 +5,9 @@ import {Classe} from "./Classe";
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) {
- this._id=id
- this._name=name
+ 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.name=name
//this._set=set
// this._type=type
// this._class=clas
@@ -19,27 +19,19 @@ export class Card {
// this._flavor = flavor
// this._artist = artist
// this._collectible = collectible
- this._img = img
- this._imgGold = imgGold
+ this.img = img
+ this.imgGold = imgGold
// this._cropImg = cropImg
+ this.fav = fav
}
// ID //
- private _id : number;
- get id(): number {
- return this._id
- }
+ public id;
// NAME //
- private _name : string;
- get name(): string {
- return this._name;
- }
- set name(value: string) {
- this._name = value;
- }
+ public name;
// private _set : CardSet;
@@ -131,22 +123,8 @@ export class Card {
// this._collectible = value;
// }
- private _img : string
-
- 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 ;
- }
+ public img;
+ public imgGold;
// private _cropImg : string
// get cropImg(): string {
@@ -155,4 +133,6 @@ export class Card {
// set cropImg(value: string) {
// this._cropImg = value;
// }
+
+ public fav;
}
\ No newline at end of file
diff --git a/package.json b/package.json
index 691dc31..58c75a2 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"web": "expo start --web"
},
"dependencies": {
+ "@react-native-async-storage/async-storage": "1.17.11",
"@react-navigation/bottom-tabs": "^6.5.5",
"@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10",
diff --git a/props/favprops.tsx b/props/favprops.tsx
new file mode 100644
index 0000000..2662592
--- /dev/null
+++ b/props/favprops.tsx
@@ -0,0 +1,8 @@
+import { Card } from "../models/Card";
+
+export interface CardProps{
+ route : {
+ card: Card;
+ bool: boolean;
+ }
+}
\ No newline at end of file
diff --git a/redux/actions/actionSelection.tsx b/redux/actions/actionSelection.tsx
index 533a5d9..3b2cf3f 100644
--- a/redux/actions/actionSelection.tsx
+++ b/redux/actions/actionSelection.tsx
@@ -25,7 +25,7 @@ import { Card } from "../../models/Card";
// constructor(cardId : String, name : String, manaCost : number, attack : number, health : number, desc : String){
// this.cardId = cardId;
// this.name = name;
-// this.manaCost = manaCost;
+// this.manaCost = manaCost;ADD_FAVORITE_DATA, FETCH_DATA,
// this.attack = attack;
// this.health = health;
// this.desc = desc;
@@ -50,7 +50,7 @@ export const getAllCards = () => {
// 'content-length':'9505',
// 'content-type':'application/json; charset=utf-8',
// 'etag':'W/"74bb-QMT8DIj6saBS1wT4u5WWcEmZAdw"'
- // }
+ // }ADD_FAVORITE_DATA, FETCH_DATA,
//! Actualisation de l'API (16/03) :
headers: {
@@ -61,7 +61,7 @@ export const getAllCards = () => {
//'pageSize':'100'
};
//! 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);
//console.log("FETCH")
//console.log(CardsPromise)
diff --git a/redux/actions/action_setFavList.tsx b/redux/actions/action_setFavList.tsx
index 960fe9d..8707ffa 100644
--- a/redux/actions/action_setFavList.tsx
+++ b/redux/actions/action_setFavList.tsx
@@ -1,8 +1,10 @@
+import { Card } from '../../models/Card';
+import { CardProps } from '../../props/favprops';
import {ADD_FAVORITE_DATA, FETCH_DATA} from '../constants';
-export const setFavList = (List: String[]) => {
+export const setFavList = (props : CardProps) => {
return {
type: ADD_FAVORITE_DATA,
- payload: List,
+ payload: props,
};
}
\ No newline at end of file
diff --git a/redux/actions/action_setFavs.tsx b/redux/actions/action_setFavs.tsx
new file mode 100644
index 0000000..6dac0df
--- /dev/null
+++ b/redux/actions/action_setFavs.tsx
@@ -0,0 +1,9 @@
+import { Card } from '../../models/Card';
+import {SET_FAVS} from '../constants';
+
+export const setList = (list: []) => {
+ return {
+ type: SET_FAVS,
+ payload: list
+ };
+}
diff --git a/redux/actions/action_setList.tsx b/redux/actions/action_setList.tsx
deleted file mode 100644
index e443c32..0000000
--- a/redux/actions/action_setList.tsx
+++ /dev/null
@@ -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,
-// };
-// }
\ No newline at end of file
diff --git a/redux/constants.tsx b/redux/constants.tsx
index ff6ccf4..3bf354d 100644
--- a/redux/constants.tsx
+++ b/redux/constants.tsx
@@ -4,4 +4,7 @@ export const FETCH_DATA = "FETCH_DATA"
export const ADD_FAVORITE_DATA = "ADD_FAVORITE_DATA"
-export const DISPLAY_ALL_CARD = "DISPLAY_ALL_CARD"
\ No newline at end of file
+export const DISPLAY_ALL_CARD = "DISPLAY_ALL_CARD"
+
+export const SET_FAVS = "SET_FAVS"
+
diff --git a/redux/reducers/appReducer.tsx b/redux/reducers/appReducer.tsx
index 0af429d..06f3da2 100644
--- a/redux/reducers/appReducer.tsx
+++ b/redux/reducers/appReducer.tsx
@@ -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 = {
cards: [],
- favoriteCards: [],
- // cards: ["C_ace", "C_K", "C_Q", "C_J"],
- // favoriteCards: [ "C_ace", "C_K"],
+ favoriteCards: []
}
@@ -12,11 +14,35 @@ const initialState = {
export default appReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_FAVORITE_DATA:
- // @ts-ignore
- return {...state, favoriteCards: state.favoriteCards.push(action.payload)};
+
+ 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
+ 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:
- // @ts-ignore
return {...state, cards: action.payload};
+ case SET_FAVS:
+ //@ts-ignore
+ console.log("Set_favs : ",action.payload)
+ return {...state, favoriteCards: action.payload}
default:
return state;
}
diff --git a/screens/HomeScreen.tsx b/screens/HomeScreen.tsx
index a0e2deb..ede4152 100644
--- a/screens/HomeScreen.tsx
+++ b/screens/HomeScreen.tsx
@@ -4,11 +4,53 @@ import { useNavigation } from '@react-navigation/native';
import { NavigationContainer } from '@react-navigation/native';
import StackNavigation from '../navigation/StackNavigation'
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}) {
+
+
+ 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 (
diff --git a/screens/ListFav.tsx b/screens/ListFav.tsx
index 61bb8fe..1f96496 100644
--- a/screens/ListFav.tsx
+++ b/screens/ListFav.tsx
@@ -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 {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';
+//* Icons
+// import { BiSearchAlt } from 'react-icons';
-//@ts-ignore
-const Item = ({title}) => (
-
- {title}
-
-);
-
-
-
-//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)
+ const [searchValue, setSearchValue] = useState('');
-export default function Main(){
- const [count, setCount] = useState(0);
-
return (
- Maman, J4AI UNE LISTE DE FAVORIS ! !
-
- {count}
-
+
+
);
}
@@ -94,17 +66,18 @@ export default function Main(){
const styles = StyleSheet.create({
container: {
flex: 1,
- backgroundColor: '#fff',
+ backgroundColor: '#ac9585',
alignItems: 'center',
- justifyContent: 'center',
+ justifyContent: 'space-evenly',
+
},
- item: {
+ textInput: {
+ padding: 15,
+ margin: 5,
+ width:200,
+ backgroundColor: '#ffffff',
borderRadius : 15,
- backgroundColor: '#efefef',
- padding: 20,
- margin : 10,
- },
- title: {
- fontStyle: "italic",
+ shadowColor: 'grey',
+ textAlign:'center'
}
});
diff --git a/screens/ListScreen.tsx b/screens/ListScreen.tsx
index 7c68a24..863029a 100644
--- a/screens/ListScreen.tsx
+++ b/screens/ListScreen.tsx
@@ -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 React, { useState, useEffect } from "react";
import { FlatList } from 'react-native-gesture-handler';
import {useDispatch, useSelector} from 'react-redux';
-
+import { FontAwesome } from '@expo/vector-icons';
import { ThunkAction } from 'redux-thunk';
//? possiblement à supprimer
import { getAllCards } from "../redux/actions/actionSelection"
-
-import { StubLib } from '../data/stub';
import { Card } from '../models/Card';
import { Image } from 'react-native';
import { ImageURISource } from 'react-native';
@@ -20,42 +18,31 @@ import { ImageURISource } from 'react-native';
// import { BiSearchAlt } from 'react-icons';
//* Components
-import {ListItemComponent} from '../components/ListItemComponent'
-
+import { setFavList } from '../redux/actions/action_setFavList';
+import Item from '../components/ListItemComponent';
//@ts-ignore
export default function ListScreen({navigation}){
const [count, setCount] = useState(0);
-
-
// // Initialize the binding content with the application initial state
-
//@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
const dispatch = useDispatch();
// 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
- useEffect(() => {
- console.log("USEEFFECT")
- const loadCards = async () => {
- //@ts-ignore
- await dispatch(getAllCards());
- };
- loadCards();
- }, [dispatch]);
-
-
-
- //* Stub
- // const {getCards} = new StubLib();
- // const list: Card[] = getCards();
- // const req = fetch('https://omgvamp-hearthstone-v1.p.rapidapi.com/cards')
+ // useEffect(() => {
+ // console.log("USEEFFECT")
+ // const loadCards = async () => {
+ // //@ts-ignore
+ // await dispatch(getAllCards());
+ // };
+ // loadCards();
+ // }, [dispatch]);
- //https://us.api.blizzard.com/hearthstone/cards/678?locale=en_US
//* Search :
const [searchValue, setSearchValue] = useState('');
@@ -78,7 +65,10 @@ export default function ListScreen({navigation}){
data={filteredList}
renderItem={({item}) =>
navigation.navigate("ListFav")}>
-
+
}
keyExtractor={(item: Card) => item.id.toString()}
@@ -99,25 +89,6 @@ const styles = StyleSheet.create({
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: {
padding: 15,
margin: 5,
@@ -128,3 +99,4 @@ const styles = StyleSheet.create({
textAlign:'center'
}
});
+
diff --git a/service/AsyncStorage.tsx b/service/AsyncStorage.tsx
new file mode 100644
index 0000000..65a16e3
--- /dev/null
+++ b/service/AsyncStorage.tsx
@@ -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 {
+ 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 {
+ try {
+ await AsyncStorage.setItem(key, JSON.stringify(value));
+ console.log("save")
+ } catch (e) {
+ console.error(`AsyncStorage setItem error: ${e}`);
+ }
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 03494ae..e1933de 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1550,6 +1550,13 @@
mkdirp "^1.0.4"
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":
version "10.1.1"
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"
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:
version "2.0.4"
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"
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:
version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"